python-openstackclient 8.0.0__py3-none-any.whl → 8.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. openstackclient/api/compute_v2.py +2 -2
  2. openstackclient/api/volume_v2.py +60 -0
  3. openstackclient/api/volume_v3.py +60 -0
  4. openstackclient/compute/client.py +5 -0
  5. openstackclient/compute/v2/console.py +7 -0
  6. openstackclient/compute/v2/console_connection.py +48 -0
  7. openstackclient/compute/v2/flavor.py +14 -1
  8. openstackclient/compute/v2/keypair.py +10 -3
  9. openstackclient/compute/v2/server.py +76 -13
  10. openstackclient/compute/v2/server_event.py +1 -1
  11. openstackclient/identity/common.py +85 -11
  12. openstackclient/identity/v3/application_credential.py +88 -87
  13. openstackclient/identity/v3/domain.py +67 -49
  14. openstackclient/identity/v3/group.py +113 -68
  15. openstackclient/identity/v3/project.py +42 -20
  16. openstackclient/identity/v3/role.py +7 -2
  17. openstackclient/identity/v3/user.py +38 -5
  18. openstackclient/image/client.py +5 -0
  19. openstackclient/image/v1/image.py +16 -1
  20. openstackclient/image/v2/cache.py +10 -6
  21. openstackclient/image/v2/image.py +59 -12
  22. openstackclient/image/v2/metadef_objects.py +8 -2
  23. openstackclient/image/v2/metadef_properties.py +9 -2
  24. openstackclient/network/client.py +0 -6
  25. openstackclient/network/v2/floating_ip.py +58 -29
  26. openstackclient/network/v2/network_qos_rule.py +3 -11
  27. openstackclient/network/v2/port.py +16 -0
  28. openstackclient/network/v2/router.py +1 -1
  29. openstackclient/network/v2/security_group.py +49 -7
  30. openstackclient/network/v2/security_group_rule.py +18 -1
  31. openstackclient/shell.py +1 -1
  32. openstackclient/tests/functional/base.py +5 -1
  33. openstackclient/tests/functional/compute/v2/test_keypair.py +41 -5
  34. openstackclient/tests/functional/identity/v3/test_access_rule.py +1 -1
  35. openstackclient/tests/functional/identity/v3/test_application_credential.py +7 -7
  36. openstackclient/tests/functional/image/v2/test_image.py +36 -14
  37. openstackclient/tests/functional/volume/v2/test_volume.py +1 -1
  38. openstackclient/tests/functional/volume/v3/test_volume.py +2 -2
  39. openstackclient/tests/unit/api/test_volume_v2.py +124 -0
  40. openstackclient/tests/unit/api/test_volume_v3.py +124 -0
  41. openstackclient/tests/unit/compute/v2/fakes.py +81 -305
  42. openstackclient/tests/unit/compute/v2/test_console.py +18 -1
  43. openstackclient/tests/unit/compute/v2/test_console_connection.py +72 -0
  44. openstackclient/tests/unit/compute/v2/test_flavor.py +160 -175
  45. openstackclient/tests/unit/compute/v2/test_keypair.py +12 -5
  46. openstackclient/tests/unit/compute/v2/test_server.py +211 -97
  47. openstackclient/tests/unit/compute/v2/test_server_backup.py +32 -71
  48. openstackclient/tests/unit/compute/v2/test_server_event.py +2 -2
  49. openstackclient/tests/unit/compute/v2/test_server_image.py +33 -72
  50. openstackclient/tests/unit/compute/v2/test_server_migration.py +4 -4
  51. openstackclient/tests/unit/identity/v3/test_application_credential.py +93 -65
  52. openstackclient/tests/unit/identity/v3/test_domain.py +117 -107
  53. openstackclient/tests/unit/identity/v3/test_group.py +353 -202
  54. openstackclient/tests/unit/identity/v3/test_project.py +46 -53
  55. openstackclient/tests/unit/identity/v3/test_role.py +2 -8
  56. openstackclient/tests/unit/identity/v3/test_user.py +86 -6
  57. openstackclient/tests/unit/image/v1/test_image.py +55 -9
  58. openstackclient/tests/unit/image/v2/test_image.py +128 -58
  59. openstackclient/tests/unit/image/v2/test_metadef_objects.py +22 -0
  60. openstackclient/tests/unit/image/v2/test_metadef_properties.py +24 -10
  61. openstackclient/tests/unit/network/v2/fakes.py +406 -485
  62. openstackclient/tests/unit/network/v2/test_floating_ip_network.py +13 -19
  63. openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py +2 -2
  64. openstackclient/tests/unit/network/v2/test_ndp_proxy.py +3 -5
  65. openstackclient/tests/unit/network/v2/test_network.py +4 -4
  66. openstackclient/tests/unit/network/v2/test_network_agent.py +15 -29
  67. openstackclient/tests/unit/network/v2/test_network_qos_policy.py +16 -19
  68. openstackclient/tests/unit/network/v2/test_network_qos_rule.py +79 -152
  69. openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py +4 -6
  70. openstackclient/tests/unit/network/v2/test_network_rbac.py +2 -2
  71. openstackclient/tests/unit/network/v2/test_port.py +57 -17
  72. openstackclient/tests/unit/network/v2/test_router.py +73 -57
  73. openstackclient/tests/unit/network/v2/test_security_group_network.py +31 -27
  74. openstackclient/tests/unit/network/v2/test_security_group_rule_compute.py +1 -3
  75. openstackclient/tests/unit/network/v2/test_security_group_rule_network.py +82 -39
  76. openstackclient/tests/unit/volume/v2/fakes.py +1 -2
  77. openstackclient/tests/unit/volume/v2/test_service.py +57 -91
  78. openstackclient/tests/unit/volume/v2/test_volume.py +466 -410
  79. openstackclient/tests/unit/volume/v2/test_volume_backup.py +141 -148
  80. openstackclient/tests/unit/volume/v2/test_volume_snapshot.py +293 -283
  81. openstackclient/tests/unit/volume/v3/test_block_storage_log_level.py +61 -71
  82. openstackclient/tests/unit/volume/v3/test_service.py +221 -141
  83. openstackclient/tests/unit/volume/v3/test_volume.py +569 -534
  84. openstackclient/tests/unit/volume/v3/test_volume_attachment.py +1 -1
  85. openstackclient/tests/unit/volume/v3/test_volume_backup.py +198 -203
  86. openstackclient/tests/unit/volume/v3/test_volume_snapshot.py +682 -47
  87. openstackclient/volume/v2/service.py +41 -38
  88. openstackclient/volume/v2/volume.py +140 -88
  89. openstackclient/volume/v2/volume_backup.py +9 -3
  90. openstackclient/volume/v2/volume_snapshot.py +121 -84
  91. openstackclient/volume/v3/block_storage_log_level.py +22 -28
  92. openstackclient/volume/v3/service.py +105 -14
  93. openstackclient/volume/v3/volume.py +287 -99
  94. openstackclient/volume/v3/volume_backup.py +24 -19
  95. openstackclient/volume/v3/volume_group.py +1 -1
  96. openstackclient/volume/v3/volume_snapshot.py +485 -10
  97. {python_openstackclient-8.0.0.dist-info → python_openstackclient-8.2.0.dist-info}/AUTHORS +13 -0
  98. python_openstackclient-8.2.0.dist-info/METADATA +264 -0
  99. {python_openstackclient-8.0.0.dist-info → python_openstackclient-8.2.0.dist-info}/RECORD +104 -98
  100. {python_openstackclient-8.0.0.dist-info → python_openstackclient-8.2.0.dist-info}/entry_points.txt +7 -6
  101. python_openstackclient-8.2.0.dist-info/pbr.json +1 -0
  102. python_openstackclient-8.0.0.dist-info/METADATA +0 -166
  103. python_openstackclient-8.0.0.dist-info/pbr.json +0 -1
  104. {python_openstackclient-8.0.0.dist-info → python_openstackclient-8.2.0.dist-info}/LICENSE +0 -0
  105. {python_openstackclient-8.0.0.dist-info → python_openstackclient-8.2.0.dist-info}/WHEEL +0 -0
  106. {python_openstackclient-8.0.0.dist-info → python_openstackclient-8.2.0.dist-info}/top_level.txt +0 -0
