Exemplo n.º 1
0
    def test_module_should_fail_if_validation_error_in_data(self, connection_mock):
        connection_mock.get_operation_spec.return_value = {'method': HTTPMethod.POST, 'url': '/test'}
        report = {
            'required': ['objects[0].type'],
            'invalid_type': [
                {
                    'path': 'objects[3].id',
                    'expected_type': 'string',
                    'actually_value': 1
                }
            ]
        }
        connection_mock.validate_data.return_value = (False, json.dumps(report, sort_keys=True, indent=4))

        with pytest.raises(ValidationError) as e_info:
            resource = BaseConfigurationResource(connection_mock, False)
            resource.crud_operation('addTest', {'data': {}})

        result = e_info.value.args[0]
        key = 'Invalid data provided'
        assert result[key]
        result[key] = json.loads(result[key])
        assert result == {key: {
            'invalid_type': [{'actually_value': 1, 'expected_type': 'string', 'path': 'objects[3].id'}],
            'required': ['objects[0].type']
        }}
Exemplo n.º 2
0
    def _resource_execute_operation(params, connection):
        resource = BaseConfigurationResource(connection)
        op_name = params['operation']

        resp = resource.execute_operation(op_name, params)

        return resp
def main():
    fields = dict(
        operation=dict(type='str', required=True),
        data=dict(type='dict'),
        query_params=dict(type='dict'),
        path_params=dict(type='dict'),
        register_as=dict(type='str'),
        filters=dict(type='dict')
    )
    module = AnsibleModule(argument_spec=fields,
                           supports_check_mode=True)
    params = module.params

    connection = Connection(module._socket_path)
    resource = BaseConfigurationResource(connection, module.check_mode)
    op_name = params['operation']
    try:
        resp = resource.execute_operation(op_name, params)
        module.exit_json(changed=resource.config_changed, response=resp,
                         ansible_facts=construct_ansible_facts(resp, module.params))
    except FtdInvalidOperationNameError as e:
        module.fail_json(msg='Invalid operation name provided: %s' % e.operation_name)
    except FtdConfigurationError as e:
        module.fail_json(msg='Failed to execute %s operation because of the configuration error: %s' % (op_name, e.msg))
    except FtdServerError as e:
        module.fail_json(msg='Server returned an error trying to execute %s operation. Status code: %s. '
                             'Server response: %s' % (op_name, e.code, e.response))
    except FtdUnexpectedResponse as e:
        module.fail_json(msg=e.args[0])
    except ValidationError as e:
        module.fail_json(msg=e.args[0])
    except CheckModeException:
        module.exit_json(changed=False)
