Skip to content

Commit 17a5ee2

Browse files
authored
Enable localhost connection strings w/no auth in AzureManaged (#379)
1 parent 55481a3 commit 17a5ee2

File tree

9 files changed

+80
-11
lines changed

9 files changed

+80
-11
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## vNext
44

5+
- Added new preview packages, `Microsoft.DurableTask.Client.AzureManaged` and `Microsoft.DurableTask.Worker.AzureManaged`
6+
57
### Microsoft.DurableTask.Client
68

79
- Add new `IDurableTaskClientBuilder AddDurableTaskClient(IServiceCollection, string?)` API

src/Client/AzureManaged/DurableTaskSchedulerClientExtensions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public static void UseDurableTaskScheduler(
5959
options.EndpointAddress = connectionOptions.EndpointAddress;
6060
options.TaskHubName = connectionOptions.TaskHubName;
6161
options.Credential = connectionOptions.Credential;
62+
options.AllowInsecureCredentials = connectionOptions.AllowInsecureCredentials;
6263
},
6364
configure);
6465
}

src/Client/AzureManaged/DurableTaskSchedulerClientOptions.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,17 @@ public static DurableTaskSchedulerClientOptions FromConnectionString(string conn
5959
/// <param name="connectionString">The connection string to parse.</param>
6060
/// <returns>A new instance of <see cref="DurableTaskSchedulerClientOptions"/>.</returns>
6161
internal static DurableTaskSchedulerClientOptions FromConnectionString(
62-
DurableTaskSchedulerConnectionString connectionString) => new()
62+
DurableTaskSchedulerConnectionString connectionString)
63+
{
64+
TokenCredential? credential = GetCredentialFromConnectionString(connectionString);
65+
return new DurableTaskSchedulerClientOptions()
6366
{
6467
EndpointAddress = connectionString.Endpoint,
6568
TaskHubName = connectionString.TaskHubName,
66-
Credential = GetCredentialFromConnectionString(connectionString),
69+
Credential = credential,
70+
AllowInsecureCredentials = credential is null,
6771
};
72+
}
6873

6974
/// <summary>
7075
/// Creates a gRPC channel for communicating with the Durable Task Scheduler service.

src/Worker/AzureManaged/DurableTaskSchedulerWorkerExtensions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ public static void UseDurableTaskScheduler(
6060
options.EndpointAddress = connectionOptions.EndpointAddress;
6161
options.TaskHubName = connectionOptions.TaskHubName;
6262
options.Credential = connectionOptions.Credential;
63+
options.AllowInsecureCredentials = connectionOptions.AllowInsecureCredentials;
6364
},
6465
configure);
6566
}

src/Worker/AzureManaged/DurableTaskSchedulerWorkerOptions.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,17 @@ public static DurableTaskSchedulerWorkerOptions FromConnectionString(string conn
6565
/// <param name="connectionString">The connection string to parse.</param>
6666
/// <returns>A new instance of <see cref="DurableTaskSchedulerWorkerOptions"/>.</returns>
6767
internal static DurableTaskSchedulerWorkerOptions FromConnectionString(
68-
DurableTaskSchedulerConnectionString connectionString) => new()
68+
DurableTaskSchedulerConnectionString connectionString)
69+
{
70+
TokenCredential? credential = GetCredentialFromConnectionString(connectionString);
71+
return new DurableTaskSchedulerWorkerOptions()
6972
{
7073
EndpointAddress = connectionString.Endpoint,
7174
TaskHubName = connectionString.TaskHubName,
72-
Credential = GetCredentialFromConnectionString(connectionString),
75+
Credential = credential,
76+
AllowInsecureCredentials = credential is null,
7377
};
78+
}
7479

7580
/// <summary>
7681
/// Creates a gRPC channel for communicating with the Durable Task Scheduler service.

src/Worker/Grpc/GrpcDurableTaskWorker.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ public GrpcDurableTaskWorker(
4646
/// <inheritdoc />
4747
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
4848
{
49-
await using AsyncDisposable disposable = this.GetCallInvoker(out CallInvoker callInvoker);
50-
this.logger.StartingTaskHubWorker();
49+
await using AsyncDisposable disposable = this.GetCallInvoker(out CallInvoker callInvoker, out string address);
50+
this.logger.StartingTaskHubWorker(address);
5151
await new Processor(this, new(callInvoker)).ExecuteAsync(stoppingToken);
5252
}
5353

@@ -75,22 +75,25 @@ static GrpcChannel GetChannel(string? address)
7575
}
7676
#endif
7777

78-
AsyncDisposable GetCallInvoker(out CallInvoker callInvoker)
78+
AsyncDisposable GetCallInvoker(out CallInvoker callInvoker, out string address)
7979
{
8080
if (this.grpcOptions.Channel is GrpcChannel c)
8181
{
8282
callInvoker = c.CreateCallInvoker();
83+
address = c.Target;
8384
return default;
8485
}
8586

8687
if (this.grpcOptions.CallInvoker is CallInvoker invoker)
8788
{
8889
callInvoker = invoker;
90+
address = "(unspecified)";
8991
return default;
9092
}
9193

9294
c = GetChannel(this.grpcOptions.Address);
9395
callInvoker = c.CreateCallInvoker();
96+
address = c.Target;
9497
return new AsyncDisposable(() => new(c.ShutdownAsync()));
9598
}
9699
}

