예제 #1
0
def _handle_global_configuration(config):
    # print location of global configuration
    print(MSG_GLOBAL_SETTINGS_LOCATION.format(config.config_path))
    # set up the config parsers
    file_config = config.config_parser
    config_exists = file_config.read([config.config_path])
    should_modify_global_config = False
    if config_exists:
        # print current config and prompt to allow global config modification
        _print_cur_configuration(file_config)
        should_modify_global_config = prompt_y_n(MSG_PROMPT_MANAGE_GLOBAL, default='n')
        answers['modify_global_prompt'] = should_modify_global_config
    if not config_exists or should_modify_global_config:
        # no config exists yet so configure global config or user wants to modify global config
        output_index = prompt_choice_list(MSG_PROMPT_GLOBAL_OUTPUT, OUTPUT_LIST,
                                          default=get_default_from_config(config.config_parser,
                                                                          'core', 'output',
                                                                          OUTPUT_LIST))
        answers['output_type_prompt'] = output_index
        answers['output_type_options'] = str(OUTPUT_LIST)
        enable_file_logging = prompt_y_n(MSG_PROMPT_FILE_LOGGING, default='n')
        allow_telemetry = prompt_y_n(MSG_PROMPT_TELEMETRY, default='y')
        answers['telemetry_prompt'] = allow_telemetry
        # save the global config
        try:
            config.config_parser.add_section('core')
        except configparser.DuplicateSectionError:
            pass
        try:
            config.config_parser.add_section('logging')
        except configparser.DuplicateSectionError:
            pass
        config.set_value('core', 'output', OUTPUT_LIST[output_index]['name'])
        config.set_value('core', 'collect_telemetry', 'yes' if allow_telemetry else 'no')
        config.set_value('logging', 'enable_log_file', 'yes' if enable_file_logging else 'no')
예제 #2
0
def create(
        client, resource_group_name, account_name, sku_name, kind, location, tags=None, api_properties=None, yes=None):

    terms = 'Notice\nMicrosoft will use data you send to Bing Search Services'\
        ' or the Translator Speech API to improve Microsoft products and services.'\
        'Where you send personal data to these Cognitive Services, you are responsible '\
        'for obtaining sufficient consent from the data subjects.'\
        'The General Privacy and Security Terms in the Online Services Terms '\
        'do not apply to these Cognitive Services.'\
        'Please refer to the Microsoft Cognitive Services section in the Online '\
        'Services Terms'\
        ' (https://www.microsoft.com/en-us/Licensing/product-licensing/products.aspx)'\
        ' for details.'\
        'Microsoft offers policy controls that may be used to disable new Cognitive'\
        ' Services deployments (https://docs.microsoft.com/en-us/azure/cognitive-servic'\
        'es/cognitive-services-apis-create-account).'
    hint = '\nPlease select'
    if yes:
        logger.warning(terms)
    else:
        logger.warning(terms)
        option = prompt_y_n(hint)
        if not option:
            raise CLIError('Operation cancelled.')
    sku = Sku(name=sku_name)

    if api_properties is None:
        properties = {}
    else:
        properties = {"apiProperties": api_properties}
    params = CognitiveServicesAccountCreateParameters(sku=sku, kind=kind, location=location,
                                                      properties=properties, tags=tags)
    return client.create(resource_group_name, account_name, params)
예제 #3
0
def user_confirmation(message, yes=False):
    if yes:
        return
    try:
        if not prompt_y_n(message):
            raise CLIError('Operation cancelled.')
    except NoTTYException:
        raise CLIError('Unable to prompt for confirmation as no tty available. Use --yes.')
예제 #4
0
def _check_wincred(login_server):
    import platform
    if platform.system() == 'Windows':
        import json
        from os.path import expanduser, isfile, join
        docker_directory = join(expanduser('~'), '.docker')
        config_path = join(docker_directory, 'config.json')
        logger.debug("Docker config file path %s", config_path)
        if isfile(config_path):
            with open(config_path) as input_file:
                content = json.load(input_file)
                input_file.close()
            wincred = content.pop('credsStore', None)
            if wincred and wincred.lower() == 'wincred':
                # Ask for confirmation
                from knack.prompting import prompt_y_n, NoTTYException
                message = "This operation will disable wincred and use file system to store docker credentials." \
                          " All registries that are currently logged in will be logged out." \
                          "\nAre you sure you want to continue?"
                try:
                    if prompt_y_n(message):
                        with open(config_path, 'w') as output_file:
                            json.dump(content, output_file, indent=4)
                            output_file.close()
                        return True
                    return False
                except NoTTYException:
                    return False
            # Don't update config file or retry as this doesn't seem to be a wincred issue
            return False
        else:
            import os
            content = {
                "auths": {
                    login_server: {}
                }
            }
            try:
                os.makedirs(docker_directory)
            except OSError:
                pass
            with open(config_path, 'w') as output_file:
                json.dump(content, output_file, indent=4)
                output_file.close()
            return True

    return False
예제 #5
0
def create_account(client, resource_group_name, account_name, sku_name='S0', tags=None, force=None):
    terms = 'By creating an Azure Maps account, you agree that you have read and agree to the ' \
            '\nLicense (https://azure.microsoft.com/en-us/support/legal/) and ' \
            '\nPrivacy Statement (https://privacy.microsoft.com/en-us/privacystatement).'
    hint = 'Please select.'
    client_denied_terms = 'You must agree to the License and Privacy Statement to create an account.'

    # Show ToS message to the user
    logger.warning(terms)

    # Prompt yes/no for the user, if --force parameter is not passed in.
    if not force:
        option = prompt_y_n(hint)
        if not option:
            raise CLIError(client_denied_terms)

    # Submit query
    sku = Sku(name=sku_name)
    maps_account_create_params = MapsAccountCreateParameters(location=ACCOUNT_LOCATION, sku=sku, tags=tags)
    return client.create_or_update(resource_group_name, account_name, maps_account_create_params)