Exemplo n.º 4
0
    def test_get_objects_by_filter_with_multiple_responses(
            self, send_request_mock):
        send_request_mock.side_effect = [{
            'items': [{
                'name': 'obj1',
                'type': 'foo'
            }, {
                'name': 'obj2',
                'type': 'bar'
            }]
        }, {
            'items': [{
                'name': 'obj3',
                'type': 'foo'
            }]
        }, {
            'items': []
        }]

        resource = BaseConfigurationResource(None)

        assert [{
            'name': 'obj1',
            'type': 'foo'
        }, {
            'name': 'obj3',
            'type': 'foo'
        }] == resource.get_objects_by_filter('/objects', {'type': 'foo'})
 def setUp(self, fetch_system_info_mock):
     self._conn = mock.MagicMock()
     self._resource = BaseConfigurationResource(self._conn)
     fetch_system_info_mock.return_value = {
         'databaseInfo': {
             'buildVersion': '6.3.0'
         }
     }
    def test_get_objects_by_filter_with_multiple_responses(self, send_request_mock, fetch_system_info_mock,
                                                           connection_mock):
        send_request_mock.side_effect = [
            {'items': [
                {'name': 'obj1', 'type': 'foo'},
                {'name': 'obj2', 'type': 'bar'}
            ]},
            {'items': [
                {'name': 'obj3', 'type': 'foo'}
            ]},
            {'items': []}
        ]
        fetch_system_info_mock.return_value = {
            'databaseInfo': {
                'buildVersion': '6.3.0'
            }
        }
        connection_mock.get_operation_spec.return_value = {
            'method': HTTPMethod.GET,
            'url': '/object/'
        }
        resource = BaseConfigurationResource(connection_mock, False)
        assert [{'name': 'obj1', 'type': 'foo'}] == list(resource.get_objects_by_filter(
            'test',
            {ParamName.FILTERS: {'type': 'foo'}}))
        send_request_mock.assert_has_calls(
            [
                mock.call('/object/', 'get', {}, {}, {'limit': 10, 'offset': 0})
            ]
        )

        send_request_mock.reset_mock()
        send_request_mock.side_effect = [
            {'items': [
                {'name': 'obj1', 'type': 'foo'},
                {'name': 'obj2', 'type': 'bar'}
            ]},
            {'items': [
                {'name': 'obj3', 'type': 'foo'}
            ]},
            {'items': []}
        ]
        resp = list(resource.get_objects_by_filter(
            'test',
            {
                ParamName.FILTERS: {'type': 'foo'},
                ParamName.QUERY_PARAMS: {'limit': 2}
            }))
        assert [{'name': 'obj1', 'type': 'foo'}, {'name': 'obj3', 'type': 'foo'}] == resp
        send_request_mock.assert_has_calls(
            [
                mock.call('/object/', 'get', {}, {}, {'limit': 2, 'offset': 0}),
                mock.call('/object/', 'get', {}, {}, {'limit': 2, 'offset': 2})
            ]
        )
    def test_get_objects_by_filter_with_multiple_filters(self, send_request_mock, fetch_system_info_mock,
                                                         connection_mock):
        objects = [
            {'name': 'obj1', 'type': 1, 'foo': {'bar': 'buzz'}},
            {'name': 'obj2', 'type': 1, 'foo': {'bar': 'buz'}},
            {'name': 'obj3', 'type': 2, 'foo': {'bar': 'buzz'}}
        ]

        fetch_system_info_mock.return_value = {
            'databaseInfo': {
                'buildVersion': '6.3.0'
            }
        }

        connection_mock.get_operation_spec.return_value = {
            'method': HTTPMethod.GET,
            'url': '/object/'
        }
        resource = BaseConfigurationResource(connection_mock, False)

        send_request_mock.side_effect = [{'items': objects}, {'items': []}]
        # resource.get_objects_by_filter returns generator so to be able compare generated list with expected list
        # we need evaluate it.
        assert objects == list(resource.get_objects_by_filter('test', {}))
        send_request_mock.assert_has_calls(
            [
                mock.call('/object/', 'get', {}, {}, {'limit': 10, 'offset': 0})
            ]
        )

        send_request_mock.reset_mock()
        send_request_mock.side_effect = [{'items': objects}, {'items': []}]
        # resource.get_objects_by_filter returns generator so to be able compare generated list with expected list
        # we need evaluate it.
        assert [objects[0]] == list(resource.get_objects_by_filter('test', {ParamName.FILTERS: {'name': 'obj1'}}))
        send_request_mock.assert_has_calls(
            [
                mock.call('/object/', 'get', {}, {}, {QueryParams.FILTER: 'name:obj1', 'limit': 10, 'offset': 0})
            ]
        )

        send_request_mock.reset_mock()
        send_request_mock.side_effect = [{'items': objects}, {'items': []}]
        # resource.get_objects_by_filter returns generator so to be able compare generated list with expected list
        # we need evaluate it.
        assert [objects[1]] == list(resource.get_objects_by_filter(
            'test',
            {ParamName.FILTERS: {'name': 'obj2', 'type': 1, 'foo': {'bar': 'buz'}}}))

        send_request_mock.assert_has_calls(
            [
                mock.call('/object/', 'get', {}, {}, {QueryParams.FILTER: 'name:obj2', 'limit': 10, 'offset': 0})
            ]
        )
    def test_stringify_name_filter(self, test_api_version, expected_result, connection_mock):
        filters = {"name": "object_name"}

        with patch.object(BaseConfigurationResource, '_fetch_system_info') as fetch_system_info_mock:
            fetch_system_info_mock.return_value = {
                'databaseInfo': {
                    'buildVersion': test_api_version
                }
            }
            resource = BaseConfigurationResource(connection_mock, False)

            assert resource._stringify_name_filter(filters) == expected_result, "Unexpected result for version %s" % (
                test_api_version)
Exemplo n.º 9
0
    def _resource_execute_operation(params, connection):

        with mock.patch.object(BaseConfigurationResource, '_fetch_system_info') as fetch_system_info_mock:
            fetch_system_info_mock.return_value = {
                'databaseInfo': {
                    'buildVersion': '6.3.0'
                }
            }
            resource = BaseConfigurationResource(connection)
            op_name = params['operation']

            resp = resource.execute_operation(op_name, params)

        return resp
