예제 #1
0
def create_bot_json(cmd, client, resource_group_name, resource_name, app_password=None, raw_bot_properties=None):
    if not raw_bot_properties:
        raw_bot_properties = client.bots.get(
            resource_group_name=resource_group_name,
            resource_name=resource_name
        )
    if not app_password:
        app_settings = get_app_settings(
            cmd=cmd,
            resource_group_name=resource_group_name,
            name=resource_name
        )
        app_password = [item['value'] for item in app_settings if item['name'] == 'MicrosoftAppPassword'][0]

    profile = Profile(cli_ctx=cmd.cli_ctx)
    return {
        'type': 'abs',
        'id': raw_bot_properties.name,
        'name': raw_bot_properties.properties.display_name,
        'appId': raw_bot_properties.properties.msa_app_id,
        'appPassword': app_password,
        'endpoint': raw_bot_properties.properties.endpoint,
        'resourceGroup': str(resource_group_name),
        'tenantId': profile.get_subscription(subscription=client.config.subscription_id)['tenantId'],
        'subscriptionId': client.config.subscription_id
    }
예제 #2
0
    def show(self):
        output = {'Application name': self.name}

        settings = {}
        for setting in get_app_settings(self.__cmd,
                                        resource_group_name=self.name,
                                        name=self.name):
            settings.update({setting['name']: setting['value']})
        if settings:
            output.update({
                'Application settings (stored as environmental variables on server)':
                settings
            })

        output.update({
            'Deployment info': {
                'Git url': self.deployment_info.git_url,
                'User name': self.deployment_info.name,
                'User password': self.deployment_info.password
            }
        })

        output.update(
            {'Website url': 'https://{}.azurewebsites.net'.format(self.name)})

        return output
    def process_functionapp(self):
        """Helper to retrieve information about a functionapp"""
        if self.functionapp_name is None:
            functionapp = self._select_functionapp()
            self.functionapp_name = functionapp.name
        else:
            functionapp = self.cmd_selector.cmd_functionapp(
                self.functionapp_name)

        kinds = show_functionapp(self.cmd, functionapp.resource_group,
                                 functionapp.name).kind.split(',')

        # Get functionapp settings in Azure
        app_settings = get_app_settings(self.cmd, functionapp.resource_group,
                                        functionapp.name)

        self.resource_group_name = functionapp.resource_group
        self.functionapp_type = self._find_type(kinds)

        try:
            self.functionapp_language = self._get_functionapp_runtime_language(
                app_settings)
            self.storage_name = self._get_functionapp_storage_name(
                app_settings)
        except LanguageNotSupportException as lnse:
            raise CLIError(
                "Sorry, currently we do not support {language}.".format(
                    language=lnse.message)) from lnse