예제 #6
0
파일: custom.py 프로젝트: woakesd/azure-cli
def upgrade_version(cmd, update_all=None, yes=None):  # pylint: disable=too-many-locals, too-many-statements, too-many-branches, no-member, unused-argument
    import platform
    import sys
    import subprocess
    from azure.cli.core import telemetry
    from azure.cli.core import __version__ as local_version
    from azure.cli.core._environment import _ENV_AZ_INSTALLER
    from azure.cli.core.extension import get_extensions, WheelExtension
    from packaging.version import parse

    update_cli = True
    from azure.cli.core.util import get_latest_from_github
    try:
        latest_version = get_latest_from_github()
        if latest_version and parse(latest_version) <= parse(local_version):
            logger.warning("You already have the latest azure-cli version: %s",
                           local_version)
            update_cli = False
            if not update_all:
                return
    except Exception as ex:  # pylint: disable=broad-except
        logger.debug("Failed to get the latest version. %s", str(ex))
    exts = [ext.name for ext in get_extensions(
        ext_type=WheelExtension)] if update_all else []

    exit_code = 0
    installer = os.getenv(_ENV_AZ_INSTALLER) or ''
    installer = installer.upper()
    if update_cli:
        latest_version_msg = 'It will be updated to {}.'.format(latest_version) if yes \
            else 'Latest version available is {}.'.format(latest_version)
        logger.warning("Your current Azure CLI version is %s. %s",
                       local_version, latest_version_msg)
        from knack.prompting import prompt_y_n, NoTTYException
        if not yes:
            logger.warning(
                "Please check the release notes first: https://docs.microsoft.com/"
                "cli/azure/release-notes-azure-cli")
            try:
                confirmation = prompt_y_n("Do you want to continue?",
                                          default='y')
            except NoTTYException:
                from azure.cli.core.azclierror import UnclassifiedUserFault
                raise UnclassifiedUserFault("No tty available.",
                                            "Please run command with --yes.")

            if not confirmation:
                telemetry.set_success("Upgrade stopped by user")
                return

        if installer == 'DEB':
            from azure.cli.core.util import in_cloud_console
            if in_cloud_console():
                raise CLIError("az upgrade is not supported in Cloud Shell.")
            apt_update_cmd = 'apt-get update'.split()
            az_update_cmd = 'apt-get install --only-upgrade -y azure-cli'.split(
            )
            if os.geteuid() != 0:  # pylint: disable=no-member
                apt_update_cmd.insert(0, 'sudo')
                az_update_cmd.insert(0, 'sudo')
            exit_code = subprocess.call(apt_update_cmd)
            if exit_code == 0:
                logger.debug("Update azure cli with '%s'",
                             " ".join(az_update_cmd))
                exit_code = subprocess.call(az_update_cmd)
        elif installer == 'RPM':
            from azure.cli.core.util import get_linux_distro
            distname, _ = get_linux_distro()
            if not distname:
                logger.warning(UPGRADE_MSG)
            else:
                distname = distname.lower().strip()
                if any(x in distname
                       for x in ['centos', 'rhel', 'red hat', 'fedora']):
                    update_cmd = 'yum update -y azure-cli'.split()
                    if os.geteuid() != 0:  # pylint: disable=no-member
                        update_cmd.insert(0, 'sudo')
                    logger.debug("Update azure cli with '%s'",
                                 " ".join(update_cmd))
                    exit_code = subprocess.call(update_cmd)
                elif any(x in distname for x in ['opensuse', 'suse', 'sles']):
                    zypper_refresh_cmd = ['zypper', 'refresh']
                    az_update_cmd = 'zypper update -y azure-cli'.split()
                    if os.geteuid() != 0:  # pylint: disable=no-member
                        zypper_refresh_cmd.insert(0, 'sudo')
                        az_update_cmd.insert(0, 'sudo')
                    exit_code = subprocess.call(zypper_refresh_cmd)
                    if exit_code == 0:
                        logger.debug("Update azure cli with '%s'",
                                     " ".join(az_update_cmd))
                        exit_code = subprocess.call(az_update_cmd)
                else:
                    logger.warning(UPGRADE_MSG)
        elif installer == 'HOMEBREW':
            logger.debug("Update homebrew formulae")
            exit_code = subprocess.call(['brew', 'update'])
            if exit_code == 0:
                update_cmd = ['brew', 'upgrade', 'azure-cli']
                logger.debug("Update azure cli with '%s'",
                             " ".join(update_cmd))
                exit_code = subprocess.call(update_cmd)
        elif installer == 'PIP':
            pip_args = [
                sys.executable, '-m', 'pip', 'install', '--upgrade',
                'azure-cli', '-vv', '--disable-pip-version-check',
                '--no-cache-dir'
            ]
            logger.debug("Update azure cli with '%s'", " ".join(pip_args))
            exit_code = subprocess.call(pip_args,
                                        shell=platform.system() == 'Windows')
        elif installer == 'DOCKER':
            logger.warning(
                "Exit the container to pull latest image with 'docker pull mcr.microsoft.com/azure-cli' "
                "or run 'pip install --upgrade azure-cli' in this container")
        elif installer == 'MSI':
            exit_code = _upgrade_on_windows()
        else:
            logger.warning(UPGRADE_MSG)
    if exit_code:
        err_msg = "CLI upgrade failed."
        logger.warning(err_msg)
        telemetry.set_failure(err_msg)
        sys.exit(exit_code)

    # Avoid using python modules directly as they may have been changed due to upgrade.
    # If you do need to use them, you may need to reload them and their dependent modules.
    # Otherwise you may have such issue https://github.com/Azure/azure-cli/issues/16952
    import importlib
    import json
    importlib.reload(subprocess)
    importlib.reload(json)

    version_result = subprocess.check_output(
        ['az', 'version', '-o', 'json'], shell=platform.system() == 'Windows')
    version_json = json.loads(version_result)
    new_version = version_json['azure-cli-core']

    if update_cli and new_version == local_version:
        err_msg = "CLI upgrade failed or aborted."
        logger.warning(err_msg)
        telemetry.set_failure(err_msg)
        sys.exit(1)

    if exts:
        logger.warning("Upgrading extensions")
    for ext_name in exts:
        try:
            logger.warning("Checking update for %s", ext_name)
            subprocess.call(['az', 'extension', 'update', '-n', ext_name],
                            shell=platform.system() == 'Windows')
        except Exception as ex:  # pylint: disable=broad-except
            msg = "Extension {} update failed during az upgrade. {}".format(
                ext_name, str(ex))
            raise CLIError(msg)
    auto_upgrade_msg = "You can enable auto-upgrade with 'az config set auto-upgrade.enable=yes'. " \
        "More details in https://docs.microsoft.com/cli/azure/update-azure-cli#automatic-update"
    logger.warning(
        "Upgrade finished.%s", "" if cmd.cli_ctx.config.getboolean(
            'auto-upgrade', 'enable', False) else auto_upgrade_msg)
