Prioritize retrieval of environment variables from IConfiguration instead of directly (#1363)

* Implemented against Dapr.Client.AspNetCore and Dapr.Client

Signed-off-by: Whit Waldo <whit.waldo@innovian.net>

* SImplified DaprWorkflow DI registration and updated to use IConfiguration preference. Needs testing.

Signed-off-by: Whit Waldo <whit.waldo@innovian.net>

* Added missing copyright header

Signed-off-by: Whit Waldo <whit.waldo@innovian.net>

* Updated actor registration to prefer the updated IConfiguration-based approach for pulling the HTTP endpoint and API token

Signed-off-by: Whit Waldo <whit.waldo@innovian.net>

* Adopted accepted proposal's guidelines for favoring different environment variables for determining the sidecar endpoint. Added notes to explain this in the code going forward.

Signed-off-by: Whit Waldo <whit.waldo@innovian.net>

* Made some lines a little more concise, added hostname default to DaprDefaults to use when building endpoints.

Signed-off-by: Whit Waldo <whit.waldo@innovian.net>

* Fixed and updated unit tests

Signed-off-by: Whit Waldo <whit.waldo@innovian.net>

* Updated to put endpoint resolution mechanism in DaprDefaults within Dapr.Common  - updating projects and unit tests

Signed-off-by: Whit Waldo <whit.waldo@innovian.net>

* Updated packages to fix security advisory https://github.com/advisories/GHSA-447r-wph3-92pm

Signed-off-by: Whit Waldo <whit.waldo@innovian.net>

* Updated Workflow builder to use DaprDefaults with IConfiguration

Signed-off-by: Whit Waldo <whit.waldo@innovian.net>

* Updating global.json

Signed-off-by: Whit Waldo <whit.waldo@innovian.net>

* Tweaked global.json comment

Signed-off-by: Whit Waldo <whit.waldo@innovian.net>

* Adding braces per nit

Signed-off-by: Whit Waldo <whit.waldo@innovian.net>

* Consolidated both registration extension methods to remove duplication

Signed-off-by: Whit Waldo <whit.waldo@innovian.net>

---------

Signed-off-by: Whit Waldo <whit.waldo@innovian.net>
This commit is contained in:
Whit Waldo 2024-10-18 03:20:01 -05:00 committed by GitHub
parent 1e148874bb
commit 5548c670f4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 919 additions and 266 deletions

View File

@ -5,6 +5,7 @@
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="BenchmarkDotNet" Version="0.14.0" />
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
<PackageVersion Include="coverlet.msbuild" Version="6.0.2"/>
<PackageVersion Include="FluentAssertions" Version="5.9.0" />
@ -26,6 +27,7 @@
<PackageVersion Include="Microsoft.DurableTask.Client.Grpc" Version="1.3.0" />
<PackageVersion Include="Microsoft.DurableTask.Worker.Grpc" Version="1.3.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="6.0.1" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.4" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="6.0.0"/>
@ -39,6 +41,7 @@
<PackageVersion Include="Serilog.AspNetCore" Version="6.1.0" />
<PackageVersion Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageVersion Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageVersion Include="System.Formats.Asn1" Version="6.0.1" />
<PackageVersion Include="System.Text.Json" Version="6.0.10"/>
<PackageVersion Include="xunit" Version="2.9.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2"/>

View File

@ -122,6 +122,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapr.Protos", "src\Dapr.Pro
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapr.Common", "src\Dapr.Common\Dapr.Common.csproj", "{B445B19C-A925-4873-8CB7-8317898B6970}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapr.Common.Test", "test\Dapr.Common.Test\Dapr.Common.Test.csproj", "{CDB47863-BEBD-4841-A807-46D868962521}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -302,6 +304,10 @@ Global
{B445B19C-A925-4873-8CB7-8317898B6970}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B445B19C-A925-4873-8CB7-8317898B6970}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B445B19C-A925-4873-8CB7-8317898B6970}.Release|Any CPU.Build.0 = Release|Any CPU
{CDB47863-BEBD-4841-A807-46D868962521}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CDB47863-BEBD-4841-A807-46D868962521}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CDB47863-BEBD-4841-A807-46D868962521}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CDB47863-BEBD-4841-A807-46D868962521}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -357,6 +363,7 @@ Global
{C74FBA78-13E8-407F-A173-4555AEE41FF3} = {A7F41094-8648-446B-AECD-DCC2CC871F73}
{DFBABB04-50E9-42F6-B470-310E1B545638} = {27C5D71D-0721-4221-9286-B94AB07B58CF}
{B445B19C-A925-4873-8CB7-8317898B6970} = {27C5D71D-0721-4221-9286-B94AB07B58CF}
{CDB47863-BEBD-4841-A807-46D868962521} = {DD020B34-460F-455F-8D17-CF4A949F100B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {65220BF2-EAE1-4CB2-AA58-EBE80768CB40}

View File

@ -1,7 +1,7 @@
{
"_comment": "This policy allows the 7.0.101 SDK or patches in that family.",
"_comment": "This policy allows the 8.0.100 SDK or patches in that family.",
"sdk": {
"version": "7.0.101",
"rollForward": "latestMajor"
"version": "8.0.100",
"rollForward": "minor"
}
}

View File

@ -1,4 +1,4 @@
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// Copyright 2021 The Dapr Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -11,9 +11,13 @@
// limitations under the License.
// ------------------------------------------------------------------------
#nullable enable
using System;
using Dapr;
using Dapr.Actors.Client;
using Dapr.Actors.Runtime;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@ -30,12 +34,9 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary>
/// <param name="services">The <see cref="IServiceCollection" />.</param>
/// <param name="configure">A delegate used to configure actor options and register actor types.</param>
public static void AddActors(this IServiceCollection services, Action<ActorRuntimeOptions> configure)
public static void AddActors(this IServiceCollection? services, Action<ActorRuntimeOptions>? configure)
{
if (services is null)
{
throw new ArgumentNullException(nameof(services));
}
ArgumentNullException.ThrowIfNull(services, nameof(services));
// Routing and health checks are required dependencies.
services.AddRouting();
@ -45,6 +46,8 @@ namespace Microsoft.Extensions.DependencyInjection
services.TryAddSingleton<ActorRuntime>(s =>
{
var options = s.GetRequiredService<IOptions<ActorRuntimeOptions>>().Value;
ConfigureActorOptions(s, options);
var loggerFactory = s.GetRequiredService<ILoggerFactory>();
var activatorFactory = s.GetRequiredService<ActorActivatorFactory>();
var proxyFactory = s.GetRequiredService<IActorProxyFactory>();
@ -54,6 +57,8 @@ namespace Microsoft.Extensions.DependencyInjection
services.TryAddSingleton<IActorProxyFactory>(s =>
{
var options = s.GetRequiredService<IOptions<ActorRuntimeOptions>>().Value;
ConfigureActorOptions(s, options);
var factory = new ActorProxyFactory()
{
DefaultOptions =
@ -72,5 +77,16 @@ namespace Microsoft.Extensions.DependencyInjection
services.Configure<ActorRuntimeOptions>(configure);
}
}
private static void ConfigureActorOptions(IServiceProvider serviceProvider, ActorRuntimeOptions options)
{
var configuration = serviceProvider.GetService<IConfiguration>();
options.DaprApiToken = !string.IsNullOrWhiteSpace(options.DaprApiToken)
? options.DaprApiToken
: DaprDefaults.GetDefaultDaprApiToken(configuration);
options.HttpEndpoint = !string.IsNullOrWhiteSpace(options.HttpEndpoint)
? options.HttpEndpoint
: DaprDefaults.GetDefaultHttpEndpoint();
}
}
}

View File

@ -11,5 +11,6 @@
<ItemGroup>
<ProjectReference Include="..\Dapr.Actors\Dapr.Actors.csproj" />
<ProjectReference Include="..\Dapr.Common\Dapr.Common.csproj" />
</ItemGroup>
</Project>

View File

@ -45,7 +45,7 @@ namespace Dapr.Actors.Client
/// <summary>
/// The Dapr Api Token that is added to the header for all requests.
/// </summary>
public string DaprApiToken { get; set; } = DaprDefaults.GetDefaultDaprApiToken();
public string DaprApiToken { get; set; } = DaprDefaults.GetDefaultDaprApiToken(null);
/// <summary>
/// Gets or sets the HTTP endpoint URI used to communicate with the Dapr sidecar.

View File

@ -13,6 +13,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" />
</ItemGroup>
</Project>

View File

@ -11,6 +11,8 @@
// limitations under the License.
// ------------------------------------------------------------------------
#nullable enable
using System;
using System.Text.Json;
@ -34,7 +36,7 @@ namespace Dapr.Actors.Runtime
};
private bool useJsonSerialization = false;
private JsonSerializerOptions jsonSerializerOptions = JsonSerializerDefaults.Web;
private string daprApiToken = DaprDefaults.GetDefaultDaprApiToken();
private string daprApiToken = string.Empty;
private int? remindersStoragePartitions = null;
/// <summary>
@ -180,19 +182,14 @@ namespace Dapr.Actors.Runtime
set
{
if (value is null)
{
throw new ArgumentNullException(nameof(JsonSerializerOptions), $"{nameof(ActorRuntimeOptions)}.{nameof(JsonSerializerOptions)} cannot be null");
}
this.jsonSerializerOptions = value;
this.jsonSerializerOptions = value ?? throw new ArgumentNullException(nameof(JsonSerializerOptions), $"{nameof(ActorRuntimeOptions)}.{nameof(JsonSerializerOptions)} cannot be null");
}
}
/// <summary>
/// The <see cref="DaprApiToken"/> to add to the headers in requests to Dapr runtime
/// </summary>
public string DaprApiToken
public string? DaprApiToken
{
get
{
@ -201,12 +198,7 @@ namespace Dapr.Actors.Runtime
set
{
if (value is null)
{
throw new ArgumentNullException(nameof(DaprApiToken), $"{nameof(ActorRuntimeOptions)}.{nameof(DaprApiToken)} cannot be null");
}
this.daprApiToken = value;
this.daprApiToken = value ?? throw new ArgumentNullException(nameof(DaprApiToken), $"{nameof(ActorRuntimeOptions)}.{nameof(DaprApiToken)} cannot be null");
}
}
@ -241,6 +233,6 @@ namespace Dapr.Actors.Runtime
/// corresponding environment variables.
/// </remarks>
/// <value></value>
public string HttpEndpoint { get; set; } = DaprDefaults.GetDefaultHttpEndpoint();
public string? HttpEndpoint { get; set; }
}
}

