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)
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)
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.")
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)