예제 #4
0
def __read_kv_from_app_service(cmd, appservice_account, prefix_to_add="", content_type=None):
    try:
        key_values = []
        from azure.cli.command_modules.appservice.custom import get_app_settings
        settings = get_app_settings(
            cmd, resource_group_name=appservice_account["resource_group"], name=appservice_account["name"], slot=None)
        for item in settings:
            key = prefix_to_add + item['name']
            if validate_import_key(key):
                tags = {'AppService:SlotSetting': str(item['slotSetting']).lower()} if item['slotSetting'] else {}
                value = item['value']

                # Value will look like one of the following if it is a KeyVault reference:
                # @Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/mysecret/ec96f02080254f109c51a1f14cdb1931)
                # @Microsoft.KeyVault(VaultName=myvault;SecretName=mysecret;SecretVersion=ec96f02080254f109c51a1f14cdb1931)
                if value and value.strip().lower().startswith(KeyVaultConstants.APPSVC_KEYVAULT_PREFIX.lower()):
                    try:
                        # Strip all whitespaces from value string.
                        # Valid values of SecretUri, VaultName, SecretName or SecretVersion will never have whitespaces.
                        value = value.replace(" ", "")
                        appsvc_value_dict = dict(x.split('=') for x in value[len(KeyVaultConstants.APPSVC_KEYVAULT_PREFIX) + 1: -1].split(';'))
                        appsvc_value_dict = {k.lower(): v for k, v in appsvc_value_dict.items()}
                        secret_identifier = appsvc_value_dict.get('secreturi')
                        if not secret_identifier:
                            # Construct secreturi
                            vault_name = appsvc_value_dict.get('vaultname')
                            secret_name = appsvc_value_dict.get('secretname')
                            secret_version = appsvc_value_dict.get('secretversion')
                            secret_identifier = "https://{0}.vault.azure.net/secrets/{1}/{2}".format(vault_name, secret_name, secret_version)
                        try:
                            from azure.keyvault.key_vault_id import KeyVaultIdentifier
                            # this throws an exception for invalid format of secret identifier
                            KeyVaultIdentifier(uri=secret_identifier)
                            kv = KeyValue(key=key,
                                          value=json.dumps({"uri": secret_identifier}, ensure_ascii=False, separators=(',', ':')),
                                          tags=tags,
                                          content_type=KeyVaultConstants.KEYVAULT_CONTENT_TYPE)
                            key_values.append(kv)
                            continue
                        except (TypeError, ValueError) as e:
                            logger.debug(
                                'Exception while validating the format of KeyVault identifier. Key "%s" with value "%s" will be treated like a regular key-value.\n%s', key, value, str(e))
                    except (AttributeError, TypeError, ValueError) as e:
                        logger.debug(
                            'Key "%s" with value "%s" is not a well-formatted KeyVault reference. It will be treated like a regular key-value.\n%s', key, value, str(e))

                elif content_type and __is_json_content_type(content_type):
                    # If appservice values are being imported with JSON content type,
                    # we need to validate that values are in valid JSON format.
                    try:
                        json.loads(value)
                    except ValueError:
                        raise CLIError('Value "{}" for key "{}" is not a valid JSON object, which conflicts with the provided content type "{}".'.format(value, key, content_type))

                kv = KeyValue(key=key, value=value, tags=tags)
                key_values.append(kv)
        return key_values
    except Exception as exception:
        raise CLIError("Failed to read key-values from appservice.\n" + str(exception))
 def show(self):
     output = {}
     settings = {}
     for setting in get_app_settings(self.__cmd,
                                     resource_group_name=self.name,
                                     name=self.name):
         settings.update({setting['name']: setting['value']})
     output.update({'App settings': settings})
     urls = {}
     repo_url = 'https://{}.scm.azurewebsites.net/{}.git'.format(
         self.name, self.name)
     urls.update({'Git url': repo_url})
     urls.update({'Website url': repo_url.replace('scm.', '')})
     output.update({'URLs': urls})
     return output
예제 #6
0
def __read_kv_from_app_service(cmd, appservice_account, prefix_to_add=""):
    try:
        key_values = []
        from azure.cli.command_modules.appservice.custom import get_app_settings
        settings = get_app_settings(
            cmd, resource_group_name=appservice_account["resource_group"], name=appservice_account["name"], slot=None)
        for item in settings:
            key = prefix_to_add + item['name']
            value = item['value']
            tags = {'AppService:SlotSetting': str(item['slotSetting']).lower()}
            kv = KeyValue(key=key, value=value, tags=tags)
            key_values.append(kv)
        return key_values
    except Exception as exception:
        raise CLIError(
            "Fail to read key-values from appservice." + str(exception))
예제 #7
0
 def show(self):
     output = {}
     settings = {}
     for setting in get_app_settings(self.__cmd,
                                     resource_group_name=self.name,
                                     name=self.name):
         settings.update({setting['name']: setting['value']})
     output.update({'App settings': settings})
     urls = {}
     repo_url = show_source_control(self.__cmd,
                                    resource_group_name=self.name,
                                    name=self.name).repo_url
     urls.update({'Git url': repo_url})
     urls.update({'Website url': repo_url.replace('scm.', '')})
     output.update({'URLs': urls})
     return output