View File

@ -11,7 +11,6 @@
// limitations under the License.
// ------------------------------------------------------------------------
using System;
using Microsoft.AspNetCore.Authentication;
namespace Dapr.AspNetCore
@ -29,6 +28,6 @@ namespace Dapr.AspNetCore
/// Gets or sets the App API token.
/// By default, the token will be read from the APP_API_TOKEN environment variable.
/// </summary>
public string Token { get; set; } = DaprDefaults.GetDefaultAppApiToken();
public string Token { get; set; } = DaprDefaults.GetDefaultAppApiToken(null);
}
}

View File

@ -1,4 +1,4 @@
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// Copyright 2021 The Dapr Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -11,55 +11,76 @@
// limitations under the License.
// ------------------------------------------------------------------------
namespace Microsoft.Extensions.DependencyInjection
#nullable enable
namespace Microsoft.Extensions.DependencyInjection;
using System;
using Dapr;
using Dapr.Client;
using Extensions;
using Configuration;
/// <summary>
/// Provides extension methods for <see cref="IServiceCollection" />.
/// </summary>
public static class DaprServiceCollectionExtensions
{
using System;
using System.Linq;
using Dapr.Client;
using Extensions;
/// <summary>
/// Adds Dapr client services to the provided <see cref="IServiceCollection" />. This does not include integration
/// with ASP.NET Core MVC. Use the <c>AddDapr()</c> extension method on <c>IMvcBuilder</c> to register MVC integration.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection" />.</param>
/// <param name="configure"></param>
public static void AddDaprClient(this IServiceCollection services, Action<DaprClientBuilder>? configure = null)
{
ArgumentNullException.ThrowIfNull(services, nameof(services));
services.TryAddSingleton(serviceProvider =>
{
var builder = CreateDaprClientBuilder(serviceProvider);
configure?.Invoke(builder);
return builder.Build();
});
}
/// <summary>
/// Provides extension methods for <see cref="IServiceCollection" />.
/// Adds Dapr client services to the provided <see cref="IServiceCollection"/>. This does not include integration
/// with ASP.NET Core MVC. Use the <c>AddDapr()</c> extension method on <c>IMvcBuilder</c> to register MVC integration.
/// </summary>
public static class DaprServiceCollectionExtensions
/// <param name="services">The <see cref="IServiceCollection"/>.</param>
/// <param name="configure"></param>
public static void AddDaprClient(this IServiceCollection services,
Action<IServiceProvider, DaprClientBuilder> configure)
{
/// <summary>
/// Adds Dapr client services to the provided <see cref="IServiceCollection" />. This does not include integration
/// with ASP.NET Core MVC. Use the <c>AddDapr()</c> extension method on <c>IMvcBuilder</c> to register MVC integration.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection" />.</param>
/// <param name="configure"></param>
public static void AddDaprClient(this IServiceCollection services, Action<DaprClientBuilder> configure = null)
ArgumentNullException.ThrowIfNull(services, nameof(services));
services.TryAddSingleton(serviceProvider =>
{
ArgumentNullException.ThrowIfNull(services, nameof(services));
var builder = CreateDaprClientBuilder(serviceProvider);
configure?.Invoke(serviceProvider, builder);
return builder.Build();
});
}
private static DaprClientBuilder CreateDaprClientBuilder(IServiceProvider serviceProvider)
{
var builder = new DaprClientBuilder();
var configuration = serviceProvider.GetService<IConfiguration>();
services.TryAddSingleton(_ =>
{
var builder = new DaprClientBuilder();
configure?.Invoke(builder);
// Set the HTTP endpoint, if provided, else use the default endpoint
builder.UseHttpEndpoint(DaprDefaults.GetDefaultHttpEndpoint(configuration));
return builder.Build();
});
}
/// <summary>
/// Adds Dapr client services to the provided <see cref="IServiceCollection"/>. This does not include integration
/// with ASP.NET Core MVC. Use the <c>AddDapr()</c> extension method on <c>IMvcBuilder</c> to register MVC integration.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/>.</param>
/// <param name="configure"></param>
public static void AddDaprClient(this IServiceCollection services,
Action<IServiceProvider, DaprClientBuilder> configure)
// Set the gRPC endpoint, if provided
builder.UseGrpcEndpoint(DaprDefaults.GetDefaultGrpcEndpoint(configuration));
// Set the API token, if provided
var apiToken = DaprDefaults.GetDefaultDaprApiToken(configuration);
if (!string.IsNullOrWhiteSpace(apiToken))
{
ArgumentNullException.ThrowIfNull(services, nameof(services));
services.TryAddSingleton(serviceProvider =>
{
var builder = new DaprClientBuilder();
configure?.Invoke(serviceProvider, builder);
return builder.Build();
});
builder.UseDaprApiToken(apiToken);
}
return builder;
}
}

