def launch_cloudshell(shell='bash'): is_current = False latest_azssh = get_latest_azssh() azssh = os.path.join(get_config_dir(), 'azssh') if os.path.isfile(azssh): match = re.search( 'https://github.com/noelbundick/azssh/releases/download/v(?P<version>.*)/(.*).tar.gz', latest_azssh) latest_version = match.group('version') current_version = subprocess.check_output([azssh, 'version' ]).decode("utf-8").strip() logger.info('Current azssh: {}, Latest azssh: {}'.format( current_version, latest_version)) if latest_version == current_version: is_current = True if not is_current: logger.warn('Downloading latest azssh from {}'.format(latest_azssh)) tarball = os.path.join(get_config_dir(), 'azssh.tar.gz') r = requests.get(latest_azssh, allow_redirects=True, stream=True) with open(tarball, 'wb') as f: shutil.copyfileobj(r.raw, f) logger.warn('Extracting tarball: {}'.format(tarball)) with tarfile.open(tarball) as f: f.extractall(path=get_config_dir()) logger.warn('Launching Azure Cloud Shell, type `exit` to disconnect') os.system('{} -s {}'.format(azssh, shell))
def _fzf_get_install_dir(install_dir=None): """ Return the installation directory and check if it's in the PATH. Default: get_config_dir(). """ if not install_dir: install_dir = get_config_dir() else: if _fzf_get_system() == 'Windows': # be verbose, as the install_location likely not in Windows's search PATHs env_paths = os.environ['PATH'].split(';') env_paths_iter = (x for x in env_paths if x.lower().rstrip('\\') == install_dir.lower()) found = next(env_paths_iter, None) if not found: # pylint: disable=logging-format-interpolation,line-too-long LOGGER.warning( 'Please add "{0}" to your search PATH so the `fzf` can be found. 2 options: \n' ' 1. Run "set PATH=%PATH%;{0}" or "$env:path += \'{0}\'" for PowerShell. ' 'This is good for the current command session.\n' ' 2. Update system PATH environment variable by following ' '"Control Panel->System->Advanced->Environment Variables", and re-open the command window. ' 'You only need to do it once'.format(install_dir)) else: LOGGER.warning( 'Please ensure that %s is in your search PATH, so the `fzf` command can' 'be found.', install_dir) return os.path.expanduser(install_dir)
def load_acs_service_principal(subscription_id, file_name='acsServicePrincipal.json'): config_path = os.path.join(get_config_dir(), file_name) config = load_service_principals(config_path) if not config: return None return config.get(subscription_id)
def launch_azbrowse(): config_dir = get_config_dir() executable = "azbrowse" current_platform = platform.system() if current_platform == "Windows": executable += ".exe" azbrowse = os.path.join(config_dir, executable) # azbrowse is self-updating if not os.path.isfile(azbrowse): latest_azbrowse = get_latest_azbrowse(current_platform) LOGGER.warning("Downloading latest azbrowse from %s", latest_azbrowse) r = requests.get(latest_azbrowse, allow_redirects=True, stream=True) if latest_azbrowse.endswith(".zip"): with ZipFile(BytesIO(r.content)) as zipfile: zipfile.extract(executable, path=config_dir) elif latest_azbrowse.endswith(".tar.gz"): with tarfile.open(fileobj=BytesIO(r.content), mode="r:gz") as tar: tar.extract(executable, path=config_dir) os.chmod(azbrowse, 0o755) LOGGER.warning("Launching azbrowse, hit `Ctrl+C` to close") os.system(azbrowse)
def launch_cloudshell(shell="bash"): is_current = False config_dir = get_config_dir() executable = "azssh" current_platform = platform.system() if current_platform == "Windows": executable += ".exe" azssh = os.path.join(config_dir, executable) latest_azssh = get_latest_azssh(current_platform) if os.path.isfile(azssh): match = re.search( "https://github.com/noelbundick/azssh/releases/download/v(?P<version>.*)/(.*).tar.gz", latest_azssh, ) latest_version = match.group("version") current_version = (subprocess.check_output([azssh, "version" ]).decode("utf-8").strip()) LOGGER.info("Current azssh: %s, Latest azssh: %s", current_version, latest_version) if latest_version == current_version: is_current = True if not is_current: LOGGER.warning("Downloading latest azssh from %s", latest_azssh) r = requests.get(latest_azssh, allow_redirects=True, stream=True) with tarfile.open(fileobj=BytesIO(r.content)) as tar: tar.extract("./{}".format(executable), path=config_dir) LOGGER.warning("Launching Azure Cloud Shell, type `exit` to disconnect") os.system("{} -s {}".format(azssh, shell))
def launch_azbrowse(): config_dir = get_config_dir() executable = 'azbrowse' current_platform = platform.system() if current_platform == 'Windows': executable += '.exe' azbrowse = os.path.join(config_dir, executable) # azbrowse is self-updating if not os.path.isfile(azbrowse): latest_azbrowse = get_latest_azbrowse(current_platform) logger.warn('Downloading latest azbrowse from {}'.format(latest_azbrowse)) r = requests.get(latest_azbrowse, allow_redirects=True, stream=True) if latest_azbrowse.endswith('.zip'): with ZipFile(BytesIO(r.content)) as zipfile: zipfile.extract(executable, path=config_dir) elif latest_azbrowse.endswith('.tar.gz'): with tarfile.open(fileobj=BytesIO(r.content), mode='r:gz') as tar: tar.extract(executable, path=config_dir) os.chmod(azbrowse, 0o755) logger.warn('Launching azbrowse, hit `Ctrl+C` to close') os.system(azbrowse)
def show_management_cluster(_cmd, yes=False): # TODO: check to see if a management cluster is specified in the config config = get_default_cli().config # Config can also be set by the AZURE_CAPI_KUBECONFIG environment variable. kubeconfig = config.get("capi", "kubeconfig", fallback=os.environ.get("KUBECONFIG")) if not kubeconfig: raise InvalidArgumentValueError("no kubeconfig") # make a $HOME/.azure/capi directory for storing cluster configurations path = os.path.join(get_config_dir(), "capi") if not os.path.exists(path): os.makedirs(path) command = ["kubectl", "config", "get-contexts", "--no-headers", "--output", "name"] try: output = subprocess.check_output(command, universal_newlines=True) logger.info("%s returned:\n%s", " ".join(command), output) contexts = output.splitlines() logger.info(contexts) except subprocess.CalledProcessError as err: raise UnclassifiedUserFault from err msg = path + "ok" if not yes and prompt_y_n(msg, default="n"): logger.info("yes")
def launch_cloudshell(shell='bash'): is_current = False config_dir = get_config_dir() executable = 'azssh' current_platform = platform.system() if current_platform == 'Windows': executable += '.exe' azssh = os.path.join(config_dir, executable) latest_azssh = get_latest_azssh(current_platform) if os.path.isfile(azssh): match = re.search( 'https://github.com/noelbundick/azssh/releases/download/v(?P<version>.*)/(.*).tar.gz', latest_azssh) latest_version = match.group('version') current_version = subprocess.check_output([azssh, 'version' ]).decode("utf-8").strip() logger.info('Current azssh: {}, Latest azssh: {}'.format( current_version, latest_version)) if latest_version == current_version: is_current = True if not is_current: logger.warn('Downloading latest azssh from {}'.format(latest_azssh)) r = requests.get(latest_azssh, allow_redirects=True, stream=True) with tarfile.open(fileobj=BytesIO(r.content)) as tar: tar.extract('./{}'.format(executable), path=config_dir) logger.warn('Launching Azure Cloud Shell, type `exit` to disconnect') os.system('{} -s {}'.format(azssh, shell))
def cli_execute(self, cmd): """ sends the command to the CLI to be executed """ try: args = parse_quotes(cmd) if args and args[0] == 'feedback': self.config.set_feedback('yes') self.user_feedback = False azure_folder = get_config_dir() if not os.path.exists(azure_folder): os.makedirs(azure_folder) ACCOUNT.load(os.path.join(azure_folder, 'azureProfile.json')) CONFIG.load(os.path.join(azure_folder, 'az.json')) SESSION.load(os.path.join(azure_folder, 'az.sess'), max_age=3600) invocation = self.cli_ctx.invocation_cls( cli_ctx=self.cli_ctx, parser_cls=self.cli_ctx.parser_cls, commands_loader_cls=self.cli_ctx.commands_loader_cls, help_cls=self.cli_ctx.help_cls) if '--progress' in args: args.remove('--progress') execute_args = [args] thread = Thread(target=invocation.execute, args=execute_args) thread.daemon = True thread.start() self.threads.append(thread) self.curr_thread = thread progress_args = [self] thread = Thread(target=progress_view, args=progress_args) thread.daemon = True thread.start() self.threads.append(thread) result = None else: result = invocation.execute(args) self.last_exit = 0 if result and result.result is not None: if self.output: self.output.write(result) self.output.flush() else: formatter = self.cli_ctx.output.get_formatter( self.cli_ctx.invocation.data['output']) self.cli_ctx.output.out(result, formatter=formatter, out_file=sys.stdout) self.last = result except Exception as ex: # pylint: disable=broad-except self.last_exit = handle_exception(ex) except SystemExit as ex: self.last_exit = int(ex.code)
def cli_execute(self, cmd): """ sends the command to the CLI to be executed """ try: args = parse_quotes(cmd) if args and args[0] == 'feedback': self.config.set_feedback('yes') self.user_feedback = False azure_folder = get_config_dir() if not os.path.exists(azure_folder): os.makedirs(azure_folder) ACCOUNT.load(os.path.join(azure_folder, 'azureProfile.json')) CONFIG.load(os.path.join(azure_folder, 'az.json')) SESSION.load(os.path.join(azure_folder, 'az.sess'), max_age=3600) invocation = self.cli_ctx.invocation_cls(cli_ctx=self.cli_ctx, parser_cls=self.cli_ctx.parser_cls, commands_loader_cls=self.cli_ctx.commands_loader_cls, help_cls=self.cli_ctx.help_cls) if '--progress' in args: args.remove('--progress') execute_args = [args] thread = Thread(target=invocation.execute, args=execute_args) thread.daemon = True thread.start() self.threads.append(thread) self.curr_thread = thread progress_args = [self] thread = Thread(target=progress_view, args=progress_args) thread.daemon = True thread.start() self.threads.append(thread) result = None else: result = invocation.execute(args) self.last_exit = 0 if result and result.result is not None: from azure.cli.core._output import OutputProducer if self.output: self.output.write(result) self.output.flush() else: formatter = OutputProducer.get_formatter(self.cli_ctx.invocation.data['output']) OutputProducer(formatter=formatter).out(result) self.last = result except Exception as ex: # pylint: disable=broad-except self.last_exit = handle_exception(ex) except SystemExit as ex: self.last_exit = int(ex.code)
def launch_azbrowse(): azbrowse = os.path.join(get_config_dir(), 'azbrowse') # azbrowse is self-updating if not os.path.isfile(azbrowse): latest_azbrowse = get_latest_azbrowse() logger.warn( 'Downloading latest azbrowse from {}'.format(latest_azbrowse)) r = requests.get(latest_azbrowse, allow_redirects=True, stream=True) with open(azbrowse, 'wb') as f: shutil.copyfileobj(r.raw, f) os.chmod(azbrowse, 0o755) logger.warn('Launching azbrowse, hit `Ctrl+C` to close') os.system(azbrowse)
def store_acs_service_principal(subscription_id, client_secret, service_principal, file_name='acsServicePrincipal.json'): obj = {} if client_secret: obj['client_secret'] = client_secret if service_principal: obj['service_principal'] = service_principal config_path = os.path.join(get_config_dir(), file_name) full_config = load_service_principals(config_path=config_path) if not full_config: full_config = {} full_config[subscription_id] = obj with os.fdopen(os.open(config_path, os.O_RDWR | os.O_CREAT | os.O_TRUNC, 0o600), 'w+') as spFile: json.dump(full_config, spFile)
def _fzf(items, **kwargs): """ Calls the fzf finder with the correct arguments and input. Keyword arguments are available to override most FZF settings. # Search options exact (switch) case_insensitive (switch) case_sensitive (switch) nth (string) with_nth (string) delimiter (string) sort (switch) reverse_input (switch) tiebreak (string) # Interface options multi (switch) no_mouse (switch) cycle (switch) keep_right (switch) no_hscroll (switch) hscroll_off (string) filepath_word (switch) # Layout options layout (string) border (string) prompt (string) header (string) header_lines (integer) # Display ansi (switch) tabstop (string) color (string) no_bold (switch) # Preview preview (string) preview_window (string) # Scripting options query (string) select_1 (switch) exit_0 (switch) filter (string) print_query (switch) """ # Find FZF. Check for get_config_dir() first, then fall back to system path. if shutil.which(_fzf_get_filename(), path=get_config_dir()): executable_path = shutil.which(_fzf_get_filename(), path=get_config_dir()) else: executable_path = shutil.which(_fzf_get_filename(), path=os.environ.get('PATH')) if not executable_path: raise CLIError( 'Couldn\'t find fzf. You can install it via `az fzf install`.') LOGGER.info('Found fzf at %s.', executable_path) # Transformation between python function arguments and fzf command line arguments. fzf_arguments = { 'exact': '--exact', 'case_insensitive': '-i', 'case_sensitive': '+i', 'nth': '--nth={value}', 'with_nth': '--with-nth={value}', 'delimiter': '--delimiter={value}', 'not sort': '--no-sort', 'reverse_input': '--tac', 'tiebreak': '--tiebreak={value}', 'multi': '--multi', 'no_mouse': '--no-mouse', 'cycle': '--cycle', 'keep_right': '--keep-right', 'no_hscroll': '--no-hscroll', 'hscroll_off': '--hscroll-off={value}', 'filepath_word': '--filepath-word', 'layout': '--layout={value}', 'border': '--border={value}', 'prompt': '--prompt={value}', 'header': '--header={value}', 'header_lines': '--header-lines={value}', 'ansi': '--ansi', 'tabstop': '--tabstop={value}', 'color': '--color={value}', 'no_bold': '--no-bold', 'preview': '--preview={value}', 'preview_window': '--preview-window={value}', 'query': '--query={value}', 'select_1': '--select-1', 'exit_0': '--exit-0', 'fzf_filter': '--filter={value}', 'print_query': '--print-query' } # Build arguments list by iterating through kwargs. fzf_command = [executable_path] for key, value in kwargs.items(): if value is not None: fzf_command.append(fzf_arguments[key].format(**locals())) LOGGER.info('fzf command: %s', " ".join(fzf_command)) # Join the items array to a zero-delimited string for better handling # of embedded newlines and special characters items = "\0".join(items) fzf_command.append("--read0") # Open the process, then get the response back and return it. with subprocess.Popen(fzf_command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=None) as fzf: stdout, _ = fzf.communicate(input=items.encode('UTF-8')) output = stdout.decode('UTF-8') LOGGER.info('fzf output: %s', output) return output
FileOperationError, ValidationError, UnclassifiedUserFault, ClientRequestError, InvalidTemplateError, ) # See: https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string _semver_pattern = r"(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?" # pylint: disable=line-too-long # See: https://docs.microsoft.com/azure/azure-resource-manager/templates/template-syntax#template-format _template_schema_pattern = r"https?://schema\.management\.azure\.com/schemas/[0-9a-zA-Z-]+/(?P<templateType>[a-zA-Z]+)Template\.json#?" # pylint: disable=line-too-long _bicep_diagnostic_warning_pattern = r"^([^\s].*)\((\d+)(?:,\d+|,\d+,\d+)?\)\s+:\s+(Warning)\s+([a-zA-Z-\d]+):\s*(.*?)\s+\[(.*?)\]$" # pylint: disable=line-too-long _config_dir = get_config_dir() _bicep_installation_dir = os.path.join(_config_dir, "bin") _bicep_version_check_file_path = os.path.join(_config_dir, "bicepVersionCheck.json") _bicep_version_check_cache_ttl = timedelta(minutes=10) _bicep_version_check_time_format = "%Y-%m-%dT%H:%M:%S.%f" _logger = get_logger(__name__) def validate_bicep_target_scope(template_schema, deployment_scope): target_scope = _template_schema_to_target_scope(template_schema) if target_scope != deployment_scope: raise InvalidTemplateError( f'The target scope "{target_scope}" does not match the deployment scope "{deployment_scope}".' )
def _purge(): for f in os.listdir(get_config_dir()): if re.search("^{}_*".format(INDEX_DIR_PREFIX), f): shutil.rmtree(os.path.join(get_config_dir(), f))
from __future__ import print_function import os import textwrap import shutil import re import six from azure.cli.command_modules.find._gather_commands import build_command_table from azure.cli.core.api import get_config_dir INDEX_DIR_PREFIX = 'search_index' INDEX_VERSION = 'v1' INDEX_PATH = os.path.join(get_config_dir(), '{}_{}'.format(INDEX_DIR_PREFIX, INDEX_VERSION)) def _get_schema(): from whoosh.fields import TEXT, Schema from whoosh.analysis import StemmingAnalyzer stem_ana = StemmingAnalyzer() return Schema( cmd_name=TEXT(stored=True, analyzer=stem_ana, field_boost=1.3), short_summary=TEXT(stored=True, analyzer=stem_ana), long_summary=TEXT(stored=True, analyzer=stem_ana), examples=TEXT(stored=True, analyzer=stem_ana)) def _purge(): for f in os.listdir(get_config_dir()):
from __future__ import print_function import os import textwrap import shutil import re import six from azure.cli.command_modules.find._gather_commands import build_command_table from azure.cli.core.api import get_config_dir INDEX_DIR_PREFIX = 'search_index' INDEX_VERSION = 'v1' INDEX_PATH = os.path.join(get_config_dir(), '{}_{}'.format(INDEX_DIR_PREFIX, INDEX_VERSION)) def _get_schema(): from whoosh.fields import TEXT, Schema from whoosh.analysis import StemmingAnalyzer stem_ana = StemmingAnalyzer() return Schema(cmd_name=TEXT(stored=True, analyzer=stem_ana, field_boost=1.3), short_summary=TEXT(stored=True, analyzer=stem_ana), long_summary=TEXT(stored=True, analyzer=stem_ana), examples=TEXT(stored=True, analyzer=stem_ana))