@@ -13,34 +13,185 @@
13
13
 
14
14
  from unittest import mock
15
15
 
16
+ from openstack.block_storage.v3 import snapshot as _snapshot
17
+ from openstack.block_storage.v3 import volume as _volume
18
+ from openstack import exceptions as sdk_exceptions
19
+ from openstack.test import fakes as sdk_fakes
20
+ from osc_lib.cli import format_columns
16
21
  from osc_lib import exceptions
17
- from osc_lib import utils
18
22
 
19
- from openstackclient.tests.unit.volume.v2 import fakes as volume_fakes
20
- from openstackclient.tests.unit.volume.v3 import fakes as volume_fakes_v3
23
+ from openstackclient.tests.unit.identity.v3 import fakes as project_fakes
24
+ from openstackclient.tests.unit import utils as test_utils
25
+ from openstackclient.tests.unit.volume.v3 import fakes as volume_fakes
21
26
  from openstackclient.volume.v3 import volume_snapshot
22
27
 
23
28
 
24
- class TestVolumeSnapshot(volume_fakes_v3.TestVolume):
29
+ class TestVolumeSnapshotCreate(volume_fakes.TestVolume):
25
30
  def setUp(self):
26
31
  super().setUp()
27
32
 
28
- self.snapshots_mock = self.volume_client.volume_snapshots
29
- self.snapshots_mock.reset_mock()
33
+ self.volume = sdk_fakes.generate_fake_resource(_volume.Volume)
34
+ self.volume_sdk_client.find_volume.return_value = self.volume
35
+ self.snapshot = sdk_fakes.generate_fake_resource(
36
+ _snapshot.Snapshot, volume_id=self.volume.id
37
+ )
38
+ self.volume_sdk_client.create_snapshot.return_value = self.snapshot
39
+ self.volume_sdk_client.manage_snapshot.return_value = self.snapshot
40
+
41
+ self.columns = (
42
+ 'created_at',
43
+ 'description',
44
+ 'id',
45
+ 'name',
46
+ 'properties',
47
+ 'size',
48
+ 'status',
49
+ 'volume_id',
50
+ )
51
+ self.data = (
52
+ self.snapshot.created_at,
53
+ self.snapshot.description,
54
+ self.snapshot.id,
55
+ self.snapshot.name,
56
+ format_columns.DictColumn(self.snapshot.metadata),
57
+ self.snapshot.size,
58
+ self.snapshot.status,
59
+ self.snapshot.volume_id,
60
+ )
30
61
 
