From aab12d8db1dc9be250891b6b70777777fe8e803c Mon Sep 17 00:00:00 2001 From: Vladimir Sedmik Date: Fri, 19 Apr 2024 18:23:34 +0200 Subject: [PATCH 1/2] Add new verify_checksum endpoints --- nailgun/entities.py | 44 ++++++++++++++++++++++++++++++++++++++++-- tests/test_entities.py | 5 +++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/nailgun/entities.py b/nailgun/entities.py index 20601ffc..034c4b1a 100644 --- a/nailgun/entities.py +++ b/nailgun/entities.py @@ -1022,6 +1022,24 @@ def content_reclaim_space(self, synchronous=True, timeout=None, **kwargs): response = client.post(self.path('content_reclaim_space'), **kwargs) return _handle_response(response, self._server_config, synchronous, timeout) + def content_verify_checksum(self, synchronous=True, timeout=None, **kwargs): + """Check for missing or corrupted artifacts, and attempt to redownload them. + + :param synchronous: What should happen if the server returns an HTTP + 202 (accepted) status code? Wait for the task to complete if + ``True``. Immediately return the server's response otherwise. + :param timeout: Maximum number of seconds to wait until timing out. + Defaults to ``nailgun.entity_mixins.TASK_TIMEOUT``. + :param kwargs: Arguments to pass to requests. + :returns: The server's response, with all JSON decoded. + :raises: ``requests.exceptions.HTTPError`` If the server responds with + an HTTP 4XX or 5XX message. + """ + kwargs = kwargs.copy() + kwargs.update(self._server_config.get_client_kwargs()) + response = client.post(self.path('content_verify_checksum'), **kwargs) + return _handle_response(response, self._server_config, synchronous, timeout) + def path(self, which=None): """Extend ``nailgun.entity_mixins.Entity.path``. @@ -1037,7 +1055,8 @@ def path(self, which=None): /capsules//content/update_counts content_reclaim_space /capsules//content/reclaim_space - + content_verify_checksum + /capsules//content/verify_checksum ``super`` is called otherwise. """ @@ -2596,11 +2615,13 @@ def path(self, which=None): /content_view_versions/incremental_update promote /content_view_versions//promote + verify_checksum + /content_view_versions//verify_checksum ``super`` is called otherwise. """ - if which in ("incremental_update", "promote"): + if which in ("incremental_update", "promote", "verify_checksum"): prefix = "base" if which == "incremental_update" else "self" return f"{super().path(prefix)}/{which}" return super().path(which) @@ -2643,6 +2664,25 @@ def promote(self, synchronous=True, timeout=None, **kwargs): response = client.post(self.path('promote'), **kwargs) return _handle_response(response, self._server_config, synchronous, timeout) + def verify_checksum(self, synchronous=True, timeout=None, **kwargs): + """Verify checksum of repository contents in the content view version. + + :param synchronous: What should happen if the server returns an HTTP + 202 (accepted) status code? Wait for the task to complete if + ``True``. Immediately return the server's response otherwise. + :param timeout: Maximum number of seconds to wait until timing out. + Defaults to ``nailgun.entity_mixins.TASK_TIMEOUT``. + :param kwargs: Arguments to pass to requests. + :returns: The server's response, with all JSON decoded. + :raises: ``requests.exceptions.HTTPError`` If the server responds with + an HTTP 4XX or 5XX message. + + """ + kwargs = kwargs.copy() # shadow the passed-in kwargs + kwargs.update(self._server_config.get_client_kwargs()) + response = client.post(self.path('verify_checksum'), **kwargs) + return _handle_response(response, self._server_config, synchronous, timeout) + class ContentViewFilterRule( Entity, diff --git a/tests/test_entities.py b/tests/test_entities.py index a20fb636..1f9d568f 100644 --- a/tests/test_entities.py +++ b/tests/test_entities.py @@ -310,6 +310,7 @@ def test_id_and_which(self): (entities.ContentView, 'copy'), (entities.ContentView, 'publish'), (entities.ContentViewVersion, 'promote'), + (entities.ContentViewVersion, 'verify_checksum'), (entities.DiscoveredHost, 'auto_provision'), (entities.DiscoveredHost, 'refresh_facts'), (entities.DiscoveredHost, 'reboot'), @@ -398,6 +399,7 @@ def test_no_such_path_error(self): (entities.ContentView, 'content_view_versions'), (entities.ContentView, 'publish'), (entities.ContentViewVersion, 'promote'), + (entities.ContentViewVersion, 'verify_checksum'), (entities.ForemanTask, 'self'), (entities.HostGroup, 'rebuild_config'), (entities.Organization, 'products'), @@ -569,6 +571,7 @@ def test_capsule(self): 'content_counts', 'content_update_counts', 'content_reclaim_space', + 'content_verify_checksum', ): with self.subTest(which): path = capsule.path(which) @@ -2110,6 +2113,7 @@ def setUpClass(cls): (entities.Capsule(**generic).content_counts, 'get'), (entities.Capsule(**generic).content_update_counts, 'post'), (entities.Capsule(**generic).content_reclaim_space, 'post'), + (entities.Capsule(**generic).content_verify_checksum, 'post'), (entities.Role(**generic).clone, 'post'), (entities.ProvisioningTemplate(**generic).build_pxe_default, 'post'), (entities.ProvisioningTemplate(**generic).clone, 'post'), @@ -2118,6 +2122,7 @@ def setUpClass(cls): (entities.ContentView(**generic).publish, 'post'), (entities.ContentViewVersion(**generic).incremental_update, 'post'), (entities.ContentViewVersion(**generic).promote, 'post'), + (entities.ContentViewVersion(**generic).verify_checksum, 'post'), (entities.DiscoveredHost(cfg).facts, 'post'), (entities.DiscoveredHost(**generic).refresh_facts, 'put'), (entities.DiscoveredHost(**generic).reboot, 'put'), From 0da546efeab742ae8d1a7f69a7e5fc9a52527a5f Mon Sep 17 00:00:00 2001 From: Vladimir Sedmik Date: Mon, 22 Apr 2024 11:44:25 +0200 Subject: [PATCH 2/2] Add support for older verify_checksum endpoints --- nailgun/entities.py | 46 +++++++++++++++++++++++++++++++++++++++++- tests/test_entities.py | 4 ++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/nailgun/entities.py b/nailgun/entities.py index 034c4b1a..d29e58b5 100644 --- a/nailgun/entities.py +++ b/nailgun/entities.py @@ -1057,6 +1057,7 @@ def path(self, which=None): /capsules//content/reclaim_space content_verify_checksum /capsules//content/verify_checksum + ``super`` is called otherwise. """ @@ -6336,11 +6337,13 @@ def path(self, which=None): /products/bulk/sync_plan http_proxy /products/bulk/http_proxy + verify_checksum + /products/bulk/verify_checksum ``super`` is called otherwise. """ - if which in ("destroy", "sync", "sync_plan", "http_proxy"): + if which in ("destroy", "sync", "sync_plan", "http_proxy", "verify_checksum"): return f'{super().path(which="base")}/{which}' return super().path(which) @@ -6420,6 +6423,25 @@ def sync_plan(self, synchronous=True, timeout=None, **kwargs): response = client.put(self.path('sync_plan'), **kwargs) return _handle_response(response, self._server_config, synchronous, timeout) + def verify_checksum(self, synchronous=True, timeout=None, **kwargs): + """Verify checksum for one or more products. + + :param synchronous: What should happen if the server returns an HTTP + 202 (accepted) status code? Wait for the task to complete if + ``True``. Immediately return the server's response otherwise. + :param timeout: Maximum number of seconds to wait until timing out. + Defaults to ``nailgun.entity_mixins.TASK_TIMEOUT``. + :param kwargs: Arguments to pass to requests. + :returns: The server's response, with all JSON decoded. + :raises: ``requests.exceptions.HTTPError`` If the server responds with + an HTTP 4XX or 5XX message. + + """ + kwargs = kwargs.copy() # shadow the passed-in kwargs + kwargs.update(self._server_config.get_client_kwargs()) + response = client.put(self.path('verify_checksum'), **kwargs) + return _handle_response(response, self._server_config, synchronous, timeout) + class PartitionTable( Entity, @@ -6868,6 +6890,8 @@ def path(self, which=None): /repositories//remove_content sync /repositories//sync + verify_checksum + /repositories//verify_checksum upload_content /repositories//upload_content import_uploads @@ -6883,6 +6907,7 @@ def path(self, which=None): 'module_streams', 'remove_content', 'sync', + 'verify_checksum', 'import_uploads', 'upload_content', ): @@ -6953,6 +6978,25 @@ def sync(self, synchronous=True, timeout=None, **kwargs): response = client.post(self.path('sync'), **kwargs) return _handle_response(response, self._server_config, synchronous, timeout) + def verify_checksum(self, synchronous=True, timeout=None, **kwargs): + """Verify checksum of repository contents. + + :param synchronous: What should happen if the server returns an HTTP + 202 (accepted) status code? Wait for the task to complete if + ``True``. Immediately return the server's response otherwise. + :param timeout: Maximum number of seconds to wait until timing out. + Defaults to ``nailgun.entity_mixins.TASK_TIMEOUT``. + :param kwargs: Arguments to pass to requests. + :returns: The server's response, with all JSON decoded. + :raises: ``requests.exceptions.HTTPError`` If the server responds with + an HTTP 4XX or 5XX message. + + """ + kwargs = kwargs.copy() # shadow the passed-in kwargs + kwargs.update(self._server_config.get_client_kwargs()) + response = client.post(self.path('verify_checksum'), **kwargs) + return _handle_response(response, self._server_config, synchronous, timeout) + def upload_content(self, synchronous=True, timeout=None, **kwargs): """Upload a file or files to the current repository. diff --git a/tests/test_entities.py b/tests/test_entities.py index 1f9d568f..232c7c63 100644 --- a/tests/test_entities.py +++ b/tests/test_entities.py @@ -347,6 +347,7 @@ def test_id_and_which(self): (entities.Repository, 'packages'), (entities.Repository, 'remove_content'), (entities.Repository, 'sync'), + (entities.Repository, 'verify_checksum'), (entities.Repository, 'upload_content'), (entities.RHCIDeployment, 'deploy'), (entities.ScapContents, 'xml'), @@ -415,6 +416,7 @@ def test_no_such_path_error(self): (entities.Organization, 'repo_discover'), (entities.Product, 'repository_sets'), (entities.Repository, 'sync'), + (entities.Repository, 'verify_checksum'), (entities.Repository, 'upload_content'), (entities.ScapContents, 'xml'), (entities.RHCIDeployment, 'deploy'), @@ -2159,6 +2161,7 @@ def setUpClass(cls): (entities.ProductBulkAction(**generic).sync, 'put'), (entities.ProductBulkAction(**generic).http_proxy, 'put'), (entities.ProductBulkAction(**generic).sync_plan, 'put'), + (entities.ProductBulkAction(**generic).verify_checksum, 'put'), (entities.PuppetClass(**generic).list_scparams, 'get'), (entities.RHCIDeployment(**generic).deploy, 'put'), (entities.RecurringLogic(**generic).cancel, 'post'), @@ -2167,6 +2170,7 @@ def setUpClass(cls): (entities.Repository(**generic).module_streams, 'get'), (entities.Repository(**generic).remove_content, 'put'), (entities.Repository(**generic).sync, 'post'), + (entities.Repository(**generic).verify_checksum, 'post'), (entities.ScapContents(**generic).xml, 'get'), (entities.SmartProxy(**generic).import_puppetclasses, 'post'), (entities.SmartProxy(**generic).refresh, 'put'),