Exemplo n.º 10
0
def main():
    fields = dict(device_hostname=dict(type='str', required=True),
                  device_username=dict(type='str',
                                       required=False,
                                       default='admin'),
                  device_password=dict(type='str', required=True, no_log=True),
                  device_sudo_password=dict(type='str',
                                            required=False,
                                            no_log=True),
                  device_new_password=dict(type='str',
                                           required=False,
                                           no_log=True),
                  device_ip=dict(type='str', required=False),
                  device_netmask=dict(type='str', required=False),
                  device_gateway=dict(type='str', required=False),
                  device_model=dict(type='str',
                                    required=False,
                                    choices=FtdModel.supported_models()),
                  dns_server=dict(type='str', required=False),
                  search_domains=dict(type='str',
                                      required=False,
                                      default='cisco.com'),
                  console_ip=dict(type='str', required=True),
                  console_port=dict(type='str', required=True),
                  console_username=dict(type='str', required=True),
                  console_password=dict(type='str', required=True,
                                        no_log=True),
                  rommon_file_location=dict(type='str', required=True),
                  image_file_location=dict(type='str', required=True),
                  image_version=dict(type='str', required=True),
                  force_install=dict(type='bool',
                                     required=False,
                                     default=False))
    module = AnsibleModule(argument_spec=fields)
    assert_kick_is_installed(module)

    use_local_connection = module._socket_path is None
    if use_local_connection:
        check_required_params_for_local_connection(module, module.params)
        platform_model = module.params['device_model']
        check_that_model_is_supported(module, platform_model)
    else:
        connection = Connection(module._socket_path)
        resource = BaseConfigurationResource(connection, module.check_mode)
        system_info = get_system_info(resource)

        platform_model = module.params['device_model'] or system_info[
            'platformModel']
        check_that_model_is_supported(module, platform_model)
        check_that_update_is_needed(module, system_info)
        check_management_and_dns_params(resource, module.params)

    ftd_platform = FtdPlatformFactory.create(platform_model, module.params)
    ftd_platform.install_ftd_image(module.params)

    module.exit_json(
        changed=True,
        msg='Successfully installed FTD image %s on the firewall device.' %
        module.params["image_version"])
Exemplo n.º 11
0
    def test_get_objects_by_filter_with_multiple_filters(self, send_request_mock):
        objects = [
            {'name': 'obj1', 'type': 1, 'foo': {'bar': 'buzz'}},
            {'name': 'obj2', 'type': 1, 'foo': {'bar': 'buz'}},
            {'name': 'obj3', 'type': 2, 'foo': {'bar': 'buzz'}}
        ]
        resource = BaseConfigurationResource(None)

        send_request_mock.side_effect = [{'items': objects}, {'items': []}]
        assert objects == resource.get_objects_by_filter('/objects', {})

        send_request_mock.side_effect = [{'items': objects}, {'items': []}]
        assert [objects[0]] == resource.get_objects_by_filter('/objects', {'name': 'obj1'})

        send_request_mock.side_effect = [{'items': objects}, {'items': []}]
        assert [objects[1]] == resource.get_objects_by_filter('/objects',
                                                              {'type': 1, 'foo': {'bar': 'buz'}})
Exemplo n.º 12
0
def main():
    fields = dict(operation=dict(type='str', required=True),
                  data=dict(type='dict'),
                  query_params=dict(type='dict'),
                  path_params=dict(type='dict'),
                  register_as=dict(type='str'),
                  filters=dict(type='dict'))
    module = AnsibleModule(argument_spec=fields, supports_check_mode=True)
    params = module.params

    connection = Connection(module._socket_path)

    op_name = params['operation']
    op_spec = connection.get_operation_spec(op_name)
    if op_spec is None:
        module.fail_json(msg='Invalid operation name provided: %s' % op_name)

    data, query_params, path_params = params['data'], params[
        'query_params'], params['path_params']

    try:
        validate_params(connection, op_name, query_params, path_params, data,
                        op_spec)
    except ValidationError as e:
        module.fail_json(msg=e.args[0])

    try:
        if module.check_mode:
            module.exit_json(changed=False)

        resource = BaseConfigurationResource(connection)
        url = op_spec[OperationField.URL]

        if is_add_operation(op_name, op_spec):
            resp = resource.add_object(url, data, path_params, query_params)
        elif is_edit_operation(op_name, op_spec):
            resp = resource.edit_object(url, data, path_params, query_params)
        elif is_delete_operation(op_name, op_spec):
            resp = resource.delete_object(url, path_params)
        elif is_find_by_filter_operation(op_name, op_spec, params):
            resp = resource.get_objects_by_filter(url, params['filters'],
                                                  path_params, query_params)
        else:
            resp = resource.send_request(url, op_spec[OperationField.METHOD],
                                         data, path_params, query_params)

        module.exit_json(changed=resource.config_changed,
                         response=resp,
                         ansible_facts=construct_ansible_facts(
                             resp, module.params))
    except FtdConfigurationError as e:
        module.fail_json(
            msg=
            'Failed to execute %s operation because of the configuration error: %s'
            % (op_name, e))
    except FtdServerError as e:
        module.fail_json(
            msg=
            'Server returned an error trying to execute %s operation. Status code: %s. '
            'Server response: %s' % (op_name, e.code, e.response))