예제 #7
0
def _check_value_in_extensions(cli_ctx, parser, args, no_prompt):  # pylint: disable=too-many-statements, too-many-locals
    """Check if the command args can be found in extension commands.
       Exit command if the error is caused by an extension not installed.
       Otherwise return.
    """
    # Check if the command is from an extension
    from azure.cli.core.util import roughly_parse_command
    from azure.cli.core.azclierror import NoTTYError
    exit_code = 2
    command_str = roughly_parse_command(args[1:])
    allow_prefix_match = args[-1] == '-h' or args[-1] == '--help'
    ext_name = _search_in_extension_commands(cli_ctx, command_str, allow_prefix_match=allow_prefix_match)
    # ext_name is a list if the input command matches the prefix of one or more extension commands,
    # for instance: `az blueprint` when running `az blueprint -h`
    # ext_name is a str if the input command matches a complete command of an extension,
    # for instance: `az blueprint create`
    if isinstance(ext_name, list):
        if len(ext_name) > 1:
            from knack.prompting import prompt_choice_list, NoTTYException
            prompt_msg = "The command requires the latest version of one of the following " \
                "extensions. You need to pick one to install:"
            try:
                choice_idx = prompt_choice_list(prompt_msg, ext_name)
                ext_name = ext_name[choice_idx]
                no_prompt = True
            except NoTTYException:
                tty_err_msg = "{}{}\nUnable to prompt for selection as no tty available. Please update or " \
                    "install the extension with 'az extension add --upgrade -n <extension-name>'." \
                    .format(prompt_msg, ext_name)
                az_error = NoTTYError(tty_err_msg)
                az_error.print_error()
                az_error.send_telemetry()
                parser.exit(exit_code)
        else:
            ext_name = ext_name[0]
    if not ext_name:
        return

    # If a valid command has parser error, it may be caused by CLI running on a profile that is
    # not 'latest' and the command is not supported in that profile. If this command exists in an extension,
    # CLI will try to download the extension and rerun the command. But the parser will fail again and try to
    # install the extension and rerun the command infinitely. So we need to check if the latest version of the
    # extension is already installed and return if yes as the error is not caused by extension not installed.
    from azure.cli.core.extension import get_extension, ExtensionNotInstalledException
    from azure.cli.core.extension._resolve import resolve_from_index, NoExtensionCandidatesError
    try:
        ext = get_extension(ext_name)
    except ExtensionNotInstalledException:
        pass
    else:
        try:
            resolve_from_index(ext_name, cur_version=ext.version, cli_ctx=cli_ctx)
        except NoExtensionCandidatesError:
            return

    telemetry.set_command_details(command_str,
                                  parameters=AzCliCommandInvoker._extract_parameter_names(args),  # pylint: disable=protected-access
                                  extension_name=ext_name)
    run_after_extension_installed = _get_extension_run_after_dynamic_install_config(cli_ctx)
    prompt_info = ""
    if no_prompt:
        logger.warning('The command requires the extension %s. It will be installed first.', ext_name)
        install_ext = True
    else:  # yes_prompt
        from knack.prompting import prompt_y_n, NoTTYException
        prompt_msg = 'The command requires the extension {}. Do you want to install it now?'.format(ext_name)
        if run_after_extension_installed:
            prompt_msg = '{} The command will continue to run after the extension is installed.' \
                .format(prompt_msg)
        NO_PROMPT_CONFIG_MSG = "Run 'az config set extension.use_dynamic_install=" \
            "yes_without_prompt' to allow installing extensions without prompt."
        try:
            install_ext = prompt_y_n(prompt_msg, default='y')
            if install_ext:
                prompt_info = " with prompt"
                logger.warning(NO_PROMPT_CONFIG_MSG)
        except NoTTYException:
            tty_err_msg = "The command requires the extension {}. " \
                          "Unable to prompt for extension install confirmation as no tty " \
                          "available. {}".format(ext_name, NO_PROMPT_CONFIG_MSG)
            az_error = NoTTYError(tty_err_msg)
            az_error.print_error()
            az_error.send_telemetry()
            parser.exit(exit_code)

    print_error = True
    if install_ext:
        from azure.cli.core.extension.operations import add_extension
        add_extension(cli_ctx=cli_ctx, extension_name=ext_name, upgrade=True)
        if run_after_extension_installed:
            import subprocess
            import platform
            exit_code = subprocess.call(args, shell=platform.system() == 'Windows')
            # In this case, error msg is for telemetry recording purpose only.
            # From UX perspective, the command will rerun in subprocess. Whether it succeeds or fails,
            # mesages will be shown from the subprocess and this process should not print more message to
            # interrupt that.
            print_error = False
            error_msg = ("Extension {} dynamically installed{} and commands will be "
                         "rerun automatically.").format(ext_name, prompt_info)
        else:
            error_msg = 'Extension {} installed{}. Please rerun your command.' \
                .format(ext_name, prompt_info)
    else:
        error_msg = "The command requires the latest version of extension {ext_name}. " \
            "To install, run 'az extension add --upgrade -n {ext_name}'.".format(
                ext_name=ext_name)
    az_error = CommandNotFoundError(error_msg)
    if print_error:
        az_error.print_error()
    az_error.send_telemetry()
    parser.exit(exit_code)
예제 #8
0
 def ext_add_has_confirmed(command_args):
     return bool(
         not command_args.get('source') or
         prompt_y_n('Are you sure you want to install this extension?'))
예제 #9
0
def _interactive_setup():
    from knack.prompting import prompt_y_n, prompt
    while True:
        cli_path = None
        ext_repos = []
        exts = []

        # CLI Installation
        if prompt_y_n('Do you plan to develop CLI modules?'):
            display(
                '\nGreat! Please enter the path to your azure-cli repo or press '
                'RETURN and we will attempt to find it for you.')
            while True:
                cli_path = prompt('\nPath (RETURN to auto-find): ', None)
                cli_path = os.path.abspath(cli_path) if cli_path else None
                CLI_SENTINEL = 'azure-cli.pyproj'
                if not cli_path:
                    cli_path = find_file(CLI_SENTINEL)
                if not cli_path:
                    raise CLIError(
                        'Unable to locate your CLI repo. Things to check:'
                        '\n    Ensure you have cloned the repo. '
                        '\n    Specify the path explicitly with `-c PATH`. '
                        '\n    If you run with `-c` to autodetect, ensure you are running '
                        'this command from a folder upstream of the repo.')
                try:
                    cli_path = _check_path(cli_path, CLI_SENTINEL)
                    display('Found: {}'.format(cli_path))
                    break
                except CLIError as ex:
                    logger.error(ex)
                    continue
        else:
            display(
                '\nOK. We will install the latest `azure-cli` from PyPI then.')

        # Determine extension repos
        if prompt_y_n('\nDo you plan to develop CLI extensions?'):
            display(
                '\nGreat! Input the paths for the extension repos you wish to develop for, one per'
                'line. You can add as many repos as you like. Press RETURN to continue to the next step.'
            )
            while True:
                ext_repo_path = prompt('\nPath (RETURN to continue): ', None)
                if not ext_repo_path:
                    break
                try:
                    _check_repo(os.path.abspath(ext_repo_path))
                except CLIError as ex:
                    logger.error(ex)
                    continue
                ext_repos.append(ext_repo_path)
                display('Repo {} OK.'.format(ext_repo_path))

        if not ext_repos:
            display(
                '\nNo problem! You can always add extension repos later with `azdev extension repo add`.'
            )

        # Determine extensions
        if ext_repos:
            if prompt_y_n(
                    '\nWould you like to install certain extensions by default? '
            ):
                display(
                    '\nGreat! Input the names of the extensions you wish to install, one per '
                    'line. You can add as many repos as you like. Press RETURN to continue to the next step.'
                )
                available_extensions = [x['name'] for x in list_extensions()]
                while True:
                    ext_name = prompt('\nName (RETURN to continue): ', None)
                    if not ext_name:
                        break
                    if ext_name not in available_extensions:
                        logger.error(
                            "Extension '%s' not found. Check the spelling, and make "
                            "sure you added the repo first!", ext_name)
                        continue
                    display('Extension {} OK.'.format(ext_name))
                    exts.append(
                        next(x['path'] for x in list_extensions()
                             if x['name'] == ext_name))
            else:
                display(
                    '\nNo problem! You can always add extensions later with `azdev extension add`.'
                )

        subheading('Summary')
        display('CLI: {}'.format(cli_path if cli_path else 'PyPI'))
        display('Extension repos: {}'.format(' '.join(ext_repos)))
        display('Extensions: \n    {}'.format('\n    '.join(exts)))
        if prompt_y_n('\nProceed with installation? '):
            return cli_path, ext_repos, exts
        display("\nNo problem! Let's start again.\n")
