Skip to content

Commit ce4fa5f

Browse files
authored
new api to get triggers (#11021)
* new api to get triggers * GetTriggers will return 403 instead of 500 * GetTriggersAsync will throw ex * Added comment on why string content
1 parent 7e3e7b7 commit ce4fa5f

File tree

12 files changed

+94
-14
lines changed

12 files changed

+94
-14
lines changed

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,25 @@ public async Task<IActionResult> SyncTriggers()
421421
: StatusCode(StatusCodes.Status500InternalServerError, new { status = result.Error });
422422
}
423423

424+
[HttpGet]
425+
[Route("admin/host/triggers")]
426+
[Authorize(Policy = PolicyNames.AdminAuthLevelOrInternal)]
427+
[ResourceContainsSecrets]
428+
[RequiresRunningHost]
429+
public async Task<IActionResult> GetTriggers()
430+
{
431+
_metricsLogger.LogEvent(MetricEventNames.GetTriggersInvoked);
432+
433+
var result = await _functionsSyncManager.GetTriggersAsync();
434+
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 });
441+
}
442+
424443
[HttpPost]
425444
[Route("admin/host/restart")]
426445
[Authorize(Policy = PolicyNames.AdminAuthLevel)]

src/WebJobs.Script.WebHost/Management/FunctionsSyncManager.cs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,9 @@ internal bool ArmCacheEnabled
9292
}
9393
}
9494

