1# Copyright 2018 SUSE Linux GmbH 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); you may 4# not use this file except in compliance with the License. You may obtain 5# a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12# License for the specific language governing permissions and limitations 13# under the License. 14# 15 16import copy 17import json 18from unittest import mock 19 20from osc_lib import exceptions 21from osc_lib import utils 22 23from openstackclient.identity.v3 import application_credential 24from openstackclient.tests.unit import fakes 25from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes 26 27 28class TestApplicationCredential(identity_fakes.TestIdentityv3): 29 30 def setUp(self): 31 super(TestApplicationCredential, self).setUp() 32 33 identity_manager = self.app.client_manager.identity 34 self.app_creds_mock = identity_manager.application_credentials 35 self.app_creds_mock.reset_mock() 36 self.roles_mock = identity_manager.roles 37 self.roles_mock.reset_mock() 38 39 40class TestApplicationCredentialCreate(TestApplicationCredential): 41 42 def setUp(self): 43 super(TestApplicationCredentialCreate, self).setUp() 44 45 self.roles_mock.get.return_value = fakes.FakeResource( 46 None, 47 copy.deepcopy(identity_fakes.ROLE), 48 loaded=True, 49 ) 50 51 # Get the command object to test 52 self.cmd = application_credential.CreateApplicationCredential( 53 self.app, None) 54 55 def test_application_credential_create_basic(self): 56 self.app_creds_mock.create.return_value = fakes.FakeResource( 57 None, 58 copy.deepcopy(identity_fakes.APP_CRED_BASIC), 59 loaded=True, 60 ) 61 62 name = identity_fakes.app_cred_name 63 arglist = [ 64 name 65 ] 66 verifylist = [ 67 ('name', identity_fakes.app_cred_name) 68 ] 69 parsed_args = self.check_parser(self.cmd, arglist, verifylist) 70 71 # In base command class ShowOne in cliff, abstract method take_action() 72 # returns a two-part tuple with a tuple of column names and a tuple of 73 # data to be shown. 74 columns, data = self.cmd.take_action(parsed_args) 75 76 # Set expected values 77 kwargs = { 78 'secret': None, 79 'roles': [], 80 'expires_at': None, 81 'description': None, 82 'unrestricted': False, 83 'access_rules': None, 84 } 85 self.app_creds_mock.create.assert_called_with( 86 name, 87 **kwargs 88 ) 89 90 collist = ('access_rules', 'description', 'expires_at', 'id', 'name', 91 'project_id', 'roles', 'secret', 'unrestricted') 92 self.assertEqual(collist, columns) 93 datalist = ( 94 None, 95 None, 96 None, 97 identity_fakes.app_cred_id, 98 identity_fakes.app_cred_name, 99 identity_fakes.project_id, 100 identity_fakes.role_name, 101 identity_fakes.app_cred_secret, 102 False, 103 ) 104 self.assertEqual(datalist, data) 105 106 def test_application_credential_create_with_options(self): 107 name = identity_fakes.app_cred_name 108 self.app_creds_mock.create.return_value = fakes.FakeResource( 109 None, 110 copy.deepcopy(identity_fakes.APP_CRED_OPTIONS), 111 loaded=True, 112 ) 113 114 arglist = [ 115 name, 116 '--secret', 'moresecuresecret', 117 '--role', identity_fakes.role_id, 118 '--expiration', identity_fakes.app_cred_expires_str, 119 '--description', 'credential for testing' 120 ] 121 verifylist = [ 122 ('name', identity_fakes.app_cred_name), 123 ('secret', 'moresecuresecret'), 124 ('role', [identity_fakes.role_id]), 125 ('expiration', identity_fakes.app_cred_expires_str), 126 ('description', 'credential for testing') 127 ] 128 parsed_args = self.check_parser(self.cmd, arglist, verifylist) 129 130 # In base command class ShowOne in cliff, abstract method take_action() 131 # returns a two-part tuple with a tuple of column names and a tuple of 132 # data to be shown. 133 columns, data = self.cmd.take_action(parsed_args) 134 135 # Set expected values 136 kwargs = { 137 'secret': 'moresecuresecret', 138 'roles': [identity_fakes.role_id], 139 'expires_at': identity_fakes.app_cred_expires, 140 'description': 'credential for testing', 141 'unrestricted': False, 142 'access_rules': None, 143 } 144 self.app_creds_mock.create.assert_called_with( 145 name, 146 **kwargs 147 ) 148 149 collist = ('access_rules', 'description', 'expires_at', 'id', 'name', 150 'project_id', 'roles', 'secret', 'unrestricted') 151 self.assertEqual(collist, columns) 152 datalist = ( 153 None, 154 identity_fakes.app_cred_description, 155 identity_fakes.app_cred_expires_str, 156 identity_fakes.app_cred_id, 157 identity_fakes.app_cred_name, 158 identity_fakes.project_id, 159 identity_fakes.role_name, 160 identity_fakes.app_cred_secret, 161 False, 162 ) 163 self.assertEqual(datalist, data) 164 165 def test_application_credential_create_with_access_rules_string(self): 166 name = identity_fakes.app_cred_name 167 self.app_creds_mock.create.return_value = fakes.FakeResource( 168 None, 169 copy.deepcopy(identity_fakes.APP_CRED_ACCESS_RULES), 170 loaded=True, 171 ) 172 173 arglist = [ 174 name, 175 '--access-rules', identity_fakes.app_cred_access_rules, 176 ] 177 verifylist = [ 178 ('name', identity_fakes.app_cred_name), 179 ('access_rules', identity_fakes.app_cred_access_rules), 180 ] 181 parsed_args = self.check_parser(self.cmd, arglist, verifylist) 182 183 columns, data = self.cmd.take_action(parsed_args) 184 185 # Set expected values 186 kwargs = { 187 'secret': None, 188 'roles': [], 189 'expires_at': None, 190 'description': None, 191 'unrestricted': False, 192 'access_rules': json.loads(identity_fakes.app_cred_access_rules) 193 } 194 self.app_creds_mock.create.assert_called_with( 195 name, 196 **kwargs 197 ) 198 199 collist = ('access_rules', 'description', 'expires_at', 'id', 'name', 200 'project_id', 'roles', 'secret', 'unrestricted') 201 self.assertEqual(collist, columns) 202 datalist = ( 203 identity_fakes.app_cred_access_rules, 204 None, 205 None, 206 identity_fakes.app_cred_id, 207 identity_fakes.app_cred_name, 208 identity_fakes.project_id, 209 identity_fakes.role_name, 210 identity_fakes.app_cred_secret, 211 False, 212 ) 213 self.assertEqual(datalist, data) 214 215 @mock.patch('openstackclient.identity.v3.application_credential.json.load') 216 @mock.patch('openstackclient.identity.v3.application_credential.open') 217 def test_application_credential_create_with_access_rules_file( 218 self, _, mock_json_load): 219 mock_json_load.return_value = identity_fakes.app_cred_access_rules 220 221 name = identity_fakes.app_cred_name 222 self.app_creds_mock.create.return_value = fakes.FakeResource( 223 None, 224 copy.deepcopy(identity_fakes.APP_CRED_ACCESS_RULES), 225 loaded=True, 226 ) 227 228 arglist = [ 229 name, 230 '--access-rules', identity_fakes.app_cred_access_rules_path, 231 ] 232 verifylist = [ 233 ('name', identity_fakes.app_cred_name), 234 ('access_rules', identity_fakes.app_cred_access_rules_path), 235 ] 236 parsed_args = self.check_parser(self.cmd, arglist, verifylist) 237 238 columns, data = self.cmd.take_action(parsed_args) 239 240 # Set expected values 241 kwargs = { 242 'secret': None, 243 'roles': [], 244 'expires_at': None, 245 'description': None, 246 'unrestricted': False, 247 'access_rules': identity_fakes.app_cred_access_rules 248 } 249 self.app_creds_mock.create.assert_called_with( 250 name, 251 **kwargs 252 ) 253 254 collist = ('access_rules', 'description', 'expires_at', 'id', 'name', 255 'project_id', 'roles', 'secret', 'unrestricted') 256 self.assertEqual(collist, columns) 257 datalist = ( 258 identity_fakes.app_cred_access_rules, 259 None, 260 None, 261 identity_fakes.app_cred_id, 262 identity_fakes.app_cred_name, 263 identity_fakes.project_id, 264 identity_fakes.role_name, 265 identity_fakes.app_cred_secret, 266 False, 267 ) 268 self.assertEqual(datalist, data) 269 270 271class TestApplicationCredentialDelete(TestApplicationCredential): 272 273 def setUp(self): 274 super(TestApplicationCredentialDelete, self).setUp() 275 276 # This is the return value for utils.find_resource() 277 self.app_creds_mock.get.return_value = fakes.FakeResource( 278 None, 279 copy.deepcopy(identity_fakes.APP_CRED_BASIC), 280 loaded=True, 281 ) 282 self.app_creds_mock.delete.return_value = None 283 284 # Get the command object to test 285 self.cmd = application_credential.DeleteApplicationCredential( 286 self.app, None) 287 288 def test_application_credential_delete(self): 289 arglist = [ 290 identity_fakes.app_cred_id, 291 ] 292 verifylist = [ 293 ('application_credential', [identity_fakes.app_cred_id]) 294 ] 295 parsed_args = self.check_parser(self.cmd, arglist, verifylist) 296 297 result = self.cmd.take_action(parsed_args) 298 299 self.app_creds_mock.delete.assert_called_with( 300 identity_fakes.app_cred_id, 301 ) 302 self.assertIsNone(result) 303 304 @mock.patch.object(utils, 'find_resource') 305 def test_delete_multi_app_creds_with_exception(self, find_mock): 306 find_mock.side_effect = [self.app_creds_mock.get.return_value, 307 exceptions.CommandError] 308 arglist = [ 309 identity_fakes.app_cred_id, 310 'nonexistent_app_cred', 311 ] 312 verifylist = [ 313 ('application_credential', arglist), 314 ] 315 parsed_args = self.check_parser(self.cmd, arglist, verifylist) 316 317 try: 318 self.cmd.take_action(parsed_args) 319 self.fail('CommandError should be raised.') 320 except exceptions.CommandError as e: 321 self.assertEqual('1 of 2 application credentials failed to' 322 ' delete.', str(e)) 323 324 find_mock.assert_any_call(self.app_creds_mock, 325 identity_fakes.app_cred_id) 326 find_mock.assert_any_call(self.app_creds_mock, 327 'nonexistent_app_cred') 328 329 self.assertEqual(2, find_mock.call_count) 330 self.app_creds_mock.delete.assert_called_once_with( 331 identity_fakes.app_cred_id) 332 333 334class TestApplicationCredentialList(TestApplicationCredential): 335 336 def setUp(self): 337 super(TestApplicationCredentialList, self).setUp() 338 339 self.app_creds_mock.list.return_value = [ 340 fakes.FakeResource( 341 None, 342 copy.deepcopy(identity_fakes.APP_CRED_BASIC), 343 loaded=True, 344 ), 345 ] 346 347 # Get the command object to test 348 self.cmd = application_credential.ListApplicationCredential(self.app, 349 None) 350 351 def test_application_credential_list(self): 352 arglist = [] 353 verifylist = [] 354 parsed_args = self.check_parser(self.cmd, arglist, verifylist) 355 356 # In base command class Lister in cliff, abstract method take_action() 357 # returns a tuple containing the column names and an iterable 358 # containing the data to be listed. 359 columns, data = self.cmd.take_action(parsed_args) 360 361 self.app_creds_mock.list.assert_called_with(user=None) 362 363 collist = ('ID', 'Name', 'Project ID', 'Description', 'Expires At') 364 self.assertEqual(collist, columns) 365 datalist = (( 366 identity_fakes.app_cred_id, 367 identity_fakes.app_cred_name, 368 identity_fakes.project_id, 369 None, 370 None 371 ), ) 372 self.assertEqual(datalist, tuple(data)) 373 374 375class TestApplicationCredentialShow(TestApplicationCredential): 376 377 def setUp(self): 378 super(TestApplicationCredentialShow, self).setUp() 379 380 self.app_creds_mock.get.return_value = fakes.FakeResource( 381 None, 382 copy.deepcopy(identity_fakes.APP_CRED_BASIC), 383 loaded=True, 384 ) 385 386 # Get the command object to test 387 self.cmd = application_credential.ShowApplicationCredential(self.app, 388 None) 389 390 def test_application_credential_show(self): 391 arglist = [ 392 identity_fakes.app_cred_id, 393 ] 394 verifylist = [ 395 ('application_credential', identity_fakes.app_cred_id), 396 ] 397 parsed_args = self.check_parser(self.cmd, arglist, verifylist) 398 399 # In base command class ShowOne in cliff, abstract method take_action() 400 # returns a two-part tuple with a tuple of column names and a tuple of 401 # data to be shown. 402 columns, data = self.cmd.take_action(parsed_args) 403 404 self.app_creds_mock.get.assert_called_with(identity_fakes.app_cred_id) 405 406 collist = ('access_rules', 'description', 'expires_at', 'id', 'name', 407 'project_id', 'roles', 'secret', 'unrestricted') 408 self.assertEqual(collist, columns) 409 datalist = ( 410 None, 411 None, 412 None, 413 identity_fakes.app_cred_id, 414 identity_fakes.app_cred_name, 415 identity_fakes.project_id, 416 identity_fakes.role_name, 417 identity_fakes.app_cred_secret, 418 False, 419 ) 420 self.assertEqual(datalist, data) 421