예제 #10
0
def aks_kollect_cmd(
        cmd,  # pylint: disable=too-many-statements,too-many-locals
        client,
        resource_group_name: str,
        name: str,
        storage_account: str,
        sas_token: str,
        container_logs: str,
        kube_objects: str,
        node_logs: str,
        node_logs_windows: str) -> None:
    colorama.init()

    mc = client.get(resource_group_name, name)

    if not which('kubectl'):
        raise CLIError('Can not find kubectl executable in PATH')

    storage_account_id = None
    if storage_account is None:
        print(
            "No storage account specified. Try getting storage account from diagnostic settings"
        )
        storage_account_id = _get_storage_account_from_diag_settings(
            cmd.cli_ctx, resource_group_name, name)
        if storage_account_id is None:
            raise CLIError(
                "A storage account must be specified, since there isn't one in the diagnostic settings."
            )

    from msrestazure.tools import (is_valid_resource_id, parse_resource_id,
                                   resource_id)
    if storage_account_id is None:
        if not is_valid_resource_id(storage_account):
            storage_account_id = resource_id(
                subscription=get_subscription_id(cmd.cli_ctx),
                resource_group=resource_group_name,
                namespace='Microsoft.Storage',
                type='storageAccounts',
                name=storage_account)
        else:
            storage_account_id = storage_account

    if is_valid_resource_id(storage_account_id):
        try:
            parsed_storage_account = parse_resource_id(storage_account_id)
        except CloudError as ex:
            raise CLIError(ex.message)
    else:
        raise CLIError("Invalid storage account id %s" % storage_account_id)

    storage_account_name = parsed_storage_account['name']

    readonly_sas_token = None
    if sas_token is None:
        storage_client = get_storage_client(
            cmd.cli_ctx, parsed_storage_account['subscription'])
        storage_account_keys = storage_client.storage_accounts.list_keys(
            parsed_storage_account['resource_group'], storage_account_name)
        kwargs = {
            'account_name': storage_account_name,
            'account_key': storage_account_keys.keys[0].value
        }
        cloud_storage_client = _cloud_storage_account_service_factory(
            cmd.cli_ctx, kwargs)

        sas_token = cloud_storage_client.generate_shared_access_signature(
            'b', 'sco', 'rwdlacup',
            datetime.datetime.utcnow() + datetime.timedelta(days=1))

        readonly_sas_token = cloud_storage_client.generate_shared_access_signature(
            'b', 'sco', 'rl',
            datetime.datetime.utcnow() + datetime.timedelta(days=1))

        readonly_sas_token = readonly_sas_token.strip('?')

    print()
    print(
        'This will deploy a daemon set to your cluster to collect logs and diagnostic information and '
        f'save them to the storage account '
        f'{colorama.Style.BRIGHT}{colorama.Fore.GREEN}{storage_account_name}{colorama.Style.RESET_ALL} as '
        f'outlined in {_format_hyperlink("http://aka.ms/AKSPeriscope")}.')
    print()
    print(
        'If you share access to that storage account to Azure support, you consent to the terms outlined'
        f' in {_format_hyperlink("http://aka.ms/DiagConsent")}.')
    print()
    if not prompt_y_n('Do you confirm?', default="n"):
        return

    print()
    print("Getting credentials for cluster %s " % name)
    _, temp_kubeconfig_path = tempfile.mkstemp()
    credentialResults = client.list_cluster_admin_credentials(
        resource_group_name, name, None)
    kubeconfig = credentialResults.kubeconfigs[0].value.decode(
        encoding='UTF-8')
    print_or_merge_credentials(temp_kubeconfig_path, kubeconfig, False, None)

    print()
    print("Starts collecting diag info for cluster %s " % name)

    # Base the container name on the fqdn (or private fqdn) of the managed cluster
    container_name = _generate_container_name(mc.fqdn, mc.private_fqdn)
    sas_token = sas_token.strip('?')

    cluster_features = _get_cluster_features(cmd.cli_ctx, resource_group_name,
                                             name)

    run_id = datetime.datetime.utcnow().strftime("%Y-%m-%dT%H-%M-%SZ")
    kustomize_yaml = _get_kustomize_yaml(storage_account_name, sas_token,
                                         container_name, run_id,
                                         cluster_features, container_logs,
                                         kube_objects, node_logs,
                                         node_logs_windows)
    kustomize_folder = tempfile.mkdtemp()
    kustomize_file_path = os.path.join(kustomize_folder, "kustomization.yaml")
    try:
        with os.fdopen(os.open(kustomize_file_path, os.O_RDWR | os.O_CREAT),
                       'w+t') as kustomize_file:
            kustomize_file.write(kustomize_yaml)

        try:
            print()
            print("Cleaning up aks-periscope resources if existing")

            subprocess.call([
                "kubectl", "--kubeconfig", temp_kubeconfig_path, "delete",
                "serviceaccount,configmap,daemonset,secret", "--all", "-n",
                CONST_PERISCOPE_NAMESPACE, "--ignore-not-found"
            ],
                            stderr=subprocess.STDOUT)

            subprocess.call([
                "kubectl", "--kubeconfig", temp_kubeconfig_path, "delete",
                "ClusterRoleBinding", "aks-periscope-role-binding",
                "--ignore-not-found"
            ],
                            stderr=subprocess.STDOUT)

            subprocess.call([
                "kubectl", "--kubeconfig", temp_kubeconfig_path, "delete",
                "ClusterRoleBinding", "aks-periscope-role-binding-view",
                "--ignore-not-found"
            ],
                            stderr=subprocess.STDOUT)

            subprocess.call([
                "kubectl", "--kubeconfig", temp_kubeconfig_path, "delete",
                "ClusterRole", "aks-periscope-role", "--ignore-not-found"
            ],
                            stderr=subprocess.STDOUT)

            subprocess.call([
                "kubectl", "--kubeconfig", temp_kubeconfig_path, "delete",
                "--all", "apd", "-n", CONST_PERISCOPE_NAMESPACE,
                "--ignore-not-found"
            ],
                            stderr=subprocess.DEVNULL)

            subprocess.call([
                "kubectl", "--kubeconfig", temp_kubeconfig_path, "delete",
                "CustomResourceDefinition",
                "diagnostics.aks-periscope.azure.github.com",
                "--ignore-not-found"
            ],
                            stderr=subprocess.STDOUT)

            print()
            print("Deploying aks-periscope")

            subprocess.check_output([
                "kubectl", "--kubeconfig", temp_kubeconfig_path, "apply", "-k",
                kustomize_folder, "-n", CONST_PERISCOPE_NAMESPACE
            ],
                                    stderr=subprocess.STDOUT)
        except subprocess.CalledProcessError as err:
            raise CLIError(err.output)
    finally:
        os.remove(kustomize_file_path)
        os.rmdir(kustomize_folder)

    print()

    token_in_storage_account_url = readonly_sas_token if readonly_sas_token is not None else sas_token
    log_storage_account_url = f"https://{storage_account_name}.blob.core.windows.net/" \
                              f"{container_name}?{token_in_storage_account_url}"

    print(
        f'{colorama.Fore.GREEN}Your logs are being uploaded to storage account {_format_bright(storage_account_name)}'
    )

    print()
    print(
        f'You can download Azure Storage Explorer here '
        f'{_format_hyperlink("https://azure.microsoft.com/en-us/features/storage-explorer/")}'
        f' to check the logs by adding the storage account using the following URL:'
    )
    print(f'{_format_hyperlink(log_storage_account_url)}')

    print()
    if not prompt_y_n('Do you want to see analysis results now?', default="n"):
        print(
            f"You can run 'az aks kanalyze -g {resource_group_name} -n {name}' "
            f"anytime to check the analysis results.")
    else:
        _display_diagnostics_report(temp_kubeconfig_path)
