Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,24 @@
import os

NODE_VERSION_DEFAULT = "10.14"
NODE_VERSION_NEWER = "12-lts"
NODE_EXACT_VERSION_DEFAULT = "10.14.1"
NETCORE_VERSION_DEFAULT = "3.1"
DOTNET_VERSION_DEFAULT = "4.7"
ASPDOTNET_VERSION_DEFAULT = "4.8"
DOTNET_VERSION_DEFAULT = "5.0"
DOTNET_TARGET_FRAMEWORK_STRING = "net5.0"
PYTHON_VERSION_DEFAULT = "3.7"
NETCORE_RUNTIME_NAME = "dotnetcore"
DOTNET_RUNTIME_NAME = "aspnet"
ASPDOTNET_RUNTIME_NAME = "aspnet"
DOTNET_RUNTIME_NAME = "dotnet"
NODE_RUNTIME_NAME = "node"
PYTHON_RUNTIME_NAME = "python"
OS_DEFAULT = "Windows"
STATIC_RUNTIME_NAME = "static" # not an official supported runtime but used for CLI logic
NODE_VERSIONS = ['10.6', '10.14']
PYTHON_VERSIONS = ['3.8', '3.7', '3.6']
NETCORE_VERSIONS = ['2.1', '3.1']
DOTNET_VERSIONS = ['3.5', '4.7']
DOTNET_VERSIONS = ['3.5', '4.8']
LINUX_SKU_DEFAULT = "P1V2"
FUNCTIONS_VERSIONS = ['2', '3']
FUNCTIONS_STACKS_API_JSON_PATHS = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@
from azure.mgmt.web.models import SkuDescription

from ._constants import (NETCORE_VERSION_DEFAULT, NETCORE_VERSIONS, NODE_VERSION_DEFAULT,
NODE_VERSIONS, NETCORE_RUNTIME_NAME, NODE_RUNTIME_NAME, DOTNET_RUNTIME_NAME,
DOTNET_VERSION_DEFAULT, DOTNET_VERSIONS, STATIC_RUNTIME_NAME,
PYTHON_RUNTIME_NAME, PYTHON_VERSION_DEFAULT, LINUX_SKU_DEFAULT, OS_DEFAULT)
NODE_VERSIONS, NETCORE_RUNTIME_NAME, NODE_RUNTIME_NAME, ASPDOTNET_RUNTIME_NAME,
ASPDOTNET_VERSION_DEFAULT, DOTNET_VERSIONS, STATIC_RUNTIME_NAME,
PYTHON_RUNTIME_NAME, PYTHON_VERSION_DEFAULT, LINUX_SKU_DEFAULT, OS_DEFAULT,
NODE_VERSION_NEWER, DOTNET_RUNTIME_NAME, DOTNET_VERSION_DEFAULT,
DOTNET_TARGET_FRAMEWORK_STRING)

logger = get_logger(__name__)

Expand Down Expand Up @@ -73,11 +75,14 @@ def zip_contents_from_dir(dirPath, lang):
def get_runtime_version_details(file_path, lang_name):
version_detected = None
version_to_create = None
if lang_name.lower() == NETCORE_RUNTIME_NAME:
if lang_name.lower() == DOTNET_RUNTIME_NAME:
version_detected = DOTNET_VERSION_DEFAULT
version_to_create = DOTNET_VERSION_DEFAULT
elif lang_name.lower() == NETCORE_RUNTIME_NAME:
# method returns list in DESC, pick the first
version_detected = parse_netcore_version(file_path)[0]
version_to_create = detect_netcore_version_tocreate(version_detected)
elif lang_name.lower() == DOTNET_RUNTIME_NAME:
elif lang_name.lower() == ASPDOTNET_RUNTIME_NAME:
# method returns list in DESC, pick the first
version_detected = parse_dotnet_version(file_path)
version_to_create = detect_dotnet_version_tocreate(version_detected)
Expand Down Expand Up @@ -187,11 +192,17 @@ def detect_dotnet_lang(csproj_path):
parsed_file = ET.parse(csproj_path)
root = parsed_file.getroot()
version_lang = ''
version_full = ''
for target_ver in root.iter('TargetFramework'):
version_full = target_ver.text
version_full = ''.join(version_full.split()).lower()
version_lang = re.sub(r'([^a-zA-Z\s]+?)', '', target_ver.text)

