Esempio n. 1
0
def download_app(cmd,
                 client,
                 resource_group_name,
                 resource_name,
                 file_save_path=None):
    # get the bot and ensure it's not a registration only bot
    raw_bot_properties = client.bots.get(
        resource_group_name=resource_group_name, resource_name=resource_name)
    if raw_bot_properties.kind == 'bot':
        raise CLIError(
            'Source download is not supported for registration only bots')
    file_save_path = file_save_path or os.getcwd()
    if not os.path.isdir(file_save_path):
        raise CLIError('Path name not valid')
    folder_path = os.path.join(file_save_path, resource_name)
    if os.path.exists(folder_path):
        raise CLIError(
            'The path {0} already exists. Please delete it or specify an alternate path'
            .format(folder_path))
    os.mkdir(folder_path)

    user_name, password = _get_site_credential(cmd.cli_ctx,
                                               resource_group_name,
                                               resource_name, None)
    scm_url = _get_scm_url(cmd, resource_group_name, resource_name, None)

    import urllib3
    authorization = urllib3.util.make_headers(
        basic_auth='{0}:{1}'.format(user_name, password))
    headers = authorization
    headers['content-type'] = 'application/json'

    payload = {
        'command': 'PostDeployScripts\\prepareSrc.cmd {0}'.format(password),
        'dir': r'site\wwwroot'
    }

    import requests
    response = requests.post(scm_url + '/api/command',
                             data=json.dumps(payload),
                             headers=headers)
    if response.status_code != 200:
        raise CLIError(
            'Zip Download failed with status code {} and reason {}'.format(
                response.status_code, response.text))
    response = requests.get(scm_url + '/api/vfs/site/bot-src.zip',
                            headers=authorization)
    if response.status_code != 200:
        raise CLIError(
            'Zip Download failed with status code {} and reason {}'.format(
                response.status_code, response.text))
    download_path = os.path.join(file_save_path, 'download.zip')
    with open(os.path.join(file_save_path, 'download.zip'), 'wb') as f:
        f.write(response.content)
    import zipfile
    zip_ref = zipfile.ZipFile(download_path)
    zip_ref.extractall(folder_path)
    zip_ref.close()
    os.remove(download_path)
    return {'downloadPath': folder_path}
Esempio n. 2
0
def _get_basic_headers(params):
    import urllib3
    from azure.cli.core.util import (should_disable_connection_verify,
                                     get_az_user_agent)

    user_name, password = _get_site_credential(params.cmd.cli_ctx,
                                               params.resource_group_name,
                                               params.webapp_name, params.slot)

    if params.src_path:
        content_type = 'application/octet-stream'
    elif params.src_url:
        content_type = 'application/json'
    else:
        raise CLIError(
            'Unable to determine source location of the artifact being deployed'
        )

    headers = urllib3.util.make_headers(
        basic_auth='{0}:{1}'.format(user_name, password))
    headers['Cache-Control'] = 'no-cache'
    headers['User-Agent'] = get_az_user_agent()
    headers['Content-Type'] = content_type

    return headers
Esempio n. 3
0
def _ping_scm_site(cmd, resource_group, name):
    #  wakeup kudu, by making an SCM call
    import requests
    #  work around until the timeout limits issue for linux is investigated & fixed
    user_name, password = _get_site_credential(cmd.cli_ctx, resource_group, name)
    scm_url = _get_scm_url(cmd, resource_group, name)
    import urllib3
    authorization = urllib3.util.make_headers(basic_auth='{}:{}'.format(user_name, password))
    requests.get(scm_url + '/api/settings', headers=authorization)
Esempio n. 4
0
def start_scan(cmd, resource_group_name, name, timeout="", slot=None):
    webapp = show_webapp(cmd, resource_group_name, name, slot)
    is_linux = webapp.reserved
    if not is_linux:
        raise CLIError("Only Linux App Service Plans supported, Found a Windows App Service Plan")

    import requests
    user_name, password = _get_site_credential(cmd.cli_ctx, resource_group_name, name, slot)
    scm_url = _get_scm_url(cmd, resource_group_name, name, slot)
    start_scan_url = scm_url + '/api/scan/start/' + timeout

    import urllib3
    authorization = urllib3.util.make_headers(basic_auth='{0}:{1}'.format(user_name, password))
    headers = authorization
    headers['content-type'] = 'application/octet-stream'

    response = requests.get(start_scan_url, headers=authorization)
    return response.json()