예제 #11
0
 def test_prompt_y_n_default(self, _):
     with mock.patch('knack.prompting._input', return_value=''):
         actual_result = prompt_y_n('Do you accept?', default='y')
         self.assertTrue(actual_result)
예제 #12
0
def create(client,
           resource_group_name,
           account_name,
           sku_name,
           kind,
           location,
           custom_domain=None,
           tags=None,
           api_properties=None,
           assign_identity=False,
           storage=None,
           encryption=None,
           yes=None):

    terms = 'Notice\nMicrosoft will use data you send to Bing Search Services'\
        ' to improve Microsoft products and services.'\
        'Where you send personal data to these Cognitive Services, you are responsible '\
        'for obtaining sufficient consent from the data subjects.'\
        'The General Privacy and Security Terms in the Online Services Terms '\
        'do not apply to these Cognitive Services.'\
        'Please refer to the Microsoft Cognitive Services section in the Online '\
        'Services Terms'\
        ' (https://www.microsoft.com/Licensing/product-licensing/products.aspx)'\
        ' for details.'\
        'Microsoft offers policy controls that may be used to disable new Cognitive'\
        ' Services deployments (https://docs.microsoft.com/azure/cognitive-servic'\
        'es/cognitive-services-apis-create-account).'
    terms_not_police = 'Notice\n' \
                       'I certify that use of this service is not by or for a police department in the United States.'
    hint = 'Please select'
    import re
    pattern = re.compile("^[Bb]ing\\..*$")
    if pattern.match(kind):
        if yes:
            logger.warning(terms)
        else:
            logger.warning(terms)
            option = prompt_y_n(hint)
            if not option:
                raise CLIError('Operation cancelled.')
    if kind.lower() == 'face' or kind.lower() == 'cognitiveservices':
        if yes:
            logger.warning(terms_not_police)
        else:
            logger.warning(terms_not_police)
            option = prompt_y_n(hint)
            if not option:
                raise CLIError('Operation cancelled.')

    sku = Sku(name=sku_name)

    properties = CognitiveServicesAccountProperties()
    if api_properties is not None:
        api_properties = CognitiveServicesAccountApiProperties.deserialize(
            api_properties)
        properties.api_properties = api_properties
    if custom_domain:
        properties.custom_sub_domain_name = custom_domain
    params = CognitiveServicesAccount(sku=sku,
                                      kind=kind,
                                      location=location,
                                      properties=properties,
                                      tags=tags)
    if assign_identity:
        params.identity = Identity(type=IdentityType.system_assigned)

    if storage is not None:
        params.properties.user_owned_storage = json.loads(storage)

    if encryption is not None:
        params.properties.encryption = json.loads(encryption)

    return client.create(resource_group_name, account_name, params)
예제 #13
0
def check_binary(cmd, binary_name, install_binary_method, install=False):
    if not which(binary_name):
        logger.info("%s was not found.", binary_name)
        if install or prompt_y_n(f"Download and install {binary_name}?", default="n"):
            with Spinner(cmd, f"Downloading {binary_name}", f"✓ Downloaded {binary_name}"):
                install_binary_method(cmd)
예제 #14
0
def privatecloud_delete(client: AVSClient, resource_group_name, name, yes=False):
    from knack.prompting import prompt_y_n
    msg = 'This will delete the private cloud. Are you sure?'
    if not yes and not prompt_y_n(msg, default="n"):
        return None
    return client.private_clouds.begin_delete(resource_group_name, name)
예제 #15
0
def _interactive_setup():
    from knack.prompting import prompt_y_n, prompt
    while True:
        cli_path = None
        ext_repos = []
        exts = []

        # CLI Installation
        if prompt_y_n('Do you plan to develop CLI modules?'):
            display(
                "\nGreat! Please enter the path to your azure-cli repo, 'EDGE' to install "
                "the latest developer edge build or simply press "
                "RETURN and we will attempt to find your repo for you.")
            while True:
                cli_path = prompt('\nPath (RETURN to auto-find): ', None)
                cli_path = os.path.abspath(
                    os.path.expanduser(cli_path)) if cli_path else None
                CLI_SENTINEL = 'azure-cli.pyproj'
                if not cli_path:
                    cli_path = find_file(CLI_SENTINEL)
                if not cli_path:
                    raise CLIError(
                        'Unable to locate your CLI repo. Things to check:'
                        '\n    Ensure you have cloned the repo. '
                        '\n    Specify the path explicitly with `-c PATH`. '
                        '\n    If you run with `-c` to autodetect, ensure you are running '
                        'this command from a folder upstream of the repo.')
                try:
                    if cli_path != 'EDGE':
                        cli_path = _check_path(cli_path, CLI_SENTINEL)
                    display('Found: {}'.format(cli_path))
                    break
                except CLIError as ex:
                    logger.error(ex)
                    continue
        else:
            display(
                '\nOK. We will install the latest `azure-cli` from PyPI then.')

        def add_ext_repo(path):
            try:
                _check_repo(path)
            except CLIError as ex:
                logger.error(ex)
                return False
            ext_repos.append(path)
            display('Repo {} OK.'.format(path))
            return True

        # Determine extension repos
        # Allows the user to simply press RETURN to use their cwd, assuming they are in their desired extension
        # repo directory. To use multiple extension repos or identify a repo outside the cwd, they must specify
        # the path.
        if prompt_y_n('\nDo you plan to develop CLI extensions?'):
            display(
                '\nGreat! Input the paths for the extension repos you wish to develop for, one per '
                'line. You can add as many repos as you like. (TIP: to quickly get started, press RETURN to '
                'use your current working directory).')
            first_repo = True
            while True:
                msg = '\nPath ({}): '.format(
                    'RETURN to use current directory'
                    if first_repo else 'RETURN to continue')
                ext_repo_path = prompt(msg, None)
                if not ext_repo_path:
                    if first_repo and not add_ext_repo(os.getcwd()):
                        first_repo = False
                        continue
                    break
                add_ext_repo(os.path.abspath(
                    os.path.expanduser(ext_repo_path)))
                first_repo = False

        display(
            '\nTIP: you can manage extension repos later with the `azdev extension repo` commands.'
        )

        # Determine extensions
        if ext_repos:
            if prompt_y_n(
                    '\nWould you like to install certain extensions by default? '
            ):
                display(
                    '\nGreat! Input the names of the extensions you wish to install, one per '
                    'line. You can add as many repos as you like. Use * to install all extensions. '
                    'Press RETURN to continue to the next step.')
                available_extensions = [x['name'] for x in list_extensions()]
                while True:
                    ext_name = prompt('\nName (RETURN to continue): ', None)
                    if not ext_name:
                        break
                    if ext_name == '*':
                        exts = [x['path'] for x in list_extensions()]
                        break
                    if ext_name not in available_extensions:
                        logger.error(
                            "Extension '%s' not found. Check the spelling, and make "
                            "sure you added the repo first!", ext_name)
                        continue
                    display('Extension {} OK.'.format(ext_name))
                    exts.append(
                        next(x['path'] for x in list_extensions()
                             if x['name'] == ext_name))

            display(
                '\nTIP: you can manage extensions later with the `azdev extension` commands.'
            )

        subheading('Summary')
        display('CLI: {}'.format(cli_path if cli_path else 'PyPI'))
        display('Extension repos: {}'.format(' '.join(ext_repos)))
        display('Extensions: \n    {}'.format('\n    '.join(exts)))
        if prompt_y_n('\nProceed with installation? '):
            return cli_path, ext_repos, exts
        raise CLIError('Installation aborted.')
