diff --git a/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/README.md b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/README.md index 8cd65b959357..e9bef69338bb 100644 --- a/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/README.md +++ b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/README.md @@ -24,7 +24,7 @@ public static class Function1 [FunctionName("Function1")] public static IActionResult Run( [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, - [AzureClient("StorageConnection")] BlobServiceClient client) + [AzureClient("MyStorageConnection")] BlobServiceClient client) { return new OkObjectResult(client.GetBlobContainers().ToArray()); } @@ -33,21 +33,29 @@ public static class Function1 The connection name should correspond to a configuration section with a connection string or a set of connection parameters that correspond to a client constructor. -For example to construct a BlobClient using a connection string use the following configuration: +For example to construct a `BlobServiceClient` using a connection string use the following configuration: ```json { - "StorageConnection": "UseDevelopmentStorage=true" + "IsEncrypted": false, + "Values": { + "AzureWebJobsStorage": "UseDevelopmentStorage=true", + "MyStorageConnection": "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;QueueEndpoint=http://127.0.0.1:10001/devstoreaccount1;", + "FUNCTIONS_WORKER_RUNTIME": "dotnet" + } } ``` -To construct a client using a `blobUri`: +To construct a client using a `serviceUri`: ```json { - "StorageConnection": { - "blobUri": "https://{storage_account}.blob.core.windows.net/" - } + "IsEncrypted": false, + "Values": { + "AzureWebJobsStorage": "UseDevelopmentStorage=true", + "MyStorageConnection__serviceUri": "http://127.0.0.1:10000/devstoreaccount1/container/blob", + "FUNCTIONS_WORKER_RUNTIME": "dotnet" + } } ``` diff --git a/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/samples/Function1.cs b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/samples/Function1.cs index 43948721d370..88ed8a7fcb26 100644 --- a/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/samples/Function1.cs +++ b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/samples/Function1.cs @@ -16,7 +16,7 @@ public static class Function1 [FunctionName("Function1")] public static IActionResult Run( [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, - [AzureClient("StorageConnection")] BlobServiceClient client) + [AzureClient("MyStorageConnection")] BlobServiceClient client) { return new OkObjectResult(client.GetBlobContainers().ToArray()); } diff --git a/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/samples/host.json b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/samples/host.json index ec3f8ddb7c84..2367d9ad3afc 100644 --- a/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/samples/host.json +++ b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/samples/host.json @@ -10,6 +10,5 @@ "isEnabled": true } } - }, - "StorageConnection": "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;QueueEndpoint=http://127.0.0.1:10001/devstoreaccount1;" + } } diff --git a/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/samples/local.settings.json b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/samples/local.settings.json new file mode 100644 index 000000000000..d6efd6968cc2 --- /dev/null +++ b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/samples/local.settings.json @@ -0,0 +1,8 @@ +{ + "IsEncrypted": false, + "Values": { + "AzureWebJobsStorage": "UseDevelopmentStorage=true", + "MyStorageConnection": "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;QueueEndpoint=http://127.0.0.1:10001/devstoreaccount1;", + "FUNCTIONS_WORKER_RUNTIME": "dotnet" + } +} \ No newline at end of file diff --git a/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/src/AzureClientsExtensionConfigProvider.cs b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/src/AzureClientsExtensionConfigProvider.cs index eaeaf409a018..2e0ae31f8dae 100644 --- a/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/src/AzureClientsExtensionConfigProvider.cs +++ b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/src/AzureClientsExtensionConfigProvider.cs @@ -5,6 +5,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.WebJobs; +using Microsoft.Azure.WebJobs.Host; using Microsoft.Azure.WebJobs.Host.Bindings; using Microsoft.Azure.WebJobs.Host.Config; using Microsoft.Extensions.Azure; @@ -15,10 +16,12 @@ namespace Microsoft.Extensions.Hosting internal class AzureClientsExtensionConfigProvider : IExtensionConfigProvider { private readonly IServiceProvider _serviceProvider; + private readonly INameResolver _nameResolver; - public AzureClientsExtensionConfigProvider(IServiceProvider serviceProvider) + public AzureClientsExtensionConfigProvider(IServiceProvider serviceProvider, INameResolver nameResolver) { _serviceProvider = serviceProvider; + _nameResolver = nameResolver; } public void Initialize(ExtensionConfigContext context) @@ -29,7 +32,10 @@ public void Initialize(ExtensionConfigContext context) private IValueBinder CreateValueBinder(Type type, AzureClientAttribute attribute) { - return (IValueBinder)Activator.CreateInstance(typeof(AzureClientValueProvider<>).MakeGenericType(type), _serviceProvider, attribute.Connection); + return (IValueBinder)Activator.CreateInstance( + typeof(AzureClientValueProvider<>).MakeGenericType(type), + _serviceProvider, + _nameResolver.ResolveWholeString(attribute.Connection)); } private class AzureClientValueProvider : IValueBinder diff --git a/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/src/AzureClientsWebJobsBuilderExtensions.cs b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/src/AzureClientsWebJobsBuilderExtensions.cs index b1f116005007..b5a6e1e3dd30 100644 --- a/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/src/AzureClientsWebJobsBuilderExtensions.cs +++ b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/src/AzureClientsWebJobsBuilderExtensions.cs @@ -2,11 +2,12 @@ // Licensed under the MIT License. using System; -using Azure.Extensions.WebJobs; +using System.Collections.Generic; using Microsoft.Azure.WebJobs; using Microsoft.Extensions.Azure; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Primitives; namespace Microsoft.Extensions.Hosting { @@ -29,7 +30,7 @@ public static IWebJobsBuilder AddAzureClients(this IWebJobsBuilder builder) } builder.Services.AddAzureClients(builder => - builder.UseConfiguration(provider => provider.GetRequiredService().GetWebJobsRootConfiguration())); + builder.UseConfiguration(provider => new WebJobsConfiguration(provider.GetRequiredService()))); builder.AddExtension(); return builder; diff --git a/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/src/Properties/AssemblyInfo.cs b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/src/Properties/AssemblyInfo.cs new file mode 100644 index 000000000000..0290cac488da --- /dev/null +++ b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/src/Properties/AssemblyInfo.cs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] +[assembly: InternalsVisibleTo("Microsoft.Azure.WebJobs.Extensions.Clients.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100d15ddcb29688295338af4b7686603fe614abd555e09efba8fb88ee09e1f7b1ccaeed2e8f823fa9eef3fdd60217fc012ea67d2479751a0b8c087a4185541b851bd8b16f8d91b840e51b1cb0ba6fe647997e57429265e85ef62d565db50a69ae1647d54d7bd855e4db3d8a91510e5bcbd0edfbbecaa20a7bd9ae74593daa7b11b4")] \ No newline at end of file diff --git a/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/src/WebJobsConfiguration.cs b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/src/WebJobsConfiguration.cs new file mode 100644 index 000000000000..2b4aef0e626a --- /dev/null +++ b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/src/WebJobsConfiguration.cs @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using Microsoft.Azure.WebJobs; +using Microsoft.Extensions.Azure; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Primitives; + +namespace Microsoft.Extensions.Hosting +{ + /// + /// Wraps the instance and applies fallback rules similar to https://github.com/Azure/azure-webjobs-sdk/blob/dev/src/Microsoft.Azure.WebJobs.Host/Extensions/IConfigurationExtensions.cs. + /// + internal class WebJobsConfiguration : IConfiguration + { + private readonly IConfiguration _configuration; + + public WebJobsConfiguration(IConfiguration configuration) + { + _configuration = configuration; + } + + private const string DefaultConfigurationRootSectionName = "AzureWebJobs"; + + public string this[string key] + { + get => _configuration[key]; + set => _configuration[key] = value; + } + + public IEnumerable GetChildren() => _configuration.GetChildren(); + + public IChangeToken GetReloadToken() => _configuration.GetReloadToken(); + + public IConfigurationSection GetSection(string key) + { + var section = _configuration.GetSection(key); + if (section.Exists()) + { + return section; + } + + var prefixedKey = DefaultConfigurationRootSectionName + key; + section = _configuration.GetSection(prefixedKey); + if (section.Exists()) + { + return section; + } + + return _configuration.GetSection("ConnectionStrings").GetSection(key); + } + } +} diff --git a/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/AzureClientAttributeFunctionalTests.cs b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/AzureClientAttributeFunctionalTests.cs new file mode 100644 index 000000000000..f3a2db5e9eb2 --- /dev/null +++ b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/AzureClientAttributeFunctionalTests.cs @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.Threading.Tasks; +using Azure.Core; +using Azure.Core.TestFramework; +using Azure.Security.KeyVault.Secrets; +using Microsoft.Azure.WebJobs.Host.TestCommon; +using Microsoft.Extensions.Azure; +using Microsoft.Extensions.Azure.WebJobs.Tests; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; + +namespace Microsoft.Azure.WebJobs.Extensions.Clients.Tests +{ + public class AzureClientAttributeFunctionalTests : RecordedTestBase + { + public AzureClientAttributeFunctionalTests(bool isAsync) : base(isAsync) + { + Matcher = new RecordMatcher() + { + VolatileQueryParameters = + { + // Ignore KeyVault client API Version when matching + "api-version" + } + }; + } + + [RecordedTest] + public async Task CanInjectKeyVaultClient() + { + var host = new HostBuilder() + .ConfigureServices(services => services.AddAzureClients(builder => builder + .ConfigureDefaults(options => Recording.InstrumentClientOptions(options)) + .UseCredential(TestEnvironment.Credential))) + .ConfigureAppConfiguration(config => + { + config.AddInMemoryCollection(new Dictionary + { + { "AzureWebJobsConnection:vaultUri", TestEnvironment.KeyVaultUrl } + }); + }) + .ConfigureDefaultTestHost(builder => + { + builder.AddAzureClients(); + }).Build(); + + var jobHost = host.GetJobHost(); + await jobHost.CallAsync(nameof(FunctionWithAzureClient.Run)); + } + + public class FunctionWithAzureClient + { + public async Task Run([AzureClient("Connection")] SecretClient keyClient) + { + await keyClient.SetSecretAsync("TestSecret", "Secret value"); + } + } + } +} diff --git a/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/AzureClientAttributeTests.cs b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/AzureClientAttributeTests.cs index a6f307791bbf..24812870a250 100644 --- a/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/AzureClientAttributeTests.cs +++ b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/AzureClientAttributeTests.cs @@ -3,60 +3,128 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Azure.Core; -using Azure.Core.TestFramework; -using Azure.Security.KeyVault.Secrets; using Microsoft.Azure.WebJobs.Host.TestCommon; -using Microsoft.Extensions.Azure; -using Microsoft.Extensions.Azure.WebJobs.Tests; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; +using NUnit.Framework; namespace Microsoft.Azure.WebJobs.Extensions.Clients.Tests { - public class AzureClientAttributeTests : RecordedTestBase + public class AzureClientAttributeTests { - public AzureClientAttributeTests(bool isAsync) : base(isAsync) + [TestCase("Connection")] + [TestCase("AzureWebJobsConnection")] + [TestCase("ConnectionStrings:Connection")] + public async Task CreatesClientUsingSectionWithUri(string keyName) { - Matcher = new RecordMatcher() + var host = new HostBuilder() + .ConfigureAppConfiguration(config => + { + config.AddInMemoryCollection(new Dictionary + { + { $"{keyName}:endpoint", "http://localhost" } + }); + }) + .ConfigureDefaultTestHost(builder => + { + builder.AddAzureClients(); + }).Build(); + + var jobHost = host.GetJobHost(); + await jobHost.CallAsync(nameof(FunctionWithAzureClient.Run)); + } + + public class FunctionWithAzureClient + { + public void Run([AzureClient("Connection")] TestClient testClient) { - VolatileQueryParameters = + Assert.NotNull(testClient.Options); + Assert.AreEqual(testClient.Uri.AbsoluteUri, "http://localhost/"); + } + } + + [TestCase("Connection")] + [TestCase("AzureWebJobsConnection")] + [TestCase("ConnectionStrings:Connection")] + public async Task CreatesClientUsingConnectionString(string keyName) + { + var host = new HostBuilder() + .ConfigureAppConfiguration(config => + { + config.AddInMemoryCollection(new Dictionary + { + { $"{keyName}", "Key=Value;Key2=Value2" } + }); + }) + .ConfigureDefaultTestHost(builder => { - // Ignore KeyVault client API Version when matching - "api-version" - } - }; + builder.AddAzureClients(); + }).Build(); + + var jobHost = host.GetJobHost(); + await jobHost.CallAsync(nameof(FunctionWithAzureClientUsingConnectionString.Run)); } - [RecordedTest] - public async Task CanInjectKeyVaultClient() + [TestCase("Connection")] + [TestCase("AzureWebJobsConnection")] + [TestCase("ConnectionStrings:Connection")] + public async Task CreatesClientUsingExplicitConnectionString(string keyName) { var host = new HostBuilder() - .ConfigureServices(services => services.AddAzureClients(builder => builder - .ConfigureDefaults(options => Recording.InstrumentClientOptions(options)) - .UseCredential(TestEnvironment.Credential))) .ConfigureAppConfiguration(config => { config.AddInMemoryCollection(new Dictionary { - { "AzureWebJobs:Connection:vaultUri", TestEnvironment.KeyVaultUrl } + { $"{keyName}:ConnectionString", "Key=Value;Key2=Value2" } }); }) - .ConfigureDefaultTestHost(builder => + .ConfigureDefaultTestHost(builder => { builder.AddAzureClients(); }).Build(); - var jobHost = host.GetJobHost(); - await jobHost.CallAsync(nameof(FunctionWithAzureClient.Run)); + var jobHost = host.GetJobHost(); + await jobHost.CallAsync(nameof(FunctionWithAzureClientUsingConnectionString.Run)); } - public class FunctionWithAzureClient + public class FunctionWithAzureClientUsingConnectionString + { + public void Run([AzureClient("Connection")] TestClient testClient) + { + Assert.NotNull(testClient.Options); + Assert.AreEqual(testClient.ConnectionString, "Key=Value;Key2=Value2"); + } + } + + [Test] + public async Task CreatesClientUsingExplicitConnectionString() + { + var host = new HostBuilder() + .ConfigureAppConfiguration(config => + { + config.AddInMemoryCollection(new Dictionary + { + { "ConnectionSettingName", "MyConnection"}, + { "MyConnection:ConnectionString", "Key=Value;Key2=Value2" } + }); + }) + .ConfigureDefaultTestHost(builder => + { + builder.AddAzureClients(); + }).Build(); + + var jobHost = host.GetJobHost(); + await jobHost.CallAsync(nameof(FunctionWithAzureClientUsingFormattedString.Run)); + } + + public class FunctionWithAzureClientUsingFormattedString { - public async Task Run([AzureClient("Connection")] SecretClient keyClient) + public void Run([AzureClient("%ConnectionSettingName%")] TestClient testClient) { - await keyClient.SetSecretAsync("TestSecret", "Secret value"); + Assert.NotNull(testClient.Options); + Assert.AreEqual(testClient.ConnectionString, "Key=Value;Key2=Value2"); } } + } -} +} \ No newline at end of file diff --git a/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/SessionRecords/AzureClientAttributeTests/CanInjectKeyVaultClient.json b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/SessionRecords/AzureClientAttributeFunctionalTests/CanInjectKeyVaultClient.json similarity index 100% rename from sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/SessionRecords/AzureClientAttributeTests/CanInjectKeyVaultClient.json rename to sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/SessionRecords/AzureClientAttributeFunctionalTests/CanInjectKeyVaultClient.json diff --git a/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/SessionRecords/AzureClientAttributeTests/CanInjectKeyVaultClientAsync.json b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/SessionRecords/AzureClientAttributeFunctionalTests/CanInjectKeyVaultClientAsync.json similarity index 100% rename from sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/SessionRecords/AzureClientAttributeTests/CanInjectKeyVaultClientAsync.json rename to sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/SessionRecords/AzureClientAttributeFunctionalTests/CanInjectKeyVaultClientAsync.json diff --git a/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/TestClient.cs b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/TestClient.cs new file mode 100644 index 000000000000..e6e314634302 --- /dev/null +++ b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/TestClient.cs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; + +namespace Microsoft.Azure.WebJobs.Extensions.Clients.Tests +{ + public class TestClient + { + public string ConnectionString { get; } + public Uri Uri { get; } + public TestClientOptions Options { get; } + + public TestClient(string connectionString, TestClientOptions options) + { + ConnectionString = connectionString; + Options = options; + } + + public TestClient(Uri endpoint, TestClientOptions options) + { + Uri = endpoint; + Options = options; + } + } +} \ No newline at end of file diff --git a/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/TestClientOptions.cs b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/TestClientOptions.cs new file mode 100644 index 000000000000..5d43440d0c09 --- /dev/null +++ b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/TestClientOptions.cs @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core; + +namespace Microsoft.Azure.WebJobs.Extensions.Clients.Tests +{ + public class TestClientOptions: ClientOptions + { + } +} \ No newline at end of file diff --git a/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/WebJobsConfigurationTests.cs b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/WebJobsConfigurationTests.cs new file mode 100644 index 000000000000..d35a4f8abf2f --- /dev/null +++ b/sdk/extensions/Microsoft.Azure.WebJobs.Extensions.Clients/tests/WebJobsConfigurationTests.cs @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using NUnit.Framework; + +namespace Microsoft.Azure.WebJobs.Extensions.Clients.Tests +{ + public class WebJobsConfigurationTests + { + [TestCase("Key")] + [TestCase("AzureWebJobsKey")] + [TestCase("ConnectionStrings:Key")] + public void KeysAreMappedForSingleValue(string actualKeyName) + { + var builder = new ConfigurationBuilder() + .AddInMemoryCollection(new[] + { + new KeyValuePair(actualKeyName, "value") + }); + var configuration = new WebJobsConfiguration(builder.Build()); + + Assert.AreEqual(configuration.GetSection("Key").Value, "value"); + } + + [TestCase("Key")] + [TestCase("AzureWebJobsKey")] + [TestCase("ConnectionStrings:Key")] + public void KeysAreMappedForSections(string actualKeyName) + { + var builder = new ConfigurationBuilder() + .AddInMemoryCollection(new[] + { + new KeyValuePair(actualKeyName + ":Value1", "value1"), + new KeyValuePair(actualKeyName + ":Value2", "value2") + }); + var configuration = new WebJobsConfiguration(builder.Build()); + + Assert.AreEqual(configuration.GetSection("Key")["Value1"], "value1"); + Assert.AreEqual(configuration.GetSection("Key")["Value2"], "value2"); + } + } +} \ No newline at end of file