.. versionadded:: 2019.2.0

    Ensure a security policy assignment exists.

    :param name:
        Name of the policy assignment.

    :param scope:
        The scope of the policy assignment.

    :param definition_name:
        The name of the policy definition to assign.

    :param display_name:
        The display name of the policy assignment.

    :param description:
        The policy assignment description.

    :param assignment_type:
        The type of policy assignment.

    :param parameters:
        Required dictionary if a parameter is used in the policy rule.

    :param connection_auth:
        A dict with subscription and authentication parameters to be used in connecting to the
        Azure Resource Manager API.

    Example usage:

    .. code-block:: yaml

        Ensure policy assignment exists:
            azurearm_resource.policy_assignment_present:
                - name: testassign
                - scope: /subscriptions/bc75htn-a0fhsi-349b-56gh-4fghti-f84852
                - definition_name: testpolicy
                - display_name: Test Assignment
                - description: Test assignment for testing assignments.
                - connection_auth: {{ profile }}

def policy_assignment_present(name, scope, definition_name, display_name=None, description=None, assignment_type=None,
                              parameters=None, connection_auth=None, **kwargs):
    '''
    .. versionadded:: 2019.2.0

    Ensure a security policy assignment exists.

    :param name:
        Name of the policy assignment.

    :param scope:
        The scope of the policy assignment.

    :param definition_name:
        The name of the policy definition to assign.

    :param display_name:
        The display name of the policy assignment.

    :param description:
        The policy assignment description.

    :param assignment_type:
        The type of policy assignment.

    :param parameters:
        Required dictionary if a parameter is used in the policy rule.

    :param connection_auth:
        A dict with subscription and authentication parameters to be used in connecting to the
        Azure Resource Manager API.

    Example usage:

    .. code-block:: yaml

        Ensure policy assignment exists:
            azurearm_resource.policy_assignment_present:
                - name: testassign
                - scope: /subscriptions/bc75htn-a0fhsi-349b-56gh-4fghti-f84852
                - definition_name: testpolicy
                - display_name: Test Assignment
                - description: Test assignment for testing assignments.
                - connection_auth: {{ profile }}

    '''
    ret = {
        'name': name,
        'result': False,
        'comment': '',
        'changes': {}
    }

    if not isinstance(connection_auth, dict):
        ret['comment'] = 'Connection information must be specified via connection_auth dictionary!'
        return ret

    policy = __salt__['azurearm_resource.policy_assignment_get'](
        name,
        scope,
        azurearm_log_level='info',
        **connection_auth
    )

    if 'error' not in policy:
        if assignment_type and assignment_type.lower() != policy.get('type', '').lower():
            ret['changes']['type'] = {
                'old': policy.get('type'),
                'new': assignment_type
            }

        if scope.lower() != policy['scope'].lower():
            ret['changes']['scope'] = {
                'old': policy['scope'],
                'new': scope
            }

        pa_name = policy['policy_definition_id'].split('/')[-1]
        if definition_name.lower() != pa_name.lower():
            ret['changes']['definition_name'] = {
                'old': pa_name,
                'new': definition_name
            }

        if (display_name or '').lower() != policy.get('display_name', '').lower():
            ret['changes']['display_name'] = {
                'old': policy.get('display_name'),
                'new': display_name
            }

        if (description or '').lower() != policy.get('description', '').lower():
            ret['changes']['description'] = {
                'old': policy.get('description'),
                'new': description
            }

        param_changes = __utils__['dictdiffer.deep_diff'](policy.get('parameters', {}), parameters or {})
        if param_changes:
            ret['changes']['parameters'] = param_changes

        if not ret['changes']:
            ret['result'] = True
            ret['comment'] = 'Policy assignment {0} is already present.'.format(name)
            return ret

        if __opts__['test']:
            ret['comment'] = 'Policy assignment {0} would be updated.'.format(name)
            ret['result'] = None
            return ret

    else:
        ret['changes'] = {
            'old': {},
            'new': {
                'name': name,
                'scope': scope,
                'definition_name': definition_name,
                'type': assignment_type,
                'display_name': display_name,
                'description': description,
                'parameters': parameters,
            }
        }

    if __opts__['test']:
        ret['comment'] = 'Policy assignment {0} would be created.'.format(name)
        ret['result'] = None
        return ret

    if isinstance(parameters, dict):
        parameters = json.loads(json.dumps(parameters))

    policy_kwargs = kwargs.copy()
    policy_kwargs.update(connection_auth)
    policy = __salt__['azurearm_resource.policy_assignment_create'](
        name=name,
        scope=scope,
        definition_name=definition_name,
        type=assignment_type,
        display_name=display_name,
        description=description,
        parameters=parameters,
        **policy_kwargs
    )

    if 'error' not in policy:
        ret['result'] = True
        ret['comment'] = 'Policy assignment {0} has been created.'.format(name)
        return ret

    ret['comment'] = 'Failed to create policy assignment {0}! ({1})'.format(name, policy.get('error'))
    return ret