if version_full and version_full.startswith(DOTNET_TARGET_FRAMEWORK_STRING):
return DOTNET_RUNTIME_NAME
if 'netcore' in version_lang.lower():
return NETCORE_RUNTIME_NAME
return DOTNET_RUNTIME_NAME
return ASPDOTNET_RUNTIME_NAME


def parse_dotnet_version(file_path):
Expand Down Expand Up @@ -261,7 +272,7 @@ def detect_dotnet_version_tocreate(detected_ver):
return detected_ver
if detected_ver < min_ver:
return min_ver
return DOTNET_VERSION_DEFAULT
return ASPDOTNET_VERSION_DEFAULT


def detect_node_version_tocreate(detected_ver):
Expand All @@ -274,7 +285,7 @@ def detect_node_version_tocreate(detected_ver):
if major_ver <= 11:
node_ver = NODE_VERSION_DEFAULT
else:
node_ver = '12.9'
node_ver = NODE_VERSION_NEWER
return node_ver


Expand Down
98 changes: 81 additions & 17 deletions src/azure-cli/azure/cli/command_modules/appservice/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,11 @@ def create_webapp(cmd, resource_group_name, name, plan, runtime=None, startup_fi
site_config.app_command_line = startup_file

if runtime:
site_config.linux_fx_version = runtime
match = helper.resolve(runtime)
if not match:
raise CLIError("Linux Runtime '{}' is not supported."
" Please invoke 'az webapp list-runtimes --linux' to cross check".format(runtime))
match['setter'](cmd=cmd, stack=match, site_config=site_config)
elif deployment_container_image_name:
site_config.linux_fx_version = _format_fx_version(deployment_container_image_name)
if name_validation.name_available:
Expand Down Expand Up @@ -177,7 +177,7 @@ def create_webapp(cmd, resource_group_name, name, plan, runtime=None, startup_fi
current_stack = get_current_stack_from_runtime(runtime)

else: # windows webapp without runtime specified
if name_validation.name_available:
if name_validation.name_available: # If creating new webapp
site_config.app_settings.append(NameValuePair(name="WEBSITE_NODE_DEFAULT_VERSION",
value=node_default_version))

Expand All @@ -198,9 +198,7 @@ def create_webapp(cmd, resource_group_name, name, plan, runtime=None, startup_fi
webapp = LongRunningOperation(cmd.cli_ctx)(poller)

if current_stack:
app_metadata = client.web_apps.list_metadata(resource_group_name, name)
app_metadata.properties["CURRENT_STACK"] = current_stack
client.web_apps.update_metadata(resource_group_name, name, kind="app", properties=app_metadata.properties)
_update_webapp_current_stack_property_if_needed(cmd, resource_group_name, name, current_stack)

# Ensure SCC operations follow right after the 'create', no precedent appsetting update commands
_set_remote_or_local_git(cmd, webapp, resource_group_name, name, deployment_source_url,
Expand Down Expand Up @@ -2584,7 +2582,15 @@ def update_site_appsettings(cmd, stack, site_config):
NameValuePair = cmd.get_models('NameValuePair')
if site_config.app_settings is None:
site_config.app_settings = []
site_config.app_settings += [NameValuePair(name=k, value=v) for k, v in stack['configs'].items()]

for k, v in stack['configs'].items():
already_in_appsettings = False
for app_setting in site_config.app_settings:
if app_setting.name == k:
already_in_appsettings = True
app_setting.value = v
if not already_in_appsettings:
site_config.app_settings.append(NameValuePair(name=k, value=v))
return site_config

def _load_stacks_hardcoded(self):
Expand All @@ -2593,6 +2599,8 @@ def _load_stacks_hardcoded(self):
result = []
if self._linux:
result = get_file_json(RUNTIME_STACKS)['linux']
for r in result:
r['setter'] = _StackRuntimeHelper.update_site_config
else: # Windows stacks
result = get_file_json(RUNTIME_STACKS)['windows']
for r in result:
Expand Down Expand Up @@ -3701,18 +3709,26 @@ def webapp_up(cmd, name, resource_group_name=None, plan=None, location=None, sku
using_webapp_up=True, language=language)
_configure_default_logging(cmd, rg_name, name)
else: # for existing app if we might need to update the stack runtime settings
helper = _StackRuntimeHelper(cmd, client, linux=_is_linux)
match = helper.resolve(runtime_version)

if os_name.lower() == 'linux' and site_config.linux_fx_version != runtime_version:
logger.warning('Updating runtime version from %s to %s',
site_config.linux_fx_version, runtime_version)
update_site_configs(cmd, rg_name, name, linux_fx_version=runtime_version)
logger.warning('Waiting for runtime version to propagate ...')
time.sleep(30) # wait for kudu to get updated runtime before zipdeploy. Currently no way to poll for this
elif os_name.lower() == 'windows' and site_config.windows_fx_version != runtime_version:
logger.warning('Updating runtime version from %s to %s',
site_config.windows_fx_version, runtime_version)
update_site_configs(cmd, rg_name, name, windows_fx_version=runtime_version)
logger.warning('Waiting for runtime version to propagate ...')
time.sleep(30) # wait for kudu to get updated runtime before zipdeploy. Currently no way to poll for this
if match and site_config.linux_fx_version != match['configs']['linux_fx_version']:
logger.warning('Updating runtime version from %s to %s',
site_config.linux_fx_version, match['configs']['linux_fx_version'])
update_site_configs(cmd, rg_name, name, linux_fx_version=match['configs']['linux_fx_version'])
logger.warning('Waiting for runtime version to propagate ...')
time.sleep(30) # wait for kudu to get updated runtime before zipdeploy. No way to poll for this
elif not match:
logger.warning('Updating runtime version from %s to %s',
site_config.linux_fx_version, runtime_version)
update_site_configs(cmd, rg_name, name, linux_fx_version=runtime_version)
logger.warning('Waiting for runtime version to propagate ...')
time.sleep(30) # wait for kudu to get updated runtime before zipdeploy. No way to poll for this
elif os_name.lower() == 'windows':
# may need to update stack runtime settings. For node its site_config.app_settings, otherwise site_config
if match:
_update_app_settings_for_windows_if_needed(cmd, rg_name, name, match, site_config, runtime_version)
create_json['runtime_version'] = runtime_version
# Zip contents & Deploy
logger.warning("Creating zip with contents of dir %s ...", src_dir)
Expand Down Expand Up @@ -3740,6 +3756,54 @@ def webapp_up(cmd, name, resource_group_name=None, plan=None, location=None, sku
return create_json


def _update_app_settings_for_windows_if_needed(cmd, rg_name, name, match, site_config, runtime_version):
update_needed = False
if 'node' in runtime_version:
settings = []
for k, v in match['configs'].items():
for app_setting in site_config.app_settings:
if app_setting.name == k and app_setting.value != v:
update_needed = True
settings.append('%s=%s', k, v)
if update_needed:
logger.warning('Updating runtime version to %s', runtime_version)
update_app_settings(cmd, rg_name, name, settings=settings, slot=None, slot_settings=None)
else:
for k, v in match['configs'].items():
if getattr(site_config, k, None) != v:
update_needed = True
setattr(site_config, k, v)
if update_needed:
logger.warning('Updating runtime version to %s', runtime_version)
update_site_configs(cmd,
rg_name,
name,
net_framework_version=site_config.net_framework_version,
php_version=site_config.php_version,
python_version=site_config.python_version,
java_version=site_config.java_version,
java_container=site_config.java_container,
java_container_version=site_config.java_container_version)

current_stack = get_current_stack_from_runtime(runtime_version)
_update_webapp_current_stack_property_if_needed(cmd, rg_name, name, current_stack)

if update_needed:
logger.warning('Waiting for runtime version to propagate ...')
time.sleep(30) # wait for kudu to get updated runtime before zipdeploy. No way to poll for this


def _update_webapp_current_stack_property_if_needed(cmd, resource_group, name, current_stack):
if not current_stack:
return
# portal uses this current_stack value to display correct runtime for windows webapps
client = web_client_factory(cmd.cli_ctx)
app_metadata = client.web_apps.list_metadata(resource_group, name)
if 'CURRENT_STACK' not in app_metadata.properties or app_metadata.properties["CURRENT_STACK"] != current_stack:
app_metadata.properties["CURRENT_STACK"] = current_stack
client.web_apps.update_metadata(resource_group, name, kind="app", properties=app_metadata.properties)


def _ping_scm_site(cmd, resource_group, name, instance=None):
from azure.cli.core.util import should_disable_connection_verify
# wake up kudu, by making an SCM call
Expand Down
Loading