Esempio n. 1
0
    def show_version(self):
        from azure.cli.core.util import get_az_version_string
        from azure.cli.core.commands.constants import (SURVEY_PROMPT, SURVEY_PROMPT_COLOR,
                                                       UX_SURVEY_PROMPT, UX_SURVEY_PROMPT_COLOR)

        ver_string, updates_available = get_az_version_string()
        print(ver_string)
        if updates_available == -1:
            logger.warning('Unable to check if your CLI is up-to-date. Check your internet connection.')
        elif updates_available:
            warning_msg = 'You have %i updates available. Consider updating your CLI installation'
            from azure.cli.core._environment import _ENV_AZ_INSTALLER
            installer = os.getenv(_ENV_AZ_INSTALLER)
            instruction_msg = ''
            if installer in _PACKAGE_UPGRADE_INSTRUCTIONS:
                if installer == 'RPM':
                    from azure.cli.core.util import get_linux_distro
                    distname, _ = get_linux_distro()
                    if not distname:
                        instruction_msg = '. {}'.format(_GENERAL_UPGRADE_INSTRUCTION)
                    else:
                        distname = distname.lower().strip()
                        if any(x in distname for x in ['centos', 'rhel', 'red hat', 'fedora']):
                            installer = 'YUM'
                        elif any(x in distname for x in ['opensuse', 'suse', 'sles']):
                            installer = 'ZYPPER'
                        else:
                            instruction_msg = '. {}'.format(_GENERAL_UPGRADE_INSTRUCTION)
                elif installer == 'PIP':
                    import platform
                    system = platform.system()
                    alternative_command = " or '{}' if you used our script for installation. Detailed instructions can be found at {}".format(_PACKAGE_UPGRADE_INSTRUCTIONS[installer][0], _PACKAGE_UPGRADE_INSTRUCTIONS[installer][1]) if system != 'Windows' else ''
                    instruction_msg = " with 'pip install --upgrade azure-cli'{}".format(alternative_command)
                if instruction_msg:
                    warning_msg += instruction_msg
                else:
                    warning_msg += " with '{}'. Detailed instructions can be found at {}".format(_PACKAGE_UPGRADE_INSTRUCTIONS[installer][0], _PACKAGE_UPGRADE_INSTRUCTIONS[installer][1])
            else:
                warning_msg += '. {}'.format(_GENERAL_UPGRADE_INSTRUCTION)
            logger.warning(warning_msg, updates_available)
        else:
            print('Your CLI is up-to-date.')
        show_link = self.config.getboolean('output', 'show_survey_link', True)
        if show_link:
            print('\n' + (SURVEY_PROMPT_COLOR if self.enable_color else SURVEY_PROMPT))
            print(UX_SURVEY_PROMPT_COLOR if self.enable_color else UX_SURVEY_PROMPT)