예제 #8
0
def create_deploy_webapp(cmd, name, location=None, sku=None, dryrun=False):
    import os
    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
    create_new_rg = True
    create_new_asp = True
    set_build_appSetting = False

    # 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 = sku | 'F1'
        os_val = OS_DEFAULT
        detected_version = '-'
        runtime_version = '-'
    else:
        # update SKU to user set value
        if sku is None:
            sku = lang_details.get("default_sku")
        else:
            sku = sku
        language = lang_details.get("language")
        is_skip_build = language.lower(
        ) == STATIC_RUNTIME_NAME or language.lower() == PYTHON_RUNTIME_NAME
        os_val = "Linux" if language.lower() == NODE_RUNTIME_NAME \
            or language.lower() == PYTHON_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 \
            version_used_create != "-" else version_used_create

    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.name)
        location = available_locs[0]
    else:
        location = location
    # Remove spaces from the location string, incase the GeoRegion string is used
    loc_name = location.replace(" ", "").lower()

    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_exists(
            cmd, default_rg) and check_resource_group_supports_os(
                cmd, default_rg, is_linux):
        create_new_rg = False
    elif check_resource_group_exists(
            cmd, rg_name) and check_resource_group_supports_os(
                cmd, rg_name, is_linux):
        create_new_rg = False
    else:
        create_new_rg = True

    src_path = "{} {}".format(src_dir.replace("\\", "\\\\"),
                              str_no_contents_warn)
    rg_str = "{}".format(rg_name)
    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.loads(dry_run_str)

    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")
        return create_json

    # create RG if the RG doesn't already exist
    if create_new_rg:
        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 are creating a new RG we can skip the checks for if asp exists
    if create_new_rg:
        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(location=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")
        create_new_asp = True

    elif not check_if_asp_exists(cmd, rg_name, asp, location):
        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(location=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)
        create_new_asp = True
        logger.warning("App service plan creation complete")
    else:
        logger.warning("App service plan '%s' already exists.", asp)
        create_new_asp = False

    # create the app, skip checks for if app exists if a New RG or New ASP is created
    if create_new_rg or create_new_asp:
        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")
        set_build_appSetting = True
    elif 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")
        set_build_appSetting = True
    else:
        logger.warning("App '%s' already exists", name)
        if do_deployment:
            # setting the appsettings causes a app restart so we avoid if not needed
            set_build_appSetting = False
            _app_settings = get_app_settings(cmd, rg_name, name)
            if all(not d for d in _app_settings):
                set_build_appSetting = True
            elif '"name": "SCM_DO_BUILD_DURING_DEPLOYMENT", "value": "true"' not in json.dumps(
                    _app_settings[0]):
                set_build_appSetting = True
            else:
                set_build_appSetting = False

    # update create_json to include the app_url
    url = _get_app_url(
        cmd, rg_name,
        name)  # picks the custom domain URL incase a domain is assigned

    if do_deployment:
        if not is_skip_build and set_build_appSetting:
            # 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
        # TODO: replace this with a call to check if AppSettings, was set before calling zip deployment
        import time
        time.sleep(5)
        _ping_scm_site(cmd, rg_name, name)

        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("Preparing to deploy %s contents to app.",
                       '' if is_skip_build else 'and build')
        enable_zip_deploy(cmd, rg_name, name, zip_file_path)
        # Remove the file afer deployment, handling exception if user removed the file manually
        try:
            os.remove(zip_file_path)
        except OSError:
            pass
    else:
        logger.warning(
            'No known package (Node, ASP.NET, .NETCORE, or Static Html) '
            'found skipping zip and deploy process')
    create_json.update({'app_url': url})
    logger.warning("All done.")
    return create_json