Skip to content

Commit ba9095b

Browse files
[v3.x] Introduce admin/host/config api (#8211)
1 parent 9e91b7e commit ba9095b

22 files changed

+614
-20
lines changed

release_notes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<!-- Please add your release notes in the following format:
33
- My change description (#PR)
44
-->
5+
- Add admin/host/config API (#7394)
56

67
**Release sprint:** Sprint 118
78
[ [bugs](https://github.com/Azure/azure-functions-host/issues?q=is%3Aissue+milestone%3A%22Functions+Sprint+<successiveSprint>%22+label%3Abug+is%3Aclosed) | [features](https://github.com/Azure/azure-functions-host/issues?q=is%3Aissue+milestone%3A%22Functions+Sprint+<successiveSprint>%22+label%3Afeature+is%3Aclosed) ]

sample/CSharp/HttpTrigger-Cancellation/run.csx

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,7 @@ using Microsoft.Extensions.Primitives;
66
public static async Task<IActionResult> Run(HttpRequest req, ILogger log, CancellationToken token)
77
{
88
log.LogInformation("C# HTTP trigger cancellation function processing a request.");
9-
10-
try
11-
{
12-
await Task.Delay(10000, token);
13-
log.LogInformation("Function invocation successful.");
14-
return new OkResult();
15-
16-
}
17-
catch (OperationCanceledException)
18-
{
19-
log.LogInformation("Function invocation cancelled.");
20-
return new NotFoundResult();
21-
}
22-
catch (Exception e)
23-
{
24-
return new StatusCodeResult(500);
25-
}
9+
await Task.Delay(10000, token);
10+
log.LogInformation("Function invocation successful.");
11+
return new OkResult();
2612
}

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,5 +395,21 @@ public async Task<IActionResult> ExtensionWebHookHandler(string extensionName, C
395395

396396
return NotFound();
397397
}
398+
399+
[HttpGet]
400+
[Route("admin/host/config")]
401+
[Authorize(Policy = PolicyNames.AdminAuthLevelOrInternal)]
402+
[RequiresRunningHost]
403+
public IActionResult GetConfig([FromServices] IScriptHostManager scriptHostManager)
404+
{
405+
if (Utility.TryGetHostService(scriptHostManager, out IHostOptionsProvider provider))
406+
{
407+
return Ok(provider.GetOptions().ToString());
408+
}
409+
else
410+
{
411+
return StatusCode(StatusCodes.Status503ServiceUnavailable);
412+
}
413+
}
398414
}
399415
}

src/WebJobs.Script.WebHost/WebJobs.Script.WebHost.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
<PackageReference Include="Microsoft.Azure.Services.AppAuthentication" Version="1.0.3" />
7575
<PackageReference Include="Microsoft.Azure.Storage.File" Version="11.1.7" />
7676
<PackageReference Include="Microsoft.Azure.KeyVault" Version="3.0.3" />
77-
<PackageReference Include="Microsoft.Azure.WebJobs" Version="3.0.32" />
77+
<PackageReference Include="Microsoft.Azure.WebJobs" Version="3.0.33-11908" />
7878
<PackageReference Include="Microsoft.Azure.WebJobs.Host.Storage" Version="4.0.4" />
7979
<PackageReference Include="Microsoft.Azure.WebJobs.Logging" Version="4.0.2" />
8080
<PackageReference Include="Microsoft.Azure.WebSites.DataProtection" Version="2.1.91-alpha" />
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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.Linq;
5+
using Microsoft.CodeAnalysis.CSharp.Syntax;
6+
using Newtonsoft.Json.Linq;
7+
8+
namespace Microsoft.Azure.WebJobs.Script.Extensions
9+
{
10+
public static class JObjectExtensions
11+
{
12+
public static JObject ToCamelCase(this JObject obj)
13+
{
14+
var camelObj = new JObject();
15+
foreach (var property in obj.Properties())
16+
{
17+
string camelCaseName = property.Name.CamelCaseString();
18+
if (camelCaseName != null)
19+
{
20+
camelObj[camelCaseName] = property.Value.ToCamelCaseJToken();
21+
}
22+
}
23+
return camelObj;
24+
}
25+
26+
public static string CamelCaseString(this string str)
27+
{
28+
if (str != null)
29+
{
30+
if (str.Length < 1)
31+
{
32+
return str.ToLower();
33+
}
34+
else
35+
{
36+
return $"{str.Substring(0, 1).ToLower()}{str.Substring(1)}";
37+
}
38+
}
39+
return str;
40+
}
41+
42+
private static JToken ToCamelCaseJToken(this JToken obj)
43+
{
44+
switch (obj.Type)
45+
{
46+
case JTokenType.Object:
47+
return ((JObject)obj).ToCamelCase();
48+
case JTokenType.Array:
49+
return new JArray(((JArray)obj).Select(x => x.ToCamelCaseJToken()));
50+
default:
51+
return obj.DeepClone();
52+
}
53+
}
54+
}
55+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
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.Linq;
7+
using Microsoft.Azure.WebJobs.Host.Config;
8+
using Microsoft.Azure.WebJobs.Host.Scale;
9+
using Microsoft.Azure.WebJobs.Hosting;
10+
using Microsoft.Azure.WebJobs.Script.Extensions;
11+
using Microsoft.Extensions.Logging;
12+
using Microsoft.Extensions.Options;
13+
using Newtonsoft.Json;
14+
using Newtonsoft.Json.Linq;
15+
using Newtonsoft.Json.Serialization;
16+
17+
namespace Microsoft.Azure.WebJobs.Script
18+
{
19+
public class HostOptionsProvider : IHostOptionsProvider
20+
{
21+
private readonly JsonSerializer _serializer = JsonSerializer.Create(new JsonSerializerSettings
22+
{
23+
ContractResolver = new CamelCasePropertyNamesContractResolver(),
24+
});
25+
26+
private readonly IEnumerable<IExtensionOptionsProvider> _extensionOptionsProviders;
27+
private readonly ILogger<HostOptionsProvider> _logger;
28+
private readonly IOptionsMonitor<ConcurrencyOptions> _concurrencyOptions;
29+
30+
public HostOptionsProvider(IEnumerable<IExtensionOptionsProvider> extensionOptionsProviders, IOptionsMonitor<ConcurrencyOptions> concurrencyOptions, ILogger<HostOptionsProvider> logger)
31+
{
32+
_extensionOptionsProviders = extensionOptionsProviders;
33+
_logger = logger;
34+
_concurrencyOptions = concurrencyOptions;
35+
}
36+
37+
public JObject GetOptions()
38+
{
39+
var payload = new JObject();
40+
var extensions = new JObject();
41+
var extensionOptions = GetExtensionOptions();
42+
foreach (var extension in extensionOptions)
43+
{
44+
extensions.Add(extension.Key, extension.Value);
45+
}
46+
if (extensionOptions.Count != 0)
47+
{
48+
payload.Add("extensions", extensions);
49+
}
50+
51+
var concurrency = GetConcurrencyOptions();
52+
payload.Add("concurrency", concurrency);
53+
return payload;
54+
}
55+
56+
private Dictionary<string, JObject> GetExtensionOptions()
57+
{
58+
Dictionary<string, JObject> result = new Dictionary<string, JObject>();
59+
foreach (IExtensionOptionsProvider extensionOptionsProvider in _extensionOptionsProviders)
60+
{
61+
var options = extensionOptionsProvider.GetOptions();
62+
if (typeof(IOptionsFormatter).IsAssignableFrom(options.GetType()))
63+
{
64+
var optionsFormatter = (IOptionsFormatter)options;
65+
string sectionName = extensionOptionsProvider?.ExtensionInfo?.ConfigurationSectionName?.CamelCaseString();
66+
result.Add(sectionName, JObject.Parse(optionsFormatter.Format()).ToCamelCase());
67+
}
68+
}
69+
70+
return result;
71+
}
72+
73+
private JObject GetConcurrencyOptions()
74+
{
75+
var concurrencyOptions = _concurrencyOptions.CurrentValue;
76+
return JObject.FromObject(concurrencyOptions, _serializer);
77+
}
78+
}
79+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
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.Collections.Generic;
5+
using Microsoft.Extensions.DependencyInjection;
6+
using Newtonsoft.Json.Linq;
7+
8+
namespace Microsoft.Azure.WebJobs.Script
9+
{
10+
public interface IHostOptionsProvider
11+
{
12+
JObject GetOptions();
13+
}
14+
}

src/WebJobs.Script/ScriptHostBuilderExtensions.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,8 @@ public static IHostBuilder AddScriptHostCore(this IHostBuilder builder, ScriptAp
319319
services.TryAddEnumerable(ServiceDescriptor.Singleton<IHostedService, FunctionsScaleMonitorService>());
320320
}
321321
services.TryAddSingleton<FunctionsScaleManager>();
322+
323+
services.AddSingleton<IHostOptionsProvider, HostOptionsProvider>();
322324
});
323325

324326
RegisterFileProvisioningService(builder);

src/WebJobs.Script/WebJobs.Script.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
<PackageReference Include="Microsoft.ApplicationInsights.PerfCounterCollector" Version="2.20.0" />
4747
<PackageReference Include="Microsoft.ApplicationInsights.WindowsServer" Version="2.20.0" />
4848
<PackageReference Include="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel" Version="2.20.0" />
49-
<PackageReference Include="Microsoft.Azure.WebJobs" Version="3.0.32" />
49+
<PackageReference Include="Microsoft.Azure.WebJobs" Version="3.0.33-11908" />
5050
<PackageReference Include="Microsoft.Azure.WebJobs.Host.Storage" Version="4.0.4" />
5151
<PackageReference Include="Microsoft.Extensions.Azure" Version="1.1.1" />
5252
<PackageReference Include="Microsoft.AspNetCore.Mvc.WebApiCompatShim" Version="2.2.0">

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ await TestHelpers.Await(async () =>
7070

7171
// Call function with cancellation token handler
7272
response = await SamplesTestHelpers.InvokeHttpTrigger(this, "HttpTrigger-Cancellation");
73-
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
73+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
7474
}
7575
}
7676

0 commit comments

Comments
 (0)