Create a single instance on a cloud provider, using a salt-cloud profile.

    Note that while profiles used this function do take any configuration
    argument that would normally be used to create an instance using a profile,
    this state will not verify the state of any of those arguments on an
    existing instance. Stateful properties of an instance should be configured
    using their own individual state (i.e., cloud.tagged, cloud.untagged, etc).

    name
        The name of the instance to create

    profile
        The name of the cloud profile to use

    onlyif
        Do run the state only if is unless succeed

    unless
        Do not run the state at least unless succeed

    kwargs
        Any profile override or addition

    opts
        Any extra opts that need to be used

def profile(name, profile, onlyif=None, unless=None, opts=None, **kwargs):
    '''
    Create a single instance on a cloud provider, using a salt-cloud profile.

    Note that while profiles used this function do take any configuration
    argument that would normally be used to create an instance using a profile,
    this state will not verify the state of any of those arguments on an
    existing instance. Stateful properties of an instance should be configured
    using their own individual state (i.e., cloud.tagged, cloud.untagged, etc).

    name
        The name of the instance to create

    profile
        The name of the cloud profile to use

    onlyif
        Do run the state only if is unless succeed

    unless
        Do not run the state at least unless succeed

    kwargs
        Any profile override or addition

    opts
        Any extra opts that need to be used
    '''
    ret = {'name': name,
           'changes': {},
           'result': None,
           'comment': ''}
    retcode = __salt__['cmd.retcode']
    if onlyif is not None:
        if not isinstance(onlyif, six.string_types):
            if not onlyif:
                return _valid(name, comment='onlyif condition is false')
        elif isinstance(onlyif, six.string_types):
            if retcode(onlyif, python_shell=True) != 0:
                return _valid(name, comment='onlyif condition is false')
    if unless is not None:
        if not isinstance(unless, six.string_types):
            if unless:
                return _valid(name, comment='unless condition is true')
        elif isinstance(unless, six.string_types):
            if retcode(unless, python_shell=True) == 0:
                return _valid(name, comment='unless condition is true')
    instance = _get_instance([name])
    if instance and not any('Not Actioned' in key for key in instance):
        ret['result'] = True
        ret['comment'] = 'Already present instance {0}'.format(name)
        return ret

    if __opts__['test']:
        ret['comment'] = 'Instance {0} needs to be created'.format(name)
        return ret

    info = __salt__['cloud.profile'](profile, name, vm_overrides=kwargs, opts=opts)

    # get either {Error: ''} or {namestring: {Error: ''}}
    # which is what we can get from providers returns
    main_error = info.get('Error', '')
    name_error = ''
    if isinstance(info, dict):
        subinfo = info.get(name, {})
        if isinstance(subinfo, dict):
            name_error = subinfo.get('Error', None)
    error = main_error or name_error
    if info and not error:
        node_info = info.get(name)
        ret['result'] = True
        default_msg = 'Created instance {0} using profile {1}'.format(
            name, profile,)
        # some providers support changes
        if 'changes' in node_info:
            ret['changes'] = node_info['changes']
            ret['comment'] = node_info.get('comment', default_msg)
        else:
            ret['changes'] = info
            ret['comment'] = default_msg
    elif error:
        ret['result'] = False
        ret['comment'] = ('Failed to create instance {0}'
                          ' using profile {1}: {2}').format(
            name,
            profile,
            '{0}\n{1}\n'.format(main_error, name_error).strip(),
        )
    else:
        ret['result'] = False
        ret['comment'] = ('Failed to create instance {0}'
                          'using profile {1}').format(
            name,
            profile,
        )
    return ret