View File

@ -139,17 +139,14 @@ namespace Dapr.Client
public static CallInvoker CreateInvocationInvoker(string appId, string daprEndpoint = null, string daprApiToken = null)
{
var channel = GrpcChannel.ForAddress(daprEndpoint ?? DaprDefaults.GetDefaultGrpcEndpoint());
return channel.Intercept(new InvocationInterceptor(appId, daprApiToken ?? DaprDefaults.GetDefaultDaprApiToken()));
return channel.Intercept(new InvocationInterceptor(appId, daprApiToken ?? DaprDefaults.GetDefaultDaprApiToken(null)));
}
internal static KeyValuePair<string, string>? GetDaprApiTokenHeader(string apiToken)
{
if (string.IsNullOrWhiteSpace(apiToken))
{
return null;
}
return new KeyValuePair<string, string>("dapr-api-token", apiToken);
return string.IsNullOrWhiteSpace(apiToken)
? null
: new KeyValuePair<string, string>("dapr-api-token", apiToken);
}
/// <summary>

View File

@ -40,7 +40,7 @@ namespace Dapr.Client
};
this.JsonSerializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web);
this.DaprApiToken = DaprDefaults.GetDefaultDaprApiToken();
this.DaprApiToken = DaprDefaults.GetDefaultDaprApiToken(null);
}
// property exposed for testing purposes

View File

@ -51,7 +51,7 @@ namespace Dapr.Client
public InvocationHandler()
{
this.parsedEndpoint = new Uri(DaprDefaults.GetDefaultHttpEndpoint(), UriKind.Absolute);
this.apiToken = DaprDefaults.GetDefaultDaprApiToken();
this.apiToken = DaprDefaults.GetDefaultDaprApiToken(null);
}
/// <summary>

View File

@ -9,6 +9,8 @@
<ItemGroup>
<PackageReference Include="Grpc.Net.Client" />
<PackageReference Include="Microsoft.Extensions.Http" />
<PackageReference Include="Microsoft.Extensions.Configuration" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" />
</ItemGroup>
</Project>

View File

