From 41a71c6092906de7ac9c28cb8204692e0ffeb417 Mon Sep 17 00:00:00 2001 From: Qubad786 Date: Thu, 2 Jan 2025 20:01:07 +0500 Subject: [PATCH] Allow not retrieving user props for datasets (#15287) --- .../middlewared/plugins/pool_/dataset.py | 19 ++++++++++++------- tests/api2/test_pool_dataset_user_props.py | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 7 deletions(-) create mode 100644 tests/api2/test_pool_dataset_user_props.py diff --git a/src/middlewared/middlewared/plugins/pool_/dataset.py b/src/middlewared/middlewared/plugins/pool_/dataset.py index eac4b1c036f1f..895f3502e6ea6 100644 --- a/src/middlewared/middlewared/plugins/pool_/dataset.py +++ b/src/middlewared/middlewared/plugins/pool_/dataset.py @@ -117,7 +117,7 @@ async def get_instance_quick(self, name, options=None): def _internal_user_props(self): return TNUserProp.values() - def __transform(self, datasets, retrieve_children, children_filters): + def __transform(self, datasets, retrieve_children, children_filters, retrieve_user_props): """ We need to transform the data zfs gives us to make it consistent/user-friendly, making it match whatever pool.dataset.{create,update} uses as input. @@ -138,9 +138,10 @@ def transform(dataset): if dataset['type'] == 'VOLUME': dataset['mountpoint'] = None - dataset['user_properties'] = { - k: v for k, v in dataset['properties'].items() if ':' in k and k not in self._internal_user_props() - } + if retrieve_user_props: + dataset['user_properties'] = { + k: v for k, v in dataset['properties'].items() if ':' in k and k not in self._internal_user_props() + } del dataset['properties'] if all(k in dataset for k in ('encrypted', 'key_loaded')): @@ -194,7 +195,9 @@ def query(self, filters, options): In case only some properties are desired to be retrieved for datasets, consumer should specify `query-options.extra.properties` which when `null` ( which is the default ) will retrieve all properties and otherwise a list can be specified like `["type", "used", "available"]` to retrieve selective properties. - If no properties are desired, in that case an empty list should be sent. + If no properties are desired, in that case an empty list should be sent. It should be noted that specifying + empty list will still retrieve user properties. If user properties are not desired, in that case + `query-options.extra.retrieve_user_props` should be set to `false`. `query-options.extra.snapshots` can be set to retrieve snapshot(s) of dataset in question. @@ -220,6 +223,7 @@ def query(self, filters, options): snapshots = extra.get('snapshots') snapshots_recursive = extra.get('snapshots_recursive') snapshots_count = extra.get('snapshots_count') + retrieve_user_props = extra.get('retrieve_user_props', True) return filter_list( self.__transform(self.middleware.call_sync( 'zfs.dataset.query', zfsfilters, { @@ -230,10 +234,11 @@ def query(self, filters, options): 'snapshots': snapshots, 'snapshots_recursive': snapshots_recursive, 'snapshots_count': snapshots_count, - 'snapshots_properties': extra.get('snapshots_properties', []) + 'snapshots_properties': extra.get('snapshots_properties', []), + 'user_properties': retrieve_user_props, } } - ), retrieve_children, internal_datasets_filters, + ), retrieve_children, internal_datasets_filters, retrieve_user_props, ), filters, options ) diff --git a/tests/api2/test_pool_dataset_user_props.py b/tests/api2/test_pool_dataset_user_props.py new file mode 100644 index 0000000000000..96e8f8f9ff544 --- /dev/null +++ b/tests/api2/test_pool_dataset_user_props.py @@ -0,0 +1,18 @@ +import pytest + +from middlewared.test.integration.assets.pool import dataset +from middlewared.test.integration.utils import call + + +@pytest.mark.parametrize('user_props', [True, False]) +def test_pool_dataset_query_user_props_true_false(user_props): + with dataset("query_test") as ds: + result = call( + "pool.dataset.query", + [["id", "=", ds]], + {"extra": {"flat": False, "properties": [], "retrieve_user_props": user_props}} + ) + if user_props: + assert "user_properties" in result[0], f"'user_properties' not found in result: {result}" + else: + assert "user_properties" not in result[0], f"'user_properties' found in result: {result}"