def test_update_public_zone_no_changes(self, find_zones_mock, time_mock, client_mock): client_mock.return_value.get_hosted_zone.return_value = { 'HostedZone': { 'Id': '/hostedzone/ZONE_ID', 'Name': 'example.com.', 'Config': { 'Comment': '', 'PrivateZone': False }, }, } with self.assertRaises(AnsibleExitJson) as exec_info: set_module_args({ 'secret_key': 'SECRET_KEY', 'access_key': 'ACCESS_KEY', 'region': 'eu-central-1', 'zone': 'example.com', 'comment': '', 'state': 'present', }) route53_zone.main() client_mock.return_value.update_hosted_zone_comment.assert_not_called() self.assertEqual(exec_info.exception.args[0]['changed'], False)
def test_update_lambda_if_code_changed(): set_module_args(base_module_args) (boto3_conn_double, lambda_client_double) = make_mock_connection(code_change_lambda_config) with patch.object(lda, 'boto3_conn', boto3_conn_double): try: lda.main() except SystemExit: pass # guard against calling other than for a lambda connection (e.g. IAM) assert (len(boto3_conn_double.mock_calls) > 0), "boto connections never used" assert (len(boto3_conn_double.mock_calls) < 2), "multiple boto connections used unexpectedly" assert(len(lambda_client_double.update_function_configuration.mock_calls) == 0), \ "unexpectedly updatede lambda configuration when only code changed" assert(len(lambda_client_double.update_function_configuration.mock_calls) < 2), \ "lambda function update called multiple times when only one time should be needed" assert(len(lambda_client_double.update_function_code.mock_calls) > 1), \ "failed to update lambda function when code changed" # 3 because after uploading we call into the return from mock to try to find what function version # was returned so the MagicMock actually sees two calls for one update. assert(len(lambda_client_double.update_function_code.mock_calls) < 3), \ "lambda function code update called multiple times when only one time should be needed"
def test_update_lambda_if_added_environment_variable(): set_module_args(module_args_with_environment) (boto3_conn_double, lambda_client_double) = make_mock_connection(base_lambda_config) with patch.object(lda, 'boto3_conn', boto3_conn_double): try: lda.main() except SystemExit: pass # guard against calling other than for a lambda connection (e.g. IAM) assert (len(boto3_conn_double.mock_calls) > 0), "boto connections never used" assert (len(boto3_conn_double.mock_calls) < 2), "multiple boto connections used unexpectedly" assert(len(lambda_client_double.update_function_configuration.mock_calls) > 0), \ "failed to update lambda function when configuration changed" assert(len(lambda_client_double.update_function_configuration.mock_calls) < 2), \ "lambda function update called multiple times when only one time should be needed" assert(len(lambda_client_double.update_function_code.mock_calls) == 0), \ "updated lambda code when no change should have happened" (update_args, update_kwargs ) = lambda_client_double.update_function_configuration.call_args assert ( len(update_kwargs) > 0 ), "expected update configuration called with keyword args, none found" assert update_kwargs['Environment'][ 'Variables'] == module_args_with_environment['environment_variables']
def test_update_vpc_private_zone(self, find_zones_mock, time_mock, client_mock, check_mode, response): client_mock.return_value.get_hosted_zone.return_value = { 'HostedZone': { 'Id': '/hostedzone/ZONE_ID', 'Name': 'example.com.', 'Config': { 'Comment': 'foobar', 'PrivateZone': True }, }, 'VPCs': [{ 'VPCRegion': 'eu-central-1', 'VPCId': 'vpc-1' }], } client_mock.return_value.create_hosted_zone.return_value = { 'HostedZone': { 'Id': '/hostedzone/ZONE_ID_2', 'Name': 'example.com.', 'Config': { 'Comment': 'foobar', 'PrivateZone': True }, }, } with self.assertRaises(AnsibleExitJson) as exec_info: set_module_args({ 'secret_key': 'SECRET_KEY', 'access_key': 'ACCESS_KEY', 'region': 'us-east-2', 'zone': 'example.com', 'comment': 'foobar', 'vpc_id': 'vpc-2', 'vpc_region': 'us-east-2', 'state': 'present', '_ansible_check_mode': check_mode, }) route53_zone.main() if check_mode: client_mock.return_value.create_hosted_zone.assert_not_called() else: client_mock.return_value.create_hosted_zone.assert_called_once_with( **{ 'HostedZoneConfig': { 'Comment': 'foobar', 'PrivateZone': True, }, 'Name': 'example.com.', 'CallerReference': 'example.com.-1', 'VPC': { 'VPCRegion': 'us-east-2', 'VPCId': 'vpc-2', }, }) self.assertEqual(exec_info.exception.args[0]['changed'], True) self.assertTrue(is_subdict(response, exec_info.exception.args[0]))
def test_confirm(self, mock_client): mock_client.return_value.describe_connections.return_value = { "connections": [{ "connectionState": "ordering", "connectionId": "dxcon-fgq9rgot", "location": "EqSe2", "connectionName": "ansible-test-connection", "bandwidth": "1Gbps", "ownerAccount": "448830907657", "region": "us-west-2" }] } mock_client.return_value.confirm_connection.return_value = [{}] set_module_args({"connection_id": "dxcon-fgq9rgot"}) with self.assertRaises(AnsibleExitJson) as exec_info: aws_direct_connect_confirm_connection.main() result = exec_info.exception.args[0] assert result["changed"] is True mock_client.return_value.describe_connections.assert_has_calls([ call(connectionId="dxcon-fgq9rgot"), call(connectionId="dxcon-fgq9rgot"), call(connectionId="dxcon-fgq9rgot") ]) mock_client.return_value.confirm_connection.assert_called_once_with( connectionId="dxcon-fgq9rgot")
def test_missing_required_parameters(self, *args): set_module_args({}) with self.assertRaises(AnsibleFailJson) as exec_info: aws_direct_connect_confirm_connection.main() result = exec_info.exception.args[0] assert result["failed"] is True assert "name" in result["msg"] assert "connection_id" in result["msg"]
def test_warn_if_region_not_specified(): set_module_args({ "name": "aws_api_gateway", "state": "present", "runtime": 'python2.7', "role": 'arn:aws:iam::987654321012:role/lambda_basic_execution', "handler": 'lambda_python.my_handler' }) with pytest.raises(SystemExit): print(agw.main())
def test_missing_connection_id(self, mock_client): mock_client.return_value.describe_connections.side_effect = ClientError( {'Error': { 'Code': 'ResourceNotFoundException' }}, 'DescribeConnection') set_module_args({"connection_id": "dxcon-aaaabbbb"}) with self.assertRaises(AnsibleFailJson) as exec_info: aws_direct_connect_confirm_connection.main() result = exec_info.exception.args[0] assert result["failed"] is True mock_client.return_value.describe_connections.assert_has_calls( [call(connectionId="dxcon-aaaabbbb")])
def test_delete_absent_zone(self, find_zones_mock, time_mock, client_mock): with self.assertRaises(AnsibleExitJson) as exec_info: set_module_args({ 'secret_key': 'SECRET_KEY', 'access_key': 'ACCESS_KEY', 'region': 'eu-central-1', 'zone': 'example.com', 'state': 'absent', }) route53_zone.main() client_mock.return_value.delete_hosted_zone.assert_not_called() self.assertEqual(exec_info.exception.args[0]['changed'], False)
def test_warn_if_state_not_specified(): set_module_args({ "min_pw_length": "8", "require_symbols": "false", "require_numbers": "true", "require_uppercase": "true", "require_lowercase": "true", "allow_pw_change": "true", "pw_max_age": "60", "pw_reuse_prevent": "5", "pw_expire": "false" }) with pytest.raises(SystemExit): print(iam_password_policy.main())
def test_delete_by_zone_id(self, find_zones_mock, time_mock, client_mock, hosted_zone_id, call_params, check_mode): with self.assertRaises(AnsibleExitJson) as exec_info: set_module_args({ 'secret_key': 'SECRET_KEY', 'access_key': 'ACCESS_KEY', 'region': 'eu-central-1', 'zone': 'example.com', 'hosted_zone_id': hosted_zone_id, 'state': 'absent', '_ansible_check_mode': check_mode, }) route53_zone.main() if check_mode: client_mock.return_value.delete_hosted_zone.assert_not_called() else: client_mock.return_value.delete_hosted_zone.assert_has_calls(call_params) self.assertEqual(exec_info.exception.args[0]['changed'], True)
def test_mutually_exclusive(self, *args): with self.assertRaises(AnsibleFailJson) as exec_info: set_module_args({ 'secret_key': 'SECRET_KEY', 'access_key': 'ACCESS_KEY', 'region': 'eu-central-1', 'zone': 'example.com', 'vpc_id': 'vpc-94ccc2ff', 'vpc_region': 'eu-central-1', 'comment': 'foobar', 'delegation_set_id': 'A1BCDEF2GHIJKL', 'state': 'present', }) route53_zone.main() self.assertEqual( exec_info.exception.args[0]['msg'], 'parameters are mutually exclusive: delegation_set_id|vpc_id, delegation_set_id|vpc_region', )
def test_decryption(self, mock_connect): path = fixture_prefix + '/ec2_win_password.pem' with open(path, 'r') as f: pem = to_text(f.read()) with self.assertRaises(AnsibleExitJson) as exec_info: set_module_args({'instance_id': 'i-12345', 'key_data': pem}) module = setup_module_object() mock_connect().get_password_data.return_value = 'L2k1iFiu/TRrjGr6Rwco/T3C7xkWxUw4+YPYpGGOmP3KDdy3hT1' \ '8RvdDJ2i0e+y7wUcH43DwbRYSlkSyALY/nzjSV9R5NChUyVs3W5' \ '5oiVuyTKsk0lor8dFJ9z9unq14tScZHvyQ3Nx1ggOtS18S9Pk55q' \ 'IaCXfx26ucH76VRho=' ec2_win_password(module) self.assertEqual( exec_info.exception.args[0]['win_password'], to_bytes('Ansible_AWS_EC2_Win_Password'), )
def test_update_private_zone_no_changes(self, find_zones_mock, time_mock, client_mock): client_mock.return_value.get_hosted_zone.return_value = { 'HostedZone': { 'Id': '/hostedzone/ZONE_ID', 'Name': 'example.com.', 'Config': { 'Comment': 'foobar', 'PrivateZone': True }, }, 'VPCs': [{ 'VPCRegion': 'eu-central-1', 'VPCId': 'vpc-1' }], } with self.assertRaises(AnsibleExitJson) as exec_info: set_module_args({ 'secret_key': 'SECRET_KEY', 'access_key': 'ACCESS_KEY', 'region': 'eu-central-1', 'zone': 'example.com', 'comment': 'foobar', 'vpc_id': 'vpc-1', 'vpc_region': 'eu-central-1', 'state': 'present', }) route53_zone.main() client_mock.return_value.update_hosted_zone_comment.assert_not_called() self.assertEqual(exec_info.exception.args[0]['changed'], False) response = { 'private_zone': True, 'vpc_id': 'vpc-1', 'vpc_region': 'eu-central-1', 'comment': 'foobar', 'name': 'example.com.', 'delegation_set_id': None, 'zone_id': 'ZONE_ID', } self.assertTrue(is_subdict(response, exec_info.exception.args[0]))
def test_missing_name(self, mock_client): mock_client.return_value.describe_connections.return_value = { "connections": [{ "connectionState": "requested", "connectionId": "dxcon-fgq9rgot", "location": "EqSe2", "connectionName": "ansible-test-connection", "bandwidth": "1Gbps", "ownerAccount": "448830907657", "region": "us-west-2" }] } set_module_args({"name": "foobar"}) with self.assertRaises(AnsibleFailJson) as exec_info: aws_direct_connect_confirm_connection.main() result = exec_info.exception.args[0] assert result["failed"] is True mock_client.return_value.describe_connections.assert_has_calls( [call()])
def test_dont_update_lambda_if_nothing_changed(): set_module_args(base_module_args) (boto3_conn_double, lambda_client_double) = make_mock_connection(base_lambda_config) with patch.object(lda, 'boto3_conn', boto3_conn_double): try: lda.main() except SystemExit: pass # guard against calling other than for a lambda connection (e.g. IAM) assert (len(boto3_conn_double.mock_calls) > 0), "boto connections never used" assert (len(boto3_conn_double.mock_calls) < 2), "multiple boto connections used unexpectedly" assert(len(lambda_client_double.update_function_configuration.mock_calls) == 0), \ "updated lambda function when no configuration changed" assert(len(lambda_client_double.update_function_code.mock_calls) == 0), \ "updated lambda code when no change should have happened"
def test_add_s3_bucket_notification(self, aws_client): aws_client.return_value.get_bucket_notification_configuration.return_value = { 'LambdaFunctionConfigurations': [] } set_module_args({ 'region': 'us-east-2', 'lambda_function_arn': 'test-lambda-arn', 'bucket_name': 'test-lambda', 'event_name': 'test-id', 'events': ['s3:ObjectCreated:*', 's3:ObjectRemoved:*'], 'state': 'present', 'prefix': '/images', 'suffix': '.jpg' }) with pytest.raises(AnsibleExitJson) as context: s3_bucket_notification.main() result = context.value.args[0] assert result['changed'] is True assert aws_client.return_value.get_bucket_notification_configuration.call_count == 1 aws_client.return_value.put_bucket_notification_configuration.assert_called_with( Bucket='test-lambda', NotificationConfiguration={ 'LambdaFunctionConfigurations': [{ 'Id': 'test-id', 'LambdaFunctionArn': 'test-lambda-arn', 'Events': ['s3:ObjectCreated:*', 's3:ObjectRemoved:*'], 'Filter': { 'Key': { 'FilterRules': [{ 'Name': 'Prefix', 'Value': '/images' }, { 'Name': 'Suffix', 'Value': '.jpg' }] } } }] })
def test_upload_api(monkeypatch): class FakeConnection: def put_rest_api(self, *args, **kwargs): assert kwargs["body"] == "the-swagger-text-is-fake" return {"msg": "success!"} def return_fake_connection(*args, **kwargs): return FakeConnection() monkeypatch.setattr(core, "boto3_conn", return_fake_connection) monkeypatch.setattr(core.AnsibleAWSModule, "exit_json", fake_exit_json) set_module_args({ "api_id": "fred", "state": "present", "swagger_text": "the-swagger-text-is-fake", "region": 'mars-north-1', "_ansible_tmpdir": "/tmp/ansibl-abcdef", }) with pytest.raises(SystemExit): agw.main() assert exit_return_dict["changed"]
def test_get_by_name(self, mock_client): mock_client.return_value.describe_connections.return_value = { "connections": [{ "connectionState": "requested", "connectionId": "dxcon-fgq9rgot", "location": "EqSe2", "connectionName": "ansible-test-connection", "bandwidth": "1Gbps", "ownerAccount": "448830907657", "region": "us-west-2" }] } set_module_args({"name": "ansible-test-connection"}) with self.assertRaises(AnsibleExitJson) as exec_info: aws_direct_connect_confirm_connection.main() result = exec_info.exception.args[0] assert result["changed"] is False assert result["connection_state"] == "requested" mock_client.return_value.describe_connections.assert_has_calls( [call(), call(connectionId="dxcon-fgq9rgot")]) mock_client.return_value.confirm_connection.assert_not_called()
def test_warn_region_not_specified(): set_module_args({ "name": "lambda_name", "state": "present", # Module is called without a region causing error # "region": "us-east-1", "zip_file": "test/units/modules/fixturesthezip.zip", "runtime": 'python2.7', "role": 'arn:aws:iam::987654321012:role/lambda_basic_execution', "handler": 'lambda_python.my_handler' }) get_aws_connection_info_double = Mock(return_value=(None, None, None)) with patch.object(lda, 'get_aws_connection_info', get_aws_connection_info_double): with patch.object(basic.AnsibleModule, 'fail_json', fail_json_double): try: lda.main() except AnsibleFailJson as e: result = e.args[0] assert ("region must be specified" in result['msg'])
def test_create_lambda_if_not_exist(): set_module_args(base_module_args) (boto3_conn_double, lambda_client_double ) = make_mock_no_connection_connection(code_change_lambda_config) with patch.object(lda, 'boto3_conn', boto3_conn_double): try: lda.main() except SystemExit: pass # guard against calling other than for a lambda connection (e.g. IAM) assert (len(boto3_conn_double.mock_calls) > 0), "boto connections never used" assert (len(boto3_conn_double.mock_calls) < 2), "multiple boto connections used unexpectedly" assert(len(lambda_client_double.update_function_configuration.mock_calls) == 0), \ "unexpectedly updated lambda configuration when should have only created" assert(len(lambda_client_double.update_function_code.mock_calls) == 0), \ "update lambda function code when function should have been created only" assert(len(lambda_client_double.create_function.mock_calls) > 0), \ "failed to call create_function " (create_args, create_kwargs) = lambda_client_double.create_function.call_args assert (len(create_kwargs) > 0), "expected create called with keyword args, none found" try: # For now I assume that we should NOT send an empty environment. It might # be okay / better to explicitly send an empty environment. However `None' # is not acceptable - mikedlr create_kwargs["Environment"] raise (Exception("Environment sent to boto when none expected")) except KeyError: pass # We are happy, no environment is fine
def test_module_is_created_sensibly(): set_module_args(base_module_args) module = setup_module_object() assert module.params['function_name'] == 'this_is_a_test_function'
def test_module_fail_when_required_args_missing(self): with pytest.raises(AnsibleFailJson): set_module_args({}) s3_bucket_notification.main()