Add 'details' parameter to various 'find' proxy methods

Allow retrieving "detailed" results where the API supports this.

Change-Id: I13f32e6ca9be9ed4eb42398aace47e3c5205a81f
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
Stephen Finucane 2022-12-19 10:49:04 +00:00
parent 6fee18fcd1
commit f9a3cc2f13
8 changed files with 213 additions and 39 deletions

View File

@ -112,7 +112,7 @@ class Proxy(proxy.Proxy):
"""
return self._create(_chassis.Chassis, **attrs)
def find_chassis(self, name_or_id, ignore_missing=True):
def find_chassis(self, name_or_id, ignore_missing=True, *, details=True):
"""Find a single chassis.
:param str name_or_id: The ID of a chassis.
@ -120,11 +120,19 @@ class Proxy(proxy.Proxy):
:class:`~openstack.exceptions.ResourceNotFound` will be raised
when the chassis does not exist. When set to `True``, None will
be returned when attempting to find a nonexistent chassis.
:param details: A boolean indicating whether the detailed information
for the chassis should be returned.
:returns: One :class:`~openstack.baremetal.v1.chassis.Chassis` object
or None.
"""
return self._find(_chassis.Chassis, name_or_id,
ignore_missing=ignore_missing)
list_base_path = '/chassis/detail' if details else None
return self._find(
_chassis.Chassis,
name_or_id,
ignore_missing=ignore_missing,
list_base_path=list_base_path,
)
def get_chassis(self, chassis, fields=None):
"""Get a specific chassis.
@ -300,7 +308,7 @@ class Proxy(proxy.Proxy):
"""
return self._create(_node.Node, **attrs)
def find_node(self, name_or_id, ignore_missing=True):
def find_node(self, name_or_id, ignore_missing=True, *, details=True):
"""Find a single node.
:param str name_or_id: The name or ID of a node.
@ -308,11 +316,18 @@ class Proxy(proxy.Proxy):
:class:`~openstack.exceptions.ResourceNotFound` will be raised
when the node does not exist. When set to `True``, None will
be returned when attempting to find a nonexistent node.
:param details: A boolean indicating whether the detailed information
for the node should be returned.
:returns: One :class:`~openstack.baremetal.v1.node.Node` object
or None.
"""
return self._find(_node.Node, name_or_id,
ignore_missing=ignore_missing)
list_base_path = '/nodes/detail' if details else None
return self._find(
_node.Node,
name_or_id,
ignore_missing=ignore_missing,
list_base_path=list_base_path,
)
def get_node(self, node, fields=None):
"""Get a specific node.
@ -685,7 +700,7 @@ class Proxy(proxy.Proxy):
"""
return self._create(_port.Port, **attrs)
def find_port(self, name_or_id, ignore_missing=True):
def find_port(self, name_or_id, ignore_missing=True, *, details=True):
"""Find a single port.
:param str name_or_id: The ID of a port.
@ -693,11 +708,18 @@ class Proxy(proxy.Proxy):
:class:`~openstack.exceptions.ResourceNotFound` will be raised
when the port does not exist. When set to `True``, None will
be returned when attempting to find a nonexistent port.
:param details: A boolean indicating whether the detailed information
for every port should be returned.
:returns: One :class:`~openstack.baremetal.v1.port.Port` object
or None.
"""
return self._find(_port.Port, name_or_id,
ignore_missing=ignore_missing)
list_base_path = '/ports/detail' if details else None
return self._find(
_port.Port,
name_or_id,
ignore_missing=ignore_missing,
list_base_path=list_base_path,
)
def get_port(self, port, fields=None):
"""Get a specific port.
@ -803,7 +825,13 @@ class Proxy(proxy.Proxy):
"""
return self._create(_portgroup.PortGroup, **attrs)
def find_port_group(self, name_or_id, ignore_missing=True):
def find_port_group(
self,
name_or_id,
ignore_missing=True,
*,
details=True,
):
"""Find a single port group.
:param str name_or_id: The name or ID of a portgroup.
@ -811,11 +839,18 @@ class Proxy(proxy.Proxy):
:class:`~openstack.exceptions.ResourceNotFound` will be raised
when the port group does not exist. When set to `True``, None will
be returned when attempting to find a nonexistent port group.
:param details: A boolean indicating whether the detailed information
for the port group should be returned.
:returns: One :class:`~openstack.baremetal.v1.port_group.PortGroup`
object or None.
"""
return self._find(_portgroup.PortGroup, name_or_id,
ignore_missing=ignore_missing)
list_base_path = '/portgroups/detail' if details else None
return self._find(
_portgroup.PortGroup,
name_or_id,
ignore_missing=ignore_missing,
list_base_path=list_base_path,
)
def get_port_group(self, port_group, fields=None):
"""Get a specific port group.
@ -1169,6 +1204,8 @@ class Proxy(proxy.Proxy):
"""
return self._create(_volumeconnector.VolumeConnector, **attrs)
# TODO(stephenfin): Delete this. You can't lookup a volume connector by
# name so this is identical to get_volume_connector
def find_volume_connector(self, vc_id, ignore_missing=True):
"""Find a single volume connector.
@ -1183,8 +1220,11 @@ class Proxy(proxy.Proxy):
:class:`~openstack.baremetal.v1.volumeconnector.VolumeConnector`
object or None.
"""
return self._find(_volumeconnector.VolumeConnector, vc_id,
ignore_missing=ignore_missing)
return self._find(
_volumeconnector.VolumeConnector,
vc_id,
ignore_missing=ignore_missing,
)
def get_volume_connector(self, volume_connector, fields=None):
"""Get a specific volume_connector.
@ -1309,6 +1349,8 @@ class Proxy(proxy.Proxy):
"""
return self._create(_volumetarget.VolumeTarget, **attrs)
# TODO(stephenfin): Delete this. You can't lookup a volume target by
# name so this is identical to get_volume_connector
def find_volume_target(self, vt_id, ignore_missing=True):
"""Find a single volume target.
@ -1323,8 +1365,11 @@ class Proxy(proxy.Proxy):
:class:`~openstack.baremetal.v1.volumetarget.VolumeTarget`
object or None.
"""
return self._find(_volumetarget.VolumeTarget, vt_id,
ignore_missing=ignore_missing)
return self._find(
_volumetarget.VolumeTarget,
vt_id,
ignore_missing=ignore_missing,
)
def get_volume_target(self, volume_target, fields=None):
"""Get a specific volume_target.