Esempio n. 5
0
def _zip_deploy(cmd, rg_name, name, zip_path):
    user_name, password = _get_site_credential(cmd.cli_ctx, rg_name, name)
    scm_url = _get_scm_url(cmd, rg_name, name)
    zip_url = scm_url + '/api/zipdeploy?isAsync=true'

    import urllib3
    authorization = urllib3.util.make_headers(
        basic_auth='{0}:{1}'.format(user_name, password))
    headers = authorization
    headers['content-type'] = 'application/octet-stream'

    import requests
    import os
    # Read file content
    with open(os.path.realpath(os.path.expanduser(zip_path)), 'rb') as fs:
        zip_content = fs.read()
        requests.post(zip_url, data=zip_content, headers=headers)
    # keep checking for status of the deployment
    deployment_url = scm_url + '/api/deployments/latest'
    response = requests.get(deployment_url, headers=authorization)
    if response.json()['status'] != 4:
        logger.warning(response.json()['progress'])
        _check_deployment_status(deployment_url, authorization)
def enable_zip_deploy(cmd, resource_group_name, name, src, slot=None):
    user_name, password = _get_site_credential(cmd.cli_ctx,
                                               resource_group_name, name, slot)
    scm_url = _get_scm_url(cmd, resource_group_name, name, slot)
    zip_url = scm_url + '/api/zipdeploy?isAsync=true'
    deployment_status_url = scm_url + '/api/deployments/latest'

    import urllib3
    authorization = urllib3.util.make_headers(
        basic_auth='{0}:{1}'.format(user_name, password))
    headers = authorization
    headers['content-type'] = 'application/octet-stream'

    import requests
    import os
    # Read file content
    with open(os.path.realpath(os.path.expanduser(src)), 'rb') as fs:
        zip_content = fs.read()
        requests.post(zip_url, data=zip_content, headers=headers)
    # check the status of async deployment
    try:
        from json.decoder import JSONDecodeError
    except ImportError:
        JSONDecodeError = ValueError

    response = requests.get(deployment_status_url, headers=authorization)
    try:
        response = response.json()
        if response.get('status', 0) != 4:
            logger.warning(response.get('progress', ''))
            response = _check_zip_deployment_status(deployment_status_url,
                                                    authorization)
        return response
    except JSONDecodeError:
        logger.warning(
            """Unable to fetch status of deployment. Please check status manually using link '%s'
            """, deployment_status_url)