Exemplo n.º 13
0
    def test_module_should_fail_if_validation_error_in_all_params(
            self, connection_mock):
        connection_mock.get_operation_spec.return_value = {
            'method': HTTPMethod.POST,
            'url': '/test'
        }
        report = {
            'data': {
                'required': ['objects[0].type'],
                'invalid_type': [{
                    'path': 'objects[3].id',
                    'expected_type': 'string',
                    'actually_value': 1
                }]
            },
            'path_params': {
                'required': ['some_param'],
                'invalid_type': [{
                    'path': 'name',
                    'expected_type': 'string',
                    'actually_value': True
                }]
            },
            'query_params': {
                'required': ['other_param'],
                'invalid_type': [{
                    'path': 'f_integer',
                    'expected_type': 'integer',
                    'actually_value': "test"
                }]
            }
        }
        connection_mock.validate_data.return_value = (False,
                                                      json.dumps(
                                                          report['data'],
                                                          sort_keys=True,
                                                          indent=4))
        connection_mock.validate_query_params.return_value = (
            False, json.dumps(report['query_params'], sort_keys=True,
                              indent=4))
        connection_mock.validate_path_params.return_value = (
            False, json.dumps(report['path_params'], sort_keys=True, indent=4))

        with pytest.raises(ValidationError) as e_info:
            resource = BaseConfigurationResource(connection_mock, False)
            resource.crud_operation('putTest', {'data': {}})

        result = e_info.value.args[0]

        key_data = 'Invalid data provided'
        assert result[key_data]
        result[key_data] = json.loads(result[key_data])

        key_path_params = 'Invalid path_params provided'
        assert result[key_path_params]
        result[key_path_params] = json.loads(result[key_path_params])

        key_query_params = 'Invalid query_params provided'
        assert result[key_query_params]
        result[key_query_params] = json.loads(result[key_query_params])

        assert result == {
            key_data: {
                'invalid_type': [{
                    'actually_value': 1,
                    'expected_type': 'string',
                    'path': 'objects[3].id'
                }],
                'required': ['objects[0].type']
            },
            key_path_params: {
                'invalid_type': [{
                    'actually_value': True,
                    'expected_type': 'string',
                    'path': 'name'
                }],
                'required': ['some_param']
            },
            key_query_params: {
                'invalid_type': [{
                    'actually_value': 'test',
                    'expected_type': 'integer',
                    'path': 'f_integer'
                }],
                'required': ['other_param']
            }
        }
Exemplo n.º 14
0
 def setUp(self):
     self._conn = mock.MagicMock()
     self._resource = BaseConfigurationResource(self._conn)
