Skip to content

Commit

Permalink
Merge branch 'master' into Added-ActorReference-creation-from-the-act…
Browse files Browse the repository at this point in the history
…or-base-class
  • Loading branch information
m3nax committed Jun 26, 2024
2 parents 4293a91 + 8496253 commit 68a1bda
Show file tree
Hide file tree
Showing 10 changed files with 258 additions and 35 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/itests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ jobs:
GOARCH: amd64
GOPROXY: https://proxy.golang.org
DAPR_CLI_VER: 1.13.0
DAPR_RUNTIME_VER: 1.13.0
DAPR_INSTALL_URL: https://raw.githubusercontent.com/dapr/cli/release-1.13/install/install.sh
DAPR_RUNTIME_VER: 1.13.2
DAPR_INSTALL_URL: https://raw.githubusercontent.com/dapr/cli/release-1.12/install/install.sh
DAPR_CLI_REF: ''
steps:
- name: Set up Dapr CLI
Expand Down
14 changes: 1 addition & 13 deletions all.sln
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{1BD1276E-D28A-45EA-89B1-6AD48471500D}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
README.md = README.md
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapr.Actors.AspNetCore.Test", "test\Dapr.Actors.AspNetCore.Test\Dapr.Actors.AspNetCore.Test.csproj", "{9C1D6ABA-5EDE-4FA0-A8A9-0AB98CB74737}"
Expand Down Expand Up @@ -347,16 +348,3 @@ Global
SolutionGuid = {65220BF2-EAE1-4CB2-AA58-EBE80768CB40}
EndGlobalSection
EndGlobal
8-446B-AECD-DCC2CC871F73}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {65220BF2-EAE1-4CB2-AA58-EBE80768CB40}
EndGlobalSection
EndGlobal
C991940} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{C74FBA78-13E8-407F-A173-4555AEE41FF3} = {A7F41094-8648-446B-AECD-DCC2CC871F73}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {65220BF2-EAE1-4CB2-AA58-EBE80768CB40}
EndGlobalSection
EndGlobal
29 changes: 20 additions & 9 deletions examples/Actor/DemoActor/DemoActor.csproj
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net6</TargetFramework>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\src\Dapr.Actors.AspNetCore\Dapr.Actors.AspNetCore.csproj" />
<ProjectReference Include="..\..\..\src\Dapr.Actors\Dapr.Actors.csproj" />
<ProjectReference Include="..\IDemoActor\IDemoActor.csproj" />
</ItemGroup>
<PropertyGroup>
<TargetFramework>net6</TargetFramework>
</PropertyGroup>

<PropertyGroup>
<IsPublishable>true</IsPublishable>
<EnableSdkContainerSupport>true</EnableSdkContainerSupport>
<ContainerRepository>demo-actor</ContainerRepository>
</PropertyGroup>

<ItemGroup>
<ContainerEnvironmentVariable Include="ASPNETCORE_URLS" Value="http://+:8080" />
<ContainerPort Include="8080" Type="tcp" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\src\Dapr.Actors.AspNetCore\Dapr.Actors.AspNetCore.csproj" />
<ProjectReference Include="..\..\..\src\Dapr.Actors\Dapr.Actors.csproj" />
<ProjectReference Include="..\IDemoActor\IDemoActor.csproj" />
</ItemGroup>