Esempio n. 7
0
def create_deploy_webapp(cmd, name, location=None, dryrun=False):
    import os
    import json

    client = web_client_factory(cmd.cli_ctx)
    # the code to deploy is expected to be the current directory the command is running from
    src_dir = os.getcwd()

    # if dir is empty, show a message in dry run
    do_deployment = False if os.listdir(src_dir) == [] else True

    # determine the details for app to be created from src contents
    lang_details = get_lang_from_content(src_dir)
    # we support E2E create and deploy for Node & dotnetcore, any other stack, set defaults for os & runtime
    # and skip deployment
    if lang_details['language'] is None:
        do_deployment = False
        sku = 'F1'
        os_val = OS_DEFAULT
        detected_version = '-'
        runtime_version = '-'
    else:
        sku = lang_details.get("default_sku")
        language = lang_details.get("language")
        os_val = "Linux" if language.lower(
        ) == NODE_RUNTIME_NAME else OS_DEFAULT
        # detect the version
        data = get_runtime_version_details(lang_details.get('file_loc'),
                                           language)
        version_used_create = data.get('to_create')
        detected_version = data.get('detected')
        runtime_version = "{}|{}".format(language, version_used_create)

    if location is None:
        locs = client.list_geo_regions(sku, True)
        available_locs = []
        for loc in locs:
            available_locs.append(loc.geo_region_name)
        location = available_locs[0]
    # Remove spaces from the location string, incase the GeoRegion string is used
    loc_name = location.replace(" ", "")
    full_sku = _get_sku_name(sku)

    is_linux = True if os_val == 'Linux' else False

    asp = "appsvc_asp_{}_{}".format(os_val, loc_name)
    rg_name = "appsvc_rg_{}_{}".format(os_val, loc_name)

    str_no_contents_warn = ""
    if not do_deployment:
        str_no_contents_warn = "[Empty directory, no deployment will be triggered]"

    # Resource group: check if default RG is set
    default_rg = cmd.cli_ctx.config.get('defaults', 'group', fallback=None)
    if default_rg and check_resource_group_supports_os(cmd, default_rg,
                                                       location, is_linux):
        rg_name = default_rg
        rg_mssg = "[Using default Resource group]"
    else:
        rg_mssg = ""

    src_path = "{} {}".format(src_dir.replace("\\", "\\\\"),
                              str_no_contents_warn)
    rg_str = "{} {}".format(rg_name, rg_mssg)

    dry_run_str = r""" {
            "name" : "%s",
            "serverfarm" : "%s",
            "resourcegroup" : "%s",
            "sku": "%s",
            "os": "%s",
            "location" : "%s",
            "src_path" : "%s",
            "version_detected": "%s",
            "version_to_create": "%s"
            }
            """ % (name, asp, rg_str, full_sku, os_val, location, src_path,
                   detected_version, runtime_version)

    create_json = json.dumps(json.loads(dry_run_str), indent=4, sort_keys=True)
    if dryrun:
        logger.warning(
            "Web app will be created with the below configuration,re-run command "
            "without the --dryrun flag to create & deploy a new app")
        logger.warning(create_json)
        return None

    # create RG if the RG doesn't already exist
    if not check_resource_group_exists(cmd, rg_name):
        logger.warning("Creating Resource group '%s' ...", rg_name)
        create_resource_group(cmd, rg_name, location)
        logger.warning("Resource group creation complete")
    else:
        logger.warning("Resource group '%s' already exists.", rg_name)

    # create asp
    if not check_if_asp_exists(cmd, rg_name, asp):
        logger.warning("Creating App service plan '%s' ...", asp)
        sku_def = SkuDescription(tier=full_sku,
                                 name=sku,
                                 capacity=(1 if is_linux else None))
        plan_def = AppServicePlan(loc_name,
                                  app_service_plan_name=asp,
                                  sku=sku_def,
                                  reserved=(is_linux or None))
        client.app_service_plans.create_or_update(rg_name, asp, plan_def)
        logger.warning("App service plan creation complete")
    else:
        logger.warning("App service plan '%s' already exists.", asp)

    # create the app
    if not check_app_exists(cmd, rg_name, name):
        logger.warning("Creating app '%s' ....", name)
        create_webapp(cmd, rg_name, name, asp,
                      runtime_version if is_linux else None)
        logger.warning("Webapp creation complete")
    else:
        logger.warning("App '%s' already exists", name)

    if do_deployment:
        # setting to build after deployment
        logger.warning(
            "Updating app settings to enable build after deployment")
        update_app_settings(cmd, rg_name, name,
                            ["SCM_DO_BUILD_DURING_DEPLOYMENT=true"])
        # work around until the timeout limits issue for linux is investigated & fixed
        # wakeup kudu, by making an SCM call

        import requests
        # work around until the timeout limits issue for linux is investigated & fixed
        user_name, password = _get_site_credential(cmd.cli_ctx, rg_name, name)
        scm_url = _get_scm_url(cmd, rg_name, name)
        import urllib3
        authorization = urllib3.util.make_headers(
            basic_auth='{0}:{1}'.format(user_name, password))
        requests.get(scm_url + '/api/settings', headers=authorization)

        logger.warning("Creating zip with contents of dir %s ...", src_dir)
        # zip contents & deploy
        zip_file_path = zip_contents_from_dir(src_dir, language)

        logger.warning("Deploying and building contents to app."
                       "This operation can take some time to finish...")
        enable_zip_deploy(cmd, rg_name, name, zip_file_path)
    else:
        logger.warning(
            "No 'NODE' or 'DOTNETCORE' package detected, skipping zip and deploy process"
        )

    logger.warning("All done. %s", create_json)
    return None
