Skip to content

Commit 55faf4e

Browse files
TsuyoshiUshiopragnagopa
authored andcommitted
Add extensions config from host.json to sync trigger payload (#7386)
1 parent 70fa587 commit 55faf4e

File tree

3 files changed

+154
-2
lines changed

3 files changed

+154
-2
lines changed

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

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,17 @@ public async Task<SyncTriggersPayload> GetSyncTriggersPayload()
304304
var functionDetails = await WebFunctionsManager.GetFunctionMetadataResponse(listableFunctions, hostOptions, _hostNameProvider);
305305
result.Add("functions", new JArray(functionDetails.Select(p => JObject.FromObject(p))));
306306

307+
// TEMP: refactor this code to properly add extensions in all scenario(#7394)
308+
// Add the host.json extensions to the payload
309+
if (_environment.IsKubernetesManagedHosting())
310+
{
311+
JObject extensionsPayload = await GetHostJsonExtensionsAsync(_applicationHostOptions, _logger);
312+
if (extensionsPayload != null)
313+
{
314+
result.Add("extensions", extensionsPayload);
315+
}
316+
}
317+
307318
// Add functions secrets to the payload
308319
// Only secret types we own/control can we cache directly
309320
// Encryption is handled by Antares before storage
@@ -346,7 +357,8 @@ public async Task<SyncTriggersPayload> GetSyncTriggersPayload()
346357
}
347358

348359
string json = JsonConvert.SerializeObject(result);
349-
if (json.Length > ScriptConstants.MaxTriggersStringLength)
360+
361+
if (json.Length > ScriptConstants.MaxTriggersStringLength && !_environment.IsKubernetesManagedHosting())
350362
{
351363
// The settriggers call to the FE enforces a max request size
352364
// limit. If we're over limit, revert to the minimal triggers
@@ -366,6 +378,34 @@ public async Task<SyncTriggersPayload> GetSyncTriggersPayload()
366378
};
367379
}
368380

