Skip to content

Commit b1f35f2

Browse files
authored
[Core] BREAKING CHANGE: az extension add/update and az upgrade: Install stable version for extension by default, use preview if unapplicable (#30163)
* switch default value for allow-preview
1 parent 2cb3d51 commit b1f35f2

File tree

8 files changed

+83
-64
lines changed

8 files changed

+83
-64
lines changed

src/azure-cli-core/azure/cli/core/extension/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,3 +380,9 @@ def is_stable_from_metadata(item):
380380
return not (item["metadata"].get(EXT_METADATA_ISPREVIEW, False) or
381381
item["metadata"].get(EXT_METADATA_ISEXPERIMENTAL, False) or
382382
is_preview_from_semantic_version(item["metadata"]['version']))
383+
384+
385+
def is_preview_from_metadata(item):
386+
return bool(item["metadata"].get(EXT_METADATA_ISPREVIEW, False) or
387+
item["metadata"].get(EXT_METADATA_ISEXPERIMENTAL, False) or
388+
is_preview_from_semantic_version(item["metadata"]['version']))

src/azure-cli-core/azure/cli/core/extension/_resolve.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
from packaging.version import parse
66
from typing import Callable, List, NamedTuple, Union
77

8-
from azure.cli.core.extension import ext_compat_with_cli, WHEEL_INFO_RE, is_stable_from_metadata
8+
from azure.cli.core.extension import (ext_compat_with_cli, WHEEL_INFO_RE,
9+
is_stable_from_metadata, is_preview_from_metadata)
910
from azure.cli.core.extension._index import get_index_extensions
1011

1112
from knack.log import get_logger
@@ -104,6 +105,28 @@ def resolve_from_index(extension_name, cur_version=None, index_url=None, target_
104105
if not candidates:
105106
raise NoExtensionCandidatesError(f"No extension found with name '{extension_name}'")
106107

108+
if allow_preview is None:
109+
# default value of allow-preview changed from true to false
110+
# and the following part deals with two influenced scenariors if user does not specify allow-preview
111+
# 1. if extension module does not have any stable version, set allow-preview=True and display warning message to
112+
# unblock those extension module user
113+
# 2. if extension module has a later preview version than stable one, dispaly a warning message to user
114+
# indicating how to try the newer preview one, but allow-preview is still set to be False by default
115+
allow_preview = False
116+
stable_candidates = list(filter(is_stable_from_metadata, candidates))
117+
preview_candidates = list(filter(is_preview_from_metadata, candidates))
118+
if len(stable_candidates) == 0:
119+
logger.warning("No stable version of '%s' to install. Preview versions allowed.", extension_name)
120+
allow_preview = True
121+
elif len(preview_candidates) != 0:
122+
max_preview_item = max(preview_candidates, key=lambda x: parse(x['metadata']['version']))
123+
max_stable_item = max(stable_candidates, key=lambda x: parse(x['metadata']['version']))
124+
if parse(max_preview_item['metadata']['version']) > parse(max_stable_item['metadata']['version']):
125+
logger.warning("Extension '%s' has a later preview version to install, add `--allow-preview True` "
126+
"to try preview version.", extension_name)
127+
else:
128+
logger.info("No preview versions need to be tried.")
129+
107130
# Helper to curry predicate functions
108131
def list_filter(f):
109132
return lambda cs: list(filter(f, cs))
@@ -120,7 +143,7 @@ def list_filter(f):
120143
_ExtensionFilter(
121144
filter=list_filter(is_stable_from_metadata),
122145
on_empty_results_message=f"No suitable stable version of '{extension_name}' to install. "
123-
f"Add `--allow-preview` to try preview versions"
146+
f"Add `--allow-preview True` to try preview versions"
124147
)]
125148

126149
if target_version:

src/azure-cli-core/azure/cli/core/extension/dynamic_install.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -110,15 +110,15 @@ def _get_extension_run_after_dynamic_install_config(cli_ctx):
110110

111111

112112
def _get_extension_allow_preview_install_config(cli_ctx):
113-
default_value = True
114-
if cli_ctx and cli_ctx.config.get('extension', 'dynamic_install_allow_preview', None) is None:
115-
logger.warning("Preview version of extension is enabled by default for extension installation now. "
116-
"Will be disabled in future release. ")
117-
logger.warning("Please run 'az config set extension.dynamic_install_allow_preview=true or false' "
118-
"to config it specifically. ")
119-
dynamic_install_allow_preview = cli_ctx.config.getboolean('extension',
120-
'dynamic_install_allow_preview',
121-
default_value) if cli_ctx else default_value
113+
dynamic_install_allow_preview = None
114+
if cli_ctx:
115+
if cli_ctx.config.get('extension', 'dynamic_install_allow_preview', None) is None:
116+
logger.warning("Preview version of extension is disabled by default for extension installation, "
117+
"enabled for modules without stable versions. ")
118+
logger.warning("Please run 'az config set extension.dynamic_install_allow_preview=true or false' "
119+
"to config it specifically. ")
120+
else:
121+
dynamic_install_allow_preview = cli_ctx.config.getboolean('extension', 'dynamic_install_allow_preview')
122122
return dynamic_install_allow_preview
123123

124124

src/azure-cli-core/azure/cli/core/extension/operations.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -306,12 +306,6 @@ def check_version_compatibility(azext_metadata):
306306
def add_extension(cmd=None, source=None, extension_name=None, index_url=None, yes=None, # pylint: disable=unused-argument, too-many-statements
307307
pip_extra_index_urls=None, pip_proxy=None, system=None,
308308
version=None, cli_ctx=None, upgrade=None, allow_preview=None):
309-
if allow_preview is None:
310-
logger.warning("Default enabled including preview versions for extension installation now. "
311-
"Disabled in future release. "
312-
"Use '--allow-preview true' to enable it specifically if needed. "
313-
"Use '--allow-preview false' to install stable version only. ")
314-
allow_preview = True
315309
ext_sha256 = None
316310
update_to_latest = version == 'latest' and not source
317311

@@ -405,12 +399,6 @@ def show_extension(extension_name):
405399

406400

407401
def update_extension(cmd=None, extension_name=None, index_url=None, pip_extra_index_urls=None, pip_proxy=None, allow_preview=None, cli_ctx=None, version=None, download_url=None, ext_sha256=None):
408-
if allow_preview is None:
409-
logger.warning("Default enabled including preview versions for extension installation now. "
410-
"Disabled in future release. "
411-
"Use '--allow-preview true' to enable it specifically if needed. "
412-
"Use '--allow-preview false' to install stable version only. ")
413-
allow_preview = True
414402
try:
415403
cmd_cli_ctx = cli_ctx or cmd.cli_ctx
416404
ext = get_extension(extension_name, ext_type=WheelExtension)

src/azure-cli-core/azure/cli/core/tests/test_extension.py

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -323,15 +323,9 @@ def test_add_list_show_preview_extension(self):
323323
self.assertEqual(ext["version"], "2.0.0a1")
324324
remove_extension("ml")
325325

326-
def test_add_preview_extension_by_default(self):
326+
def test_add_stable_extension_by_default(self):
327327
test_ext_source = _get_test_data_file('extension_test_pkg-1.2.3-py3-none-any.whl')
328-
with mock.patch('azure.cli.core.extension.operations.logger') as mock_logger:
329-
add_extension(cmd=self.cmd, source=test_ext_source)
330-
call_args = mock_logger.warning.call_args
331-
self.assertEqual("Default enabled including preview versions for extension installation now. "
332-
"Disabled in future release. "
333-
"Use '--allow-preview true' to enable it specifically if needed. "
334-
"Use '--allow-preview false' to install stable version only. ", call_args[0][0])
328+
add_extension(cmd=self.cmd, source=test_ext_source)
335329
ext = show_extension("extension-test-pkg")
336330
self.assertEqual(ext["name"], "extension-test-pkg")
337331
self.assertEqual(ext["version"], "1.2.3")
@@ -395,9 +389,47 @@ def test_add_extension_preview_inavailable(self):
395389
from knack.util import CLIError
396390
with mock.patch('azure.cli.core.extension._resolve.get_index_extensions',
397391
return_value=mocked_index_data):
398-
with self.assertRaisesRegex(CLIError, "No suitable stable version of 'extension-test-pkg' to install. Add `--allow-preview` to try preview versions"):
392+
with self.assertRaisesRegex(CLIError, "No suitable stable version of 'extension-test-pkg' to install. Add `--allow-preview True` to try preview versions"):
399393
add_extension(cmd=self.cmd, extension_name=extension_name, allow_preview=False)
400394

395+
with mock.patch('azure.cli.core.extension._resolve.logger') as mock_logger:
396+
add_extension(cmd=self.cmd, extension_name=extension_name)
397+
call_args = mock_logger.warning.call_args
398+
self.assertEqual("No stable version of '%s' to install. Preview versions allowed.", call_args[0][0])
399+
self.assertEqual(extension_name, call_args[0][1])
400+
self.assertEqual(mock_logger.warning.call_count, 1)
401+
ext = show_extension(extension_name)
402+
self.assertEqual(ext["name"], extension_name)
403+
self.assertEqual(ext["version"], "1.4.1a1")
404+
remove_extension(extension_name)
405+
406+
def test_add_extension_with_later_preview(self):
407+
extension_name = "extension-test-pkg"
408+
extension1 = 'extension_test_pkg-1.0.0b1-py3-none-any.whl'
409+
extension2 = 'extension_test_pkg-1.2.3-py3-none-any.whl'
410+
extension3 = 'extension_test_pkg-1.4.1a1-py3-none-any.whl'
411+
412+
mocked_index_data = {
413+
extension_name: [
414+
mock_ext(extension1, version='1.0.0b1', download_url=_get_test_data_file(extension1)),
415+
mock_ext(extension2, version='1.2.3', download_url=_get_test_data_file(extension2)),
416+
mock_ext(extension3, version='1.4.1a1', download_url=_get_test_data_file(extension3))
417+
]
418+
}
419+
from knack.util import CLIError
420+
with mock.patch('azure.cli.core.extension._resolve.get_index_extensions',
421+
return_value=mocked_index_data):
422+
with mock.patch('azure.cli.core.extension._resolve.logger') as mock_logger:
423+
add_extension(cmd=self.cmd, extension_name=extension_name)
424+
call_args = mock_logger.warning.call_args
425+
self.assertEqual("Extension '%s' has a later preview version to install, add `--allow-preview True` to try preview version.", call_args[0][0])
426+
self.assertEqual(extension_name, call_args[0][1])
427+
self.assertEqual(mock_logger.warning.call_count, 1)
428+
ext = show_extension(extension_name)
429+
self.assertEqual(ext["name"], extension_name)
430+
self.assertEqual(ext["version"], "1.2.3")
431+
remove_extension(extension_name)
432+
401433
def test_update_extension_with_preview(self):
402434
extension_name = "extension-test-pkg"
403435
extension1 = 'extension_test_pkg-1.0.0b1-py3-none-any.whl'

src/azure-cli/azure/cli/command_modules/extension/_breaking_change.py

Lines changed: 0 additions & 12 deletions
This file was deleted.

src/azure-cli/azure/cli/command_modules/util/_breaking_change.py

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/azure-cli/azure/cli/command_modules/util/custom.py

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -172,20 +172,12 @@ def upgrade_version(cmd, update_all=None, yes=None, allow_preview=None): # pyli
172172

173173
if exts:
174174
logger.warning("Upgrading extensions")
175-
if allow_preview is None:
176-
logger.warning("Default enabled including preview versions for extension installation now. "
177-
"Disabled in future release. "
178-
"Use '--allow-preview-extensions true' to enable it specifically if needed. "
179-
"Use '--allow-preview-extensions false' to install stable version only. ")
180-
allow_preview = True
181175
for ext_name in exts:
182176
try:
183177
logger.warning("Checking update for %s", ext_name)
184178
cmds = ['az', 'extension', 'update', '-n', ext_name]
185-
if allow_preview:
186-
cmds += ["--allow-preview", "true"]
187-
else:
188-
cmds += ["--allow-preview", "false"]
179+
if allow_preview is not None:
180+
cmds += ["--allow-preview", str(allow_preview)]
189181
subprocess.call(cmds, shell=platform.system() == 'Windows')
190182
except Exception as ex: # pylint: disable=broad-except
191183
msg = "Extension {} update failed during az upgrade. {}".format(ext_name, str(ex))

0 commit comments

Comments
 (0)