Skip to content

Commit 3ee5f6c

Browse files
pgombarpragnagopa
authored andcommitted
Refactor Linux-specific options setup into ScriptApplicationHostOptionsSetup (#7366)
1 parent 5f2342d commit 3ee5f6c

File tree

6 files changed

+155
-199
lines changed

6 files changed

+155
-199
lines changed

src/WebJobs.Script.WebHost/Configuration/LinuxScriptApplicationHostOptionsSetup.cs

Lines changed: 0 additions & 92 deletions
This file was deleted.

src/WebJobs.Script.WebHost/Configuration/ScriptApplicationHostOptionsSetup.cs

Lines changed: 92 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@
33

44
using System;
55
using System.IO;
6+
using System.Threading;
7+
using Microsoft.Azure.Storage.Blob;
68
using Microsoft.Azure.WebJobs.Script.Configuration;
9+
using Microsoft.Azure.WebJobs.Script.WebHost.Diagnostics;
710
using Microsoft.Extensions.Configuration;
11+
using Microsoft.Extensions.Logging;
812
using Microsoft.Extensions.Options;
913
using static Microsoft.Azure.WebJobs.Script.EnvironmentSettingNames;
1014

@@ -65,14 +69,99 @@ public void Configure(string name, ScriptApplicationHostOptions options)
6569
options.IsStandbyConfiguration = true;
6670
}
6771

68-
options.IsFileSystemReadOnly = IsZipDeployment();
72+
options.IsFileSystemReadOnly = IsZipDeployment(out bool isScmRunFromPackage);
73+
options.IsScmRunFromPackage = isScmRunFromPackage;
6974
}
7075

71-
private bool IsZipDeployment()
76+
private bool IsZipDeployment(out bool isScmRunFromPackage)
7277
{
73-
return Utility.IsValidZipSetting(_environment.GetEnvironmentVariable(AzureWebsiteZipDeployment)) ||
78+
// Check app settings for run from package.
79+
bool runFromPkgConfigured = Utility.IsValidZipSetting(_environment.GetEnvironmentVariable(AzureWebsiteZipDeployment)) ||
7480
Utility.IsValidZipSetting(_environment.GetEnvironmentVariable(AzureWebsiteAltZipDeployment)) ||
7581
Utility.IsValidZipSetting(_environment.GetEnvironmentVariable(AzureWebsiteRunFromPackage));
82+
83+
if (!_environment.IsLinuxConsumption())
84+
{
85+
isScmRunFromPackage = false;
86+
// This check is strong enough for SKUs other than Linux Consumption.
87+
return runFromPkgConfigured;
88+
}
89+
90+
// The following logic only applies to Linux Consumption, since currently SCM_RUN_FROM_PACKAGE is always set even if we are not using it.
91+
if (runFromPkgConfigured)
92+
{
93+
isScmRunFromPackage = false;
94+
return true;
95+
}
96+
97+
// If SCM_RUN_FROM_PACKAGE is set to a valid value and the blob exists, it's a zip deployment.
98+
var url = _environment.GetEnvironmentVariable(ScmRunFromPackage);
99+
if (string.IsNullOrEmpty(url))
100+
{
101+
LinuxContainerEventGenerator.LogEvent(message: $"{nameof(ScmRunFromPackage)} is empty.", source: nameof(ScriptApplicationHostOptionsSetup));
102+
isScmRunFromPackage = false;
103+
return false;
104+
}
105+
106+
if (Utility.TryCleanUrl(url, out string cleanedUrl))
107+
{
108+
LinuxContainerEventGenerator.LogEvent(message: $"{nameof(ScmRunFromPackage)} = {cleanedUrl}", source: nameof(ScriptApplicationHostOptionsSetup));
109+
}
110+
111+
var isValidZipSetting = Utility.IsValidZipSetting(url);
112+
LinuxContainerEventGenerator.LogEvent(message: $"{nameof(ScmRunFromPackage)} isValidZipSetting = {isValidZipSetting}", source: nameof(ScriptApplicationHostOptionsSetup));
113+
114+
if (!isValidZipSetting)
115+
{
116+
isScmRunFromPackage = false;
117+
// Return early so we don't call storage if it isn't absolutely necessary.
118+
return false;
119+
}
120+
121+
var blobExists = BlobExists(url);
122+
LinuxContainerEventGenerator.LogEvent(message: $"{nameof(ScmRunFromPackage)} blobExists = {blobExists}", source: nameof(ScriptApplicationHostOptionsSetup));
123+
124+
bool scmRunFromPkgConfigured = isValidZipSetting && blobExists;
125+
isScmRunFromPackage = scmRunFromPkgConfigured;
126+
return scmRunFromPkgConfigured;
127+
}
128+
129+
public virtual bool BlobExists(string url)
130+
{
131+
if (string.IsNullOrEmpty(url))
132+
{
133+
return false;
134+
}
135+
136+
try
137+
{
138+
CloudBlockBlob blob = new CloudBlockBlob(new Uri(url));
139+
140+
int attempt = 0;
141+
while (true)
142+
{
143+
try
144+
{
145+
return blob.Exists();
146+
}
147+
catch (Exception ex) when (!ex.IsFatal())
148+
{
149+
LinuxContainerEventGenerator.LogEvent(message: $"Exception when checking if {nameof(ScmRunFromPackage)} blob exists", e: ex,
150+
logLevel: LogLevel.Error, source: nameof(ScriptApplicationHostOptionsSetup));
151+
if (++attempt > 2)
152+
{
153+
return false;
154+
}
155+
Thread.Sleep(TimeSpan.FromSeconds(0.3));
156+
}
157+
}
158+
}
159+
catch (Exception ex)
160+
{
161+
LinuxContainerEventGenerator.LogEvent(message: $"Failed to check status of {nameof(ScmRunFromPackage)}", e: ex,
162+
logLevel: LogLevel.Error, source: nameof(ScriptApplicationHostOptionsSetup));
163+
return false;
164+
}
76165
}
77166

