Skip to content

Commit 7d25c4f

Browse files
authored
In validation mode, disable background sync trigger and warmup function (#11024)
* In validation mode, disable background sync trigger and warmup function * GetTriggers API restricted to validation mode * using existing TryGetFunctionsTargetGroup to get group
1 parent ce4fa5f commit 7d25c4f

File tree

7 files changed

+75
-13
lines changed

7 files changed

+75
-13
lines changed

src/WebJobs.Script.WebHost/Controllers/HostController.cs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -430,14 +430,20 @@ public async Task<IActionResult> GetTriggers()
430430
{
431431
_metricsLogger.LogEvent(MetricEventNames.GetTriggersInvoked);
432432

433-
var result = await _functionsSyncManager.GetTriggersAsync();
433+
// This endpoint is only available in validation mode
434+
if (_environment.IsInValidationMode())
435+
{
436+
var result = await _functionsSyncManager.GetTriggersAsync();
434437

435-
// GetTriggersAsync() does not swallow exceptions,so any failures will still be a 500.
436-
// The only result.Success == false we need to consideris when the environment
437-
// does not support sync triggers.
438-
return result.Success
439-
? Ok(result)
440-
: StatusCode(StatusCodes.Status403Forbidden, new { status = result.Error });
438+
// GetTriggersAsync() does not swallow exceptions, so any failures will still be a 500.
439+
// The only result.Success == false we need to consider is when the environment
440+
// does not support sync triggers.
441+
return result.Success
442+
? Ok(result)
443+
: StatusCode(StatusCodes.Status403Forbidden, new { status = result.Error });
444+
}
445+
446+
return StatusCode(StatusCodes.Status403Forbidden, new { status = "GetTriggers operation is not supported in for this instance." });
441447
}
442448

443449
[HttpPost]

src/WebJobs.Script.WebHost/FunctionsSyncService.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,19 @@ public class FunctionsSyncService : IHostedService, IDisposable
2121
private readonly IScriptHostManager _scriptHostManager;
2222
private readonly IPrimaryHostStateProvider _primaryHostStateProvider;
2323
private readonly IFunctionsSyncManager _functionsSyncManager;
24+
private readonly IEnvironment _environment;
2425
private Timer _syncTimer;
2526
private bool _disposed = false;
2627

27-
public FunctionsSyncService(ILoggerFactory loggerFactory, IScriptHostManager scriptHostManager, IPrimaryHostStateProvider primaryHostStateProvider, IFunctionsSyncManager functionsSyncManager)
28+
public FunctionsSyncService(ILoggerFactory loggerFactory, IScriptHostManager scriptHostManager, IPrimaryHostStateProvider primaryHostStateProvider, IFunctionsSyncManager functionsSyncManager, IEnvironment environment)
2829
{
2930
ArgumentNullException.ThrowIfNull(loggerFactory);
3031

3132
DueTime = 30 * 1000;
3233
_scriptHostManager = scriptHostManager;
3334
_primaryHostStateProvider = primaryHostStateProvider;
3435
_functionsSyncManager = functionsSyncManager;
36+
_environment = environment;
3537
_logger = loggerFactory.CreateLogger(ScriptConstants.LogCategoryHostGeneral);
3638
}
3739

@@ -43,7 +45,8 @@ internal bool ShouldSyncTriggers
4345
get
4446
{
4547
return _primaryHostStateProvider.IsPrimary &&
46-
(_scriptHostManager.State == ScriptHostState.Running);
48+
(_scriptHostManager.State == ScriptHostState.Running) &&
49+
!_environment.IsInValidationMode();
4750
}
4851
}
4952

src/WebJobs.Script.WebHost/WebScriptHostHttpRoutesManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public void InitializeHttpFunctionRoutes(IScriptJobHost host)
6969

7070
LogRouteMap(routesLogBuilder, function.Metadata.Name, route, httpTrigger.Methods, isProxy, _httpOptions.Value.RoutePrefix);
7171
}
72-
else if (warmupRouteBuilder != null && function.IsWarmupFunction())
72+
else if (warmupRouteBuilder != null && !_environment.IsInValidationMode() && function.IsWarmupFunction())
7373
{
7474
warmupRouteBuilder.MapFunctionRoute(function.Metadata.Name, "warmup", function.Metadata.Name);
7575
}

src/WebJobs.Script/Description/FunctionGroups.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ public static class FunctionGroups
1111
public const string Durable = "durable";
1212
public const string Blob = "blob";
1313

14+
// Function group for validation worker used by Functions Deployment Manager
15+
public const string ValidationWorker = "deployment:validation";
16+
1417
public static string ForFunction(string function)
1518
{
1619
return $"function:{function}";

src/WebJobs.Script/Environment/EnvironmentExtensions.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Linq;
99
using System.Runtime.InteropServices;
1010
using Microsoft.Azure.WebJobs.Script.Config;
11+
using Microsoft.Azure.WebJobs.Script.Description;
1112
using Microsoft.Azure.WebJobs.Script.Workers.Rpc;
1213
using static Microsoft.Azure.WebJobs.Script.EnvironmentSettingNames;
1314

@@ -748,5 +749,14 @@ public static bool TryGetFunctionsTargetGroup(this IEnvironment environment, out
748749

749750
return group is not null;
750751
}
752+
753+
/// <summary>
754+
/// Returns true if the worker is running in validation mode.
755+
/// </summary>
756+
public static bool IsInValidationMode(this IEnvironment environment)
757+
{
758+
return environment.TryGetFunctionsTargetGroup(out string group)
759+
&& string.Equals(group, FunctionGroups.ValidationWorker, StringComparison.InvariantCultureIgnoreCase);
760+
}
751761
}
752762
}