95-
public async Task<SyncTriggersResult> TrySyncTriggersAsync(bool isBackgroundSync = false)
95+
public async Task<TriggersOperationResult> TrySyncTriggersAsync(bool isBackgroundSync = false)
9696
{
97-
var result = new SyncTriggersResult
97+
var result = new TriggersOperationResult
9898
{
9999
Success = true
100100
};
@@ -111,8 +111,6 @@ public async Task<SyncTriggersResult> TrySyncTriggersAsync(bool isBackgroundSync
111111
{
112112
await _syncSemaphore.WaitAsync();
113113

114-
PrepareSyncTriggers();
115-
116114
var hashBlobClient = await GetHashBlobAsync();
117115
if (isBackgroundSync && hashBlobClient == null && !_environment.IsAnyKubernetesEnvironment())
118116
{
@@ -308,6 +306,8 @@ internal async Task<BlobClient> GetHashBlobAsync()
308306

309307
private async Task<SyncTriggersPayload> GetSyncTriggersPayload()
310308
{
309+
PrepareSyncTriggers();
310+
311311
var hostOptions = _applicationHostOptions.CurrentValue.ToHostOptions();
312312
var functionsMetadata = _functionMetadataManager.GetFunctionMetadata().Where(m => !m.IsProxy());
313313

@@ -786,6 +786,26 @@ internal HttpRequestMessage BuildSetTriggersRequest()
786786
}
787787
}
788788

789+
public async Task<TriggersResult> GetTriggersAsync()
790+
{
791+
var result = new TriggersResult
792+
{
793+
Success = true
794+
};
795+
796+
if (!IsSyncTriggersEnvironment(_webHostEnvironment, _environment))
797+
{
798+
result.Success = false;
799+
result.Error = "Invalid environment for GetTriggers operation.";
800+
_logger.LogWarning(result.Error);
801+
return result;
802+
}
803+
804+
var payload = await GetSyncTriggersPayload();
805+
result.Content = payload.Content;
806+
return result;
807+
}
808+
789809
public void Dispose()
790810
{
791811
_syncSemaphore.Dispose();

src/WebJobs.Script.WebHost/Management/IFunctionsSyncManager.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,13 @@ public interface IFunctionsSyncManager
1111
/// Sync function triggers with Antares infrastructure.
1212
/// </summary>
1313
/// <param name="isBackgroundSync">Indicates whether this is a background sync operation.</param>
14-
/// <returns>The <see cref="SyncTriggersResult"/> for the request.</returns>
15-
Task<SyncTriggersResult> TrySyncTriggersAsync(bool isBackgroundSync = false);
14+
/// <returns>The <see cref="TriggersOperationResult"/> for the request.</returns>
15+
Task<TriggersOperationResult> TrySyncTriggersAsync(bool isBackgroundSync = false);
16+
17+
/// <summary>
18+
/// Get function triggers payload.
19+
/// </summary>
20+
/// <returns>The <see cref="TriggersResult"/> for the request.</returns>
21+
Task<TriggersResult> GetTriggersAsync();
1622
}
1723
}

src/WebJobs.Script.WebHost/Management/SyncTriggersResult.cs renamed to src/WebJobs.Script.WebHost/Management/TriggersOperationResult.cs

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

44
namespace Microsoft.Azure.WebJobs.Script.WebHost.Management
55
{
6-
public class SyncTriggersResult
6+
public class TriggersOperationResult
77
{
88
/// <summary>
9-
/// Gets or sets a value indicating whether the sync operation was successful.
9+
/// Gets or sets a value indicating whether the operation was successful.
1010
/// </summary>
1111
public bool Success { get; set; }
1212

1313
/// <summary>
14-
/// Gets or sets the error string in the case of a failed sync operation.
14+
/// Gets or sets the error string in the case of a failed operation.
1515
/// </summary>
1616
public string Error { get; set; }
1717
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for license information.
3+
4+
namespace Microsoft.Azure.WebJobs.Script.WebHost.Management
5+
{
6+
public sealed class TriggersResult : TriggersOperationResult
7+
{
8+
/// <summary>
9+
/// Gets or sets the triggers payload.
10+
/// </summary>
11+
/// <remarks>
12+
/// Use of an already formatted JSON string here as opposed to a JObject is by design.
13+
/// We want to ensure that the result we return here is the exact same JSON payload
14+
/// as is generated during a sync triggers operation (down to whitespacing).
15+
/// </remarks>
16+
public string Content { get; set; }
17+
}
18+
}

src/WebJobs.Script/Diagnostics/MetricEventNames.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public static class MetricEventNames
2323
public const string HISStrictModeEnabled = "host.hismode.strict";
2424
public const string HISStrictModeWarn = "host.hismode.warn";
2525
public const string SyncTriggersInvoked = "host.synctriggers.invoke";
26+
public const string GetTriggersInvoked = "host.gettriggers.invoke";
2627

2728
// Script host level events
2829
public const string ScriptHostManagerBuildScriptHost = "scripthostmanager.buildscripthost.latency";

test/WebJobs.Script.Tests.Integration/Management/FunctionsSyncManagerTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,22 @@ private void ResetMockFileSystem(string hostJsonContent = null, string extension
256256
FileUtility.Instance = fileSystem;
257257
}
258258

259+
[Fact]
260+
public async Task GetTriggersAsync_ReturnsExpectedContent()
261+
{
262+
// Act
263+
var result = await _functionsSyncManager.GetTriggersAsync();
264+
265+
// Assert
266+
Assert.True(result.Success);
267+
Assert.Null(result.Error);
268+
Assert.NotNull(result.Content);
269+
270+
var content = JObject.Parse(result.Content);
271+
var triggers = content["triggers"];
272+
Assert.Equal(GetExpectedTriggersPayload(durableVersion: "V1"), triggers.ToString(Formatting.None));
273+
}
274+
259275
[Fact]
260276
public async Task TrySyncTriggers_StandbyMode_ReturnsFalse()
261277
{

test/WebJobs.Script.Tests.Integration/WebHostEndToEnd/CodelessEndToEndTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ private TestFunctionHost StartLocalHost(string baseTestPath, string sourceFuncti
244244
string testLogPath = Path.Combine(baseTestPath, "Logs");
245245

246246
var syncTriggerMock = new Mock<IFunctionsSyncManager>(MockBehavior.Strict);
247-
syncTriggerMock.Setup(p => p.TrySyncTriggersAsync(It.IsAny<bool>())).ReturnsAsync(new SyncTriggersResult { Success = true });
247+
syncTriggerMock.Setup(p => p.TrySyncTriggersAsync(It.IsAny<bool>())).ReturnsAsync(new TriggersOperationResult { Success = true });
248248

249249
FileUtility.CopyDirectory(sourceFunctionApp, appContent);
250250
var host = new TestFunctionHost(sourceFunctionApp, testLogPath,

test/WebJobs.Script.Tests.Integration/WebHostEndToEnd/EndToEndTestFixture.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ string GetDestPath(int counter)
148148
}
149149

150150
FunctionsSyncManagerMock = new Mock<IFunctionsSyncManager>(MockBehavior.Strict);
151-
FunctionsSyncManagerMock.Setup(p => p.TrySyncTriggersAsync(It.IsAny<bool>())).ReturnsAsync(new SyncTriggersResult { Success = true });
151+
FunctionsSyncManagerMock.Setup(p => p.TrySyncTriggersAsync(It.IsAny<bool>())).ReturnsAsync(new TriggersOperationResult { Success = true });
152152

153153
string azuriteConnectionString = _azurite.GetConnectionString();
154154
Host = new TestFunctionHost(_copiedRootPath, logPath, addTestSettings: _addTestSettings,

test/WebJobs.Script.Tests.Integration/WebHostEndToEnd/MultiLanguageEndToEndTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ private TestFunctionHost StartLocalHost(string baseTestPath, string sourceFuncti
199199
string testLogPath = Path.Combine(baseTestPath, "Logs");
200200

201201
var syncTriggerMock = new Mock<IFunctionsSyncManager>(MockBehavior.Strict);
202-
syncTriggerMock.Setup(p => p.TrySyncTriggersAsync(It.IsAny<bool>())).ReturnsAsync(new SyncTriggersResult { Success = true });
202+
syncTriggerMock.Setup(p => p.TrySyncTriggersAsync(It.IsAny<bool>())).ReturnsAsync(new TriggersOperationResult { Success = true });
203203

204204
FileUtility.CopyDirectory(sourceFunctionApp, appContent);
205205
var host = new TestFunctionHost(sourceFunctionApp, testLogPath,

0 commit comments

Comments
 (0)