@ -11,6 +11,8 @@
// limitations under the License.
// ------------------------------------------------------------------------
using Microsoft.Extensions.Configuration;
namespace Dapr
{
internal static class DaprDefaults
@ -20,82 +22,111 @@ namespace Dapr
private static string daprApiToken = string.Empty;
private static string appApiToken = string.Empty;
public const string DaprApiTokenName = "DAPR_API_TOKEN";
public const string AppApiTokenName = "APP_API_TOKEN";
public const string DaprHttpEndpointName = "DAPR_HTTP_ENDPOINT";
public const string DaprHttpPortName = "DAPR_HTTP_PORT";
public const string DaprGrpcEndpointName = "DAPR_GRPC_ENDPOINT";
public const string DaprGrpcPortName = "DAPR_GRPC_PORT";
public const string DefaultDaprScheme = "http";
public const string DefaultDaprHost = "localhost";
public const int DefaultHttpPort = 3500;
public const int DefaultGrpcPort = 50001;
/// <summary>
/// Get the value of environment variable DAPR_API_TOKEN
/// </summary>
/// <param name="configuration">The optional <see cref="IConfiguration"/> to pull the value from.</param>
/// <returns>The value of environment variable DAPR_API_TOKEN</returns>
public static string GetDefaultDaprApiToken()
{
// Lazy-init is safe because this is just populating the default
// We don't plan to support the case where the user changes environment variables
// for a running process.
if (string.IsNullOrEmpty(daprApiToken))
{
// Treat empty the same as null since it's an environment variable
var value = Environment.GetEnvironmentVariable("DAPR_API_TOKEN");
daprApiToken = string.IsNullOrEmpty(value) ? string.Empty : value;
}
return daprApiToken;
}
public static string GetDefaultDaprApiToken(IConfiguration? configuration) =>
GetResourceValue(configuration, DaprApiTokenName) ?? string.Empty;
/// <summary>
/// Get the value of environment variable APP_API_TOKEN
/// </summary>
/// <param name="configuration">The optional <see cref="IConfiguration"/> to pull the value from.</param>
/// <returns>The value of environment variable APP_API_TOKEN</returns>
public static string GetDefaultAppApiToken()
{
if (string.IsNullOrEmpty(appApiToken))
{
var value = Environment.GetEnvironmentVariable("APP_API_TOKEN");
appApiToken = string.IsNullOrEmpty(value) ? string.Empty : value;
}
return appApiToken;
}
public static string GetDefaultAppApiToken(IConfiguration? configuration) =>
GetResourceValue(configuration, AppApiTokenName) ?? string.Empty;
/// <summary>
/// Get the value of HTTP endpoint based off environment variables
/// </summary>
/// <param name="configuration">The optional <see cref="IConfiguration"/> to pull the value from.</param>
/// <returns>The value of HTTP endpoint based off environment variables</returns>
public static string GetDefaultHttpEndpoint()
public static string GetDefaultHttpEndpoint(IConfiguration? configuration = null)
{
if (string.IsNullOrEmpty(httpEndpoint))
{
var endpoint = Environment.GetEnvironmentVariable("DAPR_HTTP_ENDPOINT");
if (!string.IsNullOrEmpty(endpoint)) {
httpEndpoint = endpoint;
return httpEndpoint;
}
//Prioritize pulling from the IConfiguration and fallback to the environment variable if not populated
var endpoint = GetResourceValue(configuration, DaprHttpEndpointName);
var port = GetResourceValue(configuration, DaprHttpPortName);
//Use the default HTTP port if we're unable to retrieve/parse the provided port
int? parsedGrpcPort = string.IsNullOrWhiteSpace(port) ? DefaultHttpPort : int.Parse(port);
var port = Environment.GetEnvironmentVariable("DAPR_HTTP_PORT");
port = string.IsNullOrEmpty(port) ? "3500" : port;
httpEndpoint = $"http://127.0.0.1:{port}";
}
return httpEndpoint;
return BuildEndpoint(endpoint, parsedGrpcPort.Value);
}
/// <summary>
/// Get the value of gRPC endpoint based off environment variables
/// </summary>
/// <param name="configuration">The optional <see cref="IConfiguration"/> to pull the value from.</param>
/// <returns>The value of gRPC endpoint based off environment variables</returns>
public static string GetDefaultGrpcEndpoint()
public static string GetDefaultGrpcEndpoint(IConfiguration? configuration = null)
{
if (string.IsNullOrEmpty(grpcEndpoint))
{
var endpoint = Environment.GetEnvironmentVariable("DAPR_GRPC_ENDPOINT");
if (!string.IsNullOrEmpty(endpoint)) {
grpcEndpoint = endpoint;
return grpcEndpoint;
}
//Prioritize pulling from the IConfiguration and fallback to the environment variable if not populated
var endpoint = GetResourceValue(configuration, DaprGrpcEndpointName);
var port = GetResourceValue(configuration, DaprGrpcPortName);
//Use the default gRPC port if we're unable to retrieve/parse the provided port
int? parsedGrpcPort = string.IsNullOrWhiteSpace(port) ? DefaultGrpcPort : int.Parse(port);
var port = Environment.GetEnvironmentVariable("DAPR_GRPC_PORT");
port = string.IsNullOrEmpty(port) ? "50001" : port;
grpcEndpoint = $"http://127.0.0.1:{port}";
return BuildEndpoint(endpoint, parsedGrpcPort.Value);
}
/// <summary>
/// Builds the Dapr endpoint.
/// </summary>
/// <param name="endpoint">The endpoint value.</param>
/// <param name="endpointPort">The endpoint port value, whether pulled from configuration/envvar or the default.</param>
/// <returns>A constructed endpoint value.</returns>
private static string BuildEndpoint(string? endpoint, int endpointPort)
{
var endpointBuilder = new UriBuilder { Scheme = DefaultDaprScheme, Host = DefaultDaprHost }; //Port depends on endpoint
if (!string.IsNullOrWhiteSpace(endpoint)) //If the endpoint is set, it doesn't matter if the port is
{
//Extract the scheme, host and port from the endpoint and replace defaults
var uri = new Uri(endpoint);
endpointBuilder.Scheme = uri.Scheme;
endpointBuilder.Host = uri.Host;
endpointBuilder.Port = uri.Port;
}
else
{
//Should only set the port if the endpoint isn't populated
endpointBuilder.Port = endpointPort;
}
return grpcEndpoint;
return endpointBuilder.ToString();
}
/// <summary>
/// Retrieves the specified value prioritizing pulling it from <see cref="IConfiguration"/>, falling back
/// to an environment variable, and using an empty string as a default.
/// </summary>
/// <param name="configuration">An instance of an <see cref="IConfiguration"/>.</param>
/// <param name="name">The name of the value to retrieve.</param>
/// <returns>The value of the resource.</returns>
private static string? GetResourceValue(IConfiguration? configuration, string name)
{
//Attempt to retrieve first from the configuration
var configurationValue = configuration?[name];
if (configurationValue is not null)
return configurationValue;
//Fall back to the environment variable with the same name or default to an empty string
return Environment.GetEnvironmentVariable(name);
}
}
}

View File

@ -0,0 +1,95 @@
// ------------------------------------------------------------------------
// Copyright 2024 The Dapr Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
using System;
using System.Net.Http;
using Grpc.Net.Client;
using Microsoft.DurableTask.Client;
using Microsoft.DurableTask.Worker;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
#nullable enable
namespace Dapr.Workflow;
/// <summary>
/// A factory for building a <see cref="DaprWorkflowClient"/>.
/// </summary>
internal sealed class DaprWorkflowClientBuilderFactory
{
private readonly IConfiguration _configuration;
private readonly IHttpClientFactory _httpClientFactory;
private readonly IServiceCollection _services;
/// <summary>
/// Constructor used to inject the required types into the factory.
/// </summary>
public DaprWorkflowClientBuilderFactory(IConfiguration configuration, IHttpClientFactory httpClientFactory, IServiceCollection services)
{
_configuration = configuration;
_httpClientFactory = httpClientFactory;
_services = services;
}
/// <summary>
/// Responsible for building the client itself.
/// </summary>
/// <returns></returns>
public void CreateClientBuilder(Action<WorkflowRuntimeOptions> configure)
{
_services.AddDurableTaskClient(builder =>
{
var apiToken = DaprDefaults.GetDefaultDaprApiToken(_configuration);
var grpcEndpoint = DaprDefaults.GetDefaultGrpcEndpoint(_configuration);
var httpClient = _httpClientFactory.CreateClient();
if (!string.IsNullOrWhiteSpace(apiToken))
{
httpClient.DefaultRequestHeaders.Add( "Dapr-Api-Token", apiToken);
}
builder.UseGrpc(GrpcChannel.ForAddress(grpcEndpoint, new GrpcChannelOptions { HttpClient = httpClient }));
builder.RegisterDirectly();
});
_services.AddDurableTaskWorker(builder =>
{
WorkflowRuntimeOptions options = new();
configure?.Invoke(options);
var apiToken = DaprDefaults.GetDefaultDaprApiToken(_configuration);
var grpcEndpoint = DaprDefaults.GetDefaultGrpcEndpoint(_configuration);
if (!string.IsNullOrEmpty(grpcEndpoint))
{
var httpClient = _httpClientFactory.CreateClient();
if (!string.IsNullOrWhiteSpace(apiToken))
{
httpClient.DefaultRequestHeaders.Add("Dapr-Api-Token", apiToken);
}
builder.UseGrpc(
GrpcChannel.ForAddress(grpcEndpoint, new GrpcChannelOptions { HttpClient = httpClient }));
}
else
{
builder.UseGrpc();
}
builder.AddTasks(registry => options.AddWorkflowsAndActivitiesToRegistry(registry));
});
}
}

View File

