diff --git a/README.md b/README.md index 5b4a2e2..34248e0 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,9 @@ wis2-gdc register /path/to/dir/of/wcmp2-files # loading metadata manually (from URL) wis2-gdc register https://example.org/wcmp2-file.json +# deleting metadata by identifier +wis2-gdc unregister "urn:wmo:md:ca-eccc-msc:id123" + # loading metadata from a known harvest endpoint # load from wis2box known deployments (https://demo.wis2box.wis.wmo.int) diff --git a/wis2-gdc-management/wis2_gdc/__init__.py b/wis2-gdc-management/wis2_gdc/__init__.py index 2c08ae0..754fac2 100644 --- a/wis2-gdc-management/wis2_gdc/__init__.py +++ b/wis2-gdc-management/wis2_gdc/__init__.py @@ -21,7 +21,7 @@ import click -from wis2_gdc.registrar import register, setup, teardown +from wis2_gdc.registrar import register, setup, teardown, unregister from wis2_gdc.archive import archive from wis2_gdc.sync import sync @@ -38,6 +38,7 @@ def cli(): cli.add_command(setup) cli.add_command(teardown) +cli.add_command(unregister) cli.add_command(register) cli.add_command(sync) cli.add_command(archive) diff --git a/wis2-gdc-management/wis2_gdc/backend/base.py b/wis2-gdc-management/wis2_gdc/backend/base.py index 9f1efbf..232e00c 100644 --- a/wis2-gdc-management/wis2_gdc/backend/base.py +++ b/wis2-gdc-management/wis2_gdc/backend/base.py @@ -50,7 +50,7 @@ def teardown(self) -> None: raise NotImplementedError() @abstractmethod - def save(self, record: dict) -> None: + def save_record(self, record: dict) -> None: """ Upsert a resource to a backend @@ -83,5 +83,17 @@ def record_exists(self, identifier: str) -> bool: raise NotImplementedError() + @abstractmethod + def delete_record(self, identifier: str) -> None: + """ + Delete a record from the backend + + :param identifier: `str` of record identifier + + :returns: `None` + """ + + raise NotImplementedError() + def __repr__(self): return '' diff --git a/wis2-gdc-management/wis2_gdc/backend/elastic.py b/wis2-gdc-management/wis2_gdc/backend/elastic.py index c6cf1a0..994a76f 100644 --- a/wis2-gdc-management/wis2_gdc/backend/elastic.py +++ b/wis2-gdc-management/wis2_gdc/backend/elastic.py @@ -153,10 +153,14 @@ def teardown(self) -> None: LOGGER.debug(f'Deleting index {self.index_name}') self.es.indices.delete(index=self.index_name) - def save(self, record: dict) -> None: + def save_record(self, record: dict) -> None: LOGGER.debug(f"Indexing record {record['id']}") self.es.index(index=self.index_name, id=record['id'], body=record) + def delete_record(self, identifier: str) -> None: + LOGGER.debug(f"Deleting record {identifier}") + self.es.delete(index=self.index_name, id=identifier) + def exists(self) -> bool: LOGGER.debug('Checking whether backend exists') diff --git a/wis2-gdc-management/wis2_gdc/backend/ogcapi_records.py b/wis2-gdc-management/wis2_gdc/backend/ogcapi_records.py index 18a17e1..fa7a575 100644 --- a/wis2-gdc-management/wis2_gdc/backend/ogcapi_records.py +++ b/wis2-gdc-management/wis2_gdc/backend/ogcapi_records.py @@ -38,7 +38,7 @@ def __init__(self, defs): self.conn = Records(env.API_URL) self.collection = 'discovery-metadata' - def save(self): + def save_record(self): ttype = 'create' diff --git a/wis2-gdc-management/wis2_gdc/hook.py b/wis2-gdc-management/wis2_gdc/hook.py index 457e3cb..b9472d6 100644 --- a/wis2-gdc-management/wis2_gdc/hook.py +++ b/wis2-gdc-management/wis2_gdc/hook.py @@ -30,10 +30,19 @@ class DiscoveryMetadataHook(Hook): def execute(self, topic: str, msg_dict: dict) -> None: + wcmp2_dict = None + LOGGER.debug('Discovery metadata hook execution begin') r = Registrar() - wcmp2_dict = r.get_wcmp2(msg_dict, topic) + try: + wcmp2_dict = r.get_wcmp2(msg_dict, topic) + except (IndexError, KeyError): + is_deletion = list(filter(lambda d: d['rel'] == 'deletion', + msg_dict['links'])) + + if is_deletion: + r.delete_record(topic, msg_dict) if wcmp2_dict is not None: r.register(wcmp2_dict, topic) diff --git a/wis2-gdc-management/wis2_gdc/registrar.py b/wis2-gdc-management/wis2_gdc/registrar.py index d8988d0..7a419c7 100644 --- a/wis2-gdc-management/wis2_gdc/registrar.py +++ b/wis2-gdc-management/wis2_gdc/registrar.py @@ -246,10 +246,45 @@ def register(self, metadata: Union[dict, str], topic: str = None) -> None: message = json.dumps(message).replace(API_URL_DOCKER, API_URL) - LOGGER.info('Publishing updated record to broker') + LOGGER.info('Publishing updated record to GDC broker') publish_report_topic = f'origin/a/wis2/{CENTRE_ID}/metadata' self.broker.pub(publish_report_topic, json.dumps(ets_results)) + def delete_record(self, topic: str, wnm: dict) -> None: + """ + Delete a metadata document + + :param topic: `str` of incoming topic (default is `None`) + :param wnm: `dict` of WNM + + :returns: `None` + """ + + centre_id = topic.split('/')[3] + publish_report_topic = f'monitor/a/wis2/{CENTRE_ID}/{centre_id}' + + message = { + 'id': str(uuid.uuid4()), + 'href': None, + 'report_by': CENTRE_ID, + 'centre_id': centre_id + } + + metadata_id = wnm['properties'].get('metadata_id') + + if metadata_id is None: + message['message'] = 'No metadata id specified' + else: + try: + self.backend.delete_record(metadata_id) + message['message'] = f'metadata {metadata_id} deleted' + except Exception: + message['message'] = f'metadata {metadata_id} not found' + + self.broker.pub(publish_report_topic, json.dumps(message)) + + return + def _process_record_metric(self, identifier: str, metric_name: str, labels: list, value: Union[str, int, float] = None) -> None: @@ -317,7 +352,7 @@ def _publish(self): """ LOGGER.info(f'Saving to {BACKEND_TYPE} ({BACKEND_CONNECTION})') - self.backend.save(self.metadata) + self.backend.save_record(self.metadata) def update_record_links(self) -> None: """ @@ -418,6 +453,8 @@ def teardown(ctx, bypass, verbosity='NOTSET'): LOGGER.debug(f'Backend: {backend}') backend.teardown() + click.echo('Done') + @click.command() @click.pass_context @@ -454,3 +491,23 @@ def register(ctx, path, verbosity='NOTSET'): metadata = fh.read() r.register(metadata) + + click.echo('Done') + + +@click.command() +@click.pass_context +@click.argument('identifier') +@cli_options.OPTION_VERBOSITY +def unregister(ctx, identifier, verbosity='NOTSET'): + """Unregister discovery metadata""" + + click.echo(f'Unregistering {identifier}') + backend = BACKENDS[BACKEND_TYPE]({'connection': BACKEND_CONNECTION}) + try: + LOGGER.debug(f'Backend: {backend}') + backend.delete_record(identifier) + except Exception: + click.echo('record not found') + + click.echo('Done')