Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 25 additions & 5 deletions src/azure-cli/azure/cli/command_modules/appservice/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@
from ._constants import (FUNCTIONS_STACKS_API_KEYS, FUNCTIONS_LINUX_RUNTIME_VERSION_REGEX,
FUNCTIONS_WINDOWS_RUNTIME_VERSION_REGEX, PUBLIC_CLOUD,
LINUX_GITHUB_ACTIONS_WORKFLOW_TEMPLATE_PATH, WINDOWS_GITHUB_ACTIONS_WORKFLOW_TEMPLATE_PATH,
DOTNET_RUNTIME_NAME, NETCORE_RUNTIME_NAME, ASPDOTNET_RUNTIME_NAME, LINUX_OS_NAME,
DOTNET_RUNTIME_NAME, NETCORE_RUNTIME_NAME, ASPDOTNET_RUNTIME_NAME, NODE_RUNTIME_NAME,
LINUX_OS_NAME,
WINDOWS_OS_NAME, LINUX_FUNCTIONAPP_GITHUB_ACTIONS_WORKFLOW_TEMPLATE_PATH,
WINDOWS_FUNCTIONAPP_GITHUB_ACTIONS_WORKFLOW_TEMPLATE_PATH, DEFAULT_CENTAURI_IMAGE,
VERSION_2022_09_01, FLEX_SUBNET_DELEGATION,
Expand Down Expand Up @@ -8297,7 +8298,7 @@ def remove_delimiters(cls, runtime):
return cls.DEFAULT_DELIMETER.join(filter(None, runtime))

def resolve(self, display_name, linux=False):
display_name = self.standardize_node_runtime_name(display_name).lower()
display_name = self.standardize_runtime_name(display_name).lower()
stack = next((s for s in self.stacks if s.linux == linux and s.display_name.lower() == display_name), None)
if stack is None: # help convert previously acceptable stack names into correct ones if runtime not found
old_to_new_windows = {
Expand Down Expand Up @@ -8393,6 +8394,25 @@ def standardize_node_runtime_name(runtime_name):
return "NODE|{}".format(match.group(1))
return runtime_name

@staticmethod
def standardize_dotnet_runtime_name(runtime_name):
match = re.fullmatch(r'dotnet(?:core)?\|(\d+)(?:\.0)?', runtime_name, re.IGNORECASE)
if match and int(match.group(1)) >= 11:
return "dotnet|{}".format(match.group(1))
return runtime_name

@classmethod
def standardize_runtime_name(cls, runtime_name):
if not runtime_name:
return runtime_name

runtime_family = runtime_name.split(cls.DEFAULT_DELIMETER, 1)[0].lower()
if runtime_family == NODE_RUNTIME_NAME:
return cls.standardize_node_runtime_name(runtime_name)
if runtime_family in (DOTNET_RUNTIME_NAME, NETCORE_RUNTIME_NAME):
return cls.standardize_dotnet_runtime_name(runtime_name)
return runtime_name

@classmethod
def _is_valid_runtime_setting(cls, runtime_setting, include_eol=False):
# Using datetime module imported at the top level
Expand Down Expand Up @@ -8594,7 +8614,7 @@ def _parse_major_version_windows(self, major_version, parsed_results, config_map
eol_date = self._format_eol_date(getattr(settings, 'end_of_life_date', None))
if "Java" not in minor_version.display_text:
runtime_name = self._format_windows_display_text(minor_version.display_text)
runtime_name = self.standardize_node_runtime_name(runtime_name)
runtime_name = self.standardize_runtime_name(runtime_name)

runtime = self.Runtime(display_name=runtime_name, linux=False,
os="Windows", runtime_family=runtime_family,
Expand Down Expand Up @@ -8706,7 +8726,7 @@ def _parse_major_version_linux(self, major_version, parsed_results, seen_runtime
major_version, linux=True, java=False, include_eol=self._include_eol)
for minor_version in minor_versions:
settings = minor_version.stack_settings.linux_runtime_settings
runtime_name = self.standardize_node_runtime_name(settings.runtime_version)
runtime_name = self.standardize_runtime_name(settings.runtime_version)
runtime = self.Runtime(display_name=runtime_name,
configs={"linux_fx_version": runtime_name},
linux=True,
Expand Down Expand Up @@ -12547,7 +12567,7 @@ def add_github_actions(cmd, resource_group, name, repo, runtime=None, token=None
branch='master', login_with_github=False, force=False):
runtime = _StackRuntimeHelper(cmd).remove_delimiters(runtime) # normalize "runtime:version"
if runtime:
runtime = _StackRuntimeHelper.standardize_node_runtime_name(runtime)
runtime = _StackRuntimeHelper.standardize_runtime_name(runtime)
if not token and not login_with_github:
raise_missing_token_suggestion()
elif not token:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2319,6 +2319,81 @@ def __len__(self):
return len(self._data)


class TestStackRuntimeDotnetLinux(unittest.TestCase):

@staticmethod
def _new_helper(runtime_name):
from azure.cli.command_modules.appservice.custom import _StackRuntimeHelper
helper = _StackRuntimeHelper.__new__(_StackRuntimeHelper)
helper._include_eol = False
helper._stacks = [
helper.Runtime(
display_name=runtime_name,
configs={'linux_fx_version': runtime_name},
linux=True)
]
return helper

def test_resolve_legacy_dotnet_11_with_canonical_catalog(self):
helper = self._new_helper('dotnet|11')

runtime = helper.resolve('DOTNETCORE|11.0', linux=True)

self.assertEqual(runtime.display_name, 'dotnet|11')
self.assertEqual(runtime.configs['linux_fx_version'], 'dotnet|11')

def test_standardize_dotnet_runtime_name(self):
from azure.cli.command_modules.appservice.custom import _StackRuntimeHelper
test_cases = {
'DOTNETCORE|11.0': 'dotnet|11',
'dotnet|11': 'dotnet|11',
'DOTNET|11.0': 'dotnet|11',
'DOTNETCORE|12.0': 'dotnet|12',
'DOTNETCORE|10.0': 'DOTNETCORE|10.0',
}

for runtime_name, expected in test_cases.items():
with self.subTest(runtime_name=runtime_name):
self.assertEqual(
_StackRuntimeHelper.standardize_dotnet_runtime_name(runtime_name),
expected)

def test_standardize_runtime_name_selects_dotnet_standardizer(self):
from azure.cli.command_modules.appservice.custom import _StackRuntimeHelper

with mock.patch.object(
_StackRuntimeHelper,
'standardize_node_runtime_name',
wraps=_StackRuntimeHelper.standardize_node_runtime_name) as node_standardizer:
self.assertEqual(
_StackRuntimeHelper.standardize_runtime_name('DOTNETCORE|11.0'),
'dotnet|11')

node_standardizer.assert_not_called()

def test_parse_legacy_dotnet_11_catalog_as_canonical(self):
helper = self._new_helper('placeholder')
parsed_results = []
github_settings = types.SimpleNamespace(is_supported=True, supported_version='11.x')
settings = types.SimpleNamespace(
runtime_version='DOTNETCORE|11.0',
end_of_life_date=None,
git_hub_action_settings=github_settings)
minor_version = types.SimpleNamespace(
display_text='.NET 11 (STS)',
stack_settings=types.SimpleNamespace(linux_runtime_settings=settings))

with mock.patch.object(helper, '_get_valid_minor_versions', side_effect=[[], [minor_version]]):
helper._parse_major_version_linux(
types.SimpleNamespace(display_text='.NET 11'),
parsed_results,
set(),
runtime_family='.NET')

self.assertEqual(parsed_results[0].display_name, 'dotnet|11')
self.assertEqual(parsed_results[0].configs['linux_fx_version'], 'dotnet|11')


class TestStackRuntimeNodeStandardization(unittest.TestCase):
@staticmethod
def _new_helper():
Expand Down
Loading