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
14 changes: 11 additions & 3 deletions src/azure-cli/azure/cli/command_modules/appservice/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -7618,7 +7618,7 @@ def remove_delimiters(cls, runtime):
return cls.DEFAULT_DELIMETER.join(filter(None, runtime))

def resolve(self, display_name, linux=False):
display_name = display_name.lower()
display_name = self._standardize_node_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 @@ -7707,6 +7707,13 @@ def _format_windows_display_text(cls, display_text):
t = re.sub(r"\(.*\)", "", t) # remove "(LTS)"
return t.replace(" ", "|", 1).replace(" ", "")

@staticmethod
def _standardize_node_runtime_name(runtime_name):
match = re.fullmatch(r'node\|(\d+)(?:-?lts)?', runtime_name, re.IGNORECASE)
if match and int(match.group(1)) >= 26:
return "NODE|{}".format(match.group(1))
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 @@ -7908,6 +7915,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 = self.Runtime(display_name=runtime_name, linux=False,
os="Windows", runtime_family=runtime_family,
Expand Down Expand Up @@ -8019,9 +8027,9 @@ 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 = settings.runtime_version
runtime_name = self._standardize_node_runtime_name(settings.runtime_version)
runtime = self.Runtime(display_name=runtime_name,
configs={"linux_fx_version": runtime_name},
configs={"linux_fx_version": settings.runtime_version},
linux=True,
os="Linux",
runtime_family=runtime_family,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1643,6 +1643,74 @@ def __len__(self):
return len(self._data)


class TestStackRuntimeNodeStandardization(unittest.TestCase):
@staticmethod
def _new_helper():
from azure.cli.command_modules.appservice.custom import _StackRuntimeHelper
helper = _StackRuntimeHelper.__new__(_StackRuntimeHelper)
helper._linux = True
helper._windows = True
helper._include_eol = False
helper._stacks = []
helper.windows_config_mappings = {'node': 'WEBSITE_NODE_DEFAULT_VERSION'}
return helper

@staticmethod
def _node_stack(version, display_text, linux_runtime):
git_hub_action_settings = types.SimpleNamespace(is_supported=True, supported_version="{}.x".format(version))
linux_settings = types.SimpleNamespace(
runtime_version=linux_runtime,
is_hidden=False,
is_deprecated=False,
end_of_life_date=None,
git_hub_action_settings=git_hub_action_settings,
)
windows_settings = types.SimpleNamespace(
runtime_version="~{}".format(version),
is_hidden=False,
is_deprecated=False,
end_of_life_date=None,
git_hub_action_settings=git_hub_action_settings,
)
minor = types.SimpleNamespace(
display_text=display_text,
stack_settings=types.SimpleNamespace(
linux_container_settings=None,
linux_runtime_settings=linux_settings,
windows_container_settings=None,
windows_runtime_settings=windows_settings,
),
)
major = types.SimpleNamespace(display_text=display_text, minor_versions=[minor])
return types.SimpleNamespace(display_text='Node', major_versions=[major])

def test_node_26_uses_standard_identifier_on_both_platforms(self):
helper = self._new_helper()
helper._parse_raw_stacks([self._node_stack('26', 'Node 26 LTS', 'NODE|26-lts')])

self.assertEqual(
[(runtime.os, runtime.display_name) for runtime in helper._stacks],
[('Linux', 'NODE|26'), ('Windows', 'NODE|26')])
self.assertEqual(
[(row['os'], row['config']) for row in helper.get_stacks_as_table(runtime_filter='node')],
[('Linux', 'NODE|26'), ('Windows', 'NODE|26')])
self.assertEqual(helper.resolve('NODE|26', linux=True).configs['linux_fx_version'], 'NODE|26-lts')
self.assertEqual(
helper.resolve('NODE|26', linux=False).configs['WEBSITE_NODE_DEFAULT_VERSION'], '~26')
self.assertEqual(
helper.resolve('NODE|26-lts', linux=True).configs['linux_fx_version'], 'NODE|26-lts')
self.assertEqual(
helper.resolve('NODE|26LTS', linux=False).configs['WEBSITE_NODE_DEFAULT_VERSION'], '~26')

def test_older_node_identifiers_remain_unchanged(self):
helper = self._new_helper()
helper._parse_raw_stacks([self._node_stack('24', 'Node 24 LTS', 'NODE|24-lts')])

self.assertEqual(
[(runtime.os, runtime.display_name) for runtime in helper._stacks],
[('Linux', 'NODE|24-lts'), ('Windows', 'NODE|24LTS')])


class TestStackRuntimeJavaSELinux(unittest.TestCase):
"""Regression tests for `az webapp list-runtimes` Linux Java SE parsing.

Expand Down