Esempio n. 8
0
def create_deploy_webapp(cmd, name, location=None, dryrun=False):
    import os
    import json

    client = web_client_factory(cmd.cli_ctx)
    sku = "S1"
    os_val = "Linux"
    language = "node"
    full_sku = _get_sku_name(sku)

    if location is None:
        locs = client.list_geo_regions(sku, True)
        available_locs = []
        for loc in locs:
            available_locs.append(loc.geo_region_name)
        location = available_locs[0]

    # Remove spaces from the location string, incase the GeoRegion string is used
    loc_name = location.replace(" ", "")

    asp = "appsvc_asp_{}_{}".format(os_val, loc_name)
    rg_name = "appsvc_rg_{}_{}".format(os_val, loc_name)

    # the code to deploy is expected to be the current directory the command is running from
    src_dir = os.getcwd()

    # if dir is empty, show a message in dry run
    do_deployment = False if os.listdir(src_dir) == [] else True
    package_json_path = is_node_application(src_dir)

    str_no_contents_warn = ""
    if not do_deployment:
        str_no_contents_warn = "[Empty directory, no deployment will be triggered]"

    if package_json_path == '':
        node_version = "[No package.json file found in root directory, not a Node app?]"
        version_used_create = "8.0"
    else:
        with open(package_json_path) as data_file:
            data = json.load(data_file)
            node_version = data['version']
            version_used_create = get_node_runtime_version_toSet()

    # Resource group: check if default RG is set
    default_rg = cmd.cli_ctx.config.get('defaults', 'group', fallback=None)
    if default_rg and check_resource_group_supports_linux(
            cmd, default_rg, location):
        rg_name = default_rg
        rg_mssg = "[Using default Resource group]"
    else:
        rg_mssg = ""

    runtime_version = "{}|{}".format(language, version_used_create)
    src_path = "{} {}".format(src_dir.replace("\\", "\\\\"),
                              str_no_contents_warn)
    rg_str = "{} {}".format(rg_name, rg_mssg)

    dry_run_str = r""" {
            "name" : "%s",
            "serverfarm" : "%s",
            "resourcegroup" : "%s",
            "sku": "%s",
            "os": "%s",
            "location" : "%s",
            "src_path" : "%s",
            "version_detected": "%s",
            "version_to_create": "%s"
            }
            """ % (name, asp, rg_str, full_sku, os_val, location, src_path,
                   node_version, runtime_version)

    create_json = json.dumps(json.loads(dry_run_str), indent=4, sort_keys=True)
    if dryrun:
        logger.warning(
            "Web app will be created with the below configuration,re-run command "
            "without the --dryrun flag to create & deploy a new app")
        logger.warning(create_json)
        return None

    # create RG if the RG doesn't already exist
    if not check_resource_group_exists(cmd, rg_name):
        logger.warning("Creating Resource group '%s' ...", rg_name)
        create_resource_group(cmd, rg_name, location)
        logger.warning("Resource group creation complete")
    else:
        logger.warning("Resource group '%s' already exists.", rg_name)

    # create asp
    if not check_if_asp_exists(cmd, rg_name, asp):
        logger.warning("Creating App service plan '%s' ...", asp)
        sku_def = SkuDescription(tier=full_sku, name=sku, capacity=1)
        plan_def = AppServicePlan(loc_name,
                                  app_service_plan_name=asp,
                                  sku=sku_def,
                                  reserved=True)
        client.app_service_plans.create_or_update(rg_name, asp, plan_def)
        logger.warning("App service plan creation complete")
    else:
        logger.warning("App service plan '%s' already exists.", asp)

    # create the Linux app
    if not check_app_exists(cmd, rg_name, name):
        logger.warning("Creating app '%s' ....", name)
        create_webapp(cmd, rg_name, name, asp, runtime_version)
        logger.warning("Webapp creation complete")
    else:
        logger.warning("App '%s' already exists", name)

    # setting to build after deployment
    logger.warning("Updating app settings to enable build after deployment")
    update_app_settings(cmd, rg_name, name,
                        ["SCM_DO_BUILD_DURING_DEPLOYMENT=true"])
    # work around until the timeout limits issue for linux is investigated & fixed
    # wakeup kudu, by making an SCM call

    import requests
    # work around until the timeout limits issue for linux is investigated & fixed
    user_name, password = _get_site_credential(cmd.cli_ctx, rg_name, name)
    scm_url = _get_scm_url(cmd, rg_name, name)
    import urllib3
    authorization = urllib3.util.make_headers(
        basic_auth='{0}:{1}'.format(user_name, password))
    requests.get(scm_url + '/api/settings', headers=authorization)

    if package_json_path != '':
        logger.warning("Creating zip with contents of dir %s ...", src_dir)
        # zip contents & deploy
        zip_file_path = zip_contents_from_dir(src_dir)

        logger.warning("Deploying and building contents to app."
                       "This operation can take some time to finish...")
        enable_zip_deploy(cmd, rg_name, name, zip_file_path)
    else:
        logger.warning(
            "No package.json found, skipping zip and deploy process")

    logger.warning("All done. %s", create_json)
    return None
