Webapps: Support for asp.net, Java & static html (#159)
* SUpport for ASP.NET FW:updating to find DOTNET version Fixing logic for version detected & created for dotnot Support for Java * Support for Static HTML file deployment Check the default_RG exists in the current subscription and minor string updates Updating version Pylint fixes Minor fixes
This commit is contained in:
Родитель
3b810b4b13
Коммит
8668d165dc
|
@ -325,9 +325,9 @@
|
||||||
],
|
],
|
||||||
"webapp": [
|
"webapp": [
|
||||||
{
|
{
|
||||||
"filename": "webapp-0.2.3-py2.py3-none-any.whl",
|
"filename": "webapp-0.2.4-py2.py3-none-any.whl",
|
||||||
"sha256Digest": "c6e2c8fff7f3d88f9b7eb77327d67ab525ad9c8b8b27b3b004b565fac391c241",
|
"sha256Digest": "28736466d2602516394d3ed3cd784f318013be7624db8f3fe09012927e7e9de7",
|
||||||
"downloadUrl": "https://github.com/panchagnula/azure-cli-extensions/raw/sisirap-extensions-whl/dist/webapp-0.2.3-py2.py3-none-any.whl",
|
"downloadUrl": "https://github.com/panchagnula/azure-cli-extensions/raw/sisirap-extensions-whl/dist/webapp-0.2.4-py2.py3-none-any.whl",
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"azext.isPreview": true,
|
"azext.isPreview": true,
|
||||||
"azext.minCliCoreVersion": "2.0.24",
|
"azext.minCliCoreVersion": "2.0.24",
|
||||||
|
@ -366,7 +366,7 @@
|
||||||
"metadata_version": "2.0",
|
"metadata_version": "2.0",
|
||||||
"name": "webapp",
|
"name": "webapp",
|
||||||
"summary": "An Azure CLI Extension to manage appservice resources",
|
"summary": "An Azure CLI Extension to manage appservice resources",
|
||||||
"version": "0.2.3"
|
"version": "0.2.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -5,9 +5,14 @@
|
||||||
|
|
||||||
NODE_VERSION_DEFAULT = "8.9"
|
NODE_VERSION_DEFAULT = "8.9"
|
||||||
NETCORE_VERSION_DEFAULT = "2.0"
|
NETCORE_VERSION_DEFAULT = "2.0"
|
||||||
|
DOTNET_VERSION_DEFAULT = "4.7"
|
||||||
|
NETCORE_RUNTIME_NAME = "dotnetcore"
|
||||||
|
DOTNET_RUNTIME_NAME = "aspnet"
|
||||||
|
JAVA_RUNTIME_NAME = "java"
|
||||||
|
OS_DEFAULT = "Windows"
|
||||||
|
STATIC_RUNTIME_NAME = "static" # not an oficial supported runtime but used for CLI logic
|
||||||
# TODO: Remove this once we have the api returning the versions
|
# TODO: Remove this once we have the api returning the versions
|
||||||
NODE_VERSIONS = ['4.4', '4.5', '6.2', '6.6', '6.9', '6.11', '8.0', '8.1']
|
NODE_VERSIONS = ['4.4', '4.5', '6.2', '6.6', '6.9', '6.11', '8.0', '8.1']
|
||||||
NETCORE_VERSIONS = ['1.0', '1.1', '2.0']
|
NETCORE_VERSIONS = ['1.0', '1.1', '2.0']
|
||||||
|
DOTNET_VERSIONS = ['3.5', '4.7']
|
||||||
NODE_RUNTIME_NAME = "node"
|
NODE_RUNTIME_NAME = "node"
|
||||||
NETCORE_RUNTIME_NAME = "dotnetcore"
|
|
||||||
OS_DEFAULT = "Windows"
|
|
||||||
|
|
|
@ -13,7 +13,12 @@ from ._constants import (
|
||||||
NODE_VERSION_DEFAULT,
|
NODE_VERSION_DEFAULT,
|
||||||
NODE_VERSIONS,
|
NODE_VERSIONS,
|
||||||
NETCORE_RUNTIME_NAME,
|
NETCORE_RUNTIME_NAME,
|
||||||
NODE_RUNTIME_NAME)
|
NODE_RUNTIME_NAME,
|
||||||
|
DOTNET_RUNTIME_NAME,
|
||||||
|
DOTNET_VERSION_DEFAULT,
|
||||||
|
DOTNET_VERSIONS,
|
||||||
|
JAVA_RUNTIME_NAME,
|
||||||
|
STATIC_RUNTIME_NAME)
|
||||||
|
|
||||||
|
|
||||||
def _resource_client_factory(cli_ctx, **_):
|
def _resource_client_factory(cli_ctx, **_):
|
||||||
|
@ -57,9 +62,16 @@ def get_runtime_version_details(file_path, lang_name):
|
||||||
# method returns list in DESC, pick the first
|
# method returns list in DESC, pick the first
|
||||||
version_detected = parse_netcore_version(file_path)[0]
|
version_detected = parse_netcore_version(file_path)[0]
|
||||||
version_to_create = detect_netcore_version_tocreate(version_detected)
|
version_to_create = detect_netcore_version_tocreate(version_detected)
|
||||||
|
elif lang_name.lower() == DOTNET_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)
|
||||||
elif lang_name.lower() == NODE_RUNTIME_NAME:
|
elif lang_name.lower() == NODE_RUNTIME_NAME:
|
||||||
version_detected = parse_node_version(file_path)[0]
|
version_detected = parse_node_version(file_path)[0]
|
||||||
version_to_create = detect_node_version_tocreate(version_detected)
|
version_to_create = detect_node_version_tocreate(version_detected)
|
||||||
|
elif lang_name.lower() == STATIC_RUNTIME_NAME:
|
||||||
|
version_detected = "-"
|
||||||
|
version_to_create = "-"
|
||||||
return {'detected': version_detected, 'to_create': version_to_create}
|
return {'detected': version_detected, 'to_create': version_to_create}
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,22 +119,65 @@ def check_app_exists(cmd, rg_name, app_name):
|
||||||
def get_lang_from_content(src_path):
|
def get_lang_from_content(src_path):
|
||||||
import glob
|
import glob
|
||||||
# NODE: package.json should exist in the application root dir
|
# NODE: package.json should exist in the application root dir
|
||||||
# NETCORE: *.csproj should exist in the application root dir
|
# NETCORE & DOTNET: *.csproj should exist in the application dir
|
||||||
|
# NETCORE: <TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
|
# DOTNET: <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||||
runtime_details_dict = dict.fromkeys(['language', 'file_loc', 'default_sku'])
|
runtime_details_dict = dict.fromkeys(['language', 'file_loc', 'default_sku'])
|
||||||
package_json_file = os.path.join(src_path, 'package.json')
|
package_json_file = os.path.join(src_path, 'package.json')
|
||||||
package_netcore_glob = glob.glob("*.csproj")
|
package_netlang_glob = glob.glob("**/*.csproj", recursive=True)
|
||||||
|
runtime_java_file = glob.glob("**/*.war", recursive=True)
|
||||||
|
static_html_file = glob.glob("**/*.html", recursive=True)
|
||||||
if os.path.isfile(package_json_file):
|
if os.path.isfile(package_json_file):
|
||||||
runtime_details_dict['language'] = NODE_RUNTIME_NAME
|
runtime_details_dict['language'] = NODE_RUNTIME_NAME
|
||||||
runtime_details_dict['file_loc'] = package_json_file
|
runtime_details_dict['file_loc'] = package_json_file
|
||||||
runtime_details_dict['default_sku'] = 'S1'
|
runtime_details_dict['default_sku'] = 'S1'
|
||||||
elif package_netcore_glob:
|
elif package_netlang_glob:
|
||||||
package_netcore_file = os.path.join(src_path, package_netcore_glob[0])
|
package_netcore_file = os.path.join(src_path, package_netlang_glob[0])
|
||||||
runtime_details_dict['language'] = NETCORE_RUNTIME_NAME
|
runtime_lang = detect_dotnet_lang(package_netcore_file)
|
||||||
|
runtime_details_dict['language'] = runtime_lang
|
||||||
runtime_details_dict['file_loc'] = package_netcore_file
|
runtime_details_dict['file_loc'] = package_netcore_file
|
||||||
runtime_details_dict['default_sku'] = 'F1'
|
runtime_details_dict['default_sku'] = 'F1'
|
||||||
|
elif runtime_java_file:
|
||||||
|
runtime_details_dict['language'] = JAVA_RUNTIME_NAME
|
||||||
|
runtime_details_dict['file_loc'] = runtime_java_file
|
||||||
|
runtime_details_dict['default_sku'] = 'S1'
|
||||||
|
elif static_html_file:
|
||||||
|
runtime_details_dict['language'] = STATIC_RUNTIME_NAME
|
||||||
|
runtime_details_dict['file_loc'] = static_html_file[0]
|
||||||
|
runtime_details_dict['default_sku'] = 'F1'
|
||||||
return runtime_details_dict
|
return runtime_details_dict
|
||||||
|
|
||||||
|
|
||||||
|
def detect_dotnet_lang(csproj_path):
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
import re
|
||||||
|
parsed_file = ET.parse(csproj_path)
|
||||||
|
root = parsed_file.getroot()
|
||||||
|
version_lang = ''
|
||||||
|
for target_ver in root.iter('TargetFramework'):
|
||||||
|
version_lang = re.sub(r'([^a-zA-Z\s]+?)', '', target_ver.text)
|
||||||
|
if 'netcore' in version_lang.lower():
|
||||||
|
return NETCORE_RUNTIME_NAME
|
||||||
|
else:
|
||||||
|
return DOTNET_RUNTIME_NAME
|
||||||
|
|
||||||
|
|
||||||
|
def parse_dotnet_version(file_path):
|
||||||
|
from xml.dom import minidom
|
||||||
|
import re
|
||||||
|
xmldoc = minidom.parse(file_path)
|
||||||
|
framework_ver = xmldoc.getElementsByTagName('TargetFrameworkVersion')
|
||||||
|
version_detected = ['4.7']
|
||||||
|
target_ver = framework_ver[0].firstChild.data
|
||||||
|
non_decimal = re.compile(r'[^\d.]+')
|
||||||
|
# reduce the version to '5.7.4' from '5.7'
|
||||||
|
if target_ver is not None:
|
||||||
|
# remove the string from the beginning of the version value
|
||||||
|
c = non_decimal.sub('', target_ver)
|
||||||
|
version_detected = c[:3]
|
||||||
|
return version_detected
|
||||||
|
|
||||||
|
|
||||||
def parse_netcore_version(file_path):
|
def parse_netcore_version(file_path):
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
import re
|
import re
|
||||||
|
@ -157,6 +212,15 @@ def detect_netcore_version_tocreate(detected_ver):
|
||||||
return NETCORE_VERSION_DEFAULT
|
return NETCORE_VERSION_DEFAULT
|
||||||
|
|
||||||
|
|
||||||
|
def detect_dotnet_version_tocreate(detected_ver):
|
||||||
|
min_ver = DOTNET_VERSIONS[0]
|
||||||
|
if detected_ver in DOTNET_VERSIONS:
|
||||||
|
return detected_ver
|
||||||
|
elif detected_ver < min_ver:
|
||||||
|
return min_ver
|
||||||
|
return DOTNET_VERSION_DEFAULT
|
||||||
|
|
||||||
|
|
||||||
def detect_node_version_tocreate(detected_ver):
|
def detect_node_version_tocreate(detected_ver):
|
||||||
if detected_ver in NODE_VERSIONS:
|
if detected_ver in NODE_VERSIONS:
|
||||||
return detected_ver
|
return detected_ver
|
||||||
|
|
|
@ -19,7 +19,10 @@ from azure.cli.command_modules.appservice.custom import (
|
||||||
_get_scm_url,
|
_get_scm_url,
|
||||||
get_sku_name,
|
get_sku_name,
|
||||||
list_publish_profiles,
|
list_publish_profiles,
|
||||||
get_site_configs)
|
get_site_configs,
|
||||||
|
config_diagnostics)
|
||||||
|
|
||||||
|
from azure.cli.command_modules.appservice._appservice_utils import _generic_site_operation
|
||||||
|
|
||||||
from .create_util import (
|
from .create_util import (
|
||||||
zip_contents_from_dir,
|
zip_contents_from_dir,
|
||||||
|
@ -33,7 +36,7 @@ from .create_util import (
|
||||||
web_client_factory
|
web_client_factory
|
||||||
)
|
)
|
||||||
|
|
||||||
from ._constants import (NODE_RUNTIME_NAME, OS_DEFAULT)
|
from ._constants import (NODE_RUNTIME_NAME, OS_DEFAULT, JAVA_RUNTIME_NAME, STATIC_RUNTIME_NAME)
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
@ -64,12 +67,14 @@ def create_deploy_webapp(cmd, name, location=None, dryrun=False):
|
||||||
else:
|
else:
|
||||||
sku = lang_details.get("default_sku")
|
sku = lang_details.get("default_sku")
|
||||||
language = lang_details.get("language")
|
language = lang_details.get("language")
|
||||||
os_val = "Linux" if language.lower() == NODE_RUNTIME_NAME else OS_DEFAULT
|
is_java = language.lower() == JAVA_RUNTIME_NAME
|
||||||
|
is_skip_build = is_java or language.lower() == STATIC_RUNTIME_NAME
|
||||||
|
os_val = "Linux" if language.lower() == NODE_RUNTIME_NAME or is_java else OS_DEFAULT
|
||||||
# detect the version
|
# detect the version
|
||||||
data = get_runtime_version_details(lang_details.get('file_loc'), language)
|
data = get_runtime_version_details(lang_details.get('file_loc'), language)
|
||||||
version_used_create = data.get('to_create')
|
version_used_create = data.get('to_create')
|
||||||
detected_version = data.get('detected')
|
detected_version = data.get('detected')
|
||||||
runtime_version = "{}|{}".format(language, version_used_create)
|
runtime_version = "{}|{}".format(language, version_used_create) if version_used_create != "-" else version_used_create
|
||||||
|
|
||||||
if location is None:
|
if location is None:
|
||||||
locs = client.list_geo_regions(sku, True)
|
locs = client.list_geo_regions(sku, True)
|
||||||
|
@ -92,7 +97,7 @@ def create_deploy_webapp(cmd, name, location=None, dryrun=False):
|
||||||
|
|
||||||
# Resource group: check if default RG is set
|
# Resource group: check if default RG is set
|
||||||
default_rg = cmd.cli_ctx.config.get('defaults', 'group', fallback=None)
|
default_rg = cmd.cli_ctx.config.get('defaults', 'group', fallback=None)
|
||||||
if default_rg and check_resource_group_supports_os(cmd, default_rg, location, is_linux):
|
if default_rg and check_resource_group_exists(cmd, default_rg) and check_resource_group_supports_os(cmd, default_rg, location, is_linux):
|
||||||
rg_name = default_rg
|
rg_name = default_rg
|
||||||
rg_mssg = "[Using default Resource group]"
|
rg_mssg = "[Using default Resource group]"
|
||||||
else:
|
else:
|
||||||
|
@ -100,7 +105,6 @@ def create_deploy_webapp(cmd, name, location=None, dryrun=False):
|
||||||
|
|
||||||
src_path = "{} {}".format(src_dir.replace("\\", "\\\\"), str_no_contents_warn)
|
src_path = "{} {}".format(src_dir.replace("\\", "\\\\"), str_no_contents_warn)
|
||||||
rg_str = "{} {}".format(rg_name, rg_mssg)
|
rg_str = "{} {}".format(rg_name, rg_mssg)
|
||||||
|
|
||||||
dry_run_str = r""" {
|
dry_run_str = r""" {
|
||||||
"name" : "%s",
|
"name" : "%s",
|
||||||
"serverfarm" : "%s",
|
"serverfarm" : "%s",
|
||||||
|
@ -143,15 +147,15 @@ def create_deploy_webapp(cmd, name, location=None, dryrun=False):
|
||||||
# create the app
|
# create the app
|
||||||
if not check_app_exists(cmd, rg_name, name):
|
if not check_app_exists(cmd, rg_name, name):
|
||||||
logger.warning("Creating app '%s' ....", name)
|
logger.warning("Creating app '%s' ....", name)
|
||||||
app_created = create_webapp(cmd, rg_name, name, asp, runtime_version if is_linux else None)
|
create_webapp(cmd, rg_name, name, asp, runtime_version if is_linux else None)
|
||||||
# update create_json to include the app_url
|
|
||||||
url = app_created.enabled_host_names[0] # picks the custom domain URL incase a domain is assigned
|
|
||||||
url = 'https://' + url
|
|
||||||
logger.warning("Webapp creation complete")
|
logger.warning("Webapp creation complete")
|
||||||
else:
|
else:
|
||||||
logger.warning("App '%s' already exists", name)
|
logger.warning("App '%s' already exists", name)
|
||||||
|
# update create_json to include the app_url
|
||||||
|
url = _get_app_url(cmd, rg_name, name) # picks the custom domain URL incase a domain is assigned
|
||||||
|
|
||||||
if do_deployment:
|
if do_deployment:
|
||||||
|
if not is_skip_build:
|
||||||
# setting to build after deployment
|
# setting to build after deployment
|
||||||
logger.warning("Updating app settings to enable build after deployment")
|
logger.warning("Updating app settings to enable build after deployment")
|
||||||
update_app_settings(cmd, rg_name, name, ["SCM_DO_BUILD_DURING_DEPLOYMENT=true"])
|
update_app_settings(cmd, rg_name, name, ["SCM_DO_BUILD_DURING_DEPLOYMENT=true"])
|
||||||
|
@ -162,24 +166,29 @@ def create_deploy_webapp(cmd, name, location=None, dryrun=False):
|
||||||
# work around until the timeout limits issue for linux is investigated & fixed
|
# work around until the timeout limits issue for linux is investigated & fixed
|
||||||
user_name, password = _get_site_credential(cmd.cli_ctx, rg_name, name)
|
user_name, password = _get_site_credential(cmd.cli_ctx, rg_name, name)
|
||||||
scm_url = _get_scm_url(cmd, rg_name, name)
|
scm_url = _get_scm_url(cmd, rg_name, name)
|
||||||
|
|
||||||
import urllib3
|
import urllib3
|
||||||
authorization = urllib3.util.make_headers(basic_auth='{0}:{1}'.format(user_name, password))
|
authorization = urllib3.util.make_headers(basic_auth='{0}:{1}'.format(user_name, password))
|
||||||
requests.get(scm_url + '/api/settings', headers=authorization)
|
requests.get(scm_url + '/api/settings', headers=authorization)
|
||||||
|
|
||||||
|
if is_java:
|
||||||
|
zip_file_path = src_path + '\\\\' + lang_details.get('file_loc')[0]
|
||||||
|
else:
|
||||||
logger.warning("Creating zip with contents of dir %s ...", src_dir)
|
logger.warning("Creating zip with contents of dir %s ...", src_dir)
|
||||||
# zip contents & deploy
|
# zip contents & deploy
|
||||||
zip_file_path = zip_contents_from_dir(src_dir, language)
|
zip_file_path = zip_contents_from_dir(src_dir, language)
|
||||||
|
|
||||||
logger.warning("Deploying and building contents to app."
|
logger.warning("Deploying %s contents to app."
|
||||||
"This operation can take some time to finish...")
|
"This operation can take some time to finish...", '' if is_skip_build else 'and building')
|
||||||
enable_zip_deploy(cmd, rg_name, name, zip_file_path)
|
enable_zip_deploy(cmd, rg_name, name, zip_file_path)
|
||||||
|
if not is_java:
|
||||||
# Remove the file afer deployment, handling exception if user removed the file manually
|
# Remove the file afer deployment, handling exception if user removed the file manually
|
||||||
try:
|
try:
|
||||||
os.remove(zip_file_path)
|
os.remove(zip_file_path)
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
logger.warning("No 'NODE' or 'DOTNETCORE' package detected, skipping zip and deploy process")
|
logger.warning("No known package (Node, ASP.NET, .NETCORE, Java or Static Html) found skipping zip and deploy process")
|
||||||
create_json.update({'app_url': url})
|
create_json.update({'app_url': url})
|
||||||
logger.warning("All done.")
|
logger.warning("All done.")
|
||||||
return create_json
|
return create_json
|
||||||
|
@ -247,3 +256,8 @@ def create_tunnel(cmd, resource_group_name, name, port, slot=None):
|
||||||
break
|
break
|
||||||
logger.warning('Tunnel is ready! Creating on port %s', port)
|
logger.warning('Tunnel is ready! Creating on port %s', port)
|
||||||
tunnel_server.start_server()
|
tunnel_server.start_server()
|
||||||
|
|
||||||
|
|
||||||
|
def _get_app_url(cmd, rg_name, app_name):
|
||||||
|
site = _generic_site_operation(cmd.cli_ctx, rg_name, app_name, 'get')
|
||||||
|
return "https://" + site.enabled_host_names[0]
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
from codecs import open
|
from codecs import open
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
VERSION = "0.2.3"
|
VERSION = "0.2.4"
|
||||||
|
|
||||||
CLASSIFIERS = [
|
CLASSIFIERS = [
|
||||||
'Development Status :: 4 - Beta',
|
'Development Status :: 4 - Beta',
|
||||||
|
|
Загрузка…
Ссылка в новой задаче