Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to grab the FRAMEWORK_VERSION for function apps #91

Merged
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
5 changes: 5 additions & 0 deletions Kudu.Core/Deployment/Generator/SiteBuilderFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public ISiteBuilder CreateBuilder(ITracer tracer, ILogger logger, IDeploymentSet
return new BasicBuilder(_environment, settings, _propertyProvider, repositoryRoot, projectPath);
}

// If ENABLE_ORYX_BUILD is not set, for function app, we assume it on by default
string enableOryxBuild = System.Environment.GetEnvironmentVariable("ENABLE_ORYX_BUILD");
if (!string.IsNullOrEmpty(enableOryxBuild))
{
Expand All @@ -72,6 +73,10 @@ public ISiteBuilder CreateBuilder(ITracer tracer, ILogger logger, IDeploymentSet
return new OryxBuilder(_environment, settings, _propertyProvider, repositoryRoot);
}
}
else if (FunctionAppHelper.LooksLikeFunctionApp())
{
return new OryxBuilder(_environment, settings, _propertyProvider, repositoryRoot);
}

if (!String.IsNullOrEmpty(targetProjectPath))
{
Expand Down
6 changes: 3 additions & 3 deletions Kudu.Core/Deployment/Oryx/BuildFlags.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ public enum BuildOptimizationsFlags

public class BuildFlagsHelper
{
public static BuildOptimizationsFlags Parse(string value)
public static BuildOptimizationsFlags Parse(string value, BuildOptimizationsFlags defaultVal = BuildOptimizationsFlags.None)
{
if (string.IsNullOrEmpty(value))
{
return BuildOptimizationsFlags.None;
return defaultVal;
}

try
Expand All @@ -29,7 +29,7 @@ public static BuildOptimizationsFlags Parse(string value)
}
catch (Exception)
{
return BuildOptimizationsFlags.None;
return defaultVal;
}
}
}
Expand Down
60 changes: 55 additions & 5 deletions Kudu.Core/Deployment/Oryx/FunctionAppOryxArguments.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using Kudu.Core.Infrastructure;
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace Kudu.Core.Deployment.Oryx
{
Expand All @@ -19,7 +21,7 @@ public FunctionAppOryxArguments()
FunctionsWorkerRuntime = ResolveWorkerRuntime();
RunOryxBuild = FunctionsWorkerRuntime != WorkerRuntime.None;
var buildFlags = GetEnvironmentVariableOrNull(OryxBuildConstants.OryxEnvVars.BuildFlagsSetting);
Flags = BuildFlagsHelper.Parse(buildFlags);
Flags = BuildFlagsHelper.Parse(buildFlags, defaultVal: BuildOptimizationsFlags.UseExpressBuild);
SkipKuduSync = Flags == BuildOptimizationsFlags.UseExpressBuild;
}

Expand Down Expand Up @@ -70,10 +72,6 @@ protected void AddLanguage(StringBuilder args, WorkerRuntime workerRuntime)
case WorkerRuntime.Python:
OryxArgumentsHelper.AddLanguage(args, "python");
break;

case WorkerRuntime.PHP:
OryxArgumentsHelper.AddLanguage(args, "php");
break;
}
}

Expand Down Expand Up @@ -121,9 +119,61 @@ private WorkerRuntime ResolveWorkerRuntime()

private string ResolveWorkerRuntimeVersion(WorkerRuntime workerRuntime)
{
var framework = GetEnvironmentVariableOrNull(OryxBuildConstants.OryxEnvVars.FrameworkSetting);
var frameworkVersion = GetEnvironmentVariableOrNull(OryxBuildConstants.OryxEnvVars.FrameworkVersionSetting);

// If either of them is not set we are not in a position to determine the version, and should let the caller
// switch to default
if (string.IsNullOrEmpty(framework) || string.IsNullOrEmpty(frameworkVersion))
{
return FunctionAppSupportedWorkerRuntime.GetDefaultLanguageVersion(workerRuntime);
}

// If it's set to DOCKER, it could be a) a function app image b) a custom image
// For custom image, there's no point doing a build, so we just default them (the parser won't work).
// if it's indeed a function app image, we look for the right tag that tells us about the version.
//
// Or if it's set to a supported worker runtime that was inferred, we assume that the framework version
// that is set is the correct version requested.
if (framework.Equals("DOCKER", StringComparison.OrdinalIgnoreCase))
{
var parsedVersion = ParseRuntimeVersionFromImage(frameworkVersion);
if (!string.IsNullOrEmpty(parsedVersion))
{
return parsedVersion;
}
}
else if (framework.Equals(workerRuntime.ToString(), StringComparison.OrdinalIgnoreCase))
{
return frameworkVersion;
}

return FunctionAppSupportedWorkerRuntime.GetDefaultLanguageVersion(workerRuntime);
}