Esempio n. 9
0
def enable_one_deploy(cmd,
                      resource_group_name,
                      name,
                      src,
                      deploy_type=None,
                      is_async=None,
                      target_path=None,
                      timeout=None,
                      slot=None):
    import ntpath
    logger.info("Preparing for deployment")
    user_name, password = _get_site_credential(cmd.cli_ctx,
                                               resource_group_name, name, slot)

    try:
        scm_url = _get_scm_url(cmd, resource_group_name, name, slot)
    except ValueError:
        raise CLIError('Failed to fetch scm url for for app {}'.format(name))

    # Interpret deployment type from the file extension if the type parameter is not passed
    if deploy_type is None:
        fileName = ntpath.basename(src)
        fileExtension = fileName.split(".", 1)[1]
        if fileExtension in ('war', 'jar', 'zip', 'ear'):
            deploy_type = fileExtension
        elif fileExtension in ('sh', 'bat'):
            deploy_type = 'startup'
        else:
            deploy_type = 'static'

    logger.warning(
        "Deployment type: %s. To override deloyment type, please specify the --type parameter. Possible values: static, zip, war, jar, ear, startup",
        deploy_type)
    deploy_url = scm_url + '/api/publish?type=' + deploy_type

    if is_async is not None:
        deploy_url = deploy_url + '&async=true'

    if target_path is not None:
        deploy_url = deploy_url + '&path=' + target_path

    deployment_status_url = scm_url + '/api/deployments/latest'

    from azure.cli.core.util import (should_disable_connection_verify,
                                     get_az_user_agent)

    import urllib3
    authorization = urllib3.util.make_headers(
        basic_auth='{0}:{1}'.format(user_name, password))
    headers = authorization
    headers['Content-Type'] = 'application/octet-stream'
    headers['Cache-Control'] = 'no-cache'
    headers['User-Agent'] = get_az_user_agent()

    import requests
    import os

    # Read file content
    with open(os.path.realpath(os.path.expanduser(src)), 'rb') as fs:
        artifact_content = fs.read()
        logger.warning("Starting deployment...")
        res = requests.post(deploy_url,
                            data=artifact_content,
                            headers=headers,
                            verify=not should_disable_connection_verify())

    # check if an error occured during deployment
    if res.status_code == 400:
        raise CLIError("An error occured durng deployment: {}".format(
            res.text))

    # check if there's an ongoing process
    if res.status_code == 409:
        raise CLIError(
            "There may be an ongoing deployment or your app setting has WEBSITE_RUN_FROM_PACKAGE. "
            "Please track your deployment in {} and ensure the WEBSITE_RUN_FROM_PACKAGE app setting "
            "is removed.".format(deployment_status_url))

    # check the status of async deployment
    if res.status_code == 202:
        logger.warning("Asynchronous deployment request has been recieved")
        response = _check_zip_deployment_status(cmd, resource_group_name, name,
                                                deployment_status_url,
                                                authorization, timeout)
        return response

    return logger.warning("Deployment has completed successfully")