View File

@ -42,6 +42,7 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
name_or_id,
ignore_missing=True,
*,
details=True,
all_projects=False,
):
"""Find a single snapshot
@ -51,12 +52,18 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
:class:`~openstack.exceptions.ResourceNotFound` will be raised
when the snapshot does not exist. When set to ``True``, None will
be returned when attempting to find a nonexistent resource.
:param bool details: When set to ``False``, an
:class:`~openstack.block_storage.v2.snapshot.Snapshot` object will
be returned. The default, ``True``, will cause an
:class:`~openstack.block_storage.v2.snapshot.SnapshotDetail` object
to be returned.
:param bool all_projects: When set to ``True``, search for snapshot by
name across all projects. Note that this will likely result in
a higher chance of duplicates. Admin-only by default.
:returns: One :class:`~openstack.block_storage.v2.snapshot.Snapshot` or
None.
:returns: One :class:`~openstack.block_storage.v2.snapshot.Snapshot`,
one :class:`~openstack.block_storage.v2.snapshot.SnapshotDetail`
object, or None.
:raises: :class:`~openstack.exceptions.ResourceNotFound`
when no resource can be found.
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
@ -65,10 +72,12 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
query = {}
if all_projects:
query['all_projects'] = True
list_base_path = '/snapshots/detail' if details else None
return self._find(
_snapshot.Snapshot,
name_or_id,
ignore_missing=ignore_missing,
list_base_path=list_base_path,
**query,
)
@ -242,6 +251,7 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
name_or_id,
ignore_missing=True,
*,
details=True,
all_projects=False,
):
"""Find a single volume
@ -250,6 +260,9 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
:param bool ignore_missing: When set to ``False``
:class:`~openstack.exceptions.ResourceNotFound` will be raised
when the volume does not exist.
:param bool details: When set to ``False`` no extended attributes
will be returned. The default, ``True``, will cause an object with
additional attributes to be returned.
:param bool all_projects: When set to ``True``, search for volume by
name across all projects. Note that this will likely result in
a higher chance of duplicates. Admin-only by default.
@ -264,10 +277,12 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
query = {}
if all_projects:
query['all_projects'] = True
list_base_path = '/volumes/detail' if details else None
return self._find(
_volume.Volume,
name_or_id,
ignore_missing=ignore_missing,
list_base_path=list_base_path,
**query,
)
@ -517,13 +532,16 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
"""
return self._get(_backup.Backup, backup)
def find_backup(self, name_or_id, ignore_missing=True):
def find_backup(self, name_or_id, ignore_missing=True, *, details=True):
"""Find a single backup
:param snapshot: The name or ID a backup
:param bool ignore_missing: When set to ``False``
:class:`~openstack.exceptions.ResourceNotFound` will be raised
when the backup does not exist.
:param bool details: When set to ``False`` no additional details will
be returned. The default, ``True``, will cause objects with
additional attributes to be returned.
:returns: One :class:`~openstack.block_storage.v2.backup.Backup`
:raises: :class:`~openstack.exceptions.ResourceNotFound`
@ -531,10 +549,12 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
resources are found.
"""
list_base_path = '/backups/detail' if details else None
return self._find(
_backup.Backup,
name_or_id,
ignore_missing=ignore_missing,
list_base_path=list_base_path,
)
def create_backup(self, **attrs):

View File

@ -67,6 +67,7 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
name_or_id,
ignore_missing=True,
*,
details=True,
all_projects=False,
):
"""Find a single snapshot
@ -76,6 +77,10 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
:class:`~openstack.exceptions.ResourceNotFound` will be raised
when the snapshot does not exist. When set to ``True``, None will
be returned when attempting to find a nonexistent resource.
:param bool details: When set to ``False`` :class:
`~openstack.block_storage.v3.snapshot.Snapshot` objects will be
returned. The default, ``True``, will cause more attributes to be
returned.
:param bool all_projects: When set to ``True``, search for snapshot by
name across all projects. Note that this will likely result in
a higher chance of duplicates. Admin-only by default.
@ -89,10 +94,12 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
query = {}
if all_projects:
query['all_projects'] = True
list_base_path = '/snapshots/detail' if details else None
return self._find(
_snapshot.Snapshot,
name_or_id,
ignore_missing=ignore_missing,
list_base_path=list_base_path,
**query,
)
@ -501,6 +508,7 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
name_or_id,
ignore_missing=True,
*,
details=True,
all_projects=False,
):
"""Find a single volume
@ -509,6 +517,9 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
:param bool ignore_missing: When set to ``False``
:class:`~openstack.exceptions.ResourceNotFound` will be raised
when the volume does not exist.
:param bool details: When set to ``False`` no extended attributes
will be returned. The default, ``True``, will cause objects with
additional attributes to be returned.
:param bool all_projects: When set to ``True``, search for volume by
name across all projects. Note that this will likely result in
a higher chance of duplicates. Admin-only by default.
@ -522,11 +533,12 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
query = {}
if all_projects:
query['all_projects'] = True
list_base_path = '/volumes/detail' if details else None
return self._find(
_volume.Volume,
name_or_id,
ignore_missing=ignore_missing,
list_base_path='/volumes/detail',
list_base_path=list_base_path,
**query,
)
@ -958,13 +970,16 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
"""
return self._get(_backup.Backup, backup)
def find_backup(self, name_or_id, ignore_missing=True):
def find_backup(self, name_or_id, ignore_missing=True, *, details=True):
"""Find a single backup
:param snapshot: The name or ID a backup
:param bool ignore_missing: When set to ``False``
:class:`~openstack.exceptions.ResourceNotFound` will be raised
when the backup does not exist.
:param bool details: When set to ``False`` no additional details will
be returned. The default, ``True``, will cause objects with
additional attributes to be returned.
:returns: One :class:`~openstack.block_storage.v3.backup.Backup`
:raises: :class:`~openstack.exceptions.ResourceNotFound`
@ -972,10 +987,12 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
resources are found.
"""
list_base_path = '/backups/detail' if details else None
return self._find(
_backup.Backup,
name_or_id,
ignore_missing=ignore_missing,
list_base_path=list_base_path,
)
def create_backup(self, **attrs):
@ -1074,13 +1091,16 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
"""
return self._get(_group.Group, group_id, **attrs)
def find_group(self, name_or_id, ignore_missing=True):
def find_group(self, name_or_id, ignore_missing=True, *, details=True):
"""Find a single group
:param name_or_id: The name or ID of a group.
:param bool ignore_missing: When set to ``False``
:class:`~openstack.exceptions.ResourceNotFound` will be raised
when the group snapshot does not exist.
:param bool details: When set to ``False``, no additional details will
be returned. The default, ``True``, will cause additional details
to be returned.
:returns: One :class:`~openstack.block_storage.v3.group.Group`
:raises: :class:`~openstack.exceptions.ResourceNotFound`
@ -1088,10 +1108,12 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
resources are found.
"""
list_base_path = '/groups/detail' if details else None
return self._find(
_group.Group,
name_or_id,
ignore_missing=ignore_missing,
list_base_path=list_base_path,
)
def groups(self, *, details=True, **query):
@ -1202,13 +1224,22 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
"""
return self._get(_group_snapshot.GroupSnapshot, group_snapshot_id)
def find_group_snapshot(self, name_or_id, ignore_missing=True):
def find_group_snapshot(
self,
name_or_id,
ignore_missing=True,
*,
details=True,
):
"""Find a single group snapshot
:param name_or_id: The name or ID of a group snapshot.
:param bool ignore_missing: When set to ``False``
:class:`~openstack.exceptions.ResourceNotFound` will be raised
when the group snapshot does not exist.
:param bool details: When set to ``False``, no additional details will
be returned. The default, ``True``, will cause additional details
to be returned.
:returns: One :class:`~openstack.block_storage.v3.group_snapshot`
:raises: :class:`~openstack.exceptions.ResourceNotFound`
@ -1216,10 +1247,12 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
resources are found.
"""
list_base_path = '/group_snapshots/detail' if details else None
return self._find(
_group_snapshot.GroupSnapshot,
name_or_id,
ignore_missing=ignore_missing,
list_base_path=list_base_path,
)
def group_snapshots(self, *, details=True, **query):
@ -1232,10 +1265,7 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
the group snapshots being returned.
:returns: A generator of group snapshtos.
"""
base_path = '/group_snapshots'
if details:
base_path = '/group_snapshots/detail'
base_path = '/group_snapshots/detail' if details else None
return self._list(
_group_snapshot.GroupSnapshot,
base_path=base_path,

View File

@ -484,6 +484,8 @@ class Proxy(proxy.Proxy):
)
self._delete(_image.Image, image, ignore_missing=ignore_missing)
# NOTE(stephenfin): We haven't added 'details' support here since this
# method is deprecated
def find_image(self, name_or_id, ignore_missing=True):
"""Find a single image
@ -740,6 +742,7 @@ class Proxy(proxy.Proxy):
name_or_id,
ignore_missing=True,
*,
details=True,
all_projects=False,
):
"""Find a single server
@ -749,6 +752,9 @@ class Proxy(proxy.Proxy):
:class:`~openstack.exceptions.ResourceNotFound` will be raised when
the resource does not exist. When set to ``True``, None will be
returned when attempting to find a nonexistent resource.
:param bool details: When set to ``False``
instances with only basic data will be returned. The default,
``True``, will cause instances with full data to be returned.
:param bool all_projects: When set to ``True``, search for server
by name across all projects. Note that this will likely result in a
higher chance of duplicates. Admin-only by default.
@ -762,11 +768,12 @@ class Proxy(proxy.Proxy):
query = {}
if all_projects:
query['all_projects'] = True
list_base_path = '/servers/detail' if details else None
return self._find(
_server.Server,
name_or_id,
ignore_missing=ignore_missing,
list_base_path='/servers/detail',
list_base_path=list_base_path,
**query,
)
@ -1515,6 +1522,7 @@ class Proxy(proxy.Proxy):
instances will be returned with only basic information populated.
:param kwargs query: Optional query parameters to be sent to limit
the resources being returned.
:returns: A generator of hypervisor
:rtype: class: `~openstack.compute.v2.hypervisor.Hypervisor`
"""
@ -1542,6 +1550,9 @@ class Proxy(proxy.Proxy):
:class:`~openstack.exceptions.ResourceNotFound` will be raised when
the resource does not exist. When set to ``True``, None will be
returned when attempting to find a nonexistent resource.
:param bool details: When set to ``False``
instances with only basic data will be returned. The default,
``True``, will cause instances with full data to be returned.
:returns: One: class:`~openstack.compute.v2.hypervisor.Hypervisor`
or None
@ -1550,7 +1561,6 @@ class Proxy(proxy.Proxy):
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
resources are found.
"""
list_base_path = '/os-hypervisors/detail' if details else None
return self._find(
_hypervisor.Hypervisor,

View File

@ -60,7 +60,11 @@ class TestChassis(TestBaremetalProxy):
self.verify_create(self.proxy.create_chassis, chassis.Chassis)
def test_find_chassis(self):
self.verify_find(self.proxy.find_chassis, chassis.Chassis)
self.verify_find(
self.proxy.find_chassis,
chassis.Chassis,
expected_kwargs={'list_base_path': '/chassis/detail'},
)
def test_get_chassis(self):
self.verify_get(self.proxy.get_chassis, chassis.Chassis,
@ -94,7 +98,11 @@ class TestNode(TestBaremetalProxy):
self.verify_create(self.proxy.create_node, node.Node)
def test_find_node(self):
self.verify_find(self.proxy.find_node, node.Node)
self.verify_find(
self.proxy.find_node,
node.Node,
expected_kwargs={'list_base_path': '/nodes/detail'},
)
def test_get_node(self):
self.verify_get(self.proxy.get_node, node.Node,
@ -140,7 +148,11 @@ class TestPort(TestBaremetalProxy):
self.verify_create(self.proxy.create_port, port.Port)
def test_find_port(self):
self.verify_find(self.proxy.find_port, port.Port)
self.verify_find(
self.proxy.find_port,
port.Port,
expected_kwargs={'list_base_path': '/ports/detail'},
)
def test_get_port(self):
self.verify_get(self.proxy.get_port, port.Port,

View File

@ -39,7 +39,10 @@ class TestVolume(TestVolumeProxy):
self.proxy.find_volume,
volume.Volume,
method_kwargs={'all_projects': True},
expected_kwargs={'all_projects': True},
expected_kwargs={
'list_base_path': '/volumes/detail',
'all_projects': True,
},
)
def test_volumes_detailed(self):
@ -232,7 +235,11 @@ class TestBackup(TestVolumeProxy):
self.verify_get(self.proxy.get_backup, backup.Backup)
def test_backup_find(self):
self.verify_find(self.proxy.find_backup, backup.Backup)
self.verify_find(
self.proxy.find_backup,
backup.Backup,
expected_kwargs={'list_base_path': '/backups/detail'},
)
def test_backup_delete(self):
self.verify_delete(self.proxy.delete_backup, backup.Backup, False)
@ -281,7 +288,10 @@ class TestSnapshot(TestVolumeProxy):
self.proxy.find_snapshot,
snapshot.Snapshot,
method_kwargs={'all_projects': True},
expected_kwargs={'all_projects': True},
expected_kwargs={
'list_base_path': '/snapshots/detail',
'all_projects': True,
},
)
def test_snapshots_detailed(self):

View File

@ -158,7 +158,11 @@ class TestGroup(TestVolumeProxy):
self.verify_get(self.proxy.get_group, group.Group)
def test_group_find(self):
self.verify_find(self.proxy.find_group, group.Group)
self.verify_find(
self.proxy.find_group,
group.Group,
expected_kwargs={'list_base_path': '/groups/detail'},
)
def test_groups(self):
self.verify_list(self.proxy.groups, group.Group)
@ -198,7 +202,11 @@ class TestGroupSnapshot(TestVolumeProxy):
def test_group_snapshot_find(self):
self.verify_find(
self.proxy.find_group_snapshot, group_snapshot.GroupSnapshot
self.proxy.find_group_snapshot,
group_snapshot.GroupSnapshot,
expected_kwargs={
'list_base_path': '/group_snapshots/detail',
},
)
def test_group_snapshots(self):
@ -562,7 +570,11 @@ class TestBackup(TestVolumeProxy):
# NOTE: mock has_service
self.proxy._connection = mock.Mock()
self.proxy._connection.has_service = mock.Mock(return_value=True)
self.verify_find(self.proxy.find_backup, backup.Backup)
self.verify_find(
self.proxy.find_backup,
backup.Backup,
expected_kwargs={'list_base_path': '/backups/detail'},
)
def test_backup_delete(self):
# NOTE: mock has_service
@ -622,7 +634,10 @@ class TestSnapshot(TestVolumeProxy):
self.proxy.find_snapshot,
snapshot.Snapshot,
method_kwargs={'all_projects': True},
expected_kwargs={'all_projects': True},
expected_kwargs={
'list_base_path': '/snapshots/detail',
'all_projects': True,
},
)
def test_snapshots_detailed(self):

View File

@ -0,0 +1,32 @@
---
features:
- |
The following proxy ``find_*`` operations will now retrieve a detailed
resource by default when retrieving by name:
* Bare metal (v1)
* ``find_chassis``
* ``find_node``
* ``find_port``
* ``find_port_group``
* Block storage (v2)
* ``find_volume``
* ``find_snapshot``
* ``find_backup``
* Block storage (v3)
* ``find_volume``
* ``find_snapshot``
* ``find_backup``
* ``find_group``
* ``find_group_snapshot``
* Compute (v2)
* ``find_image``
* ``find_server``
* ``find_hypervisor``