Esempio n. 2
0
def _install_deps_for_psycopg2():  # pylint: disable=too-many-statements
    # Below system dependencies are required to install the psycopg2 dependency for Linux and macOS
    import platform
    import subprocess
    from azure.cli.core.util import get_linux_distro
    from azure.cli.core._environment import _ENV_AZ_INSTALLER
    installer = os.getenv(_ENV_AZ_INSTALLER)
    system = platform.system()
    if system == 'Darwin':
        subprocess.call(['xcode-select', '--install'],
                        stdout=subprocess.DEVNULL,
                        stderr=subprocess.DEVNULL)
        if installer != 'HOMEBREW':
            from shutil import which
            if which('brew') is None:
                logger.warning(
                    'You may need to install postgresql with homebrew first before you install this extension.'
                )
                return
        exit_code = subprocess.call(['brew', 'list', 'postgresql'],
                                    stdout=subprocess.DEVNULL,
                                    stderr=subprocess.DEVNULL)
        if exit_code != 0:
            update_cmd = ['brew', 'install', 'postgresql']
            logger.warning(
                'This extension depends on postgresql and it will be installed first.'
            )
            logger.debug("Install dependencies with '%s'",
                         " ".join(update_cmd))
            subprocess.call(update_cmd)
        # Fix the issue of -lssl not found during building psycopg2
        if os.environ.get('LIBRARY_PATH') is None:
            os.environ['LIBRARY_PATH'] = '/usr/local/opt/openssl/lib/'
        else:
            os.environ['LIBRARY_PATH'] = os.pathsep.join([
                os.environ.get('LIBRARY_PATH'), '/usr/local/opt/openssl/lib/'
            ])
    elif system == 'Linux':
        distname, _ = get_linux_distro()
        distname = distname.lower().strip()
        if installer == 'DEB' or any(x in distname
                                     for x in ['ubuntu', 'debian']):
            from azure.cli.core.util import in_cloud_console
            if in_cloud_console():
                raise CLIError(
                    "This extension is not supported in Cloud Shell as you do not have permission to install extra dependencies."
                )
            exit_code = subprocess.call(
                ['dpkg', '-s', 'gcc', 'libpq-dev', 'python3-dev'],
                stdout=subprocess.DEVNULL,
                stderr=subprocess.DEVNULL)
            if exit_code != 0:
                logger.warning(
                    'This extension depends on gcc, libpq-dev, python3-dev and they will be installed first.'
                )
                apt_update_cmd = 'apt-get update'.split()
                apt_install_cmd = 'apt-get install -y gcc libpq-dev python3-dev'.split(
                )
                if os.geteuid() != 0:  # pylint: disable=no-member
                    apt_update_cmd.insert(0, 'sudo')
                    apt_install_cmd.insert(0, 'sudo')
                exit_code = subprocess.call(apt_update_cmd, True)
                if exit_code == 0:
                    logger.debug("Install dependencies with '%s'",
                                 " ".join(apt_install_cmd))
                    subprocess.call(apt_install_cmd, True)
        elif installer == 'RPM' or any(x in distname for x in [
                'centos', 'rhel', 'red hat', 'fedora', 'opensuse', 'suse',
                'sles'
        ]):
            if any(x in distname
                   for x in ['centos', 'rhel', 'red hat', 'fedora']):
                yum_install_cmd = 'yum install -y gcc postgresql-devel python3-devel'.split(
                )
                if os.geteuid() != 0:  # pylint: disable=no-member
                    yum_install_cmd.insert(0, 'sudo')
                logger.debug("Install dependencies with '%s'",
                             " ".join(yum_install_cmd))
                logger.warning(
                    'This extension depends on gcc, postgresql-devel, python3-devel and they will be installed first if not exist.'
                )
                subprocess.call(yum_install_cmd)
            elif any(x in distname for x in ['opensuse', 'suse', 'sles']):
                zypper_refresh_cmd = ['zypper', 'refresh']
                zypper_install_cmd = 'zypper install -y gcc postgresql-devel python3-devel'.split(
                )
                logger.warning(
                    'This extension depends on gcc postgresql-devel, python3-devel and they will be installed first if not exist.'
                )
                if os.geteuid() != 0:  # pylint: disable=no-member
                    zypper_refresh_cmd.insert(0, 'sudo')
                    zypper_install_cmd.insert(0, 'sudo')
                exit_code = subprocess.call(zypper_refresh_cmd)
                if exit_code == 0:
                    logger.debug("Install dependencies with '%s'",
                                 " ".join(zypper_install_cmd))
                    subprocess.call(zypper_install_cmd)
Esempio n. 3
0
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 os
    import platform
    import sys
    import subprocess
    import azure.cli.core.telemetry as 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 distutils.version import LooseVersion
    from knack.util import CLIError

    update_cli = True
    from azure.cli.core.util import get_latest_from_github
    try:
        latest_version = get_latest_from_github()
        if latest_version and LooseVersion(latest_version) <= LooseVersion(
                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
        if not yes:
            confirmation = prompt_y_n(
                "Please check the release notes first: https://docs.microsoft.com/"
                "cli/azure/release-notes-azure-cli\nDo you want to continue?",
                default='y')
            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(apt_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.warning("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':
            logger.debug(
                "Update azure cli with MSI from https://aka.ms/installazurecliwindows"
            )
            exit_code = subprocess.call(['powershell.exe', '-NoProfile', "Start-Process msiexec.exe -Wait -ArgumentList '/i https://aka.ms/installazurecliwindows'"])  # pylint: disable=line-too-long
        else:
            logger.warning(UPGRADE_MSG)
    if exit_code:
        telemetry.set_failure("CLI upgrade failed.")
        sys.exit(exit_code)
    # Updating Azure CLI and extension together is not supported in homebrewe package.
    if installer == 'HOMEBREW' and exts:
        logger.warning("Please rerun 'az upgrade' to update all extensions.")
    else:
        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)

    logger.warning("Upgrade finished.")
Esempio n. 4
0
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 os
    import platform
    import sys
    import subprocess
    import azure.cli.core.telemetry as 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
    from knack.util import CLIError

    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':
            logger.debug(
                "Update azure cli with MSI from https://aka.ms/installazurecliwindows"
            )
            exit_code = subprocess.call(['powershell.exe', '-NoProfile', "Start-Process msiexec.exe -Wait -ArgumentList '/i https://aka.ms/installazurecliwindows'"])  # pylint: disable=line-too-long
        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)