src/Worker/Grpc/Logs.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ namespace Microsoft.DurableTask.Worker.Grpc
1313
/// </remarks>
1414
static partial class Logs
1515
{
16-
[LoggerMessage(EventId = 1, Level = LogLevel.Information, Message = "Durable Task gRPC worker starting.")]
17-
public static partial void StartingTaskHubWorker(this ILogger logger);
16+
[LoggerMessage(EventId = 1, Level = LogLevel.Information, Message = "Durable Task gRPC worker starting and connecting to {endpoint}.")]
17+
public static partial void StartingTaskHubWorker(this ILogger logger, string endpoint);
1818

1919
[LoggerMessage(EventId = 2, Level = LogLevel.Information, Message = "Durable Task gRPC worker has disconnected from gRPC server.")]
2020
public static partial void SidecarDisconnected(this ILogger logger);

test/Client/AzureManaged.Tests/DurableTaskSchedulerClientExtensionsTests.cs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,32 @@ public void UseDurableTaskScheduler_WithConnectionString_ShouldConfigureCorrectl
6565
clientOptions.Credential.Should().BeOfType<DefaultAzureCredential>();
6666
}
6767

68+
[Fact]
69+
public void UseDurableTaskScheduler_WithLocalhostConnectionString_ShouldConfigureCorrectly()
70+
{
71+
// Arrange
72+
ServiceCollection services = new();
73+
Mock<IDurableTaskClientBuilder> mockBuilder = new();
74+
mockBuilder.Setup(b => b.Services).Returns(services);
75+
string connectionString = $"Endpoint=http://localhost;Authentication=None;TaskHub={ValidTaskHub}";
76+
77+
// Act
78+
mockBuilder.Object.UseDurableTaskScheduler(connectionString);
79+
80+
// Assert
81+
ServiceProvider provider = services.BuildServiceProvider();
82+
IOptions<GrpcDurableTaskClientOptions>? options = provider.GetService<IOptions<GrpcDurableTaskClientOptions>>();
83+
options.Should().NotBeNull();
84+
85+
// Validate the configured options
86+
var workerOptions = provider.GetRequiredService<IOptions<DurableTaskSchedulerClientOptions>>().Value;
87+
workerOptions.EndpointAddress.Should().Be("http://localhost");
88+
workerOptions.TaskHubName.Should().Be(ValidTaskHub);
89+
workerOptions.Credential.Should().BeNull();
90+
workerOptions.ResourceId.Should().Be("https://durabletask.io");
91+
workerOptions.AllowInsecureCredentials.Should().BeTrue();
92+
}
93+
6894
[Theory]
6995
[InlineData(null, "testhub")]
7096
[InlineData("myaccount.westus3.durabletask.io", null)]
@@ -124,7 +150,7 @@ public void UseDurableTaskScheduler_WithInvalidConnectionString_ShouldThrowArgum
124150

125151
// Assert
126152
action.Should().Throw<ArgumentNullException>()
127-
.WithMessage("Value cannot be null. (Parameter 'Endpoint')");
153+
.WithMessage("Value cannot be null. (Parameter '*')");
128154
}
129155

130156
[Theory]

test/Worker/AzureManaged.Tests/DurableTaskSchedulerWorkerExtensionsTests.cs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,32 @@ public void UseDurableTaskScheduler_WithConnectionString_ShouldConfigureCorrectl
6969
workerOptions.AllowInsecureCredentials.Should().BeFalse();
7070
}
7171

72+
[Fact]
73+
public void UseDurableTaskScheduler_WithLocalhostConnectionString_ShouldConfigureCorrectly()
74+
{
75+
// Arrange
76+
ServiceCollection services = new();
77+
Mock<IDurableTaskWorkerBuilder> mockBuilder = new();
78+
mockBuilder.Setup(b => b.Services).Returns(services);
79+
string connectionString = $"Endpoint=http://localhost;Authentication=None;TaskHub={ValidTaskHub}";
80+
81+
// Act
82+
mockBuilder.Object.UseDurableTaskScheduler(connectionString);
83+
84+
// Assert
85+
ServiceProvider provider = services.BuildServiceProvider();
86+
IOptions<GrpcDurableTaskWorkerOptions>? options = provider.GetService<IOptions<GrpcDurableTaskWorkerOptions>>();
87+
options.Should().NotBeNull();
88+
89+
// Validate the configured options
90+
var workerOptions = provider.GetRequiredService<IOptions<DurableTaskSchedulerWorkerOptions>>().Value;
91+
workerOptions.EndpointAddress.Should().Be("http://localhost");
92+
workerOptions.TaskHubName.Should().Be(ValidTaskHub);
93+
workerOptions.Credential.Should().BeNull();
94+
workerOptions.ResourceId.Should().Be("https://durabletask.io");
95+
workerOptions.AllowInsecureCredentials.Should().BeTrue();
96+
}
97+
7298
[Theory]
7399
[InlineData(null, "testhub")]
74100
[InlineData("myaccount.westus3.durabletask.io", null)]
@@ -129,7 +155,7 @@ public void UseDurableTaskScheduler_WithInvalidConnectionString_ShouldThrowArgum
129155

130156
// Assert
131157
action.Should().Throw<ArgumentNullException>()
132-
.WithMessage("Value cannot be null. (Parameter 'Endpoint')");
158+
.WithMessage("Value cannot be null. (Parameter '*')");
133159
}
134160

135161
[Theory]

0 commit comments

Comments
 (0)