78167
public void Dispose()

src/WebJobs.Script.WebHost/Diagnostics/LinuxContainerEventGenerator.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace Microsoft.Azure.WebJobs.Script.WebHost.Diagnostics
99
internal class LinuxContainerEventGenerator : LinuxEventGenerator
1010
{
1111
private const int MaxDetailsLength = 10000;
12+
private static readonly Lazy<LinuxContainerEventGenerator> _Lazy = new Lazy<LinuxContainerEventGenerator>(() => new LinuxContainerEventGenerator(SystemEnvironment.Instance));
1213
private readonly Action<string> _writeEvent;
1314
private readonly bool _consoleEnabled = true;
1415
private readonly IEnvironment _environment;
@@ -37,6 +38,8 @@ public LinuxContainerEventGenerator(IEnvironment environment, Action<string> wri
3738

3839
public static string AzureMonitorEventRegex { get; } = $"{ScriptConstants.LinuxAzureMonitorEventStreamName} (?<Level>[0-6]),(?<ResourceId>[^,]*),(?<OperationName>[^,]*),(?<Category>[^,]*),(?<RegionName>[^,]*),\"(?<Properties>[^,]*)\",(?<ContainerName>[^,\"]*),(?<TenantId>[^,\"]*),(?<EventTimestamp>[^,]+)";
3940

41+
public static LinuxContainerEventGenerator LinuxContainerEventGeneratorInstance { get { return _Lazy.Value; } }
42+
4043
private string StampName
4144
{
4245
get
@@ -116,5 +119,26 @@ public static void LogUnhandledException(Exception e)
116119
SystemEnvironment.Instance.GetSlotName() ?? string.Empty,
117120
DateTime.UtcNow);
118121
}
122+
123+
public static void LogEvent(string message, Exception e = null, LogLevel logLevel = LogLevel.Debug, string source = null)
124+
{
125+
LinuxContainerEventGeneratorInstance.LogFunctionTraceEvent(
126+
level: logLevel,
127+
subscriptionId: SystemEnvironment.Instance.GetSubscriptionId() ?? string.Empty,
128+
appName: SystemEnvironment.Instance.GetAzureWebsiteUniqueSlotName() ?? string.Empty,
129+
functionName: string.Empty,
130+
eventName: string.Empty,
131+
source: source ?? nameof(LogEvent),
132+
details: e?.ToString() ?? string.Empty,
133+
summary: message,
134+
exceptionType: e?.GetType().ToString() ?? string.Empty,
135+
exceptionMessage: e?.ToString() ?? string.Empty,
136+
functionInvocationId: string.Empty,
137+
hostInstanceId: string.Empty,
138+
activityId: string.Empty,
139+
runtimeSiteName: SystemEnvironment.Instance.GetRuntimeSiteName() ?? string.Empty,
140+
slotName: SystemEnvironment.Instance.GetSlotName() ?? string.Empty,
141+
eventTimestamp: DateTime.UtcNow);
142+
}
119143
}
120144
}

src/WebJobs.Script.WebHost/WebHostServiceCollectionExtensions.cs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -163,15 +163,6 @@ public static void AddWebJobsScriptHost(this IServiceCollection services, IConfi
163163

164164
// Configuration
165165
services.ConfigureOptions<ScriptApplicationHostOptionsSetup>();
166-
services.AddSingleton<IConfigureOptions<ScriptApplicationHostOptions>>(p =>
167-
{
168-
var environment = p.GetService<IEnvironment>();
169-
if (environment.IsLinuxConsumption())
170-
{
171-
return new LinuxScriptApplicationHostOptionsSetup(environment);
172-
}
173-
return LinuxScriptApplicationHostOptionsSetup.NullInstance;
174-
});
175166
services.ConfigureOptions<StandbyOptionsSetup>();
176167
services.ConfigureOptions<LanguageWorkerOptionsSetup>();
177168
services.ConfigureOptionsWithChangeTokenSource<AppServiceOptions, AppServiceOptionsSetup, SpecializationChangeTokenSource<AppServiceOptions>>();

test/WebJobs.Script.Tests/Configuration/LinuxScriptApplicationHostOptionsSetupTests.cs

Lines changed: 0 additions & 93 deletions
This file was deleted.

0 commit comments

Comments
 (0)