예제 #16
0
파일: custom.py 프로젝트: woakesd/azure-cli
def sqlvm_update(instance,
                 sql_server_license_type=None,
                 sql_image_sku=None,
                 enable_auto_patching=None,
                 day_of_week=None,
                 maintenance_window_starting_hour=None,
                 maintenance_window_duration=None,
                 enable_auto_backup=None,
                 enable_encryption=False,
                 retention_period=None,
                 storage_account_url=None,
                 prompt=True,
                 storage_access_key=None,
                 backup_password=None,
                 backup_system_dbs=False,
                 backup_schedule_type=None,
                 sql_management_mode=None,
                 full_backup_frequency=None,
                 full_backup_start_time=None,
                 full_backup_window_hours=None,
                 log_backup_frequency=None,
                 enable_key_vault_credential=None,
                 credential_name=None,
                 azure_key_vault_url=None,
                 service_principal_name=None,
                 service_principal_secret=None,
                 connectivity_type=None,
                 port=None,
                 sql_workload_type=None,
                 enable_r_services=None,
                 tags=None,
                 enable_assessment=None,
                 enable_assessment_schedule=None,
                 assessment_weekly_interval=None,
                 assessment_monthly_occurrence=None,
                 assessment_day_of_week=None,
                 assessment_start_time_local=None):
    '''
    Updates a SQL virtual machine.
    '''
    if tags is not None:
        instance.tags = tags
    if sql_server_license_type is not None:
        instance.sql_server_license_type = sql_server_license_type
    if sql_image_sku is not None:
        instance.sql_image_sku = sql_image_sku
    if sql_management_mode is not None and instance.sql_management != "Full":
        from knack.prompting import prompt_y_n
        if not prompt:
            instance.sql_management = sql_management_mode
        else:
            confirmation = prompt_y_n(
                "Upgrading SQL manageability mode to Full will restart the SQL Server. Proceed?"
            )
            if confirmation:
                instance.sql_management = sql_management_mode

    if (enable_auto_patching is not None or day_of_week is not None
            or maintenance_window_starting_hour is not None
            or maintenance_window_duration is not None):

        enable_auto_patching = enable_auto_patching if enable_auto_patching is False else True
        instance.auto_patching_settings = AutoPatchingSettings(
            enable=enable_auto_patching,
            day_of_week=day_of_week,
            maintenance_window_starting_hour=maintenance_window_starting_hour,
            maintenance_window_duration=maintenance_window_duration)

    if (enable_auto_backup is not None or enable_encryption
            or retention_period is not None or storage_account_url is not None
            or storage_access_key is not None or backup_password is not None
            or backup_system_dbs or backup_schedule_type is not None
            or full_backup_frequency is not None
            or full_backup_start_time is not None
            or full_backup_window_hours is not None
            or log_backup_frequency is not None):

        enable_auto_backup = enable_auto_backup if enable_auto_backup is False else True
        if not storage_access_key:
            storage_access_key = prompt_pass('Storage Key: ', confirm=True)
        if enable_encryption and not backup_password:
            backup_password = prompt_pass('Backup Password: '******'Service Principal Secret: ', confirm=True)

        instance.key_vault_credential_settings = KeyVaultCredentialSettings(
            enable=enable_key_vault_credential,
            credential_name=credential_name,
            service_principal_name=service_principal_name,
            service_principal_secret=service_principal_secret,
            azure_key_vault_url=azure_key_vault_url)

    instance.server_configurations_management_settings = ServerConfigurationsManagementSettings(
    )

    if (connectivity_type is not None or port is not None):
        instance.server_configurations_management_settings.sql_connectivity_update_settings = SqlConnectivityUpdateSettings(
            connectivity_type=connectivity_type, port=port)

    if sql_workload_type is not None:
        instance.server_configurations_management_settings.sql_workload_type_update_settings = SqlWorkloadTypeUpdateSettings(
            sql_workload_type=sql_workload_type)

    if enable_r_services is not None:
        instance.server_configurations_management_settings.additional_features_server_configurations = AdditionalFeaturesServerConfigurations(
            is_rservices_enabled=enable_r_services)

    # If none of the settings was modified, reset server_configurations_management_settings to be null
    if (instance.server_configurations_management_settings.
            sql_connectivity_update_settings is None
            and instance.server_configurations_management_settings.
            sql_workload_type_update_settings is None
            and instance.server_configurations_management_settings.
            sql_storage_update_settings is None
            and instance.server_configurations_management_settings.
            additional_features_server_configurations is None):
        instance.server_configurations_management_settings = None

    set_assessment_properties(instance, enable_assessment,
                              enable_assessment_schedule,
                              assessment_weekly_interval,
                              assessment_monthly_occurrence,
                              assessment_day_of_week,
                              assessment_start_time_local)

    return instance
    def process_yaml_github(self):
        does_yaml_file_exist = AzureDevopsBuildProvider.check_github_file(
            self.github_pat, self.github_repository, "azure-pipelines.yml")
        if does_yaml_file_exist and self.overwrite_yaml is None:
            self.logger.warning(
                "There is already an azure-pipelines.yml file in the provided Github repository."
            )
            self.logger.warning(
                "If you are using a yaml file that was not configured "
                "through this command, this command may fail.")
            self.overwrite_yaml = prompt_y_n(
                "Do you want to generate a new one? "
                "(It will be committed to the master branch of the provided repository)"
            )

        # Create and commit the new yaml file to Github without asking
        if not does_yaml_file_exist:
            if self.github_repository:
                self.logger.warning(
                    "Creating a new azure-pipelines.yml for Github repository")
            try:
                AzureDevopsBuildProvider.create_github_yaml(
                    pat=self.github_pat,
                    language=self.functionapp_language,
                    app_type=self.functionapp_type,
                    repository_fullname=self.github_repository)
            except LanguageNotSupportException as lnse:
                raise CLIError(
                    "Sorry, currently this command does not support {language}. To proceed, "
                    "you'll need to configure your build manually at dev.azure.com"
                    .format(language=lnse.message)) from lnse
            except GithubContentNotFound as gcnf:
                raise CLIError(
                    "Sorry, the repository you provided does not exist or "
                    "you do not have sufficient permissions to write to the repository. "
                    "Please provide an access token with the proper permissions."
                ) from gcnf
            except GithubUnauthorizedError as gue:
                raise CLIError(
                    "Sorry, you do not have sufficient permissions to commit "
                    "azure-pipelines.yml to your Github repository.") from gue

        # Overwrite yaml file
        if does_yaml_file_exist and self.overwrite_yaml:
            self.logger.warning(
                "Overwrite azure-pipelines.yml file in the provided Github repository"
            )
            try:
                AzureDevopsBuildProvider.create_github_yaml(
                    pat=self.github_pat,
                    language=self.functionapp_language,
                    app_type=self.functionapp_type,
                    repository_fullname=self.github_repository,
                    overwrite=True)
            except LanguageNotSupportException as lnse:
                raise CLIError(
                    "Sorry, currently this command does not support {language}. To proceed, "
                    "you'll need to configure your build manually at dev.azure.com"
                    .format(language=lnse.message)) from lnse
            except GithubContentNotFound as gcnf:
                raise CLIError(
                    "Sorry, the repository you provided does not exist or "
                    "you do not have sufficient permissions to write to the repository. "
                    "Please provide an access token with the proper permissions."
                ) from gcnf
            except GithubUnauthorizedError as gue:
                raise CLIError(
                    "Sorry, you do not have sufficient permissions to overwrite "
                    "azure-pipelines.yml in your Github repository.") from gue
