1import logging 2import random 3import string 4 5import salt.config 6import salt.loader 7import salt.modules.boto_iot as boto_iot 8from salt.utils.versions import LooseVersion 9from tests.support.mixins import LoaderModuleMockMixin 10from tests.support.mock import MagicMock, patch 11from tests.support.unit import TestCase, skipIf 12 13# pylint: disable=import-error,no-name-in-module,unused-import 14try: 15 import boto 16 import boto3 17 from botocore.exceptions import ClientError 18 from botocore import __version__ as found_botocore_version 19 20 HAS_BOTO = True 21except ImportError: 22 HAS_BOTO = False 23 24# pylint: enable=import-error,no-name-in-module,unused-import 25 26# the boto_iot module relies on the connect_to_region() method 27# which was added in boto 2.8.0 28# https://github.com/boto/boto/commit/33ac26b416fbb48a60602542b4ce15dcc7029f12 29required_boto3_version = "1.2.1" 30required_botocore_version = "1.4.41" 31 32log = logging.getLogger(__name__) 33 34 35def _has_required_boto(): 36 """ 37 Returns True/False boolean depending on if Boto is installed and correct 38 version. 39 """ 40 if not HAS_BOTO: 41 return False 42 elif LooseVersion(boto3.__version__) < LooseVersion(required_boto3_version): 43 return False 44 elif LooseVersion(found_botocore_version) < LooseVersion(required_botocore_version): 45 return False 46 else: 47 return True 48 49 50if _has_required_boto(): 51 region = "us-east-1" 52 access_key = "GKTADJGHEIQSXMKKRBJ08H" 53 secret_key = "askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs" 54 conn_parameters = { 55 "region": region, 56 "key": access_key, 57 "keyid": secret_key, 58 "profile": {}, 59 } 60 error_message = ( 61 "An error occurred (101) when calling the {0} operation: Test-defined error" 62 ) 63 not_found_error = ClientError( 64 { 65 "Error": { 66 "Code": "ResourceNotFoundException", 67 "Message": "Test-defined error", 68 } 69 }, 70 "msg", 71 ) 72 topic_rule_not_found_error = ClientError( 73 {"Error": {"Code": "UnauthorizedException", "Message": "Test-defined error"}}, 74 "msg", 75 ) 76 error_content = {"Error": {"Code": 101, "Message": "Test-defined error"}} 77 policy_ret = dict( 78 policyName="testpolicy", 79 policyDocument=( 80 '{"Version": "2012-10-17", "Statement": [{"Action": ["iot:Publish"],' 81 ' "Resource": ["*"], "Effect": "Allow"}]}' 82 ), 83 policyArn="arn:aws:iot:us-east-1:123456:policy/my_policy", 84 policyVersionId=1, 85 defaultVersionId=1, 86 ) 87 topic_rule_ret = dict( 88 ruleName="testrule", 89 sql="SELECT * FROM 'iot/test'", 90 description="topic rule description", 91 createdAt="1970-01-01", 92 actions=[{"lambda": {"functionArn": "arn:aws:::function"}}], 93 ruleDisabled=True, 94 ) 95 96 thing_type_name = "test_thing_type" 97 thing_type_desc = "test_thing_type_desc" 98 thing_type_attr_1 = "test_thing_type_search_attr_1" 99 thing_type_ret = dict( 100 thingTypeName=thing_type_name, 101 thingTypeProperties=dict( 102 thingTypeDescription=thing_type_desc, 103 searchableAttributes=[thing_type_attr_1], 104 ), 105 thingTypeMetadata=dict( 106 deprecated=False, creationDate="test_thing_type_create_date" 107 ), 108 ) 109 thing_type_arn = "test_thing_type_arn" 110 create_thing_type_ret = dict( 111 thingTypeName=thing_type_name, thingTypeArn=thing_type_arn 112 ) 113 114 115@skipIf(HAS_BOTO is False, "The boto module must be installed.") 116@skipIf( 117 _has_required_boto() is False, 118 "The boto3 module must be greater than or equal to version {}".format( 119 required_boto3_version 120 ), 121) 122class BotoIoTTestCaseBase(TestCase, LoaderModuleMockMixin): 123 conn = None 124 125 def setup_loader_modules(self): 126 self.opts = opts = salt.config.DEFAULT_MINION_OPTS.copy() 127 utils = salt.loader.utils( 128 opts, whitelist=["boto3", "args", "systemd", "path", "platform"], context={} 129 ) 130 return {boto_iot: {"__utils__": utils}} 131 132 def setUp(self): 133 super().setUp() 134 boto_iot.__init__(self.opts) 135 del self.opts 136 137 # Set up MagicMock to replace the boto3 session 138 # connections keep getting cached from prior tests, can't find the 139 # correct context object to clear it. So randomize the cache key, to prevent any 140 # cache hits 141 conn_parameters["key"] = "".join( 142 random.choice(string.ascii_lowercase + string.digits) for _ in range(50) 143 ) 144 145 self.patcher = patch("boto3.session.Session") 146 self.addCleanup(self.patcher.stop) 147 self.addCleanup(delattr, self, "patcher") 148 mock_session = self.patcher.start() 149 150 session_instance = mock_session.return_value 151 self.conn = MagicMock() 152 self.addCleanup(delattr, self, "conn") 153 session_instance.client.return_value = self.conn 154 155 156class BotoIoTTestCaseMixin: 157 pass 158 159 160class BotoIoTThingTypeTestCase(BotoIoTTestCaseBase, BotoIoTTestCaseMixin): 161 """ 162 TestCase for salt.modules.boto_iot module 163 """ 164 165 def test_that_when_checking_if_a_thing_type_exists_and_a_thing_type_exists_the_thing_type_exists_method_returns_true( 166 self, 167 ): 168 """ 169 Tests checking iot thing type existence when the iot thing type already exists 170 """ 171 self.conn.describe_thing_type.return_value = thing_type_ret 172 result = boto_iot.thing_type_exists( 173 thingTypeName=thing_type_name, **conn_parameters 174 ) 175 176 self.assertTrue(result["exists"]) 177 178 def test_that_when_checking_if_a_thing_type_exists_and_a_thing_type_does_not_exist_the_thing_type_exists_method_returns_false( 179 self, 180 ): 181 """ 182 Tests checking iot thing type existence when the iot thing type does not exist 183 """ 184 self.conn.describe_thing_type.side_effect = not_found_error 185 result = boto_iot.thing_type_exists( 186 thingTypeName="non existent thing type", **conn_parameters 187 ) 188 189 self.assertFalse(result["exists"]) 190 191 def test_that_when_checking_if_a_thing_type_exists_and_boto3_returns_an_error_the_thing_type_exists_method_returns_error( 192 self, 193 ): 194 """ 195 Tests checking iot thing type existence when boto returns an error 196 """ 197 self.conn.describe_thing_type.side_effect = ClientError( 198 error_content, "describe_thing_type" 199 ) 200 result = boto_iot.thing_type_exists( 201 thingTypeName="mythingtype", **conn_parameters 202 ) 203 204 self.assertEqual( 205 result.get("error", {}).get("message"), 206 error_message.format("describe_thing_type"), 207 ) 208 209 def test_that_when_describing_thing_type_and_thing_type_exists_the_describe_thing_type_method_returns_thing_type( 210 self, 211 ): 212 """ 213 Tests describe thing type for an existing thing type 214 """ 215 self.conn.describe_thing_type.return_value = thing_type_ret 216 result = boto_iot.describe_thing_type( 217 thingTypeName=thing_type_name, **conn_parameters 218 ) 219 220 self.assertEqual(result.get("thing_type"), thing_type_ret) 221 222 def test_that_when_describing_thing_type_and_thing_type_does_not_exists_the_describe_thing_type_method_returns_none( 223 self, 224 ): 225 """ 226 Tests describe thing type for an non existent thing type 227 """ 228 self.conn.describe_thing_type.side_effect = not_found_error 229 result = boto_iot.describe_thing_type( 230 thingTypeName="non existent thing type", **conn_parameters 231 ) 232 233 self.assertEqual(result.get("thing_type"), None) 234 235 def test_that_when_describing_thing_type_and_boto3_returns_error_an_error_the_describe_thing_type_method_returns_error( 236 self, 237 ): 238 self.conn.describe_thing_type.side_effect = ClientError( 239 error_content, "describe_thing_type" 240 ) 241 result = boto_iot.describe_thing_type( 242 thingTypeName="mythingtype", **conn_parameters 243 ) 244 245 self.assertEqual( 246 result.get("error", {}).get("message"), 247 error_message.format("describe_thing_type"), 248 ) 249 250 def test_that_when_creating_a_thing_type_succeeds_the_create_thing_type_method_returns_true( 251 self, 252 ): 253 """ 254 tests True when thing type created 255 """ 256 self.conn.create_thing_type.return_value = create_thing_type_ret 257 result = boto_iot.create_thing_type( 258 thingTypeName=thing_type_name, 259 thingTypeDescription=thing_type_desc, 260 searchableAttributesList=[thing_type_attr_1], 261 **conn_parameters 262 ) 263 self.assertTrue(result["created"]) 264 self.assertTrue(result["thingTypeArn"], thing_type_arn) 265 266 def test_that_when_creating_a_thing_type_fails_the_create_thing_type_method_returns_error( 267 self, 268 ): 269 """ 270 tests False when thing type not created 271 """ 272 self.conn.create_thing_type.side_effect = ClientError( 273 error_content, "create_thing_type" 274 ) 275 result = boto_iot.create_thing_type( 276 thingTypeName=thing_type_name, 277 thingTypeDescription=thing_type_desc, 278 searchableAttributesList=[thing_type_attr_1], 279 **conn_parameters 280 ) 281 self.assertEqual( 282 result.get("error", {}).get("message"), 283 error_message.format("create_thing_type"), 284 ) 285 286 def test_that_when_deprecating_a_thing_type_succeeds_the_deprecate_thing_type_method_returns_true( 287 self, 288 ): 289 """ 290 tests True when deprecate thing type succeeds 291 """ 292 self.conn.deprecate_thing_type.return_value = {} 293 result = boto_iot.deprecate_thing_type( 294 thingTypeName=thing_type_name, undoDeprecate=False, **conn_parameters 295 ) 296 297 self.assertTrue(result.get("deprecated")) 298 self.assertEqual(result.get("error"), None) 299 300 def test_that_when_deprecating_a_thing_type_fails_the_deprecate_thing_type_method_returns_error( 301 self, 302 ): 303 """ 304 tests False when thing type fails to deprecate 305 """ 306 self.conn.deprecate_thing_type.side_effect = ClientError( 307 error_content, "deprecate_thing_type" 308 ) 309 result = boto_iot.deprecate_thing_type( 310 thingTypeName=thing_type_name, undoDeprecate=False, **conn_parameters 311 ) 312 313 self.assertFalse(result.get("deprecated")) 314 self.assertEqual( 315 result.get("error", {}).get("message"), 316 error_message.format("deprecate_thing_type"), 317 ) 318 319 def test_that_when_deleting_a_thing_type_succeeds_the_delete_thing_type_method_returns_true( 320 self, 321 ): 322 """ 323 tests True when delete thing type succeeds 324 """ 325 self.conn.delete_thing_type.return_value = {} 326 result = boto_iot.delete_thing_type( 327 thingTypeName=thing_type_name, **conn_parameters 328 ) 329 330 self.assertTrue(result.get("deleted")) 331 self.assertEqual(result.get("error"), None) 332 333 def test_that_when_deleting_a_thing_type_fails_the_delete_thing_type_method_returns_error( 334 self, 335 ): 336 """ 337 tests False when delete thing type fails 338 """ 339 self.conn.delete_thing_type.side_effect = ClientError( 340 error_content, "delete_thing_type" 341 ) 342 result = boto_iot.delete_thing_type( 343 thingTypeName=thing_type_name, **conn_parameters 344 ) 345 self.assertFalse(result.get("deleted")) 346 self.assertEqual( 347 result.get("error", {}).get("message"), 348 error_message.format("delete_thing_type"), 349 ) 350 351 352class BotoIoTPolicyTestCase(BotoIoTTestCaseBase, BotoIoTTestCaseMixin): 353 """ 354 TestCase for salt.modules.boto_iot module 355 """ 356 357 def test_that_when_checking_if_a_policy_exists_and_a_policy_exists_the_policy_exists_method_returns_true( 358 self, 359 ): 360 """ 361 Tests checking iot policy existence when the iot policy already exists 362 """ 363 self.conn.get_policy.return_value = {"policy": policy_ret} 364 result = boto_iot.policy_exists( 365 policyName=policy_ret["policyName"], **conn_parameters 366 ) 367 368 self.assertTrue(result["exists"]) 369 370 def test_that_when_checking_if_a_policy_exists_and_a_policy_does_not_exist_the_policy_exists_method_returns_false( 371 self, 372 ): 373 """ 374 Tests checking iot policy existence when the iot policy does not exist 375 """ 376 self.conn.get_policy.side_effect = not_found_error 377 result = boto_iot.policy_exists(policyName="mypolicy", **conn_parameters) 378 379 self.assertFalse(result["exists"]) 380 381 def test_that_when_checking_if_a_policy_exists_and_boto3_returns_an_error_the_policy_exists_method_returns_error( 382 self, 383 ): 384 """ 385 Tests checking iot policy existence when boto returns an error 386 """ 387 self.conn.get_policy.side_effect = ClientError(error_content, "get_policy") 388 result = boto_iot.policy_exists(policyName="mypolicy", **conn_parameters) 389 390 self.assertEqual( 391 result.get("error", {}).get("message"), error_message.format("get_policy") 392 ) 393 394 def test_that_when_creating_a_policy_succeeds_the_create_policy_method_returns_true( 395 self, 396 ): 397 """ 398 tests True policy created. 399 """ 400 self.conn.create_policy.return_value = policy_ret 401 result = boto_iot.create_policy( 402 policyName=policy_ret["policyName"], 403 policyDocument=policy_ret["policyDocument"], 404 **conn_parameters 405 ) 406 407 self.assertTrue(result["created"]) 408 409 def test_that_when_creating_a_policy_fails_the_create_policy_method_returns_error( 410 self, 411 ): 412 """ 413 tests False policy not created. 414 """ 415 self.conn.create_policy.side_effect = ClientError( 416 error_content, "create_policy" 417 ) 418 result = boto_iot.create_policy( 419 policyName=policy_ret["policyName"], 420 policyDocument=policy_ret["policyDocument"], 421 **conn_parameters 422 ) 423 self.assertEqual( 424 result.get("error", {}).get("message"), 425 error_message.format("create_policy"), 426 ) 427 428 def test_that_when_deleting_a_policy_succeeds_the_delete_policy_method_returns_true( 429 self, 430 ): 431 """ 432 tests True policy deleted. 433 """ 434 result = boto_iot.delete_policy(policyName="testpolicy", **conn_parameters) 435 436 self.assertTrue(result["deleted"]) 437 438 def test_that_when_deleting_a_policy_fails_the_delete_policy_method_returns_false( 439 self, 440 ): 441 """ 442 tests False policy not deleted. 443 """ 444 self.conn.delete_policy.side_effect = ClientError( 445 error_content, "delete_policy" 446 ) 447 result = boto_iot.delete_policy(policyName="testpolicy", **conn_parameters) 448 self.assertFalse(result["deleted"]) 449 450 def test_that_when_describing_policy_it_returns_the_dict_of_properties_returns_true( 451 self, 452 ): 453 """ 454 Tests describing parameters if policy exists 455 """ 456 self.conn.get_policy.return_value = {"policy": policy_ret} 457 458 result = boto_iot.describe_policy( 459 policyName=policy_ret["policyName"], **conn_parameters 460 ) 461 462 self.assertTrue(result["policy"]) 463 464 def test_that_when_describing_policy_it_returns_the_dict_of_properties_returns_false( 465 self, 466 ): 467 """ 468 Tests describing parameters if policy does not exist 469 """ 470 self.conn.get_policy.side_effect = not_found_error 471 result = boto_iot.describe_policy(policyName="testpolicy", **conn_parameters) 472 473 self.assertFalse(result["policy"]) 474 475 def test_that_when_describing_policy_on_client_error_it_returns_error(self): 476 """ 477 Tests describing parameters failure 478 """ 479 self.conn.get_policy.side_effect = ClientError(error_content, "get_policy") 480 result = boto_iot.describe_policy(policyName="testpolicy", **conn_parameters) 481 self.assertTrue("error" in result) 482 483 def test_that_when_checking_if_a_policy_version_exists_and_a_policy_version_exists_the_policy_version_exists_method_returns_true( 484 self, 485 ): 486 """ 487 Tests checking iot policy existence when the iot policy version already exists 488 """ 489 self.conn.get_policy.return_value = {"policy": policy_ret} 490 result = boto_iot.policy_version_exists( 491 policyName=policy_ret["policyName"], policyVersionId=1, **conn_parameters 492 ) 493 494 self.assertTrue(result["exists"]) 495 496 def test_that_when_checking_if_a_policy_version_exists_and_a_policy_version_does_not_exist_the_policy_version_exists_method_returns_false( 497 self, 498 ): 499 """ 500 Tests checking iot policy_version existence when the iot policy_version does not exist 501 """ 502 self.conn.get_policy_version.side_effect = not_found_error 503 result = boto_iot.policy_version_exists( 504 policyName=policy_ret["policyName"], policyVersionId=1, **conn_parameters 505 ) 506 507 self.assertFalse(result["exists"]) 508 509 def test_that_when_checking_if_a_policy_version_exists_and_boto3_returns_an_error_the_policy_version_exists_method_returns_error( 510 self, 511 ): 512 """ 513 Tests checking iot policy_version existence when boto returns an error 514 """ 515 self.conn.get_policy_version.side_effect = ClientError( 516 error_content, "get_policy_version" 517 ) 518 result = boto_iot.policy_version_exists( 519 policyName=policy_ret["policyName"], policyVersionId=1, **conn_parameters 520 ) 521 522 self.assertEqual( 523 result.get("error", {}).get("message"), 524 error_message.format("get_policy_version"), 525 ) 526 527 def test_that_when_creating_a_policy_version_succeeds_the_create_policy_version_method_returns_true( 528 self, 529 ): 530 """ 531 tests True policy_version created. 532 """ 533 self.conn.create_policy_version.return_value = policy_ret 534 result = boto_iot.create_policy_version( 535 policyName=policy_ret["policyName"], 536 policyDocument=policy_ret["policyDocument"], 537 **conn_parameters 538 ) 539 540 self.assertTrue(result["created"]) 541 542 def test_that_when_creating_a_policy_version_fails_the_create_policy_version_method_returns_error( 543 self, 544 ): 545 """ 546 tests False policy_version not created. 547 """ 548 self.conn.create_policy_version.side_effect = ClientError( 549 error_content, "create_policy_version" 550 ) 551 result = boto_iot.create_policy_version( 552 policyName=policy_ret["policyName"], 553 policyDocument=policy_ret["policyDocument"], 554 **conn_parameters 555 ) 556 self.assertEqual( 557 result.get("error", {}).get("message"), 558 error_message.format("create_policy_version"), 559 ) 560 561 def test_that_when_deleting_a_policy_version_succeeds_the_delete_policy_version_method_returns_true( 562 self, 563 ): 564 """ 565 tests True policy_version deleted. 566 """ 567 result = boto_iot.delete_policy_version( 568 policyName="testpolicy", policyVersionId=1, **conn_parameters 569 ) 570 571 self.assertTrue(result["deleted"]) 572 573 def test_that_when_deleting_a_policy_version_fails_the_delete_policy_version_method_returns_false( 574 self, 575 ): 576 """ 577 tests False policy_version not deleted. 578 """ 579 self.conn.delete_policy_version.side_effect = ClientError( 580 error_content, "delete_policy_version" 581 ) 582 result = boto_iot.delete_policy_version( 583 policyName="testpolicy", policyVersionId=1, **conn_parameters 584 ) 585 self.assertFalse(result["deleted"]) 586 587 def test_that_when_describing_policy_version_it_returns_the_dict_of_properties_returns_true( 588 self, 589 ): 590 """ 591 Tests describing parameters if policy_version exists 592 """ 593 self.conn.get_policy_version.return_value = {"policy": policy_ret} 594 595 result = boto_iot.describe_policy_version( 596 policyName=policy_ret["policyName"], policyVersionId=1, **conn_parameters 597 ) 598 599 self.assertTrue(result["policy"]) 600 601 def test_that_when_describing_policy_version_it_returns_the_dict_of_properties_returns_false( 602 self, 603 ): 604 """ 605 Tests describing parameters if policy_version does not exist 606 """ 607 self.conn.get_policy_version.side_effect = not_found_error 608 result = boto_iot.describe_policy_version( 609 policyName=policy_ret["policyName"], policyVersionId=1, **conn_parameters 610 ) 611 612 self.assertFalse(result["policy"]) 613 614 def test_that_when_describing_policy_version_on_client_error_it_returns_error(self): 615 """ 616 Tests describing parameters failure 617 """ 618 self.conn.get_policy_version.side_effect = ClientError( 619 error_content, "get_policy_version" 620 ) 621 result = boto_iot.describe_policy_version( 622 policyName=policy_ret["policyName"], policyVersionId=1, **conn_parameters 623 ) 624 self.assertTrue("error" in result) 625 626 def test_that_when_listing_policies_succeeds_the_list_policies_method_returns_true( 627 self, 628 ): 629 """ 630 tests True policies listed. 631 """ 632 self.conn.list_policies.return_value = {"policies": [policy_ret]} 633 result = boto_iot.list_policies(**conn_parameters) 634 635 self.assertTrue(result["policies"]) 636 637 def test_that_when_listing_policy_fails_the_list_policy_method_returns_false(self): 638 """ 639 tests False no policy listed. 640 """ 641 self.conn.list_policies.return_value = {"policies": []} 642 result = boto_iot.list_policies(**conn_parameters) 643 self.assertFalse(result["policies"]) 644 645 def test_that_when_listing_policy_fails_the_list_policy_method_returns_error(self): 646 """ 647 tests False policy error. 648 """ 649 self.conn.list_policies.side_effect = ClientError( 650 error_content, "list_policies" 651 ) 652 result = boto_iot.list_policies(**conn_parameters) 653 self.assertEqual( 654 result.get("error", {}).get("message"), 655 error_message.format("list_policies"), 656 ) 657 658 def test_that_when_listing_policy_versions_succeeds_the_list_policy_versions_method_returns_true( 659 self, 660 ): 661 """ 662 tests True policy versions listed. 663 """ 664 self.conn.list_policy_versions.return_value = {"policyVersions": [policy_ret]} 665 result = boto_iot.list_policy_versions( 666 policyName="testpolicy", **conn_parameters 667 ) 668 669 self.assertTrue(result["policyVersions"]) 670 671 def test_that_when_listing_policy_versions_fails_the_list_policy_versions_method_returns_false( 672 self, 673 ): 674 """ 675 tests False no policy versions listed. 676 """ 677 self.conn.list_policy_versions.return_value = {"policyVersions": []} 678 result = boto_iot.list_policy_versions( 679 policyName="testpolicy", **conn_parameters 680 ) 681 self.assertFalse(result["policyVersions"]) 682 683 def test_that_when_listing_policy_versions_fails_the_list_policy_versions_method_returns_error( 684 self, 685 ): 686 """ 687 tests False policy versions error. 688 """ 689 self.conn.list_policy_versions.side_effect = ClientError( 690 error_content, "list_policy_versions" 691 ) 692 result = boto_iot.list_policy_versions( 693 policyName="testpolicy", **conn_parameters 694 ) 695 self.assertEqual( 696 result.get("error", {}).get("message"), 697 error_message.format("list_policy_versions"), 698 ) 699 700 def test_that_when_setting_default_policy_version_succeeds_the_set_default_policy_version_method_returns_true( 701 self, 702 ): 703 """ 704 tests True policy version set. 705 """ 706 result = boto_iot.set_default_policy_version( 707 policyName="testpolicy", policyVersionId=1, **conn_parameters 708 ) 709 710 self.assertTrue(result["changed"]) 711 712 def test_that_when_set_default_policy_version_fails_the_set_default_policy_version_method_returns_error( 713 self, 714 ): 715 """ 716 tests False policy version error. 717 """ 718 self.conn.set_default_policy_version.side_effect = ClientError( 719 error_content, "set_default_policy_version" 720 ) 721 result = boto_iot.set_default_policy_version( 722 policyName="testpolicy", policyVersionId=1, **conn_parameters 723 ) 724 self.assertEqual( 725 result.get("error", {}).get("message"), 726 error_message.format("set_default_policy_version"), 727 ) 728 729 def test_that_when_list_principal_policies_succeeds_the_list_principal_policies_method_returns_true( 730 self, 731 ): 732 """ 733 tests True policies listed. 734 """ 735 self.conn.list_principal_policies.return_value = {"policies": [policy_ret]} 736 result = boto_iot.list_principal_policies( 737 principal="us-east-1:GUID-GUID-GUID", **conn_parameters 738 ) 739 740 self.assertTrue(result["policies"]) 741 742 def test_that_when_list_principal_policies_fails_the_list_principal_policies_method_returns_error( 743 self, 744 ): 745 """ 746 tests False policy version error. 747 """ 748 self.conn.list_principal_policies.side_effect = ClientError( 749 error_content, "list_principal_policies" 750 ) 751 result = boto_iot.list_principal_policies( 752 principal="us-east-1:GUID-GUID-GUID", **conn_parameters 753 ) 754 self.assertEqual( 755 result.get("error", {}).get("message"), 756 error_message.format("list_principal_policies"), 757 ) 758 759 def test_that_when_attach_principal_policy_succeeds_the_attach_principal_policy_method_returns_true( 760 self, 761 ): 762 """ 763 tests True policy attached. 764 """ 765 result = boto_iot.attach_principal_policy( 766 policyName="testpolicy", 767 principal="us-east-1:GUID-GUID-GUID", 768 **conn_parameters 769 ) 770 771 self.assertTrue(result["attached"]) 772 773 def test_that_when_attach_principal_policy_version_fails_the_attach_principal_policy_version_method_returns_error( 774 self, 775 ): 776 """ 777 tests False policy version error. 778 """ 779 self.conn.attach_principal_policy.side_effect = ClientError( 780 error_content, "attach_principal_policy" 781 ) 782 result = boto_iot.attach_principal_policy( 783 policyName="testpolicy", 784 principal="us-east-1:GUID-GUID-GUID", 785 **conn_parameters 786 ) 787 self.assertEqual( 788 result.get("error", {}).get("message"), 789 error_message.format("attach_principal_policy"), 790 ) 791 792 def test_that_when_detach_principal_policy_succeeds_the_detach_principal_policy_method_returns_true( 793 self, 794 ): 795 """ 796 tests True policy detached. 797 """ 798 result = boto_iot.detach_principal_policy( 799 policyName="testpolicy", 800 principal="us-east-1:GUID-GUID-GUID", 801 **conn_parameters 802 ) 803 804 self.assertTrue(result["detached"]) 805 806 def test_that_when_detach_principal_policy_version_fails_the_detach_principal_policy_version_method_returns_error( 807 self, 808 ): 809 """ 810 tests False policy version error. 811 """ 812 self.conn.detach_principal_policy.side_effect = ClientError( 813 error_content, "detach_principal_policy" 814 ) 815 result = boto_iot.detach_principal_policy( 816 policyName="testpolicy", 817 principal="us-east-1:GUID-GUID-GUID", 818 **conn_parameters 819 ) 820 self.assertEqual( 821 result.get("error", {}).get("message"), 822 error_message.format("detach_principal_policy"), 823 ) 824 825 826@skipIf(HAS_BOTO is False, "The boto module must be installed.") 827@skipIf( 828 _has_required_boto() is False, 829 "The boto3 module must be greater than" 830 " or equal to version {}. The botocore" 831 " module must be greater than or equal to" 832 " version {}.".format(required_boto3_version, required_botocore_version), 833) 834class BotoIoTTopicRuleTestCase(BotoIoTTestCaseBase, BotoIoTTestCaseMixin): 835 """ 836 TestCase for salt.modules.boto_iot module 837 """ 838 839 def test_that_when_checking_if_a_topic_rule_exists_and_a_topic_rule_exists_the_topic_rule_exists_method_returns_true( 840 self, 841 ): 842 """ 843 Tests checking iot topic_rule existence when the iot topic_rule already exists 844 """ 845 self.conn.get_topic_rule.return_value = {"rule": topic_rule_ret} 846 result = boto_iot.topic_rule_exists( 847 ruleName=topic_rule_ret["ruleName"], **conn_parameters 848 ) 849 850 self.assertTrue(result["exists"]) 851 852 def test_that_when_checking_if_a_rule_exists_and_a_rule_does_not_exist_the_topic_rule_exists_method_returns_false( 853 self, 854 ): 855 """ 856 Tests checking iot rule existence when the iot rule does not exist 857 """ 858 self.conn.get_topic_rule.side_effect = topic_rule_not_found_error 859 result = boto_iot.topic_rule_exists(ruleName="mypolicy", **conn_parameters) 860 861 self.assertFalse(result["exists"]) 862 863 def test_that_when_checking_if_a_topic_rule_exists_and_boto3_returns_an_error_the_topic_rule_exists_method_returns_error( 864 self, 865 ): 866 """ 867 Tests checking iot topic_rule existence when boto returns an error 868 """ 869 self.conn.get_topic_rule.side_effect = ClientError( 870 error_content, "get_topic_rule" 871 ) 872 result = boto_iot.topic_rule_exists(ruleName="myrule", **conn_parameters) 873 874 self.assertEqual( 875 result.get("error", {}).get("message"), 876 error_message.format("get_topic_rule"), 877 ) 878 879 def test_that_when_creating_a_topic_rule_succeeds_the_create_topic_rule_method_returns_true( 880 self, 881 ): 882 """ 883 tests True topic_rule created. 884 """ 885 self.conn.create_topic_rule.return_value = topic_rule_ret 886 result = boto_iot.create_topic_rule( 887 ruleName=topic_rule_ret["ruleName"], 888 sql=topic_rule_ret["sql"], 889 description=topic_rule_ret["description"], 890 actions=topic_rule_ret["actions"], 891 **conn_parameters 892 ) 893 894 self.assertTrue(result["created"]) 895 896 def test_that_when_creating_a_topic_rule_fails_the_create_topic_rule_method_returns_error( 897 self, 898 ): 899 """ 900 tests False topic_rule not created. 901 """ 902 self.conn.create_topic_rule.side_effect = ClientError( 903 error_content, "create_topic_rule" 904 ) 905 result = boto_iot.create_topic_rule( 906 ruleName=topic_rule_ret["ruleName"], 907 sql=topic_rule_ret["sql"], 908 description=topic_rule_ret["description"], 909 actions=topic_rule_ret["actions"], 910 **conn_parameters 911 ) 912 self.assertEqual( 913 result.get("error", {}).get("message"), 914 error_message.format("create_topic_rule"), 915 ) 916 917 def test_that_when_replacing_a_topic_rule_succeeds_the_replace_topic_rule_method_returns_true( 918 self, 919 ): 920 """ 921 tests True topic_rule replaced. 922 """ 923 self.conn.replace_topic_rule.return_value = topic_rule_ret 924 result = boto_iot.replace_topic_rule( 925 ruleName=topic_rule_ret["ruleName"], 926 sql=topic_rule_ret["sql"], 927 description=topic_rule_ret["description"], 928 actions=topic_rule_ret["actions"], 929 **conn_parameters 930 ) 931 932 self.assertTrue(result["replaced"]) 933 934 def test_that_when_replacing_a_topic_rule_fails_the_replace_topic_rule_method_returns_error( 935 self, 936 ): 937 """ 938 tests False topic_rule not replaced. 939 """ 940 self.conn.replace_topic_rule.side_effect = ClientError( 941 error_content, "replace_topic_rule" 942 ) 943 result = boto_iot.replace_topic_rule( 944 ruleName=topic_rule_ret["ruleName"], 945 sql=topic_rule_ret["sql"], 946 description=topic_rule_ret["description"], 947 actions=topic_rule_ret["actions"], 948 **conn_parameters 949 ) 950 self.assertEqual( 951 result.get("error", {}).get("message"), 952 error_message.format("replace_topic_rule"), 953 ) 954 955 def test_that_when_deleting_a_topic_rule_succeeds_the_delete_topic_rule_method_returns_true( 956 self, 957 ): 958 """ 959 tests True topic_rule deleted. 960 """ 961 result = boto_iot.delete_topic_rule(ruleName="testrule", **conn_parameters) 962 963 self.assertTrue(result["deleted"]) 964 965 def test_that_when_deleting_a_topic_rule_fails_the_delete_topic_rule_method_returns_false( 966 self, 967 ): 968 """ 969 tests False topic_rule not deleted. 970 """ 971 self.conn.delete_topic_rule.side_effect = ClientError( 972 error_content, "delete_topic_rule" 973 ) 974 result = boto_iot.delete_topic_rule(ruleName="testrule", **conn_parameters) 975 self.assertFalse(result["deleted"]) 976 977 def test_that_when_describing_topic_rule_it_returns_the_dict_of_properties_returns_true( 978 self, 979 ): 980 """ 981 Tests describing parameters if topic_rule exists 982 """ 983 self.conn.get_topic_rule.return_value = {"rule": topic_rule_ret} 984 985 result = boto_iot.describe_topic_rule( 986 ruleName=topic_rule_ret["ruleName"], **conn_parameters 987 ) 988 989 self.assertTrue(result["rule"]) 990 991 def test_that_when_describing_topic_rule_on_client_error_it_returns_error(self): 992 """ 993 Tests describing parameters failure 994 """ 995 self.conn.get_topic_rule.side_effect = ClientError( 996 error_content, "get_topic_rule" 997 ) 998 result = boto_iot.describe_topic_rule(ruleName="testrule", **conn_parameters) 999 self.assertTrue("error" in result) 1000 1001 def test_that_when_listing_topic_rules_succeeds_the_list_topic_rules_method_returns_true( 1002 self, 1003 ): 1004 """ 1005 tests True topic_rules listed. 1006 """ 1007 self.conn.list_topic_rules.return_value = {"rules": [topic_rule_ret]} 1008 result = boto_iot.list_topic_rules(**conn_parameters) 1009 1010 self.assertTrue(result["rules"]) 1011 1012 def test_that_when_listing_topic_rules_fails_the_list_topic_rules_method_returns_error( 1013 self, 1014 ): 1015 """ 1016 tests False policy error. 1017 """ 1018 self.conn.list_topic_rules.side_effect = ClientError( 1019 error_content, "list_topic_rules" 1020 ) 1021 result = boto_iot.list_topic_rules(**conn_parameters) 1022 self.assertEqual( 1023 result.get("error", {}).get("message"), 1024 error_message.format("list_topic_rules"), 1025 ) 1026