Skip to content

Commit 296c403

Browse files
authored
Merge pull request #474 from unity-sds/develop
release/9.1.0
2 parents b9e7739 + 335a925 commit 296c403

File tree

17 files changed

+505
-73
lines changed

17 files changed

+505
-73
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [9.1.0] - 2024-12-03
9+
### Changed
10+
- [#472](https://github.com/unity-sds/unity-data-services/pull/472) feat: amalgamation download type
11+
12+
## [9.0.1] - 2024-12-03
13+
### Fixed
14+
- [#459](https://github.com/unity-sds/unity-data-services/pull/459) fix: single catalog multiple collections
15+
816
## [9.0.0] - 2024-11-04
917
### Added
1018
- [#457](https://github.com/unity-sds/unity-data-services/pull/457) breaking change : update uds lib

cumulus_lambda_functions/cumulus_wrapper/query_collections.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
class CollectionsQuery(CumulusBase):
1414
__collections_key = 'collections'
15+
__providers_key = 'providers'
1516
__rules_key = 'rules'
1617
__stats_key = 'stats'
1718
__collection_id_key = 'collectionId'
@@ -337,3 +338,48 @@ def query(self):
337338
LOGGER.exception('error during cumulus query')
338339
return {'server_error': str(e)}
339340
return {'results': [CollectionTransformer().to_stac(k) for k in query_result]}
341+
342+
def create_provider(self, provider_name: str, s3_bucket: str, private_api_prefix: str):
343+
# INSERT INTO providers (name, protocol, host) VALUES ('unity', 's3', 'https://dev.mdps.mcp.nasa.gov');
344+
# TODO : this fails
345+
payload = {
346+
'httpMethod': 'POST',
347+
'resource': '/{proxy+}',
348+
'path': f'/{self.__providers_key}',
349+
'headers': {
350+
'Content-Type': 'application/json',
351+
},
352+
'body': json.dumps({
353+
"id": provider_name,
354+
"host": s3_bucket,
355+
"protocol": "s3",
356+
# "port": 443,
357+
"globalConnectionLimit": 1000,
358+
# "maxDownloadTime": 300,
359+
# "username": "na",
360+
# "password": "na",
361+
# "privateKey": "na",
362+
# "cmKeyId": "na",
363+
# "allowedRedirects": "na",
364+
})
365+
}
366+
LOGGER.debug(f'payload: {payload}')
367+
try:
368+
query_result = self._invoke_api(payload, private_api_prefix)
369+
"""
370+
{'statusCode': 500, 'body': '', 'headers': {}}
371+
"""
372+
if query_result['statusCode'] >= 500:
373+
LOGGER.error(f'server error status code: {query_result["statusCode"]}. details: {query_result}')
374+
return {'server_error': query_result}
375+
if query_result['statusCode'] >= 400:
376+
LOGGER.error(f'client error status code: {query_result["statusCode"]}. details: {query_result}')
377+
return {'client_error': query_result}
378+
query_result = json.loads(query_result['body'])
379+
LOGGER.debug(f'json query_result: {query_result}')
380+
if 'message' not in query_result:
381+
return {'server_error': f'invalid response: {query_result}'}
382+
except Exception as e:
383+
LOGGER.exception('error while invoking')
384+
return {'server_error': f'error while invoking:{str(e)}'}
385+
return {'status': query_result['message']}

cumulus_lambda_functions/docker_entrypoint/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def choose_process():
1717
return result_str
1818
if argv[1].strip().upper() == 'DOWNLOAD':
1919
logging.info('starting DOWNLOAD script')
20-
result_str = DownloadGranulesFactory().get_class(os.getenv('GRANULES_DOWNLOAD_TYPE', 'MISSING_GRANULES_DOWNLOAD_TYPE')).download()
20+
result_str = DownloadGranulesFactory().get_class(os.getenv('GRANULES_DOWNLOAD_TYPE', DownloadGranulesFactory.AMALGAMATION)).download()
2121
StageInOutUtils.write_output_to_file(result_str)
2222
return result_str
2323
if argv[1].strip().upper() == 'UPLOAD':

cumulus_lambda_functions/granules_cnm_ingester/granules_cnm_ingester_logic.py

Lines changed: 48 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os
22
import time
3+
from concurrent.futures import ThreadPoolExecutor, as_completed
34

45
from mdps_ds_lib.lib.aws.aws_message_transformers import AwsMessageTransformers
56
from cumulus_lambda_functions.lib.uds_db.uds_collections import UdsCollections
@@ -10,7 +11,6 @@
1011

1112
from mdps_ds_lib.lib.cumulus_stac.unity_collection_stac import UnityCollectionStac
1213
from cumulus_lambda_functions.uds_api.dapa.collections_dapa_creation import CollectionDapaCreation
13-
from mdps_ds_lib.lib.cumulus_stac.item_transformer import ItemTransformer
1414
from pystac import ItemCollection, Item
1515
from mdps_ds_lib.lib.utils.file_utils import FileUtils
1616
from cumulus_lambda_functions.lib.lambda_logger_generator import LambdaLoggerGenerator
@@ -118,41 +118,58 @@ def extract_collection_id(self):
118118
if len(self.successful_features.items) < 1:
119119
LOGGER.error(f'not required to process. No Granules: {self.successful_features.to_dict(False)}')
120120
return
121-
self.collection_id = self.successful_features.items[0].collection_id
121+
self.collection_id = list(set([k.collection_id for k in self.successful_features.items]))
122122
return
123123

124-
def has_collection(self):
125-
uds_collection_result = self.__uds_collection.get_collection(self.collection_id)
124+
def has_collection(self, collection_id_custom=None):
125+
collection_id_custom = collection_id_custom if collection_id_custom is not None else self.collection_id
126+
uds_collection_result = self.__uds_collection.get_collection(collection_id_custom)
126127
return len(uds_collection_result) > 0
127128

128-
def create_collection(self):
129+
def create_one_collection(self, collection_id):
130+
try:
131+
if collection_id is None:
132+
raise RuntimeError(f'NULL collection_id')
133+
if self.has_collection(collection_id):
134+
LOGGER.debug(f'{collection_id} already exists. continuing..')
135+
return {'status': 'success'}
136+
# ref: https://github.com/unity-sds/unity-py/blob/0.4.0/unity_sds_client/services/data_service.py
137+
dapa_collection = UnityCollectionStac() \
138+
.with_id(collection_id) \
139+
.with_graule_id_regex("^test_file.*$") \
140+
.with_granule_id_extraction_regex("(^test_file.*)(\\.nc|\\.nc\\.cas|\\.cmr\\.xml)") \
141+
.with_title(f'Collection: {collection_id}') \
142+
.with_process('stac') \
143+
.with_provider(self.__default_provider) \
144+
.add_file_type("test_file01.nc", "^test_file.*\\.nc$", 'unknown_bucket', 'application/json', 'root') \
145+
.add_file_type("test_file01.nc", "^test_file.*\\.nc$", 'protected', 'data', 'item') \
146+
.add_file_type("test_file01.nc.cas", "^test_file.*\\.nc.cas$", 'protected', 'metadata', 'item') \
147+
.add_file_type("test_file01.nc.cmr.xml", "^test_file.*\\.nc.cmr.xml$", 'protected', 'metadata', 'item') \
148+
.add_file_type("test_file01.nc.stac.json", "^test_file.*\\.nc.stac.json$", 'protected', 'metadata',
149+
'item')
150+
151+
stac_collection = dapa_collection.start()
152+
creation_result = CollectionDapaCreation(stac_collection).create()
153+
if creation_result['statusCode'] >= 400:
154+
raise RuntimeError(
155+
f'failed to create collection: {collection_id}. details: {creation_result["body"]}')
156+
time.sleep(3) # cool off period before checking DB
157+
if not self.has_collection(collection_id):
158+
LOGGER.error(f'missing collection. (failed to create): {collection_id}')
159+
raise ValueError(f'missing collection. (failed to create): {collection_id}')
160+
except Exception as e:
161+
return {'status': 'error', 'details': str(e)}
162+
return {'status': 'success'}
163+
164+
def create_collection_async(self):
129165
if self.collection_id is None:
130166
raise RuntimeError(f'NULL collection_id')
131-
if self.has_collection():
132-
LOGGER.debug(f'{self.collection_id} already exists. continuing..')
133-
return
134-
# ref: https://github.com/unity-sds/unity-py/blob/0.4.0/unity_sds_client/services/data_service.py
135-
dapa_collection = UnityCollectionStac() \
136-
.with_id(self.collection_id) \
137-
.with_graule_id_regex("^test_file.*$") \
138-
.with_granule_id_extraction_regex("(^test_file.*)(\\.nc|\\.nc\\.cas|\\.cmr\\.xml)") \
139-
.with_title(f'Collection: {self.collection_id}') \
140-
.with_process('stac') \
141-
.with_provider(self.__default_provider) \
142-
.add_file_type("test_file01.nc", "^test_file.*\\.nc$", 'unknown_bucket', 'application/json', 'root') \
143-
.add_file_type("test_file01.nc", "^test_file.*\\.nc$", 'protected', 'data', 'item') \
144-
.add_file_type("test_file01.nc.cas", "^test_file.*\\.nc.cas$", 'protected', 'metadata', 'item') \
145-
.add_file_type("test_file01.nc.cmr.xml", "^test_file.*\\.nc.cmr.xml$", 'protected', 'metadata', 'item') \
146-
.add_file_type("test_file01.nc.stac.json", "^test_file.*\\.nc.stac.json$", 'protected', 'metadata', 'item')
147-
148-
stac_collection = dapa_collection.start()
149-
creation_result = CollectionDapaCreation(stac_collection).create()
150-
if creation_result['statusCode'] >= 400:
151-
raise RuntimeError(f'failed to create collection: {self.collection_id}. details: {creation_result["body"]}')
152-
time.sleep(3) # cool off period before checking DB
153-
if not self.has_collection():
154-
LOGGER.error(f'missing collection. (failed to create): {self.collection_id}')
155-
raise ValueError(f'missing collection. (failed to create): {self.collection_id}')
167+
with ThreadPoolExecutor() as executor:
168+
futures = [executor.submit(self.create_one_collection, collection_id) for collection_id in self.collection_id]
169+
results = [future.result() for future in as_completed(futures)]
170+
errors = [k['details'] for k in results if k['status'] == 'error']
171+
if len(errors) > 0:
172+
raise ValueError(f'error while creating collections: {errors}')
156173
return
157174

158175
def send_cnm_msg(self):
@@ -188,6 +205,6 @@ def start(self, event):
188205
self.load_successful_features_s3(s3_url)
189206
self.validate_granules()
190207
self.extract_collection_id()
191-
self.create_collection()
208+
self.create_collection_async()
192209
self.send_cnm_msg()
193210
return

cumulus_lambda_functions/lib/uds_db/granules_db_index.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,13 @@ def add_entry(self, tenant: str, tenant_venue: str, json_body: dict, doc_id: str
218218

219219
def dsl_search(self, tenant: str, tenant_venue: str, search_dsl: dict):
220220
read_alias_name = f'{DBConstants.granules_read_alias_prefix}_{tenant}_{tenant_venue}'.lower().strip()
221-
original_size = search_dsl['size']
221+
if 'sort' not in search_dsl:
222+
search_result = self.__es.query(search_dsl,
223+
querying_index=read_alias_name) if 'sort' in search_dsl else self.__es.query(
224+
search_dsl, querying_index=read_alias_name)
225+
LOGGER.debug(f'search_finished: {len(search_result["hits"]["hits"])}')
226+
return search_result
227+
original_size = search_dsl['size'] if 'size' in search_dsl else 20
222228
result = []
223229
duplicates = set([])
224230
while len(result) < original_size:

cumulus_lambda_functions/metadata_stac_generate_cmr/generate_cmr.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
"required": [
7070
"type"
7171
],
72-
"oneOf": [
72+
"anyOf": [
7373
{"required": ["bucket", "key"]},
7474
{"required": ["url_path"]}
7575
],

cumulus_lambda_functions/uds_api/dapa/collections_dapa_cnm.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ def start(self):
212212
"version": '1.6.0', # TODO
213213
'product': {
214214
'name': each_granule['id'],
215-
'dataVersion': collection_id_version[1],
215+
'dataVersion': collection_id_version[1] if len(collection_id_version) > 1 else '',
216216
'files': [self.__generate_cumulus_asset(v) for k, v in each_granule['assets'].items()],
217217
}
218218
}

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jsonschema==4.23.0
1515
jsonschema-specifications==2023.12.1
1616
lark==0.12.0
1717
mangum==0.18.0
18-
mdps-ds-lib==1.0.0
18+
mdps-ds-lib==1.1.0
1919
pydantic==2.9.2
2020
pydantic_core==2.23.4
2121
pygeofilter==0.2.4

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
setup(
1414
name="cumulus_lambda_functions",
15-
version="9.0.0",
15+
version="9.1.0",
1616
packages=find_packages(),
1717
install_requires=install_requires,
1818
package_data={

tests/cumulus_lambda_functions/cumulus_wrapper/test_query_collection.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,3 +180,10 @@ def test_rules_04(self):
180180
print(json.dumps(rules, indent=4))
181181
# self.assertTrue(False, rules)
182182
return
183+
184+
def test_create_provider(self):
185+
lambda_prefix = 'uds-sbx-cumulus'
186+
collection_query = CollectionsQuery('NA', 'NA')
187+
result = collection_query.create_provider('william-test2', 'uds-sbx-staging', lambda_prefix)
188+
print(result)
189+
return

0 commit comments

Comments
 (0)