Exemplo n.º 15
0
class TestUpsertOperationUnitTests(unittest.TestCase):
    def setUp(self):
        self._conn = mock.MagicMock()
        self._resource = BaseConfigurationResource(self._conn)

    def test_get_operation_name(self):
        operation_a = mock.MagicMock()
        operation_b = mock.MagicMock()

        def checker_wrapper(expected_object):
            def checker(obj, *args, **kwargs):
                return obj == expected_object

            return checker

        operations = {
            operation_a: "spec",
            operation_b: "spec"
        }

        assert operation_a == self._resource._get_operation_name(checker_wrapper(operation_a), operations)
        assert operation_b == self._resource._get_operation_name(checker_wrapper(operation_b), operations)
        assert self._resource._get_operation_name(checker_wrapper(None), operations) is None

    @mock.patch.object(BaseConfigurationResource, "_get_operation_name")
    @mock.patch.object(BaseConfigurationResource, "add_object")
    def test_add_upserted_object(self, add_object_mock, get_operation_mock):
        model_operations = mock.MagicMock()
        params = mock.MagicMock()
        add_op_name = get_operation_mock.return_value

        assert add_object_mock.return_value == self._resource._add_upserted_object(model_operations, params)

        get_operation_mock.assert_called_once_with(
            self._resource._operation_checker.is_add_operation,
            model_operations)
        add_object_mock.assert_called_once_with(add_op_name, params)

    @mock.patch.object(BaseConfigurationResource, "_get_operation_name")
    @mock.patch.object(BaseConfigurationResource, "add_object")
    def test_add_upserted_object_with_no_add_operation(self, add_object_mock, get_operation_mock):
        model_operations = mock.MagicMock()
        get_operation_mock.return_value = None

        with pytest.raises(FtdConfigurationError) as exc_info:
            self._resource._add_upserted_object(model_operations, mock.MagicMock())
        assert ADD_OPERATION_NOT_SUPPORTED_ERROR in str(exc_info.value)

        get_operation_mock.assert_called_once_with(self._resource._operation_checker.is_add_operation, model_operations)
        add_object_mock.assert_not_called()

    @mock.patch.object(BaseConfigurationResource, "_get_operation_name")
    @mock.patch.object(BaseConfigurationResource, "edit_object")
    @mock.patch("ansible.module_utils.network.ftd.configuration.copy_identity_properties")
    @mock.patch("ansible.module_utils.network.ftd.configuration._set_default")
    def test_edit_upserted_object(self, _set_default_mock, copy_properties_mock, edit_object_mock, get_operation_mock):
        model_operations = mock.MagicMock()
        existing_object = mock.MagicMock()
        params = {
            'path_params': {},
            'data': {}
        }

        result = self._resource._edit_upserted_object(model_operations, existing_object, params)

        assert result == edit_object_mock.return_value

        _set_default_mock.assert_has_calls([
            mock.call(params, 'path_params', {}),
            mock.call(params, 'data', {})
        ])
        get_operation_mock.assert_called_once_with(
            self._resource._operation_checker.is_edit_operation,
            model_operations
        )
        copy_properties_mock.assert_called_once_with(
            existing_object,
            params['data']
        )
        edit_object_mock.assert_called_once_with(
            get_operation_mock.return_value,
            params
        )

    @mock.patch("ansible.module_utils.network.ftd.configuration.OperationChecker.is_upsert_operation_supported")
    @mock.patch.object(BaseConfigurationResource, "get_operation_specs_by_model_name")
    @mock.patch.object(BaseConfigurationResource, "_find_object_matching_params")
    @mock.patch.object(BaseConfigurationResource, "_add_upserted_object")
    @mock.patch.object(BaseConfigurationResource, "_edit_upserted_object")
    def test_upsert_object_successfully_added(self, edit_mock, add_mock, find_object, get_operation_mock,
                                              is_upsert_supported_mock):
        params = mock.MagicMock()

        is_upsert_supported_mock.return_value = True
        find_object.return_value = None

        result = self._resource.upsert_object('upsertFoo', params)

        assert result == add_mock.return_value
        self._conn.get_model_spec.assert_called_once_with('Foo')
        is_upsert_supported_mock.assert_called_once_with(get_operation_mock.return_value)
        get_operation_mock.assert_called_once_with('Foo')
        find_object.assert_called_once_with('Foo', params)
        add_mock.assert_called_once_with(get_operation_mock.return_value, params)
        edit_mock.assert_not_called()

    @mock.patch("ansible.module_utils.network.ftd.configuration.equal_objects")
    @mock.patch("ansible.module_utils.network.ftd.configuration.OperationChecker.is_upsert_operation_supported")
    @mock.patch.object(BaseConfigurationResource, "get_operation_specs_by_model_name")
    @mock.patch.object(BaseConfigurationResource, "_find_object_matching_params")
    @mock.patch.object(BaseConfigurationResource, "_add_upserted_object")
    @mock.patch.object(BaseConfigurationResource, "_edit_upserted_object")
    def test_upsert_object_successfully_edited(self, edit_mock, add_mock, find_object, get_operation_mock,
                                               is_upsert_supported_mock, equal_objects_mock):
        params = mock.MagicMock()
        existing_obj = mock.MagicMock()

        is_upsert_supported_mock.return_value = True
        find_object.return_value = existing_obj
        equal_objects_mock.return_value = False

        result = self._resource.upsert_object('upsertFoo', params)

        assert result == edit_mock.return_value
        self._conn.get_model_spec.assert_called_once_with('Foo')
        get_operation_mock.assert_called_once_with('Foo')
        is_upsert_supported_mock.assert_called_once_with(get_operation_mock.return_value)
        add_mock.assert_not_called()
        equal_objects_mock.assert_called_once_with(existing_obj, params[ParamName.DATA])
        edit_mock.assert_called_once_with(get_operation_mock.return_value, existing_obj, params)

    @mock.patch("ansible.module_utils.network.ftd.configuration.equal_objects")
    @mock.patch("ansible.module_utils.network.ftd.configuration.OperationChecker.is_upsert_operation_supported")
    @mock.patch.object(BaseConfigurationResource, "get_operation_specs_by_model_name")
    @mock.patch.object(BaseConfigurationResource, "_find_object_matching_params")
    @mock.patch.object(BaseConfigurationResource, "_add_upserted_object")
    @mock.patch.object(BaseConfigurationResource, "_edit_upserted_object")
    def test_upsert_object_returned_without_modifications(self, edit_mock, add_mock, find_object, get_operation_mock,
                                                          is_upsert_supported_mock, equal_objects_mock):
        params = mock.MagicMock()
        existing_obj = mock.MagicMock()

        is_upsert_supported_mock.return_value = True
        find_object.return_value = existing_obj
        equal_objects_mock.return_value = True

        result = self._resource.upsert_object('upsertFoo', params)

        assert result == existing_obj
        self._conn.get_model_spec.assert_called_once_with('Foo')
        get_operation_mock.assert_called_once_with('Foo')
        is_upsert_supported_mock.assert_called_once_with(get_operation_mock.return_value)
        add_mock.assert_not_called()
        equal_objects_mock.assert_called_once_with(existing_obj, params[ParamName.DATA])
        edit_mock.assert_not_called()

    @mock.patch("ansible.module_utils.network.ftd.configuration.OperationChecker.is_upsert_operation_supported")
    @mock.patch.object(BaseConfigurationResource, "get_operation_specs_by_model_name")
    @mock.patch.object(BaseConfigurationResource, "_find_object_matching_params")
    @mock.patch.object(BaseConfigurationResource, "_add_upserted_object")
    @mock.patch.object(BaseConfigurationResource, "_edit_upserted_object")
    def test_upsert_object_not_supported(self, edit_mock, add_mock, find_object, get_operation_mock,
                                         is_upsert_supported_mock):
        params = mock.MagicMock()

        is_upsert_supported_mock.return_value = False

        self.assertRaises(
            FtdInvalidOperationNameError,
            self._resource.upsert_object, 'upsertFoo', params
        )

        self._conn.get_model_spec.assert_called_once_with('Foo')
        get_operation_mock.assert_called_once_with('Foo')
        is_upsert_supported_mock.assert_called_once_with(get_operation_mock.return_value)
        find_object.assert_not_called()
        add_mock.assert_not_called()
        edit_mock.assert_not_called()

    @mock.patch("ansible.module_utils.network.ftd.configuration.OperationChecker.is_upsert_operation_supported")
    @mock.patch.object(BaseConfigurationResource, "get_operation_specs_by_model_name")
    @mock.patch.object(BaseConfigurationResource, "_find_object_matching_params")
    @mock.patch.object(BaseConfigurationResource, "_add_upserted_object")
    @mock.patch.object(BaseConfigurationResource, "_edit_upserted_object")
    def test_upsert_object_when_model_not_supported(self, edit_mock, add_mock, find_object, get_operation_mock,
                                                    is_upsert_supported_mock):
        params = mock.MagicMock()
        self._conn.get_model_spec.return_value = None

        self.assertRaises(
            FtdInvalidOperationNameError,
            self._resource.upsert_object, 'upsertNonExisting', params
        )

        self._conn.get_model_spec.assert_called_once_with('NonExisting')
        get_operation_mock.assert_not_called()
        is_upsert_supported_mock.assert_not_called()
        find_object.assert_not_called()
        add_mock.assert_not_called()
        edit_mock.assert_not_called()

    @mock.patch("ansible.module_utils.network.ftd.configuration.equal_objects")
    @mock.patch("ansible.module_utils.network.ftd.configuration.OperationChecker.is_upsert_operation_supported")
    @mock.patch.object(BaseConfigurationResource, "get_operation_specs_by_model_name")
    @mock.patch.object(BaseConfigurationResource, "_find_object_matching_params")
    @mock.patch.object(BaseConfigurationResource, "_add_upserted_object")
    @mock.patch.object(BaseConfigurationResource, "_edit_upserted_object")
    def test_upsert_object_with_fatal_error_during_edit(self, edit_mock, add_mock, find_object, get_operation_mock,
                                                        is_upsert_supported_mock, equal_objects_mock):
        params = mock.MagicMock()
        existing_obj = mock.MagicMock()

        is_upsert_supported_mock.return_value = True
        find_object.return_value = existing_obj
        equal_objects_mock.return_value = False
        edit_mock.side_effect = FtdConfigurationError("Some object edit error")

        self.assertRaises(
            FtdConfigurationError,
            self._resource.upsert_object, 'upsertFoo', params
        )

        is_upsert_supported_mock.assert_called_once_with(get_operation_mock.return_value)
        self._conn.get_model_spec.assert_called_once_with('Foo')
        get_operation_mock.assert_called_once_with('Foo')
        find_object.assert_called_once_with('Foo', params)
        add_mock.assert_not_called()
        edit_mock.assert_called_once_with(get_operation_mock.return_value, existing_obj, params)

    @mock.patch("ansible.module_utils.network.ftd.configuration.OperationChecker.is_upsert_operation_supported")
    @mock.patch.object(BaseConfigurationResource, "get_operation_specs_by_model_name")
    @mock.patch.object(BaseConfigurationResource, "_find_object_matching_params")
    @mock.patch.object(BaseConfigurationResource, "_add_upserted_object")
    @mock.patch.object(BaseConfigurationResource, "_edit_upserted_object")
    def test_upsert_object_with_fatal_error_during_add(self, edit_mock, add_mock, find_object, get_operation_mock,
                                                       is_upsert_supported_mock):
        params = mock.MagicMock()

        is_upsert_supported_mock.return_value = True
        find_object.return_value = None

        error = FtdConfigurationError("Obj duplication error")
        add_mock.side_effect = error

        self.assertRaises(
            FtdConfigurationError,
            self._resource.upsert_object, 'upsertFoo', params
        )

        is_upsert_supported_mock.assert_called_once_with(get_operation_mock.return_value)
        self._conn.get_model_spec.assert_called_once_with('Foo')
        get_operation_mock.assert_called_once_with('Foo')
        find_object.assert_called_once_with('Foo', params)
        add_mock.assert_called_once_with(get_operation_mock.return_value, params)
        edit_mock.assert_not_called()