</Project>
2 changes: 1 addition & 1 deletion examples/Actor/DemoActor/Startup.cs
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
67 changes: 67 additions & 0 deletions examples/Actor/DemoActor/demo-actor.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: statestore
spec:
type: state.in-memory
version: v1
metadata:
- name: actorStateStore
value: "true"
---
kind: Service
apiVersion: v1
metadata:
name: demoactor
labels:
app: demoactor
spec:
selector:
app: demoactor
ports:
- name: app-port
protocol: TCP
port: 5010
targetPort: app-port
- name: dapr-http
protocol: TCP
port: 3500
targetPort: 3500
type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: demoactor
labels:
app: demoactor
spec:
replicas: 1
selector:
matchLabels:
app: demoactor
template:
metadata:
labels:
app: demoactor
annotations:
dapr.io/enabled: "true"
dapr.io/app-id: "demoactor"
dapr.io/app-port: "5010"
dapr.io/enable-api-logging: "true"
dapr.io/sidecar-listen-addresses: "0.0.0.0"
spec:
containers:
- name: demoactor
# image: <your-docker-registry>/demo-actor:latest
image: demo-actor:latest
# if you are using docker desktop, you can use imagePullPolicy: Never to use local image
imagePullPolicy: Never
env:
- name: APP_PORT
value: "5010"
- name: ASPNETCORE_URLS
value: "http://+:5010"
ports:
- name: app-port
containerPort: 5010
77 changes: 77 additions & 0 deletions examples/Actor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,80 @@ On Windows:
```sh
curl -X POST http://127.0.0.1:3500/v1.0/actors/DemoActor/abc/method/GetData
```

### Build and push Docker image
You can build the docker image of `DemoActor` service by running the following commands in the `DemoActor` project directory:

``` Bash
dotnet publish --os linux --arch x64 /t:PublishContainer -p ContainerImageTags='"latest"' --self-contained
```

The build produce and image with tag `demo-actor:latest` and load it in the local registry.
Now the image can be pushed to your remote Docker registry by running the following commands:

``` Bash
# Replace <your-docker-registry> with your Docker registry
docker tag demo-actor:latest <your-docker-registry>/demo-actor:latest
# Push the image to your Docker registry
docker push <your-docker-registry>/demo-actor:latest
```

### Deploy the Actor service to Kubernetes
#### Prerequisites
- A Kubernetes cluster with `kubectl` configured to access it.
- Dapr v1.13+ installed on the Kubernetes cluster. Follow the instructions [here](https://docs.dapr.io/getting-started/install-dapr-kubernetes/).
- A Docker registry where you pushed the `DemoActor` image.

#### Deploy the Actor service
For quick deployment you can install dapr in dev mode using the following command:

``` Bash
dapr init -k --dev
```

To deploy the `DemoActor` service to Kubernetes, you can use the provided Kubernetes manifest file `demo-actor.yaml` in the `DemoActor` project directory.
Before applying the manifest file, replace the image name in the manifest file with the image name you pushed to your Docker registry.

Part to update in `demo-actor.yaml`:
``` YAML
image: <your-docker-registry>/demoactor:latest
```

To install the application in `default` namespace, run the following command:

``` Bash
kubectl apply -f demo-actor.yaml
```

This will deploy the `DemoActor` service to Kubernetes. You can check the status of the deployment by running:

``` Bash
kubectl get pods -n default --watch
```

The manifest create 2 services:

- `demoactor` service: The service that hosts the `DemoActor` actor.
- `demoactor-dapr` service: The service that hosts the Dapr sidecar for the `DemoActor` actor.

### Make client calls to the deployed Actor service
To make client calls to the deployed `DemoActor` service, you can use the `ActorClient` project.
Before running the client, update the `DAPR_HTTP_PORT` environment variable in the `ActorClient` project directory to the port on which Dapr is running in the Kubernetes cluster.

On Linux, MacOS:
``` Bash
export DAPR_HTTP_PORT=3500
```

Than port-forward the `DemoActor` service to your local machine:

``` Bash
kubectl port-forward svc/demoactor 3500:3500
```

Now you can run the client project from the `ActorClient` directory:

``` Bash
dotnet run
```
30 changes: 22 additions & 8 deletions src/Dapr.AspNetCore/DaprServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,32 @@ public static class DaprServiceCollectionExtensions
/// <param name="configure"></param>
public static void AddDaprClient(this IServiceCollection services, Action<DaprClientBuilder> configure = null)
{
if (services is null)
{
throw new ArgumentNullException(nameof(services));
}
ArgumentNullException.ThrowIfNull(services, nameof(services));

services.TryAddSingleton(_ =>
{
var builder = new DaprClientBuilder();
if (configure != null)
{
configure.Invoke(builder);
}
configure?.Invoke(builder);
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)
{
ArgumentNullException.ThrowIfNull(services, nameof(services));

services.TryAddSingleton(serviceProvider =>
{
var builder = new DaprClientBuilder();
configure?.Invoke(serviceProvider, builder);
return builder.Build();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,15 @@ private async Task LoadAsync()
$"A duplicate key '{key}' was found in the secret store '{store}'. Please remove any duplicates from your secret store.");
}

data.Add(normalizeKey ? NormalizeKey(secretDescriptor.SecretName) : secretDescriptor.SecretName,
result[key]);
// The name of the key "as desired" by the user based on the descriptor.
//
// NOTE: This should vary only if a single secret of the same name is returned.
string desiredKey = StringComparer.Ordinal.Equals(key, secretDescriptor.SecretKey) ? secretDescriptor.SecretName : key;

// The name of the key normalized based on the configured delimiters.
string normalizedKey = normalizeKey ? NormalizeKey(desiredKey) : desiredKey;

data.Add(normalizedKey, result[key]);
}
}

Expand Down
30 changes: 30 additions & 0 deletions test/Dapr.AspNetCore.Test/DaprServiceCollectionExtensionsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,31 @@ public void AddDaprClient_RegistersDaprClientOnlyOnce()
Assert.True(daprClient.JsonSerializerOptions.PropertyNameCaseInsensitive);
}

[Fact]
public void AddDaprClient_RegistersUsingDependencyFromIServiceProvider()
{

var services = new ServiceCollection();
services.AddSingleton<TestConfigurationProvider>();
services.AddDaprClient((provider, builder) =>
{
var configProvider = provider.GetRequiredService<TestConfigurationProvider>();
var caseSensitivity = configProvider.GetCaseSensitivity();
builder.UseJsonSerializationOptions(new JsonSerializerOptions
{
PropertyNameCaseInsensitive = caseSensitivity
});
});

var serviceProvider = services.BuildServiceProvider();

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);
}

