.. versionadded:: 2019.2.0

    Ensure a network security group exists.

    :param name:
        Name of the network security group.

    :param resource_group:
        The resource group assigned to the network security group.

    :param tags:
        A dictionary of strings can be passed as tag metadata to the network security group object.

    :param security_rules: An optional list of dictionaries representing valid SecurityRule objects. See the
        documentation for the security_rule_present state or security_rule_create_or_update execution module
        for more information on required and optional parameters for security rules. The rules are only
        managed if this parameter is present. When this parameter is absent, implemented rules will not be removed,
        and will merely become unmanaged.

    :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 network security group exists:
            azurearm_network.network_security_group_present:
                - name: nsg1
                - resource_group: group1
                - security_rules:
                  - name: nsg1_rule1
                    priority: 100
                    protocol: tcp
                    access: allow
                    direction: outbound
                    source_address_prefix: virtualnetwork
                    destination_address_prefix: internet
                    source_port_range: '*'
                    destination_port_range: '*'
                  - name: nsg1_rule2
                    priority: 101
                    protocol: tcp
                    access: allow
                    direction: inbound
                    source_address_prefix: internet
                    destination_address_prefix: virtualnetwork
                    source_port_range: '*'
                    destination_port_ranges:
                      - '80'
                      - '443'
                - tags:
                    contact_name: Elmer Fudd Gantry
                - connection_auth: {{ profile }}
                - require:
                  - azurearm_resource: Ensure resource group exists

def network_security_group_present(name, resource_group, tags=None, security_rules=None, connection_auth=None,
                                   **kwargs):
    '''
    .. versionadded:: 2019.2.0

    Ensure a network security group exists.

    :param name:
        Name of the network security group.

    :param resource_group:
        The resource group assigned to the network security group.

    :param tags:
        A dictionary of strings can be passed as tag metadata to the network security group object.

    :param security_rules: An optional list of dictionaries representing valid SecurityRule objects. See the
        documentation for the security_rule_present state or security_rule_create_or_update execution module
        for more information on required and optional parameters for security rules. The rules are only
        managed if this parameter is present. When this parameter is absent, implemented rules will not be removed,
        and will merely become unmanaged.

    :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 network security group exists:
            azurearm_network.network_security_group_present:
                - name: nsg1
                - resource_group: group1
                - security_rules:
                  - name: nsg1_rule1
                    priority: 100
                    protocol: tcp
                    access: allow
                    direction: outbound
                    source_address_prefix: virtualnetwork
                    destination_address_prefix: internet
                    source_port_range: '*'
                    destination_port_range: '*'
                  - name: nsg1_rule2
                    priority: 101
                    protocol: tcp
                    access: allow
                    direction: inbound
                    source_address_prefix: internet
                    destination_address_prefix: virtualnetwork
                    source_port_range: '*'
                    destination_port_ranges:
                      - '80'
                      - '443'
                - tags:
                    contact_name: Elmer Fudd Gantry
                - connection_auth: {{ profile }}
                - require:
                  - azurearm_resource: Ensure resource group exists

    '''
    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

    nsg = __salt__['azurearm_network.network_security_group_get'](
        name,
        resource_group,
        azurearm_log_level='info',
        **connection_auth
    )

    if 'error' not in nsg:
        tag_changes = __utils__['dictdiffer.deep_diff'](nsg.get('tags', {}), tags or {})
        if tag_changes:
            ret['changes']['tags'] = tag_changes

        if security_rules:
            comp_ret = __utils__['azurearm.compare_list_of_dicts'](nsg.get('security_rules', []), security_rules)

            if comp_ret.get('comment'):
                ret['comment'] = '"security_rules" {0}'.format(comp_ret['comment'])
                return ret

            if comp_ret.get('changes'):
                ret['changes']['security_rules'] = comp_ret['changes']

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

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

    else:
        ret['changes'] = {
            'old': {},
            'new': {
                'name': name,
                'resource_group': resource_group,
                'tags': tags,
                'security_rules': security_rules,
            }
        }

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

    nsg_kwargs = kwargs.copy()
    nsg_kwargs.update(connection_auth)

    nsg = __salt__['azurearm_network.network_security_group_create_or_update'](
        name=name,
        resource_group=resource_group,
        tags=tags,
        security_rules=security_rules,
        **nsg_kwargs
    )

    if 'error' not in nsg:
        ret['result'] = True
        ret['comment'] = 'Network security group {0} has been created.'.format(name)
        return ret

    ret['comment'] = 'Failed to create network security group {0}! ({1})'.format(name, nsg.get('error'))
    return ret