381+
internal static async Task<JObject> GetHostJsonExtensionsAsync(IOptionsMonitor<ScriptApplicationHostOptions> applicationHostOptions, ILogger logger)
382+
{
383+
var hostOptions = applicationHostOptions.CurrentValue.ToHostOptions();
384+
string hostJsonPath = Path.Combine(hostOptions.RootScriptPath, ScriptConstants.HostMetadataFileName);
385+
if (FileUtility.FileExists(hostJsonPath))
386+
{
387+
try
388+
{
389+
var hostJson = JObject.Parse(await FileUtility.ReadAsync(hostJsonPath));
390+
if (hostJson.TryGetValue("extensions", out JToken token))
391+
{
392+
return (JObject)token;
393+
}
394+
else
395+
{
396+
return null;
397+
}
398+
}
399+
catch (JsonException ex)
400+
{
401+
logger.LogWarning($"Unable to parse host configuration file '{hostJsonPath}'. : {ex}");
402+
return null;
403+
}
404+
}
405+
406+
return null;
407+
}
408+
369409
internal async Task<IEnumerable<JObject>> GetFunctionTriggers(IEnumerable<FunctionMetadata> functionsMetadata, ScriptJobHostOptions hostOptions)
370410
{
371411
var triggers = (await functionsMetadata
@@ -659,4 +699,4 @@ public bool HasValues()
659699
}
660700
}
661701
}
662-
}
702+
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ private void VerifyResultWithCacheOn(string connection = DefaultTestConnection,
269269
Assert.Equal("bbb", (string)function1Secrets["secrets"]["TestFunctionKey2"]);
270270

271271
var logs = _loggerProvider.GetAllLogMessages().Where(m => m.Category.Equals(SyncManagerLogCategory)).ToList();
272+
272273
var log = logs[0];
273274
int startIdx = log.FormattedMessage.IndexOf("Content=") + 8;
274275
int endIdx = log.FormattedMessage.LastIndexOf(')');
@@ -400,6 +401,7 @@ public async Task TrySyncTriggers_BackgroundSync_SetTriggersFailure_HashNotUpdat
400401

401402
// verify log statements
402403
var logMessages = _loggerProvider.GetAllLogMessages().Where(m => m.Category.Equals(SyncManagerLogCategory)).Select(p => p.FormattedMessage).ToArray();
404+
403405
Assert.True(logMessages[0].Contains("Content="));
404406
Assert.Equal(expectedErrorMessage, logMessages[1]);
405407
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
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+
using System;
5+
using System.Collections.Generic;
6+
using System.IO;
7+
using System.Text;
8+
using System.Threading.Tasks;
9+
using Microsoft.Azure.WebJobs.Script.WebHost.Management;
10+
using Microsoft.Extensions.Logging;
11+
using Microsoft.Extensions.Options;
12+
using Moq;
13+
using Xunit;
14+
15+
namespace Microsoft.Azure.WebJobs.Script.Tests.Managment
16+
{
17+
public class FunctionsSyncManagerTests
18+
{
19+
private const string HostJsonWithExtensions = @"
20+
{
21+
""version"": ""2.0"",
22+
""logging"": {
23+
""applicationInsights"": {
24+
""samplingSettings"": {
25+
""isEnabled"": true,
26+
""excludedTypes"": ""Request""
27+
}
28+
}
29+
},
30+
""extensionBundle"": {
31+
""id"": ""Microsoft.Azure.Functions.ExtensionBundle"",
32+
""version"": ""[2.*, 3.0.0)""
33+
},
34+
""extensions"": {
35+
""queues"": {
36+
""maxPollingInterval"": ""00:00:30"",
37+
""visibilityTimeout"": ""00:01:00"",
38+
""batchSize"": 16,
39+
""maxDequeueCount"": 5,
40+
""newBatchThreshold"": 8,
41+
""messageEncoding"": ""base64""
42+
}
43+
}
44+
}
45+
";
46+
47+
private const string HostJsonWithoutExtensions = @"{}";
48+
49+
private const string HostJsonWithWrongExtensions = @"
50+
{
51+
""version"": ""2.0"",
52+
""extensions"": {
53+
""queues"":
54+
""maxPollingInterval"": ""00:00:30"",
55+
""visibilityTimeout"": ""00:01:00"",
56+
""batchSize"": 16,
57+
""maxDequeueCount"": 5,
58+
""newBatchThreshold"": 8,
59+
""messageEncoding"": ""base64""
60+
}
61+
}
62+
}
63+
";
64+
65+
[Theory]
66+
[InlineData(HostJsonWithExtensions, false, false, "00:00:30")]
67+
[InlineData(HostJsonWithoutExtensions, true, false, "")]
68+
[InlineData(HostJsonWithExtensions, true, true, "")]
69+
[InlineData(HostJsonWithWrongExtensions, true, false, "")]
70+
public async Task GetHostJsonExtensionsAsyncTest(string hostJsonContents, bool isNull, bool skipWriteFile, string value)
71+
{
72+
string scriptPath = string.Empty;
73+
try
74+
{
75+
var logger = new Mock<ILogger>();
76+
var monitor = new Mock<IOptionsMonitor<ScriptApplicationHostOptions>>();
77+
var options = new ScriptApplicationHostOptions();
78+
scriptPath = GetTempDirectory();
79+
var hostJsonPath = Path.Combine(scriptPath, "host.json");
80+
if (!skipWriteFile)
81+
{
82+
await FileUtility.WriteAsync(hostJsonPath, hostJsonContents);
83+
}
84+
85+
options.ScriptPath = scriptPath;
86+
monitor.Setup(x => x.CurrentValue).Returns(options);
87+
var json = await FunctionsSyncManager.GetHostJsonExtensionsAsync(monitor.Object, logger.Object);
88+
if (isNull)
89+
{
90+
Assert.Null(json);
91+
}
92+
else
93+
{
94+
Assert.Equal(value, json["queues"]?["maxPollingInterval"]);
95+
}
96+
}
97+
finally
98+
{
99+
await FileUtility.DeleteDirectoryAsync(scriptPath, true);
100+
}
101+
}
102+
103+
private string GetTempDirectory()
104+
{
105+
var temp = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
106+
Directory.CreateDirectory(temp);
107+
return temp;
108+
}
109+
}
110+
}

0 commit comments

Comments
 (0)