@ -14,20 +14,14 @@
namespace Dapr.Workflow
{
using System;
using Grpc.Net.Client;
using Microsoft.DurableTask.Client;
using Microsoft.DurableTask.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System.Net.Http;
using Dapr;
/// <summary>
/// Contains extension methods for using Dapr Workflow with dependency injection.
/// </summary>
public static class WorkflowServiceCollectionExtensions
{
/// <summary>
/// Adds Dapr Workflow support to the service collection.
/// </summary>
@ -43,6 +37,7 @@ namespace Dapr.Workflow
}
serviceCollection.TryAddSingleton<WorkflowRuntimeOptions>();
serviceCollection.AddHttpClient();
#pragma warning disable CS0618 // Type or member is obsolete - keeping around temporarily - replaced by DaprWorkflowClient
serviceCollection.TryAddSingleton<WorkflowEngineClient>();
@ -50,135 +45,17 @@ namespace Dapr.Workflow
serviceCollection.AddHostedService<WorkflowLoggingService>();
serviceCollection.TryAddSingleton<DaprWorkflowClient>();
serviceCollection.AddDaprClient();
serviceCollection.AddDaprWorkflowClient();
serviceCollection.AddOptions<WorkflowRuntimeOptions>().Configure(configure);
serviceCollection.AddDurableTaskWorker(builder =>
serviceCollection.AddSingleton(c =>
{
WorkflowRuntimeOptions options = new();
configure?.Invoke(options);
if (TryGetGrpcAddress(out string address))
{
var daprApiToken = DaprDefaults.GetDefaultDaprApiToken();
if (!string.IsNullOrEmpty(daprApiToken))
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Dapr-Api-Token", daprApiToken);
builder.UseGrpc(CreateChannel(address, client));
}
else
{
builder.UseGrpc(address);
}
}
else
{
builder.UseGrpc();
}
builder.AddTasks(registry => options.AddWorkflowsAndActivitiesToRegistry(registry));
var factory = c.GetRequiredService<DaprWorkflowClientBuilderFactory>();
factory.CreateClientBuilder(configure);
return new object(); //Placeholder as actual registration is performed inside factory
});
return serviceCollection;
}
/// <summary>
/// Adds Dapr Workflow client support to the service collection.
/// </summary>
/// <remarks>
/// Use this extension method if you want to use <see cref="DaprWorkflowClient"/> in your app
/// but don't wish to define any workflows or activities.
/// </remarks>
/// <param name="services">The <see cref="IServiceCollection"/>.</param>
public static IServiceCollection AddDaprWorkflowClient(this IServiceCollection services)
{
services.TryAddSingleton<DaprWorkflowClient>();
services.AddDurableTaskClient(builder =>
{
if (TryGetGrpcAddress(out string address))
{
var daprApiToken = DaprDefaults.GetDefaultDaprApiToken();
if (!string.IsNullOrEmpty(daprApiToken))
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Dapr-Api-Token", daprApiToken);
builder.UseGrpc(CreateChannel(address, client));
}
else
{
builder.UseGrpc(address);
}
}
else
{
builder.UseGrpc();
}
builder.RegisterDirectly();
});
return services;
}
static bool TryGetGrpcAddress(out string address)
{
// TODO: Ideally we should be using DaprDefaults.cs for this. However, there are two blockers:
// 1. DaprDefaults.cs uses 127.0.0.1 instead of localhost, which prevents testing with Dapr on WSL2 and the app on Windows
// 2. DaprDefaults.cs doesn't compile when the project has C# nullable reference types enabled.
// If the above issues are fixed (ensuring we don't regress anything) we should switch to using the logic in DaprDefaults.cs.
var daprEndpoint = DaprDefaults.GetDefaultGrpcEndpoint();
if (!String.IsNullOrEmpty(daprEndpoint)) {
address = daprEndpoint;
return true;
}
var daprPortStr = Environment.GetEnvironmentVariable("DAPR_GRPC_PORT");
if (int.TryParse(daprPortStr, out int daprGrpcPort))
{
// There is a bug in the Durable Task SDK that requires us to change the format of the address
// depending on the version of .NET that we're targeting. For now, we work around this manually.
#if NET6_0_OR_GREATER
address = $"http://localhost:{daprGrpcPort}";
#else
address = $"localhost:{daprGrpcPort}";
#endif
return true;
}
address = string.Empty;
return false;
}
static GrpcChannel CreateChannel(string address, HttpClient client)
{
GrpcChannelOptions options = new() { HttpClient = client};
var daprEndpoint = DaprDefaults.GetDefaultGrpcEndpoint();
if (!String.IsNullOrEmpty(daprEndpoint)) {
return GrpcChannel.ForAddress(daprEndpoint, options);
}
var daprPortStr = Environment.GetEnvironmentVariable("DAPR_GRPC_PORT");
if (int.TryParse(daprPortStr, out int daprGrpcPort))
{
// If there is no address passed in, we default to localhost
if (String.IsNullOrEmpty(address))
{
// There is a bug in the Durable Task SDK that requires us to change the format of the address
// depending on the version of .NET that we're targeting. For now, we work around this manually.
#if NET6_0_OR_GREATER
address = $"http://localhost:{daprGrpcPort}";
#else
address = $"localhost:{daprGrpcPort}";
#endif
}
}
return GrpcChannel.ForAddress(address, options);
}
}
}

View File

@ -27,6 +27,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="System.Formats.Asn1" />
</ItemGroup>
</Project>

View File

