Update the salt-bootstrap script

    url can be one of:

        - The URL to fetch the bootstrap script from
        - The absolute path to the bootstrap
        - The content of the bootstrap script

def update_bootstrap(config, url=None):
    '''
    Update the salt-bootstrap script

    url can be one of:

        - The URL to fetch the bootstrap script from
        - The absolute path to the bootstrap
        - The content of the bootstrap script
    '''
    default_url = config.get('bootstrap_script_url',
                             'https://bootstrap.saltstack.com')
    if not url:
        url = default_url
    if not url:
        raise ValueError('Cant get any source to update')
    if url.startswith('http') or '://' in url:
        log.debug('Updating the bootstrap-salt.sh script to latest stable')
        try:
            import requests
        except ImportError:
            return {'error': (
                'Updating the bootstrap-salt.sh script requires the '
                'Python requests library to be installed'
            )}
        req = requests.get(url)
        if req.status_code != 200:
            return {'error': (
                'Failed to download the latest stable version of the '
                'bootstrap-salt.sh script from {0}. HTTP error: '
                '{1}'.format(
                    url, req.status_code
                )
            )}
        script_content = req.text
        if url == default_url:
            script_name = 'bootstrap-salt.sh'
        else:
            script_name = os.path.basename(url)
    elif os.path.exists(url):
        with salt.utils.files.fopen(url) as fic:
            script_content = salt.utils.stringutils.to_unicode(fic.read())
        script_name = os.path.basename(url)
    # in last case, assuming we got a script content
    else:
        script_content = url
        script_name = '{0}.sh'.format(
            hashlib.sha1(script_content).hexdigest()
        )

    if not script_content:
        raise ValueError('No content in bootstrap script !')

    # Get the path to the built-in deploy scripts directory
    builtin_deploy_dir = os.path.join(
        os.path.dirname(__file__),
        'deploy'
    )

    # Compute the search path from the current loaded opts conf_file
    # value
    deploy_d_from_conf_file = os.path.join(
        os.path.dirname(config['conf_file']),
        'cloud.deploy.d'
    )

    # Compute the search path using the install time defined
    # syspaths.CONF_DIR
    deploy_d_from_syspaths = os.path.join(
        config['config_dir'],
        'cloud.deploy.d'
    )

    # Get a copy of any defined search paths, flagging them not to
    # create parent
    deploy_scripts_search_paths = []
    for entry in config.get('deploy_scripts_search_path', []):
        if entry.startswith(builtin_deploy_dir):
            # We won't write the updated script to the built-in deploy
            # directory
            continue

        if entry in (deploy_d_from_conf_file, deploy_d_from_syspaths):
            # Allow parent directories to be made
            deploy_scripts_search_paths.append((entry, True))
        else:
            deploy_scripts_search_paths.append((entry, False))

    # In case the user is not using defaults and the computed
    # 'cloud.deploy.d' from conf_file and syspaths is not included, add
    # them
    if deploy_d_from_conf_file not in deploy_scripts_search_paths:
        deploy_scripts_search_paths.append(
            (deploy_d_from_conf_file, True)
        )
    if deploy_d_from_syspaths not in deploy_scripts_search_paths:
        deploy_scripts_search_paths.append(
            (deploy_d_from_syspaths, True)
        )

    finished = []
    finished_full = []
    for entry, makedirs in deploy_scripts_search_paths:
        # This handles duplicate entries, which are likely to appear
        if entry in finished:
            continue
        else:
            finished.append(entry)

        if makedirs and not os.path.isdir(entry):
            try:
                os.makedirs(entry)
            except (OSError, IOError) as err:
                log.info('Failed to create directory \'%s\'', entry)
                continue

        if not is_writeable(entry):
            log.debug('The \'%s\' is not writeable. Continuing...', entry)
            continue

        deploy_path = os.path.join(entry, script_name)
        try:
            finished_full.append(deploy_path)
            with salt.utils.files.fopen(deploy_path, 'w') as fp_:
                fp_.write(salt.utils.stringutils.to_str(script_content))
        except (OSError, IOError) as err:
            log.debug('Failed to write the updated script: %s', err)
            continue

    return {'Success': {'Files updated': finished_full}}