31
- self.volume_sdk_client.unmanage_snapshot.return_value = None
62
+ self.cmd = volume_snapshot.CreateVolumeSnapshot(self.app, None)
63
+
64
+ def test_snapshot_create(self):
65
+ arglist = [
66
+ "--volume",
67
+ self.snapshot.volume_id,
68
+ "--description",
69
+ self.snapshot.description,
70
+ "--force",
71
+ '--property',
72
+ 'Alpha=a',
73
+ '--property',
74
+ 'Beta=b',
75
+ self.snapshot.name,
76
+ ]
77
+ verifylist = [
78
+ ("volume", self.snapshot.volume_id),
79
+ ("description", self.snapshot.description),
80
+ ("force", True),
81
+ ('properties', {'Alpha': 'a', 'Beta': 'b'}),
82
+ ("snapshot_name", self.snapshot.name),
83
+ ]
84
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
85
+
86
+ columns, data = self.cmd.take_action(parsed_args)
87
+
88
+ self.volume_sdk_client.find_volume.assert_called_once_with(
89
+ self.snapshot.volume_id, ignore_missing=False
90
+ )
91
+ self.volume_sdk_client.create_snapshot.assert_called_with(
92
+ volume_id=self.snapshot.volume_id,
93
+ force=True,
94
+ name=self.snapshot.name,
95
+ description=self.snapshot.description,
96
+ metadata={'Alpha': 'a', 'Beta': 'b'},
97
+ )
98
+ self.assertEqual(self.columns, columns)
99
+ self.assertEqual(self.data, data)
100
+
101
+ def test_snapshot_create_without_name(self):
102
+ arglist = [
103
+ "--volume",
104
+ self.snapshot.volume_id,
105
+ ]
106
+ verifylist = [
107
+ ("volume", self.snapshot.volume_id),
108
+ ]
109
+ self.assertRaises(
110
+ test_utils.ParserException,
111
+ self.check_parser,
112
+ self.cmd,
113
+ arglist,
114
+ verifylist,
115
+ )
116
+
117
+ def test_snapshot_create_without_volume(self):
118
+ arglist = [
119
+ "--description",
120
+ self.snapshot.description,
121
+ "--force",
122
+ self.snapshot.name,
123
+ ]
124
+ verifylist = [
125
+ ("description", self.snapshot.description),
126
+ ("force", True),
127
+ ("snapshot_name", self.snapshot.name),
128
+ ]
129
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
32
130
 
131
+ columns, data = self.cmd.take_action(parsed_args)
33
132
 
34
- class TestVolumeSnapshotDelete(TestVolumeSnapshot):
35
- snapshots = volume_fakes.create_snapshots(count=2)
133
+ self.volume_sdk_client.find_volume.assert_called_once_with(
134
+ self.snapshot.name, ignore_missing=False
135
+ )
136
+ self.volume_sdk_client.create_snapshot.assert_called_with(
137
+ volume_id=self.snapshot.volume_id,
138
+ force=True,
139
+ name=self.snapshot.name,
140
+ description=self.snapshot.description,
141
+ metadata=None,
142
+ )
143
+ self.assertEqual(self.columns, columns)
144
+ self.assertEqual(self.data, data)
36
145
 
146
+ def test_snapshot_create_with_remote_source(self):
147
+ arglist = [
148
+ '--remote-source',
149
+ 'source-name=test_source_name',
150
+ '--remote-source',
151
+ 'source-id=test_source_id',
152
+ '--volume',
153
+ self.snapshot.volume_id,
154
+ self.snapshot.name,
155
+ ]
156
+ ref_dict = {
157
+ 'source-name': 'test_source_name',
158
+ 'source-id': 'test_source_id',
159
+ }
160
+ verifylist = [
161
+ ('remote_source', ref_dict),
162
+ ('volume', self.snapshot.volume_id),
163
+ ("snapshot_name", self.snapshot.name),
164
+ ]
165
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
166
+
167
+ columns, data = self.cmd.take_action(parsed_args)
168
+
169
+ self.assertEqual(self.columns, columns)
170
+ self.assertEqual(self.data, data)
171
+ self.volume_sdk_client.find_volume.assert_called_once_with(
172
+ self.snapshot.volume_id, ignore_missing=False
173
+ )
174
+ self.volume_sdk_client.manage_snapshot.assert_called_with(
175
+ volume_id=self.snapshot.volume_id,
176
+ ref=ref_dict,
177
+ name=self.snapshot.name,
178
+ description=None,
179
+ metadata=None,
180
+ )
181
+ self.volume_sdk_client.create_snapshot.assert_not_called()
182
+
183
+
184
+ class TestVolumeSnapshotDelete(volume_fakes.TestVolume):
37
185
  def setUp(self):