@ -1,4 +1,4 @@
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// Copyright 2021 The Dapr Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -11,7 +11,9 @@
// limitations under the License.
// ------------------------------------------------------------------------
using System;
#nullable enable
using System;
using System.Text.Json;
using Dapr.Client;
using Microsoft.Extensions.DependencyInjection;
@ -43,15 +45,16 @@ namespace Dapr.AspNetCore.Test
var serviceProvider = services.BuildServiceProvider();
DaprClientGrpc daprClient = serviceProvider.GetService<DaprClient>() as DaprClientGrpc;
DaprClientGrpc? daprClient = serviceProvider.GetService<DaprClient>() as DaprClientGrpc;
Assert.True(daprClient.JsonSerializerOptions.PropertyNameCaseInsensitive);
Assert.NotNull(daprClient);
Assert.True(daprClient?.JsonSerializerOptions.PropertyNameCaseInsensitive);
}
[Fact]
public void AddDaprClient_RegistersUsingDependencyFromIServiceProvider()
{
var services = new ServiceCollection();
services.AddSingleton<TestConfigurationProvider>();
services.AddDaprClient((provider, builder) =>
@ -66,13 +69,15 @@ namespace Dapr.AspNetCore.Test
});
var serviceProvider = services.BuildServiceProvider();
DaprClientGrpc client = serviceProvider.GetRequiredService<DaprClient>() as DaprClientGrpc;
DaprClientGrpc? client = serviceProvider.GetRequiredService<DaprClient>() as DaprClientGrpc;
//Registers with case-insensitive as true by default, but we set as false above
Assert.False(client.JsonSerializerOptions.PropertyNameCaseInsensitive);
Assert.NotNull(client);
Assert.False(client?.JsonSerializerOptions.PropertyNameCaseInsensitive);
}
#if NET8_0_OR_GREATER
[Fact]
public void AddDaprClient_WithKeyedServices()
@ -90,7 +95,7 @@ namespace Dapr.AspNetCore.Test
Assert.NotNull(daprClient);
}
#endif
private class TestConfigurationProvider
{
public bool GetCaseSensitivity() => false;

View File

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="coverlet.msbuild">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="FluentAssertions"/>
<PackageReference Include="Microsoft.Extensions.Configuration" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Dapr.AspNetCore\Dapr.AspNetCore.csproj" />
<ProjectReference Include="..\..\src\Dapr.Common\Dapr.Common.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,582 @@
using System;
using Microsoft.Extensions.Configuration;
using Xunit;
namespace Dapr.Common.Test;
public class DaprDefaultTest
{
[Fact]
public void ShouldBuildHttpEndpointAndPortUsingPrefixedConfiguration()
{
const string endpointVarName = "test_DAPR_HTTP_ENDPOINT";
const string portVarName = "test_DAPR_HTTP_PORT";
var original_HttpEndpoint = Environment.GetEnvironmentVariable(endpointVarName);
var original_HttpPort = Environment.GetEnvironmentVariable(portVarName);
try
{
const string prefix = "test_";
Environment.SetEnvironmentVariable(endpointVarName, "https://dapr.io");
Environment.SetEnvironmentVariable(portVarName, null); //Will use 443 from the endpoint instead
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddEnvironmentVariables(prefix);
var configuration = configurationBuilder.Build();
var httpEndpoint = DaprDefaults.GetDefaultHttpEndpoint(configuration);
Assert.Equal("https://dapr.io:443/", httpEndpoint);
}
finally
{
//Restore
Environment.SetEnvironmentVariable(endpointVarName, original_HttpEndpoint);
Environment.SetEnvironmentVariable(portVarName, original_HttpPort);
}
}
[Fact]
public void ShouldBuildHttpEndpointAndPortUsingConfiguration()
{
const string endpointVarName = "DAPR_HTTP_ENDPOINT";
const string portVarName = "DAPR_HTTP_PORT";
var original_HttpEndpoint = Environment.GetEnvironmentVariable(endpointVarName);
var original_HttpPort = Environment.GetEnvironmentVariable(portVarName);
try
{
Environment.SetEnvironmentVariable(endpointVarName, "https://dapr.io");
Environment.SetEnvironmentVariable(portVarName, null); //Will use 443 from the endpoint instead
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddEnvironmentVariables();
var configuration = configurationBuilder.Build();
var httpEndpoint = DaprDefaults.GetDefaultHttpEndpoint(configuration);
Assert.Equal("https://dapr.io:443/", httpEndpoint);
}
finally
{
//Restore
Environment.SetEnvironmentVariable(endpointVarName, original_HttpEndpoint);
Environment.SetEnvironmentVariable(portVarName, original_HttpPort);
}
}
[Fact]
public void ShouldBuildHttpEndpointUsingPrefixedConfiguration()
{
const string endpointVarName = "test_DAPR_HTTP_ENDPOINT";
const string portVarName = "test_DAPR_HTTP_PORT";
var original_HttpEndpoint = Environment.GetEnvironmentVariable(endpointVarName);
var original_HttpPort = Environment.GetEnvironmentVariable(portVarName);
try
{
const string prefix = "test_";
Environment.SetEnvironmentVariable(endpointVarName, "https://dapr.io");
Environment.SetEnvironmentVariable(portVarName, "2569");
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddEnvironmentVariables(prefix);
var configuration = configurationBuilder.Build();
var httpEndpoint = DaprDefaults.GetDefaultHttpEndpoint(configuration);
Assert.Equal("https://dapr.io:443/", httpEndpoint);
}
finally
{
//Restore
Environment.SetEnvironmentVariable(endpointVarName, original_HttpEndpoint);
Environment.SetEnvironmentVariable(portVarName, original_HttpPort);
}
}
[Fact]
public void ShouldBuildHttpEndpointUsingConfiguration()
{
const string endpointVarName = "DAPR_HTTP_ENDPOINT";
const string portVarName = "DAPR_HTTP_PORT";
var original_HttpEndpoint = Environment.GetEnvironmentVariable(endpointVarName);
var original_HttpPort = Environment.GetEnvironmentVariable(portVarName);
try
{
Environment.SetEnvironmentVariable(endpointVarName, "https://dapr.io");
Environment.SetEnvironmentVariable(portVarName, "2569");
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddEnvironmentVariables();
var configuration = configurationBuilder.Build();
var httpEndpoint = DaprDefaults.GetDefaultHttpEndpoint(configuration);
Assert.Equal("https://dapr.io:443/", httpEndpoint);
}
finally
{
//Restore
Environment.SetEnvironmentVariable(endpointVarName, original_HttpEndpoint);
Environment.SetEnvironmentVariable(portVarName, original_HttpPort);
}
}
[Fact]
public void ShouldBuildHttpEndpointUsingOnlyPortConfiguration()
{
const string portVarName = "DAPR_HTTP_PORT";
var original_HttpPort = Environment.GetEnvironmentVariable(portVarName);
try
{
Environment.SetEnvironmentVariable(portVarName, "2569");
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddEnvironmentVariables();
var configuration = configurationBuilder.Build();
var httpEndpoint = DaprDefaults.GetDefaultHttpEndpoint(configuration);
Assert.Equal("http://localhost:2569/", httpEndpoint);
}
finally
{
//Restore
Environment.SetEnvironmentVariable(portVarName, original_HttpPort);
}
}
[Fact]
public void ShouldBuildHttpEndpointUsingEnvVarValues()
{
const string endpointVarName = "DAPR_HTTP_ENDPOINT";
const string portVarName = "DAPR_HTTP_PORT";
var original_HttpEndpoint = Environment.GetEnvironmentVariable(endpointVarName);
var original_HttpPort = Environment.GetEnvironmentVariable(portVarName);
try
{
Environment.SetEnvironmentVariable(endpointVarName, "http://dapr.io");
Environment.SetEnvironmentVariable(portVarName, "2569");
var configurationBuilder = new ConfigurationBuilder();
var configuration = configurationBuilder.Build();
var httpEndpoint = DaprDefaults.GetDefaultHttpEndpoint(configuration);
Assert.Equal("http://dapr.io:80/", httpEndpoint);
}
finally
{
//Restore
Environment.SetEnvironmentVariable(endpointVarName, original_HttpEndpoint);
Environment.SetEnvironmentVariable(portVarName, original_HttpPort);
}
}
[Fact]
public void ShouldBuildHttpEndpointUsingMixedValues()
{
const string endpointVarName = "test_DAPR_HTTP_ENDPOINT";
const string portVarName = "DAPR_HTTP_PORT";
var original_HttpEndpoint = Environment.GetEnvironmentVariable(endpointVarName);
var original_HttpPort = Environment.GetEnvironmentVariable(portVarName);
try
{
Environment.SetEnvironmentVariable(endpointVarName, "https://dapr.io");
Environment.SetEnvironmentVariable(portVarName, "2569");
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddEnvironmentVariables();
configurationBuilder.AddEnvironmentVariables("test_");
var configuration = configurationBuilder.Build();
var httpEndpoint = DaprDefaults.GetDefaultHttpEndpoint(configuration);
Assert.Equal("https://dapr.io:443/", httpEndpoint);
}
finally
{
//Restore
Environment.SetEnvironmentVariable(endpointVarName, original_HttpEndpoint);
Environment.SetEnvironmentVariable(portVarName, original_HttpPort);
}
}
[Fact]
public void ShouldDefaultToEmptyHttpEndpoint()
{
const string endpointVarName = "DAPR_HTTP_ENDPOINT";
const string portVarName = "DAPR_HTTP_PORT";
var original_HttpEndpoint = Environment.GetEnvironmentVariable(endpointVarName);
var original_HttpPort = Environment.GetEnvironmentVariable(portVarName);
try
{
Environment.SetEnvironmentVariable(endpointVarName, null);
Environment.SetEnvironmentVariable(portVarName, null);
var configurationBuilder = new ConfigurationBuilder();
var configuration = configurationBuilder.Build();
var httpEndpoint = DaprDefaults.GetDefaultHttpEndpoint(configuration);
Assert.Equal("http://localhost:3500/", httpEndpoint);
}
finally
{
//Restore
Environment.SetEnvironmentVariable(endpointVarName, original_HttpEndpoint);
Environment.SetEnvironmentVariable(portVarName, original_HttpPort);
}
}
[Fact]
public void ShouldDefaultToLocalhostWithPort()
{
const string endpointVarName = "DAPR_HTTP_ENDPOINT";
const string portVarName = "DAPR_HTTP_PORT";
var original_HttpEndpoint = Environment.GetEnvironmentVariable(endpointVarName);
var original_HttpPort = Environment.GetEnvironmentVariable(portVarName);
try
{
Environment.SetEnvironmentVariable(endpointVarName, null);
Environment.SetEnvironmentVariable(portVarName, "7256");
var configurationBuilder = new ConfigurationBuilder();
var configuration = configurationBuilder.Build();
var httpEndpoint = DaprDefaults.GetDefaultHttpEndpoint(configuration);
Assert.Equal("http://localhost:7256/", httpEndpoint);
}
finally
{
//Restore
Environment.SetEnvironmentVariable(endpointVarName, original_HttpEndpoint);
Environment.SetEnvironmentVariable(portVarName, original_HttpPort);
}
}
[Fact]
public void ShouldDefaultToLocalhostWithDefaultPort()
{
const string endpointVarName = "DAPR_HTTP_ENDPOINT";
const string portVarName = "DAPR_HTTP_PORT";
var original_HttpEndpoint = Environment.GetEnvironmentVariable(endpointVarName);
var original_HttpPort = Environment.GetEnvironmentVariable(portVarName);
try
{
Environment.SetEnvironmentVariable(endpointVarName, null);
Environment.SetEnvironmentVariable(portVarName, null);
var configurationBuilder = new ConfigurationBuilder();
var configuration = configurationBuilder.Build();
var httpEndpoint = DaprDefaults.GetDefaultHttpEndpoint(configuration);
Assert.Equal("http://localhost:3500/", httpEndpoint);
}
finally
{
//Restore
Environment.SetEnvironmentVariable(endpointVarName, original_HttpEndpoint);
Environment.SetEnvironmentVariable(portVarName, original_HttpPort);
}
}
[Fact]
public void ShouldBuildGrpcEndpointAndPortUsingPrefixedConfiguration()
{
const string endpointVarName = "test_DAPR_GRPC_ENDPOINT";
const string portVarName = "test_DAPR_GRPC_PORT";
var original_GrpcEndpoint = Environment.GetEnvironmentVariable(endpointVarName);
var original_GrpcPort = Environment.GetEnvironmentVariable(portVarName);
try
{
const string prefix = "test_";
Environment.SetEnvironmentVariable(endpointVarName, "https://grpc.dapr.io");
Environment.SetEnvironmentVariable(portVarName, "2570");
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddEnvironmentVariables(prefix);
var configuration = configurationBuilder.Build();
var grpcEndpoint = DaprDefaults.GetDefaultGrpcEndpoint(configuration);
Assert.Equal("https://grpc.dapr.io:443/", grpcEndpoint);
}
finally
{
//Restore
Environment.SetEnvironmentVariable(endpointVarName, original_GrpcEndpoint);
Environment.SetEnvironmentVariable(portVarName, original_GrpcPort);
}
}
[Fact]
public void ShouldBuildGrpcEndpointAndPortUsingConfiguration()
{
const string endpointVarName = DaprDefaults.DaprGrpcEndpointName;
const string portVarName = DaprDefaults.DaprGrpcPortName;
var original_GrpcEndpoint = Environment.GetEnvironmentVariable(endpointVarName);
var original_GrpcPort = Environment.GetEnvironmentVariable(portVarName);
try
{
Environment.SetEnvironmentVariable(endpointVarName, "https://grpc.dapr.io", EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable(portVarName, null, EnvironmentVariableTarget.Process); //Will use 443 from the endpoint value instead
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddEnvironmentVariables();
var configuration = configurationBuilder.Build();
var grpcEndpoint = DaprDefaults.GetDefaultGrpcEndpoint(configuration);
Assert.Equal("https://grpc.dapr.io:443/", grpcEndpoint);
}
finally
{
//Restore
Environment.SetEnvironmentVariable(endpointVarName, original_GrpcEndpoint);
Environment.SetEnvironmentVariable(portVarName, original_GrpcPort);
}
}
[Fact]
public void ShouldBuildGrpcEndpointUsingPrefixedConfiguration()
{
const string endpointVarName = "test_DAPR_GRPC_ENDPOINT";
var original_GrpcEndpoint = Environment.GetEnvironmentVariable(endpointVarName);
try
{
const string prefix = "test_";
Environment.SetEnvironmentVariable(endpointVarName, "https://grpc.dapr.io");
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddEnvironmentVariables(prefix);
var configuration = configurationBuilder.Build();
var grpcEndpoint = DaprDefaults.GetDefaultGrpcEndpoint(configuration);
Assert.Equal("https://grpc.dapr.io:443/", grpcEndpoint);
}
finally
{
//Restore
Environment.SetEnvironmentVariable(endpointVarName, original_GrpcEndpoint);
}
}
[Fact]
public void ShouldBuildGrpcEndpointUsingConfiguration()
{
const string endpointVarName = "DAPR_GRPC_ENDPOINT";
const string portVarName = "DAPR_GRPC_PORT";
var original_GrpcEndpoint = Environment.GetEnvironmentVariable(endpointVarName);
var original_GrpcPort = Environment.GetEnvironmentVariable(portVarName);
try
{
Environment.SetEnvironmentVariable(endpointVarName, "https://grpc.dapr.io");
Environment.SetEnvironmentVariable(portVarName, null); //Will use 443 from the endpoint value instead
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddEnvironmentVariables();
var configuration = configurationBuilder.Build();
var grpcEndpoint = DaprDefaults.GetDefaultGrpcEndpoint(configuration);
Assert.Equal("https://grpc.dapr.io:443/", grpcEndpoint);
}
finally
{
//Restore
Environment.SetEnvironmentVariable(endpointVarName, original_GrpcEndpoint);
Environment.SetEnvironmentVariable(portVarName, original_GrpcPort);
}
}
[Fact]
public void ShouldBuildGrpcEndpointAndPortUsingEnvVarValues()
{
const string endpointVarName = "DAPR_GRPC_ENDPOINT";
const string portVarName = "DAPR_GRPC_PORT";
var original_GrpcEndpoint = Environment.GetEnvironmentVariable(endpointVarName);
var original_GrpcPort = Environment.GetEnvironmentVariable(portVarName);
try
{
Environment.SetEnvironmentVariable(endpointVarName, "https://grpc.dapr.io");
Environment.SetEnvironmentVariable(portVarName, "4744"); //Will use 443 from the endpoint value instead
var configurationBuilder = new ConfigurationBuilder();
var configuration = configurationBuilder.Build();
var grpcEndpoint = DaprDefaults.GetDefaultGrpcEndpoint(configuration);
Assert.Equal("https://grpc.dapr.io:443/", grpcEndpoint);
}
finally
{
//Restore
Environment.SetEnvironmentVariable(endpointVarName, original_GrpcEndpoint);
Environment.SetEnvironmentVariable(portVarName, original_GrpcPort);
}
}
[Fact]
public void ShouldBuildGrpcEndpointUsingEnvVarValues()
{
const string endpointVarName = "DAPR_GRPC_ENDPOINT";
const string portVarName = "DAPR_GRPC_PORT";
var original_GrpcEndpoint = Environment.GetEnvironmentVariable(endpointVarName);
var original_GrpcPort = Environment.GetEnvironmentVariable(portVarName);
try
{
Environment.SetEnvironmentVariable(endpointVarName, "https://grpc.dapr.io");
Environment.SetEnvironmentVariable(portVarName, null); //Will use 443 from the endpoint value instead
var configurationBuilder = new ConfigurationBuilder();
var configuration = configurationBuilder.Build();
var grpcEndpoint = DaprDefaults.GetDefaultGrpcEndpoint(configuration);
Assert.Equal("https://grpc.dapr.io:443/", grpcEndpoint);
}
finally
{
//Restore
Environment.SetEnvironmentVariable(endpointVarName, original_GrpcEndpoint);
Environment.SetEnvironmentVariable(portVarName, original_GrpcPort);
}
}
[Fact]
public void ShouldBuildGrpcEndpointDefaultToLocalhostWithPort()
{
const string endpointVarName = DaprDefaults.DaprGrpcEndpointName;
const string portVarName = DaprDefaults.DaprGrpcPortName;
var original_grpcEndpoint = Environment.GetEnvironmentVariable(endpointVarName);
var original_grpcPort = Environment.GetEnvironmentVariable(portVarName);
try
{
Environment.SetEnvironmentVariable(endpointVarName, null);
Environment.SetEnvironmentVariable(portVarName, "7256");
var configurationBuilder = new ConfigurationBuilder();
var configuration = configurationBuilder.Build();
var grpcEndpoint = DaprDefaults.GetDefaultGrpcEndpoint(configuration);
Assert.Equal($"{DaprDefaults.DefaultDaprScheme}://{DaprDefaults.DefaultDaprHost}:7256/", grpcEndpoint);
}
finally
{
//Restore
Environment.SetEnvironmentVariable(endpointVarName, original_grpcEndpoint);
Environment.SetEnvironmentVariable(portVarName, original_grpcPort);
}
}
[Fact]
public void ShouldBuildGrpcEndpointDefaultToLocalhostWithDefaultPort()
{
const string endpointVarName = DaprDefaults.DaprGrpcEndpointName;
const string portVarName = DaprDefaults.DaprGrpcPortName;
var original_grpcEndpoint = Environment.GetEnvironmentVariable(endpointVarName);
var original_grpcPort = Environment.GetEnvironmentVariable(portVarName);
try
{
Environment.SetEnvironmentVariable(endpointVarName, null);
Environment.SetEnvironmentVariable(portVarName, null);
var configurationBuilder = new ConfigurationBuilder();
var configuration = configurationBuilder.Build();
var grpcEndpoint = DaprDefaults.GetDefaultGrpcEndpoint(configuration);
Assert.Equal($"{DaprDefaults.DefaultDaprScheme}://{DaprDefaults.DefaultDaprHost}:{DaprDefaults.DefaultGrpcPort}/", grpcEndpoint);
}
finally
{
//Restore
Environment.SetEnvironmentVariable(endpointVarName, original_grpcEndpoint);
Environment.SetEnvironmentVariable(portVarName, original_grpcPort);
}
}
[Fact]
public void ShouldBuildApiTokenUsingConfiguration()
{
const string envVarName = DaprDefaults.DaprApiTokenName;
var original_ApiToken = Environment.GetEnvironmentVariable(envVarName);
try
{
const string apiToken = "abc123";
Environment.SetEnvironmentVariable(envVarName, apiToken);
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddEnvironmentVariables();
var configuration = configurationBuilder.Build();
var testApiToken = DaprDefaults.GetDefaultDaprApiToken(configuration);
Assert.Equal(apiToken, testApiToken);
}
finally
{
//Restore
Environment.SetEnvironmentVariable(envVarName, original_ApiToken);
}
}
[Fact]
public void ShouldBuildApiTokenUsingPrefixedConfiguration()
{
const string envVarName = $"test_{DaprDefaults.DaprApiTokenName}";
var original_ApiToken = Environment.GetEnvironmentVariable(envVarName);
try
{
const string prefix = "test_";
const string apiToken = "abc123";
Environment.SetEnvironmentVariable(envVarName, apiToken);
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddEnvironmentVariables(prefix);
var configuration = configurationBuilder.Build();
var testApiToken = DaprDefaults.GetDefaultDaprApiToken(configuration);
Assert.Equal(apiToken, testApiToken);
}
finally
{
//Restore
Environment.SetEnvironmentVariable(envVarName, original_ApiToken);
}
}
[Fact]
public void ShouldBuildApiTokenWithEnvVarWhenConfigurationNotAvailable()
{
const string envVarName = DaprDefaults.DaprApiTokenName;
var original_ApiToken = Environment.GetEnvironmentVariable(envVarName);
const string apiToken = "abc123";
Environment.SetEnvironmentVariable(envVarName, apiToken);
try
{
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddEnvironmentVariables();
var configuration = configurationBuilder.Build();
var testApiToken = DaprDefaults.GetDefaultDaprApiToken(configuration);
Assert.Equal(apiToken, testApiToken);
}
finally
{
//Restore
Environment.SetEnvironmentVariable(envVarName, original_ApiToken);
}
}
}