Skip to content

Commit

Permalink
Refactor eol impl and sort based on runtime eol date
Browse files Browse the repository at this point in the history
  • Loading branch information
kamperiadis committed Jan 9, 2025
1 parent 5103af8 commit 54c4130
Show file tree
Hide file tree
Showing 56 changed files with 51,823 additions and 28,900 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ def __init__(self):
self.USE_32_BIT_WORKER_PROC = 'use32BitWorkerProcess'
self.FUNCTIONS_WORKER_RUNTIME = 'FUNCTIONS_WORKER_RUNTIME'
self.GIT_HUB_ACTION_SETTINGS = 'git_hub_action_settings'
self.END_OF_LIFE_DATE = 'endOfLifeDate'


GENERATE_RANDOM_APP_NAMES = os.path.abspath(os.path.join(os.path.abspath(__file__),
Expand Down
61 changes: 24 additions & 37 deletions src/azure-cli/azure/cli/command_modules/appservice/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -4331,7 +4331,7 @@ class _FunctionAppStackRuntimeHelper(_AbstractStackRuntimeHelper):
class Runtime:
def __init__(self, name=None, version=None, is_preview=False, supported_func_versions=None, linux=False,
app_settings_dict=None, site_config_dict=None, app_insights=False, default=False,
github_actions_properties=None):
github_actions_properties=None, end_of_life_date=None):
self.name = name
self.version = version
self.is_preview = is_preview
Expand All @@ -4342,8 +4342,10 @@ def __init__(self, name=None, version=None, is_preview=False, supported_func_ver
self.app_insights = app_insights
self.default = default
self.github_actions_properties = github_actions_properties
self.end_of_life_date = end_of_life_date

self.display_name = "{}|{}".format(name, version) if version else name
self.deprecation_link = LANGUAGE_EOL_DEPRECATION_NOTICES.get(self.display_name, '')

# used for displaying stacks
def to_dict(self):
Expand All @@ -4354,29 +4356,27 @@ def to_dict(self):
d["linux_fx_version"] = self.site_config_dict.linux_fx_version
return d

class RuntimeEOL:
def __init__(self, name=None, version=None, eol=None):
self.name = name
self.version = version
self.eol = eol
self.display_name = "{}|{}".format(name, version)
self.deprecation_link = LANGUAGE_EOL_DEPRECATION_NOTICES.get(self.display_name)

def __init__(self, cmd, linux=False, windows=False):
self.disallowed_functions_versions = {"~1", "~2", "~3"}
self.KEYS = FUNCTIONS_STACKS_API_KEYS()
self.end_of_life_dates = []
super().__init__(cmd, linux=linux, windows=windows)

def validate_end_of_life_date(self, runtime, version):
from dateutil.relativedelta import relativedelta
# we would not be able to validate for a custom runtime
if runtime == 'custom':
return

today = datetime.datetime.now(datetime.timezone.utc)
six_months = today + relativedelta(months=+6)
runtimes_eol = [r for r in self.end_of_life_dates if runtime == r.name]
matched_runtime_eol = next((r for r in runtimes_eol if r.version == version), None)
if matched_runtime_eol:
eol = matched_runtime_eol.eol
runtime_deprecation_link = matched_runtime_eol.deprecation_link or ''
runtimes = [r for r in self.stacks if runtime == r.name]
matched_runtime = next((r for r in runtimes if r.version == version), None)
if matched_runtime:
eol = matched_runtime.end_of_life_date
runtime_deprecation_link = matched_runtime.deprecation_link

if eol is None:
return

if eol < today:
raise ValidationError('{} has reached EOL on {} and is no longer supported. {}'
Expand Down Expand Up @@ -4441,7 +4441,8 @@ def resolve(self, runtime, version=None, functions_version=None, linux=False, di

def get_default_version(self, runtime, functions_version, linux=False):
runtimes = [r for r in self.stacks if r.linux == linux and r.name == runtime]
runtimes.sort(key=lambda r: r.default, reverse=True) # make runtimes with default=True appear first
# sort runtimes by end of life date
runtimes.sort(key=lambda r: r.end_of_life_date or datetime.datetime.min, reverse=True)
for r in runtimes:
if functions_version in r.supported_func_versions:
return r
Expand Down Expand Up @@ -4480,8 +4481,7 @@ def _get_valid_function_versions(self, runtime_settings):
valid_versions.append(self._format_version_name(v))
return valid_versions

def _parse_minor_version(self, runtime_settings, major_version_name, minor_version_name, runtime_to_version,
runtime_to_version_eol):
def _parse_minor_version(self, runtime_settings, major_version_name, minor_version_name, runtime_to_version):
runtime_name = (runtime_settings.app_settings_dictionary.get(self.KEYS.FUNCTIONS_WORKER_RUNTIME) or
major_version_name)
if not runtime_settings.is_deprecated:
Expand All @@ -4494,17 +4494,13 @@ def _parse_minor_version(self, runtime_settings, major_version_name, minor_versi
self.KEYS.APPLICATION_INSIGHTS: runtime_settings.app_insights_settings.is_supported,
self.KEYS.SITE_CONFIG_DICT: runtime_settings.site_config_properties_dictionary,
self.KEYS.IS_DEFAULT: bool(runtime_settings.is_default),
self.KEYS.GIT_HUB_ACTION_SETTINGS: runtime_settings.git_hub_action_settings
self.KEYS.GIT_HUB_ACTION_SETTINGS: runtime_settings.git_hub_action_settings,
self.KEYS.END_OF_LIFE_DATE: runtime_settings.end_of_life_date,
}

runtime_to_version[runtime_name] = runtime_to_version.get(runtime_name, {})
runtime_to_version[runtime_name][minor_version_name] = runtime_version_properties

# obtain end of life date for all runtime versions
if runtime_settings.end_of_life_date is not None:
runtime_to_version_eol[runtime_name] = runtime_to_version_eol.get(runtime_name, {})
runtime_to_version_eol[runtime_name][minor_version_name] = runtime_settings.end_of_life_date

def _create_runtime_from_properties(self, runtime_name, version_name, version_properties, linux):
supported_func_versions = version_properties[self.KEYS.SUPPORTED_EXTENSION_VERSIONS]
return self.Runtime(name=runtime_name,
Expand All @@ -4516,14 +4512,13 @@ def _create_runtime_from_properties(self, runtime_name, version_name, version_pr
app_settings_dict=version_properties[self.KEYS.APP_SETTINGS_DICT],
app_insights=version_properties[self.KEYS.APPLICATION_INSIGHTS],
default=version_properties[self.KEYS.IS_DEFAULT],
github_actions_properties=version_properties[self.KEYS.GIT_HUB_ACTION_SETTINGS]
)
github_actions_properties=version_properties[self.KEYS.GIT_HUB_ACTION_SETTINGS],
end_of_life_date=version_properties[self.KEYS.END_OF_LIFE_DATE])

def _parse_raw_stacks(self, stacks):
# build a map of runtime -> runtime version -> runtime version properties
runtime_to_version_linux = {}
runtime_to_version_windows = {}
runtime_to_version_end_of_life = {}
for runtime in stacks:
for major_version in runtime.major_versions:
for minor_version in major_version.minor_versions:
Expand All @@ -4535,19 +4530,16 @@ def _parse_raw_stacks(self, stacks):
self._parse_minor_version(runtime_settings=linux_settings,
major_version_name=runtime.name,
minor_version_name=runtime_version,
runtime_to_version=runtime_to_version_linux,
runtime_to_version_eol=runtime_to_version_end_of_life)
runtime_to_version=runtime_to_version_linux)

if windows_settings is not None and not windows_settings.is_hidden:
self._parse_minor_version(runtime_settings=windows_settings,
major_version_name=runtime.name,
minor_version_name=runtime_version,
runtime_to_version=runtime_to_version_windows,
runtime_to_version_eol=runtime_to_version_end_of_life)
runtime_to_version=runtime_to_version_windows)

runtime_to_version_linux = self._format_version_names(runtime_to_version_linux)
runtime_to_version_windows = self._format_version_names(runtime_to_version_windows)
runtime_to_version_end_of_life = self._format_version_names(runtime_to_version_end_of_life)

for runtime_name, versions in runtime_to_version_windows.items():
for version_name, version_properties in versions.items():
Expand All @@ -4559,11 +4551,6 @@ def _parse_raw_stacks(self, stacks):
r = self._create_runtime_from_properties(runtime_name, version_name, version_properties, linux=True)
self._stacks.append(r)

for runtime_name, versions in runtime_to_version_end_of_life.items():
for version_name, version_eol in versions.items():
r = self.RuntimeEOL(name=runtime_name, version=version_name, eol=version_eol)
self.end_of_life_dates.append(r)


def get_app_insights_key(cli_ctx, resource_group, name):
appinsights_client = get_mgmt_service_client(cli_ctx, ApplicationInsightsManagementClient)
Expand Down
Loading

0 comments on commit 54c4130

Please sign in to comment.