-
Notifications
You must be signed in to change notification settings - Fork 3.3k
[Extension] Support automatically installing an extension if the extension of a command is not installed #14478
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Extension] Support automatically installing an extension if the extension of a command is not installed #14478
Conversation
|
Extension |
arrownj
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to add test for this change ?
| cmd_list = self.prog.split() + self._raw_arguments | ||
| command_str = roughly_parse_command(cmd_list[1:]) | ||
| ext_name = self._search_in_extension_commands(command_str) | ||
| if ext_name: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if ext_name is None ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If ext_name is None, error_msg will be None and below code will use the {prog}: '{value}' is not in the '{prog}' command group. for error message.
…azure-cli into dynamic_extension_install
Test added. |
arrownj
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
| return None | ||
|
|
||
| def _get_extension_use_dynamic_install_config(self): | ||
| cli_ctx = self.cli_ctx or (self.cli_help.cli_ctx if self.cli_help else None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cli_ctx seems could be None and then line 342 would crash.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
line 342 has the logic if cli_ctx else 'no' to handle None, it will use 'no' as the value.
| verify=(not should_disable_connection_verify()), | ||
| timeout=300) | ||
| except Exception as ex: # pylint: disable=broad-except | ||
| logger.info("Request failed for extension command tree: %s", str(ex)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would log at warning level be better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now, let's just fall back to previous behavior when something is wrong as the warning may confuse users when they only typed a wrong command.
| EXT_CMD_TREE.data = response.json() | ||
| EXT_CMD_TREE.save_with_retry() | ||
| else: | ||
| logger.info("Error when retrieving extension command tree. Response code: %s", response.status_code) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would log at warning level be better?
Description
When a command failed in
parser._check_valuedue to a command word is not in the choice list of its previous word, such asaz vm abcwould fail becauseabcis not a choice undervm. This failure could be caused by:az accuont showor usegetinstead of the correctshow.Previously, we cannot tell the difference and the error message is like this:
This PR adds a search for the unmatched command in all the extension commands if a close match for the wrong command is not found in all module commands (indicating it's not likely a typo). If the command (not including options) matches a complete extension command, based on config, we can automatically install the extension with or without prompt. Then the command will continue to run by default or users can choose to rerun by themselves.
A mapping of all extension commands to extension names will be fetched from a storage account and stored in ~/.azure/extCmdIndex.json. It is valid for 10 days and will only be refreshed when a parse error happens. An example of the file:
Configuration:
Both config options are under extension section:
use_dynamic_install
yes_prompt: it will use dynamic extension install and prompt to user whether they would like to install the needed extension.
yes_without_prompt: it will install the needed extension directly without confirmation from users.
no: it falls back to previous behavior and just throws an error. This is the default for now.
run_after_dynamic_install
yes/true: It’s the default and will continue to run the command after extension is installed.
no/false: It will stop when extension is installed and ask the user to rerun the command.
You can also set with environment variables (AZURE_EXTENSION_USE_DYNAMIC_INSTALL, AZURE_EXTENSION_RUN_AFTER_DYNAMIC_INSTALL)and they have higher priority.
Testing Guide
1.set env var to turn on the feature:
export AZURE_EXTENSION_USE_DYNAMIC_INSTALL=yes_promt
2.run a command from an extension not installed to chekc the behavior.
3.run a real error command to chekc the new clear error message.
This checklist is used to make sure that common guidelines for a pull request are followed.
The PR title and description has followed the guideline in Submitting Pull Requests.
I adhere to the Command Guidelines.