public static string ParseRuntimeVersionFromImage(string imageName)
{
// The image name would be in this format -- 'mcr.microsoft.com/azure-functions/python:2.0-python3.6-appservice'
// If we get any parsing issues, we return null here.
try
{
var imageTag = imageName.Substring(imageName.LastIndexOf(':') + 1);
var versionRegex = new Regex(@"^[0-9]+\.[0-9]+\-[A-Za-z]+([0-9].*)\-appservice$");
var versionMatch = versionRegex.Match(imageTag);
var version = versionMatch?.Groups[1]?.Value;
if (!string.IsNullOrEmpty(version))
{
return version;
}
return null;
}
catch (Exception)
{
// TODO: Log at ETW event later
return null;
}
}

private string GetEnvironmentVariableOrNull(string environmentVarName)
{
var environmentVarValue = System.Environment.GetEnvironmentVariable(environmentVarName);
Expand Down
10 changes: 1 addition & 9 deletions Kudu.Core/Deployment/Oryx/FunctionAppSupportedWorkerRuntime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ public enum WorkerRuntime
None,
Node,
Python,
DotNet,
PHP
DotNet
}

public class FunctionAppSupportedWorkerRuntime
Expand All @@ -31,10 +30,6 @@ public static WorkerRuntime ParseWorkerRuntime(string value)
{
return WorkerRuntime.DotNet;
}
else if (value.StartsWith("PHP", StringComparison.OrdinalIgnoreCase))
{
return WorkerRuntime.PHP;
}

return WorkerRuntime.None;
}
Expand All @@ -52,9 +47,6 @@ public static string GetDefaultLanguageVersion(WorkerRuntime workerRuntime)
case WorkerRuntime.Python:
return OryxBuildConstants.FunctionAppWorkerRuntimeDefaults.Python;

case WorkerRuntime.PHP:
return OryxBuildConstants.FunctionAppWorkerRuntimeDefaults.PHP;

default:
return "";
}
Expand Down
4 changes: 2 additions & 2 deletions Kudu.Core/Deployment/Oryx/OryxBuildConstants.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.IO;
using System.Collections.Generic;
using System.IO;

namespace Kudu.Core.Deployment.Oryx
{
Expand All @@ -23,7 +24,6 @@ internal static class FunctionAppWorkerRuntimeDefaults
public static readonly string Node = "8.15";
public static readonly string Python = "3.6";
public static readonly string Dotnet = "2.2";
public static readonly string PHP = "7.3";
}

internal static class FunctionAppBuildSettings
Expand Down
13 changes: 13 additions & 0 deletions Kudu.Tests/Core/Deployment/Oryx/OryxArgumentsFunctionAppTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,18 @@ public void SkipKuduSyncOnExpressBuildTest()
command);
}
}

[Theory]
[InlineData("mcr.microsoft.com/azure-functions/python:2.0-python3.7-appservice", "3.7")]
[InlineData("mcr.microsoft.com/azure-functions/python:2.0-python3.6-appservice", "3.6")]
[InlineData("mcr.microsoft.com/azure-functions/python:2.0-node8-appservice", "8")]
[InlineData("mcr.microsoft.com/azure-functions/python:2.0-node10-appservice", "10")]
[InlineData("mcr.microsoft.com/azure-functions/python:2.0-dotnet-appservice", null)]
[InlineData("mcr.microsoft.com/azure-functions/python:2.0-dotnet2.0-appservice", "2.0")]
[InlineData("mcr.microsoft.com/azure-functions/python:2.0-dotnet3.0-appservice", "3.0")]
public void TestVersionFromImage(string imageName, string version)
{
Assert.Equal(version, FunctionAppOryxArguments.ParseRuntimeVersionFromImage(imageName));
}
}
}