예제 #18
0
파일: parser.py 프로젝트: xiazhan/azure-cli
    def _check_value(self, action, value):  # pylint: disable=too-many-statements, too-many-locals, too-many-branches
        # Override to customize the error message when a argument is not among the available choices
        # converted value must be one of the choices (if specified)
        if action.choices is not None and value not in action.choices:  # pylint: disable=too-many-nested-blocks
            # self.cli_ctx is None when self.prog is beyond 'az', such as 'az iot'.
            # use cli_ctx from cli_help which is not lost.
            cli_ctx = self.cli_ctx or (self.cli_help.cli_ctx
                                       if self.cli_help else None)

            caused_by_extension_not_installed = False
            command_name_inferred = self.prog
            error_msg = None
            use_dynamic_install = 'no'
            if not self.command_source:
                candidates = []
                args = self.prog.split() + self._raw_arguments
                use_dynamic_install = self._get_extension_use_dynamic_install_config(
                )
                if use_dynamic_install != 'no':
                    # Check if the command is from an extension
                    from azure.cli.core.util import roughly_parse_command
                    command_str = roughly_parse_command(args[1:])
                    ext_name = self._search_in_extension_commands(command_str)
                    # The input command matches the prefix of one or more extension commands
                    if isinstance(ext_name, list):
                        if len(ext_name) > 1:
                            from knack.prompting import prompt_choice_list, NoTTYException
                            prompt_msg = "The command requires the latest version of one of the following " \
                                "extensions. You need to pick one to install:"
                            try:
                                choice_idx = prompt_choice_list(
                                    prompt_msg, ext_name)
                                ext_name = ext_name[choice_idx]
                                use_dynamic_install = 'yes_without_prompt'
                            except NoTTYException:
                                error_msg = "{}{}\nUnable to prompt for selection as no tty available. Please " \
                                    "update or install the extension with 'az extension add --upgrade -n " \
                                    "<extension-name>'.".format(prompt_msg, ext_name)
                                logger.error(error_msg)
                                telemetry.set_user_fault(error_msg)
                                self.exit(2)
                        else:
                            ext_name = ext_name[0]

                    if ext_name:
                        caused_by_extension_not_installed = True
                        telemetry.set_command_details(
                            command_str,
                            parameters=AzCliCommandInvoker.
                            _extract_parameter_names(args),  # pylint: disable=protected-access
                            extension_name=ext_name)
                        run_after_extension_installed = self._get_extension_run_after_dynamic_install_config(
                        )
                        prompt_info = ""
                        if use_dynamic_install == 'yes_without_prompt':
                            logger.warning(
                                'The command requires the extension %s. '
                                'It will be installed first.', ext_name)
                            go_on = True
                        else:
                            from knack.prompting import prompt_y_n, NoTTYException
                            prompt_msg = 'The command requires the extension {}. ' \
                                'Do you want to install it now?'.format(ext_name)
                            if run_after_extension_installed:
                                prompt_msg = '{} The command will continue to run after the extension is installed.' \
                                    .format(prompt_msg)
                            NO_PROMPT_CONFIG_MSG = "Run 'az config set extension.use_dynamic_install=" \
                                "yes_without_prompt' to allow installing extensions without prompt."
                            try:
                                go_on = prompt_y_n(prompt_msg, default='y')
                                if go_on:
                                    prompt_info = " with prompt"
                                    logger.warning(NO_PROMPT_CONFIG_MSG)
                            except NoTTYException:
                                error_msg = "The command requires the extension {}. " \
                                            "Unable to prompt for extension install confirmation as no tty " \
                                            "available. {}".format(ext_name, NO_PROMPT_CONFIG_MSG)
                                go_on = False
                        if go_on:
                            from azure.cli.core.extension.operations import add_extension
                            add_extension(cli_ctx=cli_ctx,
                                          extension_name=ext_name,
                                          upgrade=True)
                            if run_after_extension_installed:
                                import subprocess
                                import platform
                                exit_code = subprocess.call(
                                    args, shell=platform.system() == 'Windows')
                                error_msg = (
                                    "Extension {} dynamically installed{} and commands will be "
                                    "rerun automatically.").format(
                                        ext_name, prompt_info)
                                telemetry.set_user_fault(error_msg)
                                self.exit(exit_code)
                            else:
                                with CommandLoggerContext(logger):
                                    error_msg = 'Extension {} installed{}. Please rerun your command.' \
                                        .format(ext_name, prompt_info)
                                    logger.error(error_msg)
                                    telemetry.set_user_fault(error_msg)
                                self.exit(2)
                        else:
                            error_msg = "The command requires the latest version of extension {ext_name}. " \
                                "To install, run 'az extension add --upgrade -n {ext_name}'.".format(
                                    ext_name=ext_name) if not error_msg else error_msg
                if not error_msg:
                    # parser has no `command_source`, value is part of command itself
                    error_msg = "'{value}' is misspelled or not recognized by the system.".format(
                        value=value)
                az_error = CommandNotFoundError(error_msg)
                if not caused_by_extension_not_installed:
                    candidates = difflib.get_close_matches(value,
                                                           action.choices,
                                                           cutoff=0.7)
                    if candidates:
                        # use the most likely candidate to replace the misspelled command
                        args_inferred = [
                            item if item != value else candidates[0]
                            for item in args
                        ]
                        command_name_inferred = ' '.join(args_inferred).split(
                            '-')[0]

            else:
                # `command_source` indicates command values have been parsed, value is an argument
                parameter = action.option_strings[
                    0] if action.option_strings else action.dest
                error_msg = "{prog}: '{value}' is not a valid value for '{param}'.".format(
                    prog=self.prog, value=value, param=parameter)
                candidates = difflib.get_close_matches(value,
                                                       action.choices,
                                                       cutoff=0.7)
                az_error = InvalidArgumentValueError(error_msg)

            command_arguments = self._get_failure_recovery_arguments(action)
            if candidates:
                az_error.set_recommendation("Did you mean '{}' ?".format(
                    candidates[0]))

            # recommend a command for user
            if not caused_by_extension_not_installed:
                recommender = CommandRecommender(*command_arguments, error_msg,
                                                 cli_ctx)
                recommender.set_help_examples(
                    self.get_examples(command_name_inferred))
                recommendations = recommender.provide_recommendations()
                if recommendations:
                    az_error.set_aladdin_recommendation(recommendations)

                # remind user to check extensions if we can not find a command to recommend
                if isinstance(az_error, CommandNotFoundError) \
                        and not az_error.recommendations and self.prog == 'az' \
                        and use_dynamic_install == 'no':
                    az_error.set_recommendation(EXTENSION_REFERENCE)

            az_error.print_error()
            az_error.send_telemetry()

            self.exit(2)
