.. versionadded:: 2019.2.0

    Ensure an availability set exists.

    :param name:
        Name of the availability set.

    :param resource_group:
        The resource group assigned to the availability set.

    :param tags:
        A dictionary of strings can be passed as tag metadata to the availability set object.

    :param platform_update_domain_count:
        An optional parameter which indicates groups of virtual machines and underlying physical hardware that can be
        rebooted at the same time.

    :param platform_fault_domain_count:
        An optional parameter which defines the group of virtual machines that share a common power source and network
        switch.

    :param virtual_machines:
        A list of names of existing virtual machines to be included in the availability set.

    :param sku:
        The availability set SKU, which specifies whether the availability set is managed or not. Possible values are
        'Aligned' or 'Classic'. An 'Aligned' availability set is managed, 'Classic' is not.

    :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 availability set exists:
            azurearm_compute.availability_set_present:
                - name: aset1
                - resource_group: group1
                - platform_update_domain_count: 5
                - platform_fault_domain_count: 3
                - sku: aligned
                - tags:
                    contact_name: Elmer Fudd Gantry
                - connection_auth: {{ profile }}
                - require:
                  - azurearm_resource: Ensure resource group exists

def availability_set_present(name, resource_group, tags=None, platform_update_domain_count=None,
                             platform_fault_domain_count=None, virtual_machines=None, sku=None, connection_auth=None,
                             **kwargs):
    '''
    .. versionadded:: 2019.2.0

    Ensure an availability set exists.

    :param name:
        Name of the availability set.

    :param resource_group:
        The resource group assigned to the availability set.

    :param tags:
        A dictionary of strings can be passed as tag metadata to the availability set object.

    :param platform_update_domain_count:
        An optional parameter which indicates groups of virtual machines and underlying physical hardware that can be
        rebooted at the same time.

    :param platform_fault_domain_count:
        An optional parameter which defines the group of virtual machines that share a common power source and network
        switch.

    :param virtual_machines:
        A list of names of existing virtual machines to be included in the availability set.

    :param sku:
        The availability set SKU, which specifies whether the availability set is managed or not. Possible values are
        'Aligned' or 'Classic'. An 'Aligned' availability set is managed, 'Classic' is not.

    :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 availability set exists:
            azurearm_compute.availability_set_present:
                - name: aset1
                - resource_group: group1
                - platform_update_domain_count: 5
                - platform_fault_domain_count: 3
                - sku: aligned
                - 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

    if sku:
        sku = {'name': sku.capitalize()}

    aset = __salt__['azurearm_compute.availability_set_get'](
        name,
        resource_group,
        azurearm_log_level='info',
        **connection_auth
    )

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

        if platform_update_domain_count and (int(platform_update_domain_count) != aset.get('platform_update_domain_count')):
            ret['changes']['platform_update_domain_count'] = {
                'old': aset.get('platform_update_domain_count'),
                'new': platform_update_domain_count
            }

        if platform_fault_domain_count and (int(platform_fault_domain_count) != aset.get('platform_fault_domain_count')):
            ret['changes']['platform_fault_domain_count'] = {
                'old': aset.get('platform_fault_domain_count'),
                'new': platform_fault_domain_count
            }

        if sku and (sku['name'] != aset.get('sku', {}).get('name')):
            ret['changes']['sku'] = {
                'old': aset.get('sku'),
                'new': sku
            }

        if virtual_machines:
            if not isinstance(virtual_machines, list):
                ret['comment'] = 'Virtual machines must be supplied as a list!'
                return ret
            aset_vms = aset.get('virtual_machines', [])
            remote_vms = sorted([vm['id'].split('/')[-1].lower() for vm in aset_vms if 'id' in aset_vms])
            local_vms = sorted([vm.lower() for vm in virtual_machines or []])
            if local_vms != remote_vms:
                ret['changes']['virtual_machines'] = {
                    'old': aset_vms,
                    'new': virtual_machines
                }

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

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

    else:
        ret['changes'] = {
            'old': {},
            'new': {
                'name': name,
                'virtual_machines': virtual_machines,
                'platform_update_domain_count': platform_update_domain_count,
                'platform_fault_domain_count': platform_fault_domain_count,
                'sku': sku,
                'tags': tags
            }
        }

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

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

    aset = __salt__['azurearm_compute.availability_set_create_or_update'](
        name=name,
        resource_group=resource_group,
        virtual_machines=virtual_machines,
        platform_update_domain_count=platform_update_domain_count,
        platform_fault_domain_count=platform_fault_domain_count,
        sku=sku,
        tags=tags,
        **aset_kwargs
    )

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

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