Exemplo n.º 16
0
class TestUpsertOperationUnitTests(unittest.TestCase):
    def setUp(self):
        conn = mock.MagicMock()
        self._resource = BaseConfigurationResource(conn)

    def test_get_operation_name(self):
        operation_a = mock.MagicMock()
        operation_b = mock.MagicMock()

        def checker_wrapper(expected_object):
            def checker(obj, *args, **kwargs):
                return obj == expected_object

            return checker

        operations = {
            operation_a: "spec",
            operation_b: "spec"
        }

        assert operation_a == self._resource._get_operation_name(checker_wrapper(operation_a), operations)
        assert operation_b == self._resource._get_operation_name(checker_wrapper(operation_b), operations)

        self.assertRaises(
            FtdConfigurationError,
            self._resource._get_operation_name, checker_wrapper(None), operations
        )

    @mock.patch.object(BaseConfigurationResource, "_get_operation_name")
    @mock.patch.object(BaseConfigurationResource, "add_object")
    def test_add_upserted_object(self, add_object_mock, get_operation_mock):
        model_operations = mock.MagicMock()
        params = mock.MagicMock()
        add_op_name = get_operation_mock.return_value

        assert add_object_mock.return_value == self._resource._add_upserted_object(model_operations, params)

        get_operation_mock.assert_called_once_with(
            self._resource._operation_checker.is_add_operation,
            model_operations)
        add_object_mock.assert_called_once_with(add_op_name, params)

    @mock.patch.object(BaseConfigurationResource, "_get_operation_name")
    @mock.patch.object(BaseConfigurationResource, "edit_object")
    @mock.patch("ansible.module_utils.network.ftd.configuration.copy_identity_properties")
    @mock.patch("ansible.module_utils.network.ftd.configuration._set_default")
    def test_edit_upserted_object(self, _set_default_mock, copy_properties_mock, edit_object_mock, get_operation_mock):
        model_operations = mock.MagicMock()
        existing_object = mock.MagicMock()
        params = {
            'path_params': {},
            'data': {}
        }

        result = self._resource._edit_upserted_object(model_operations, existing_object, params)

        assert result == edit_object_mock.return_value

        _set_default_mock.assert_has_calls([
            mock.call(params, 'path_params', {}),
            mock.call(params, 'data', {})
        ])
        get_operation_mock.assert_called_once_with(
            self._resource._operation_checker.is_edit_operation,
            model_operations
        )
        copy_properties_mock.assert_called_once_with(
            existing_object,
            params['data']
        )
        edit_object_mock.assert_called_once_with(
            get_operation_mock.return_value,
            params
        )

    @mock.patch.object(BaseConfigurationResource, "get_operation_specs_by_model_name")
    @mock.patch("ansible.module_utils.network.ftd.configuration.OperationChecker.is_upsert_operation_supported")
    @mock.patch("ansible.module_utils.network.ftd.configuration._extract_model_from_upsert_operation")
    def test_is_upsert_operation_supported(self, extract_model_mock, is_upsert_supported_mock, get_operation_spec_mock):
        op_name = mock.MagicMock()

        result = self._resource.is_upsert_operation_supported(op_name)

        assert result == is_upsert_supported_mock.return_value
        extract_model_mock.assert_called_once_with(op_name)
        get_operation_spec_mock.assert_called_once_with(extract_model_mock.return_value)
        is_upsert_supported_mock.assert_called_once_with(get_operation_spec_mock.return_value)

    @mock.patch.object(BaseConfigurationResource, "is_upsert_operation_supported")
    @mock.patch.object(BaseConfigurationResource, "get_operation_specs_by_model_name")
    @mock.patch.object(BaseConfigurationResource, "_add_upserted_object")
    @mock.patch.object(BaseConfigurationResource, "_edit_upserted_object")
    @mock.patch("ansible.module_utils.network.ftd.configuration._extract_model_from_upsert_operation")
    def test_upsert_object_succesfully_added(self, extract_model_mock, edit_mock, add_mock, get_operation_mock,
                                             is_upsert_supported_mock):
        op_name = mock.MagicMock()
        params = mock.MagicMock()

        is_upsert_supported_mock.return_value = True

        result = self._resource.upsert_object(op_name, params)

        assert result == add_mock.return_value
        is_upsert_supported_mock.assert_called_once_with(op_name)
        extract_model_mock.assert_called_once_with(op_name)
        get_operation_mock.assert_called_once_with(extract_model_mock.return_value)
        add_mock.assert_called_once_with(get_operation_mock.return_value, params)
        edit_mock.assert_not_called()

    @mock.patch.object(BaseConfigurationResource, "is_upsert_operation_supported")
    @mock.patch.object(BaseConfigurationResource, "get_operation_specs_by_model_name")
    @mock.patch.object(BaseConfigurationResource, "_add_upserted_object")
    @mock.patch.object(BaseConfigurationResource, "_edit_upserted_object")
    @mock.patch("ansible.module_utils.network.ftd.configuration._extract_model_from_upsert_operation")
    def test_upsert_object_succesfully_edited(self, extract_model_mock, edit_mock, add_mock, get_operation_mock,
                                              is_upsert_supported_mock):
        op_name = mock.MagicMock()
        params = mock.MagicMock()

        is_upsert_supported_mock.return_value = True
        error = FtdConfigurationError("Obj duplication error")
        error.obj = mock.MagicMock()

        add_mock.side_effect = error

        result = self._resource.upsert_object(op_name, params)

        assert result == edit_mock.return_value
        is_upsert_supported_mock.assert_called_once_with(op_name)
        extract_model_mock.assert_called_once_with(op_name)
        get_operation_mock.assert_called_once_with(extract_model_mock.return_value)
        add_mock.assert_called_once_with(get_operation_mock.return_value, params)
        edit_mock.assert_called_once_with(get_operation_mock.return_value, error.obj, params)

    @mock.patch.object(BaseConfigurationResource, "is_upsert_operation_supported")
    @mock.patch.object(BaseConfigurationResource, "get_operation_specs_by_model_name")
    @mock.patch.object(BaseConfigurationResource, "_add_upserted_object")
    @mock.patch.object(BaseConfigurationResource, "_edit_upserted_object")
    @mock.patch("ansible.module_utils.network.ftd.configuration._extract_model_from_upsert_operation")
    def test_upsert_object_not_supported(self, extract_model_mock, edit_mock, add_mock, get_operation_mock,
                                         is_upsert_supported_mock):
        op_name = mock.MagicMock()
        params = mock.MagicMock()

        is_upsert_supported_mock.return_value = False

        self.assertRaises(
            FtdInvalidOperationNameError,
            self._resource.upsert_object, op_name, params
        )

        is_upsert_supported_mock.assert_called_once_with(op_name)
        extract_model_mock.assert_not_called()
        get_operation_mock.assert_not_called()
        add_mock.assert_not_called()
        edit_mock.assert_not_called()

    @mock.patch.object(BaseConfigurationResource, "is_upsert_operation_supported")
    @mock.patch.object(BaseConfigurationResource, "get_operation_specs_by_model_name")
    @mock.patch.object(BaseConfigurationResource, "_add_upserted_object")
    @mock.patch.object(BaseConfigurationResource, "_edit_upserted_object")
    @mock.patch("ansible.module_utils.network.ftd.configuration._extract_model_from_upsert_operation")
    def test_upsert_object_neither_added_nor_edited(self, extract_model_mock, edit_mock, add_mock, get_operation_mock,
                                                    is_upsert_supported_mock):
        op_name = mock.MagicMock()
        params = mock.MagicMock()

        is_upsert_supported_mock.return_value = True
        error = FtdConfigurationError("Obj duplication error")
        error.obj = mock.MagicMock()

        add_mock.side_effect = error
        edit_mock.side_effect = FtdConfigurationError("Some object edit error")

        self.assertRaises(
            FtdConfigurationError,
            self._resource.upsert_object, op_name, params
        )

        is_upsert_supported_mock.assert_called_once_with(op_name)
        extract_model_mock.assert_called_once_with(op_name)
        get_operation_mock.assert_called_once_with(extract_model_mock.return_value)
        add_mock.assert_called_once_with(get_operation_mock.return_value, params)
        edit_mock.assert_called_once_with(get_operation_mock.return_value, error.obj, params)

    @mock.patch.object(BaseConfigurationResource, "is_upsert_operation_supported")
    @mock.patch.object(BaseConfigurationResource, "get_operation_specs_by_model_name")
    @mock.patch.object(BaseConfigurationResource, "_add_upserted_object")
    @mock.patch.object(BaseConfigurationResource, "_edit_upserted_object")
    @mock.patch("ansible.module_utils.network.ftd.configuration._extract_model_from_upsert_operation")
    def test_upsert_object_with_fatal_error_during_add(self, extract_model_mock, edit_mock, add_mock,
                                                       get_operation_mock, is_upsert_supported_mock):
        op_name = mock.MagicMock()
        params = mock.MagicMock()

        is_upsert_supported_mock.return_value = True

        error = FtdConfigurationError("Obj duplication error")
        add_mock.side_effect = error

        self.assertRaises(
            FtdConfigurationError,
            self._resource.upsert_object, op_name, params
        )

        is_upsert_supported_mock.assert_called_once_with(op_name)
        extract_model_mock.assert_called_once_with(op_name)
        get_operation_mock.assert_called_once_with(extract_model_mock.return_value)
        add_mock.assert_called_once_with(get_operation_mock.return_value, params)
        edit_mock.assert_not_called()