38
186
  super().setUp()
39
187
 
40
- self.snapshots_mock.get = volume_fakes.get_snapshots(self.snapshots)
41
- self.snapshots_mock.delete.return_value = None
188
+ self.snapshots = list(
189
+ sdk_fakes.generate_fake_resources(_snapshot.Snapshot)
190
+ )
191
+ self.volume_sdk_client.find_snapshot.side_effect = self.snapshots
192
+ self.volume_sdk_client.delete_snapshot.return_value = None
193
+ self.volume_sdk_client.unmanage_snapshot.return_value = None
42
194
 
43
- # Get the command object to mock
44
195
  self.cmd = volume_snapshot.DeleteVolumeSnapshot(self.app, None)
45
196
 
46
197
  def test_snapshot_delete(self):
@@ -49,11 +200,14 @@ class TestVolumeSnapshotDelete(TestVolumeSnapshot):
49
200
  parsed_args = self.check_parser(self.cmd, arglist, verifylist)
50
201
 
51
202
  result = self.cmd.take_action(parsed_args)
203
+ self.assertIsNone(result)
52
204
 
53
- self.snapshots_mock.delete.assert_called_with(
54
- self.snapshots[0].id, False
205
+ self.volume_sdk_client.find_snapshot.assert_called_once_with(
206
+ self.snapshots[0].id, ignore_missing=False
207
+ )
208
+ self.volume_sdk_client.delete_snapshot.assert_called_once_with(
209
+ self.snapshots[0].id, force=False
55
210
  )
56
- self.assertIsNone(result)
57
211
 
58
212
  def test_snapshot_delete_with_force(self):
59
213
  arglist = ['--force', self.snapshots[0].id]
@@ -61,11 +215,14 @@ class TestVolumeSnapshotDelete(TestVolumeSnapshot):
61
215
  parsed_args = self.check_parser(self.cmd, arglist, verifylist)
62
216
 
63
217
  result = self.cmd.take_action(parsed_args)
218
+ self.assertIsNone(result)
64
219
 
65
- self.snapshots_mock.delete.assert_called_with(
66
- self.snapshots[0].id, True
220
+ self.volume_sdk_client.find_snapshot.assert_called_once_with(
221
+ self.snapshots[0].id, ignore_missing=False
222
+ )
223
+ self.volume_sdk_client.delete_snapshot.assert_called_once_with(
224
+ self.snapshots[0].id, force=True
67
225
  )
68
- self.assertIsNone(result)
69
226
 
70
227
  def test_delete_multiple_snapshots(self):
71
228
  arglist = []
@@ -74,17 +231,24 @@ class TestVolumeSnapshotDelete(TestVolumeSnapshot):
74
231
  verifylist = [
75
232
  ('snapshots', arglist),
76
233
  ]
77
-
78
234
  parsed_args = self.check_parser(self.cmd, arglist, verifylist)
79
- result = self.cmd.take_action(parsed_args)
80
235
 
81
- calls = []
82
- for s in self.snapshots:
83
- calls.append(mock.call(s.id, False))
84
- self.snapshots_mock.delete.assert_has_calls(calls)
236
+ result = self.cmd.take_action(parsed_args)
85
237
  self.assertIsNone(result)
86
238
 
239
+ self.volume_sdk_client.find_snapshot.assert_has_calls(
240
+ [mock.call(x.id, ignore_missing=False) for x in self.snapshots]
241
+ )
242
+ self.volume_sdk_client.delete_snapshot.assert_has_calls(
243
+ [mock.call(x.id, force=False) for x in self.snapshots]
244
+ )
245
+
87
246
  def test_delete_multiple_snapshots_with_exception(self):
247
+ self.volume_sdk_client.find_snapshot.side_effect = [
248
+ self.snapshots[0],
249
+ sdk_exceptions.NotFoundException(),
250
+ ]
251
+
88
252
  arglist = [
89
253
  self.snapshots[0].id,
90
254
  'unexist_snapshot',
@@ -95,25 +259,24 @@ class TestVolumeSnapshotDelete(TestVolumeSnapshot):
95
259
 
96
260
  parsed_args = self.check_parser(self.cmd, arglist, verifylist)
97
261
 
98
- find_mock_result = [self.snapshots[0], exceptions.CommandError]
99
- with mock.patch.object(
100
- utils, 'find_resource', side_effect=find_mock_result
101
- ) as find_mock:
102
- try:
103
- self.cmd.take_action(parsed_args)
104
- self.fail('CommandError should be raised.')
105
- except exceptions.CommandError as e:
106
- self.assertEqual('1 of 2 snapshots failed to delete.', str(e))
107
-
108
- find_mock.assert_any_call(
109
- self.snapshots_mock, self.snapshots[0].id
110
- )
111
- find_mock.assert_any_call(self.snapshots_mock, 'unexist_snapshot')
262
+ exc = self.assertRaises(
263
+ exceptions.CommandError,
264
+ self.cmd.take_action,
265
+ parsed_args,
266
+ )
267
+ self.assertEqual('1 of 2 snapshots failed to delete.', str(exc))
112
268
 
113
- self.assertEqual(2, find_mock.call_count)
114
- self.snapshots_mock.delete.assert_called_once_with(
115
- self.snapshots[0].id, False
116
- )
269
+ self.volume_sdk_client.find_snapshot.assert_has_calls(
270
+ [
271
+ mock.call(self.snapshots[0].id, ignore_missing=False),
272
+ mock.call('unexist_snapshot', ignore_missing=False),
273
+ ]
274
+ )
275
+ self.volume_sdk_client.delete_snapshot.assert_has_calls(
276
+ [
277
+ mock.call(self.snapshots[0].id, force=False),
278
+ ]
279
+ )
117
280
 
118
281
  def test_snapshot_delete_remote(self):
119
282
  arglist = ['--remote', self.snapshots[0].id]
@@ -121,11 +284,11 @@ class TestVolumeSnapshotDelete(TestVolumeSnapshot):
121
284
  parsed_args = self.check_parser(self.cmd, arglist, verifylist)
122
285
 
123
286
  result = self.cmd.take_action(parsed_args)
287
+ self.assertIsNone(result)
124
288
 
125
289
  self.volume_sdk_client.unmanage_snapshot.assert_called_with(
126
290
  self.snapshots[0].id
127
291
  )
128
- self.assertIsNone(result)
129
292
 
130
293
  def test_snapshot_delete_with_remote_force(self):
131
294
  arglist = ['--remote', '--force', self.snapshots[0].id]
@@ -149,12 +312,484 @@ class TestVolumeSnapshotDelete(TestVolumeSnapshot):
149
312
  for s in self.snapshots:
150
313
  arglist.append(s.id)
151
314
  verifylist = [('remote', True), ('snapshots', arglist[1:])]
152
-
153
315
  parsed_args = self.check_parser(self.cmd, arglist, verifylist)
316
+
154
317
  result = self.cmd.take_action(parsed_args)
318
+ self.assertIsNone(result)
319
+
320
+ self.volume_sdk_client.unmanage_snapshot.assert_has_calls(
321
+ [mock.call(s.id) for s in self.snapshots]
322
+ )
323
+
324
+
325
+ class TestVolumeSnapshotList(volume_fakes.TestVolume):
326
+ def setUp(self):
327
+ super().setUp()
328
+
329
+ self.volume = sdk_fakes.generate_fake_resource(_volume.Volume)
330
+ self.snapshots = list(
331
+ sdk_fakes.generate_fake_resources(
332
+ _snapshot.Snapshot, attrs={'volume_id': self.volume.name}
333
+ )
334
+ )
335
+ self.project = project_fakes.FakeProject.create_one_project()
336
+ self.volume_sdk_client.volumes.return_value = [self.volume]
337
+ self.volume_sdk_client.find_volume.return_value = self.volume
338
+ self.volume_sdk_client.snapshots.return_value = self.snapshots
339
+ self.project_mock = self.identity_client.projects
340
+ self.project_mock.get.return_value = self.project
341
+
342
+ self.columns = ("ID", "Name", "Description", "Status", "Size")
343
+ self.columns_long = self.columns + (
344
+ "Created At",
345
+ "Volume",
346
+ "Properties",
347
+ )
155
348
 
156
- calls = []
349
+ self.data = []
350
+ self.data_long = []
157
351
  for s in self.snapshots:
158
- calls.append(mock.call(s.id))
159
- self.volume_sdk_client.unmanage_snapshot.assert_has_calls(calls)
352
+ self.data.append(
353
+ (
354
+ s.id,
355
+ s.name,
356
+ s.description,
357
+ s.status,
358
+ s.size,
359
+ )
360
+ )
361
+ self.data_long.append(
362
+ (
363
+ s.id,
364
+ s.name,
365
+ s.description,
366
+ s.status,
367
+ s.size,
368
+ s.created_at,
369
+ volume_snapshot.VolumeIdColumn(
370
+ s.volume_id, volume_cache={self.volume.id: self.volume}
371
+ ),
372
+ format_columns.DictColumn(s.metadata),
373
+ )
374
+ )
375
+
376
+ self.cmd = volume_snapshot.ListVolumeSnapshot(self.app, None)
377
+
378
+ def test_snapshot_list_without_options(self):
379
+ arglist = []
380
+ verifylist = [('all_projects', False), ('long', False)]
381
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
382
+
383
+ columns, data = self.cmd.take_action(parsed_args)
384
+
385
+ self.volume_sdk_client.snapshots.assert_called_once_with(
386
+ limit=None,
387
+ marker=None,
388
+ all_projects=False,
389
+ name=None,
390
+ status=None,
391
+ project_id=None,
392
+ volume_id=None,
393
+ )
394
+ self.assertEqual(self.columns, columns)
395
+ self.assertEqual(self.data, list(data))
396
+
397
+ def test_snapshot_list_with_options(self):
398
+ arglist = [
399
+ "--long",
400
+ "--limit",
401
+ "2",
402
+ "--project",
403
+ self.project.id,
404
+ "--marker",
405
+ self.snapshots[0].id,
406
+ ]
407
+ verifylist = [
408
+ ("long", True),
409
+ ("limit", 2),
410
+ ("project", self.project.id),
411
+ ("marker", self.snapshots[0].id),
412
+ ('all_projects', False),
413
+ ]
414
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
415
+
416
+ columns, data = self.cmd.take_action(parsed_args)
417
+
418
+ self.volume_sdk_client.snapshots.assert_called_once_with(
419
+ limit=2,
420
+ marker=self.snapshots[0].id,
421
+ all_projects=True,
422
+ project_id=self.project.id,
423
+ name=None,
424
+ status=None,
425
+ volume_id=None,
426
+ )
427
+ self.assertEqual(self.columns_long, columns)
428
+ self.assertEqual(self.data_long, list(data))
429
+
430
+ def test_snapshot_list_all_projects(self):
431
+ arglist = [
432
+ '--all-projects',
433
+ ]
434
+ verifylist = [('long', False), ('all_projects', True)]
435
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
436
+
437
+ columns, data = self.cmd.take_action(parsed_args)
438
+
439
+ self.volume_sdk_client.snapshots.assert_called_once_with(
440
+ limit=None,
441
+ marker=None,
442
+ all_projects=True,
443
+ name=None,
444
+ status=None,
445
+ project_id=None,
446
+ volume_id=None,
447
+ )
448
+ self.assertEqual(self.columns, columns)
449
+ self.assertEqual(self.data, list(data))
450
+
451
+ def test_snapshot_list_name_option(self):
452
+ arglist = [
453
+ '--name',
454
+ self.snapshots[0].name,
455
+ ]
456
+ verifylist = [
457
+ ('all_projects', False),
458
+ ('long', False),
459
+ ('name', self.snapshots[0].name),
460
+ ]
461
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
462
+
463
+ columns, data = self.cmd.take_action(parsed_args)
464
+
465
+ self.volume_sdk_client.snapshots.assert_called_once_with(
466
+ limit=None,
467
+ marker=None,
468
+ all_projects=False,
469
+ name=self.snapshots[0].name,
470
+ status=None,
471
+ project_id=None,
472
+ volume_id=None,
473
+ )
474
+ self.assertEqual(self.columns, columns)
475
+ self.assertEqual(self.data, list(data))
476
+
477
+ def test_snapshot_list_status_option(self):
478
+ arglist = [
479
+ '--status',
480
+ 'available',
481
+ ]
482
+ verifylist = [
483
+ ('all_projects', False),
484
+ ('long', False),
485
+ ('status', 'available'),
486
+ ]
487
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
488
+
489
+ columns, data = self.cmd.take_action(parsed_args)
490
+
491
+ self.volume_sdk_client.snapshots.assert_called_once_with(
492
+ limit=None,
493
+ marker=None,
494
+ all_projects=False,
495
+ name=None,
496
+ status='available',
497
+ project_id=None,
498
+ volume_id=None,
499
+ )
500
+ self.assertEqual(self.columns, columns)
501
+ self.assertEqual(self.data, list(data))
502
+
503
+ def test_snapshot_list_volumeid_option(self):
504
+ arglist = [
505
+ '--volume',
506
+ self.volume.id,
507
+ ]
508
+ verifylist = [
509
+ ('all_projects', False),
510
+ ('long', False),
511
+ ('volume', self.volume.id),
512
+ ]
513
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
514
+
515
+ columns, data = self.cmd.take_action(parsed_args)
516
+
517
+ self.volume_sdk_client.snapshots.assert_called_once_with(
518
+ limit=None,
519
+ marker=None,
520
+ all_projects=False,
521
+ name=None,
522
+ status=None,
523
+ project_id=None,
524
+ volume_id=self.volume.id,
525
+ )
526
+ self.assertEqual(self.columns, columns)
527
+ self.assertEqual(self.data, list(data))
528
+
529
+ def test_snapshot_list_negative_limit(self):
530
+ arglist = [
531
+ "--limit",
532
+ "-2",
533
+ ]
534
+ verifylist = [
535
+ ("limit", -2),
536
+ ]
537
+ self.assertRaises(
538
+ test_utils.ParserException,
539
+ self.check_parser,
540
+ self.cmd,
541
+ arglist,
542
+ verifylist,
543
+ )
544
+
545
+
546
+ class TestVolumeSnapshotSet(volume_fakes.TestVolume):
547
+ def setUp(self):
548
+ super().setUp()
549
+
550
+ self.snapshot = sdk_fakes.generate_fake_resource(
551
+ _snapshot.Snapshot, metadata={'foo': 'bar'}
552
+ )
553
+ self.volume_sdk_client.find_snapshot.return_value = self.snapshot
554
+ self.volume_sdk_client.set_snapshot_metadata.return_value = None
555
+ self.volume_sdk_client.update_snapshot.return_value = None
556
+ # Get the command object to mock
557
+ self.cmd = volume_snapshot.SetVolumeSnapshot(self.app, None)
558
+
559
+ def test_snapshot_set_no_option(self):
560
+ arglist = [
561
+ self.snapshot.id,
562
+ ]
563
+ verifylist = [
564
+ ("snapshot", self.snapshot.id),
565
+ ]
566
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
567
+
568
+ result = self.cmd.take_action(parsed_args)
569
+
570
+ self.assertIsNone(result)
571
+ self.volume_sdk_client.find_snapshot.assert_called_once_with(
572
+ parsed_args.snapshot, ignore_missing=False
573
+ )
574
+ self.volume_sdk_client.reset_snapshot_status.assert_not_called()
575
+ self.volume_sdk_client.update_snapshot.assert_not_called()
576
+ self.volume_sdk_client.set_snapshot_metadata.assert_not_called()
577
+
578
+ def test_snapshot_set_name_and_property(self):
579
+ arglist = [
580
+ "--name",
581
+ "new_snapshot",
582
+ "--property",
583
+ "x=y",
584
+ "--property",
585
+ "foo=foo",
586
+ self.snapshot.id,
587
+ ]
588
+ verifylist = [
589
+ ("name", "new_snapshot"),
590
+ ("properties", {"x": "y", "foo": "foo"}),
591
+ ("snapshot", self.snapshot.id),
592
+ ]
593
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
594
+
595
+ result = self.cmd.take_action(parsed_args)
596
+
597
+ self.assertIsNone(result)
598
+ self.volume_sdk_client.update_snapshot.assert_called_with(
599
+ self.snapshot.id, name="new_snapshot"
600
+ )
601
+ self.volume_sdk_client.set_snapshot_metadata.assert_called_with(
602
+ self.snapshot.id, x="y", foo="foo"
603
+ )
604
+
605
+ def test_snapshot_set_with_no_property(self):
606
+ arglist = [
607
+ "--no-property",
608
+ self.snapshot.id,
609
+ ]
610
+ verifylist = [
611
+ ("no_property", True),
612
+ ("snapshot", self.snapshot.id),
613
+ ]
614
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
615
+
616
+ result = self.cmd.take_action(parsed_args)
617
+
618
+ self.assertIsNone(result)
619
+ self.volume_sdk_client.find_snapshot.assert_called_once_with(
620
+ parsed_args.snapshot, ignore_missing=False
621
+ )
622
+ self.volume_sdk_client.reset_snapshot_status.assert_not_called()
623
+ self.volume_sdk_client.update_snapshot.assert_not_called()
624
+ self.volume_sdk_client.set_snapshot_metadata.assert_not_called()
625
+ self.volume_sdk_client.delete_snapshot_metadata.assert_called_with(
626
+ self.snapshot.id, keys=["foo"]
627
+ )
628
+
629
+ def test_snapshot_set_with_no_property_and_property(self):
630
+ arglist = [
631
+ "--no-property",
632
+ "--property",
633
+ "foo_1=bar_1",
634
+ self.snapshot.id,
635
+ ]
636
+ verifylist = [
637
+ ("no_property", True),
638
+ ("properties", {"foo_1": "bar_1"}),
639
+ ("snapshot", self.snapshot.id),
640
+ ]
641
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
642
+
643
+ result = self.cmd.take_action(parsed_args)
644
+
160
645
  self.assertIsNone(result)
646
+ self.volume_sdk_client.find_snapshot.assert_called_once_with(
647
+ parsed_args.snapshot, ignore_missing=False
648
+ )
649
+ self.volume_sdk_client.reset_snapshot_status.assert_not_called()
650
+ self.volume_sdk_client.update_snapshot.assert_not_called()
651
+ self.volume_sdk_client.delete_snapshot_metadata.assert_called_with(
652
+ self.snapshot.id, keys=["foo"]
653
+ )
654
+ self.volume_sdk_client.set_snapshot_metadata.assert_called_once_with(
655
+ self.snapshot.id,
656
+ foo_1="bar_1",
657
+ )
658
+
659
+ def test_snapshot_set_state_to_error(self):
660
+ arglist = ["--state", "error", self.snapshot.id]
661
+ verifylist = [("state", "error"), ("snapshot", self.snapshot.id)]
662
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
663
+
664
+ result = self.cmd.take_action(parsed_args)
665
+
666
+ self.assertIsNone(result)
667
+ self.volume_sdk_client.reset_snapshot_status.assert_called_with(
668
+ self.snapshot.id, "error"
669
+ )
670
+
671
+ def test_volume_set_state_failed(self):
672
+ self.volume_sdk_client.reset_snapshot_status.side_effect = (
673
+ exceptions.CommandError()
674
+ )
675
+ arglist = ['--state', 'error', self.snapshot.id]
676
+ verifylist = [('state', 'error'), ('snapshot', self.snapshot.id)]
677
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
678
+
679
+ exc = self.assertRaises(
680
+ exceptions.CommandError,
681
+ self.cmd.take_action,
682
+ parsed_args,
683
+ )
684
+
685
+ self.assertEqual('One or more of the set operations failed', str(exc))
686
+ self.volume_sdk_client.reset_snapshot_status.assert_called_once_with(
687
+ self.snapshot.id, 'error'
688
+ )
689
+
690
+ def test_volume_set_name_and_state_failed(self):
691
+ self.volume_sdk_client.reset_snapshot_status.side_effect = (
692
+ exceptions.CommandError()
693
+ )
694
+ arglist = [
695
+ '--state',
696
+ 'error',
697
+ "--name",
698
+ "new_snapshot",
699
+ self.snapshot.id,
700
+ ]
701
+ verifylist = [
702
+ ('state', 'error'),
703
+ ("name", "new_snapshot"),
704
+ ('snapshot', self.snapshot.id),
705
+ ]
706
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
707
+
708
+ exc = self.assertRaises(
709
+ exceptions.CommandError,
710
+ self.cmd.take_action,
711
+ parsed_args,
712
+ )
713
+
714
+ self.assertEqual('One or more of the set operations failed', str(exc))
715
+ self.volume_sdk_client.update_snapshot.assert_called_once_with(
716
+ self.snapshot.id, name="new_snapshot"
717
+ )
718
+ self.volume_sdk_client.reset_snapshot_status.assert_called_once_with(
719
+ self.snapshot.id, 'error'
720
+ )
721
+
722
+
723
+ class TestVolumeSnapshotShow(volume_fakes.TestVolume):
724
+ def setUp(self):
725
+ super().setUp()
726
+
727
+ self.snapshot = sdk_fakes.generate_fake_resource(_snapshot.Snapshot)
728
+
729
+ self.columns = (
730
+ 'created_at',
731
+ 'description',
732
+ 'id',
733
+ 'name',
734
+ 'properties',
735
+ 'size',
736
+ 'status',
737
+ 'volume_id',
738
+ )
739
+ self.data = (
740
+ self.snapshot.created_at,
741
+ self.snapshot.description,
742
+ self.snapshot.id,
743
+ self.snapshot.name,
744
+ format_columns.DictColumn(self.snapshot.metadata),
745
+ self.snapshot.size,
746
+ self.snapshot.status,
747
+ self.snapshot.volume_id,
748
+ )
749
+
750
+ self.volume_sdk_client.find_snapshot.return_value = self.snapshot
751
+
752
+ self.cmd = volume_snapshot.ShowVolumeSnapshot(self.app, None)
753
+
754
+ def test_snapshot_show(self):
755
+ arglist = [self.snapshot.id]
756
+ verifylist = [("snapshot", self.snapshot.id)]
757
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
758
+
759
+ columns, data = self.cmd.take_action(parsed_args)
760
+ self.volume_sdk_client.find_snapshot.assert_called_with(
761
+ self.snapshot.id, ignore_missing=False
762
+ )
763
+
764
+ self.assertEqual(self.columns, columns)
765
+ self.assertCountEqual(self.data, data)
766
+
767
+
768
+ class TestVolumeSnapshotUnset(volume_fakes.TestVolume):
769
+ def setUp(self):
770
+ super().setUp()
771
+
772
+ self.snapshot = sdk_fakes.generate_fake_resource(_snapshot.Snapshot)
773
+ self.volume_sdk_client.find_snapshot.return_value = self.snapshot
774
+ self.volume_sdk_client.delete_snapshot_metadata.return_value = None
775
+
776
+ self.cmd = volume_snapshot.UnsetVolumeSnapshot(self.app, None)
777
+
778
+ def test_snapshot_unset(self):
779
+ arglist = [
780
+ "--property",
781
+ "foo",
782
+ self.snapshot.id,
783
+ ]
784
+ verifylist = [
785
+ ("properties", ["foo"]),
786
+ ("snapshot", self.snapshot.id),
787
+ ]
788
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
789
+
790
+ result = self.cmd.take_action(parsed_args)
791
+
792
+ self.assertIsNone(result)
793
+ self.volume_sdk_client.delete_snapshot_metadata.assert_called_with(
794
+ self.snapshot.id, keys=["foo"]
795
+ )