예제 #19
0
 def test_prompt_y_n_question_no_help_string(self, _):
     with self.assertRaises(StopIteration):
         with mock.patch('knack.prompting._input', side_effect=['?']):
             prompt_y_n('Do you accept?')
예제 #20
0
 def test_prompt_y_n_no_caps(self, _):
     my_response = 'N'
     with mock.patch('knack.prompting._input', return_value=my_response):
         actual_result = prompt_y_n('Do you accept?')
         self.assertFalse(actual_result)
예제 #21
0
def _create_package(prefix,
                    repo_path,
                    is_ext,
                    name='test',
                    display_name=None,
                    display_name_plural=None,
                    required_sdk=None,
                    client_name=None,
                    operation_name=None,
                    sdk_property=None,
                    not_preview=False,
                    local_sdk=None):
    from jinja2 import Environment, PackageLoader

    if local_sdk and required_sdk:
        raise CLIError(
            'usage error: --local-sdk PATH | --required-sdk NAME==VER')

    if name.startswith(prefix):
        name = name[len(prefix):]

    heading('Create CLI {}: {}{}'.format('Extension' if is_ext else 'Module',
                                         prefix, name))

    # package_name is how the item should show up in `pip list`
    package_name = '{}{}'.format(prefix, name.replace(
        '_', '-')) if not is_ext else name
    display_name = display_name or name.capitalize()

    kwargs = {
        'name':
        name,
        'mod_path':
        '{}{}'.format(prefix, name)
        if is_ext else 'azure.cli.command_modules.{}'.format(name),
        'display_name':
        display_name,
        'display_name_plural':
        display_name_plural or '{}s'.format(display_name),
        'loader_name':
        '{}CommandsLoader'.format(name.capitalize()),
        'pkg_name':
        package_name,
        'ext_long_name':
        '{}{}'.format(prefix, name) if is_ext else None,
        'is_ext':
        is_ext,
        'is_preview':
        not not_preview
    }

    new_package_path = os.path.join(repo_path, package_name)
    if os.path.isdir(new_package_path):
        if not prompt_y_n("{} '{}' already exists. Overwrite?".format(
                'Extension' if is_ext else 'Module', package_name),
                          default='n'):
            raise CLIError('aborted by user')

    ext_folder = '{}{}'.format(prefix, name) if is_ext else None

    # create folder tree
    if is_ext:
        _ensure_dir(
            os.path.join(new_package_path, ext_folder, 'tests', 'latest'))
        _ensure_dir(os.path.join(new_package_path, ext_folder,
                                 'vendored_sdks'))
    else:
        _ensure_dir(os.path.join(new_package_path, 'tests', 'latest'))
    env = Environment(loader=PackageLoader('azdev', 'mod_templates'))

    # determine dependencies
    dependencies = []
    if is_ext:
        dependencies.append("'azure-cli-core'")
        if required_sdk:
            _download_vendored_sdk(required_sdk,
                                   path=os.path.join(new_package_path,
                                                     ext_folder,
                                                     'vendored_sdks'))
        elif local_sdk:
            _copy_vendored_sdk(
                local_sdk,
                os.path.join(new_package_path, ext_folder, 'vendored_sdks'))
        sdk_path = None
        if any([local_sdk, required_sdk]):
            sdk_path = '{}{}.vendored_sdks'.format(prefix, package_name)
        kwargs.update({
            'sdk_path': sdk_path,
            'client_name': client_name,
            'operation_name': operation_name,
            'sdk_property': sdk_property or '{}_name'.format(name)
        })
    else:
        if required_sdk:
            version_regex = r'(?P<name>[a-zA-Z-]+)(?P<op>[~<>=]*)(?P<version>[\d.]*)'
            version_comps = re.compile(version_regex).match(required_sdk)
            sdk_kwargs = version_comps.groupdict()
            kwargs.update({
                'sdk_path': sdk_kwargs['name'].replace('-', '.'),
                'client_name': client_name,
                'operation_name': operation_name,
            })
            dependencies.append("'{}'".format(required_sdk))
        else:
            dependencies.append('# TODO: azure-mgmt-<NAME>==<VERSION>')
        kwargs.update({'sdk_property': sdk_property or '{}_name'.format(name)})

    kwargs['dependencies'] = dependencies

    # generate code for root level
    dest_path = new_package_path
    if is_ext:
        root_files = ['HISTORY.rst', 'README.rst', 'setup.cfg', 'setup.py']
        _generate_files(env, kwargs, root_files, dest_path)

    dest_path = dest_path if not is_ext else os.path.join(
        dest_path, ext_folder)
    module_files = [{
        'name': '__init__.py',
        'template': 'module__init__.py'
    }, '_client_factory.py', '_help.py', '_params.py', '_validators.py',
                    'commands.py', 'custom.py']
    if is_ext:
        module_files.append('azext_metadata.json')
    _generate_files(env, kwargs, module_files, dest_path)

    dest_path = os.path.join(dest_path, 'tests')
    blank_init = {'name': '__init__.py', 'template': 'blank__init__.py'}
    _generate_files(env, kwargs, blank_init, dest_path)

    dest_path = os.path.join(dest_path, 'latest')
    test_files = [
        blank_init, {
            'name': 'test_{}_scenario.py'.format(name),
            'template': 'test_service_scenario.py'
        }
    ]
    _generate_files(env, kwargs, test_files, dest_path)

    if is_ext:
        result = pip_cmd('install -e {}'.format(new_package_path),
                         "Installing `{}{}`...".format(prefix, name))
        if result.error:
            raise result.error  # pylint: disable=raising-bad-type
예제 #22
0
 def ext_add_has_confirmed(command_args):
     return bool(not command_args.get('source') or prompt_y_n('Are you sure you want to install this extension?'))
예제 #23
0
 def test_prompt_y_n_empty_response(self, _):
     with self.assertRaises(StopIteration):
         with mock.patch('knack.prompting._input', side_effect=['']):
             prompt_y_n('Do you accept?')