#if NET8_0_OR_GREATER
[Fact]
public void AddDaprClient_WithKeyedServices()
Expand All @@ -65,5 +90,10 @@ public void AddDaprClient_WithKeyedServices()
Assert.NotNull(daprClient);
}
#endif

private class TestConfigurationProvider
{
public bool GetCaseSensitivity() => false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,35 @@ public void LoadSecrets_FromSecretStoreThatCanReturnsMultipleValues()
config[secondSecretKey].Should().Be(secondSecretValue);
}

[Fact]
public void LoadSecrets_FromSecretStoreThatCanReturnsMultivaluedValues()
{
var storeName = "store";
var parentSecretKey = "connectionStrings";
var firstSecretKey = "first_secret";
var secondSecretKey = "second_secret";
var firstSecretValue = "secret1";
var secondSecretValue = "secret2";

var secretDescriptors = new[]
{
new DaprSecretDescriptor(parentSecretKey)
};

var daprClient = new Mock<DaprClient>();

daprClient.Setup(c => c.GetSecretAsync(storeName, parentSecretKey,
It.IsAny<Dictionary<string, string>>(), default))
.ReturnsAsync(new Dictionary<string, string> { { firstSecretKey, firstSecretValue }, { secondSecretKey, secondSecretValue } });

var config = CreateBuilder()
.AddDaprSecretStore(storeName, secretDescriptors, daprClient.Object)
.Build();

config[firstSecretKey].Should().Be(firstSecretValue);
config[secondSecretKey].Should().Be(secondSecretValue);
}

[Fact]
public void LoadSecrets_FromSecretStoreWithADifferentSecretKeyAndName()
{
Expand Down

0 comments on commit 68a1bda

Please sign in to comment.