test/WebJobs.Script.Tests/Extensions/EnvironmentExtensionsTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using Microsoft.Azure.WebJobs.Script.Description;
67
using Microsoft.Azure.WebJobs.Script.Workers.Rpc;
78
using Microsoft.WebJobs.Script.Tests;
89
using Xunit;
@@ -530,5 +531,20 @@ public void IsInProc_WithRuntimeParameter_ReturnsExpectedResult(string value, bo
530531
var environment = new TestEnvironment();
531532
Assert.Equal(expected, environment.IsInProc(value));
532533
}
534+
535+
[Theory]
536+
[InlineData(FunctionGroups.ValidationWorker, true)]
537+
[InlineData("function:http", false)]
538+
[InlineData(null, false)]
539+
public void IsInValidationMode_ReturnsExpectedResult(string functionGroup, bool expected)
540+
{
541+
IEnvironment env = new TestEnvironment();
542+
if (!string.IsNullOrEmpty(functionGroup))
543+
{
544+
env.SetEnvironmentVariable(EnvironmentSettingNames.FunctionsTargetGroup, functionGroup);
545+
}
546+
547+
Assert.Equal(expected, env.IsInValidationMode());
548+
}
533549
}
534550
}

test/WebJobs.Script.Tests/FunctionsSyncServiceTests.cs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Threading;
77
using System.Threading.Tasks;
88
using Microsoft.Azure.WebJobs.Hosting;
9+
using Microsoft.Azure.WebJobs.Script.Description;
910
using Microsoft.Azure.WebJobs.Script.WebHost;
1011
using Microsoft.Azure.WebJobs.Script.WebHost.Management;
1112
using Microsoft.Extensions.Logging;
@@ -18,6 +19,7 @@ namespace Microsoft.Azure.WebJobs.Script.Tests
1819
public class FunctionsSyncServiceTests
1920
{
2021
private readonly TestLoggerProvider _loggerProvider;
22+
private readonly LoggerFactory _loggerFactory;
2123
private readonly FunctionsSyncService _syncService;
2224
private readonly Mock<IScriptHostManager> _mockScriptHostManager;
2325
private readonly Mock<IPrimaryHostStateProvider> _mockPrimaryHostStateProviderMock;
@@ -29,8 +31,8 @@ public class FunctionsSyncServiceTests
2931
public FunctionsSyncServiceTests()
3032
{
3133
_loggerProvider = new TestLoggerProvider();
32-
var loggerFactory = new LoggerFactory();
33-
loggerFactory.AddProvider(_loggerProvider);
34+
_loggerFactory = new LoggerFactory();
35+
_loggerFactory.AddProvider(_loggerProvider);
3436

3537
_mockScriptHostManager = new Mock<IScriptHostManager>(MockBehavior.Strict);
3638
_mockPrimaryHostStateProviderMock = new Mock<IPrimaryHostStateProvider>(MockBehavior.Strict);
@@ -44,8 +46,9 @@ public FunctionsSyncServiceTests()
4446
_mockEnvironment = new Mock<IEnvironment>(MockBehavior.Strict);
4547
_mockEnvironment.Setup(p => p.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteContainerReady)).Returns("1");
4648
_mockEnvironment.Setup(p => p.GetEnvironmentVariable(EnvironmentSettingNames.CoreToolsEnvironment)).Returns((string)null);
49+
_mockEnvironment.Setup(p => p.GetEnvironmentVariable(EnvironmentSettingNames.FunctionsTargetGroup)).Returns((string)null);
4750

48-
_syncService = new FunctionsSyncService(loggerFactory, _mockScriptHostManager.Object, _mockPrimaryHostStateProviderMock.Object, _mockSyncManager.Object);
51+
_syncService = new FunctionsSyncService(_loggerFactory, _mockScriptHostManager.Object, _mockPrimaryHostStateProviderMock.Object, _mockSyncManager.Object, _mockEnvironment.Object);
4952
_syncService.DueTime = _testDueTime;
5053
}
5154

@@ -63,6 +66,27 @@ public void ShouldSyncTriggers_ReturnsExpectedResult(bool isPrimary, ScriptHostS
6366
Assert.Equal(expected, _syncService.ShouldSyncTriggers);
6467
}
6568

69+
[Theory]
70+
[InlineData(FunctionGroups.ValidationWorker, false)]
71+
[InlineData("function:http", true)]
72+
[InlineData(null, true)]
73+
public void ShouldSyncTriggers_DisabledForValidationPod(string functionGroup, bool expected)
74+
{
75+
_mockPrimaryHostStateProviderMock.Setup(p => p.IsPrimary).Returns(true);
76+
_mockScriptHostManager.Setup(p => p.State).Returns(ScriptHostState.Running);
77+
78+
var mockEnvironment = new Mock<IEnvironment>(MockBehavior.Strict);
79+
mockEnvironment.Setup(p => p.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteContainerReady)).Returns("1");
80+
mockEnvironment.Setup(p => p.GetEnvironmentVariable(EnvironmentSettingNames.CoreToolsEnvironment)).Returns((string)null);
81+
mockEnvironment.Setup(p => p.GetEnvironmentVariable(EnvironmentSettingNames.FunctionsTargetGroup)).Returns(functionGroup);
82+
83+
var syncService = new FunctionsSyncService(_loggerFactory, _mockScriptHostManager.Object, _mockPrimaryHostStateProviderMock.Object, _mockSyncManager.Object,
84+
mockEnvironment.Object);
85+
syncService.DueTime = _testDueTime;
86+
87+
Assert.Equal(expected, syncService.ShouldSyncTriggers);
88+
}
89+
6690
[Fact]
6791
public async Task StartAsync_PrimaryHost_Running_SyncsTriggers_AfterTimeout()
6892
{

0 commit comments

Comments
 (0)