Merge branch 'v1.5' into feature/pubsub_pulsar0901

This commit is contained in:
yellow chicks 2021-10-15 18:53:28 -05:00 committed by GitHub
commit 7bef63b9d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
71 changed files with 2705 additions and 580 deletions

View File

@ -3,11 +3,11 @@ name: Azure Static Web App Root
on:
push:
branches:
- v1.3
- v1.4
pull_request:
types: [opened, synchronize, reopened, closed]
branches:
- v1.3
- v1.4
jobs:
build_and_deploy_job:

View File

@ -1,13 +1,13 @@
name: Azure Static Web App v1.3
name: Azure Static Web App v1.4
on:
push:
branches:
- v1.3
- v1.5
pull_request:
types: [opened, synchronize, reopened, closed]
branches:
- v1.3
- v1.5
jobs:
build_and_deploy_job:
@ -27,7 +27,7 @@ jobs:
HUGO_ENV: production
HUGO_VERSION: "0.74.3"
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_V1_3 }}
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_V1_5 }}
repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
skip_deploy_on_missing_secrets: true
action: "upload"
@ -48,6 +48,6 @@ jobs:
id: closepullrequest
uses: Azure/static-web-apps-deploy@v0.0.1-preview
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_V1_3 }}
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_V1_5 }}
skip_deploy_on_missing_secrets: true
action: "close"

3
.gitmodules vendored
View File

@ -20,3 +20,6 @@
[submodule "sdkdocs/java"]
path = sdkdocs/java
url = https://github.com/dapr/java-sdk.git
[submodule "sdkdocs/js"]
path = sdkdocs/js
url = https://github.com/dapr/js-sdk.git

View File

@ -14,8 +14,8 @@ The following branches are currently maintained:
| Branch | Website | Description |
|--------|---------|-------------|
| [v1.3](https://github.com/dapr/docs) (primary) | https://docs.dapr.io | Latest Dapr release documentation. Typo fixes, clarifications, and most documentation goes here.
| [v1.4](https://github.com/dapr/docs/tree/v1.4) (pre-release) | https://v1-4.docs.dapr.io/ | Pre-release documentation. Doc updates that are only applicable to v1.4+ go here.
| [v1.4](https://github.com/dapr/docs) (primary) | https://docs.dapr.io | Latest Dapr release documentation. Typo fixes, clarifications, and most documentation goes here.
| [v1.5](https://github.com/dapr/docs/tree/v1.5) (pre-release) | https://v1-5.docs.dapr.io/ | Pre-release documentation. Doc updates that are only applicable to v1.5+ go here.
For more information visit the [Dapr branch structure](https://docs.dapr.io/contributing/contributing-docs/#branch-guidance) document.

View File

@ -1,5 +1,5 @@
# Site Configuration
baseURL = "https://docs.dapr.io/"
baseURL = "https://v1-5.docs.dapr.io/"
title = "Dapr Docs"
theme = "docsy"
disableFastRender = true
@ -87,6 +87,14 @@ id = "UA-149338238-3"
source = "../sdkdocs/java/daprdocs/content/en/java-sdk-contributing"
target = "content/contributing/"
lang = "en"
[[module.mounts]]
source = "../sdkdocs/js/daprdocs/content/en/js-sdk-docs"
target = "content/developing-applications/sdks/js"
lang = "en"
[[module.mounts]]
source = "../sdkdocs/js/daprdocs/content/en/js-sdk-contributing"
target = "content/contributing/"
lang = "en"
[[module.mounts]]
source = "../translations/docs-zh/content/zh-hans"
@ -149,20 +157,23 @@ offlineSearch = false
github_repo = "https://github.com/dapr/docs"
github_project_repo = "https://github.com/dapr/dapr"
github_subdir = "daprdocs"
github_branch = "v1.3"
github_branch = "v1.5"
# Versioning
version_menu = "v1.3 (latest)"
version = "v1.3"
version_menu = "v1.5 (preview)"
version = "v1.5"
archived_version = false
url_latest_version = "https://docs.dapr.io"
[[params.versions]]
version = "v1.4 (preview)"
url = "https://v1-4.docs.dapr.io"
[[params.versions]]
version = "v1.3 (latest)"
version = "v1.5 (preview)"
url = "#"
[[params.versions]]
version = "v1.4 (latest)"
url = "https://docs.dapr.io"
[[params.versions]]
version = "v1.3"
url = "https://v1-3.docs.dapr.io"
[[params.versions]]
version = "v1.2"
url = "https://v1-2.docs.dapr.io"
@ -190,6 +201,10 @@ url_latest_version = "https://docs.dapr.io"
sidebar_menu_compact = true
navbar_logo = true
sidebar_search_disable = true
[params.ui.feedback]
enable = true
yes = '<b>Glad to hear it!</b> Please <a href="https://github.com/dapr/docs/issues/new/choose">tell us how we can improve</a>.'
no = '<b>Sorry to hear that.</b> Please <a href="https://github.com/dapr/docs/issues/new/choose">tell us how we can improve</a>.'
# Links
## End user relevant links. These will show up on left side of footer and in the community page if you have one.

View File

@ -3,20 +3,39 @@ type: docs
no_list: true
---
<div class="card-deck">
<div class="card">
<div class="card-body">
<h5 class="card-title">
<img src="/images/daprcon.png" alt="DaprCon logo" width=40>
<b> Join us for DaprCon on October 19th-20th, 2021!</b>
</h5>
<p class="card-text">
The first ever DaprCon will take place October 19th-20th, 2021 virtually! Tune in for free and attend technical sessions, panels and real world examples from the community on building applications with Dapr! <br></br><i><b>Learn more >></b></i>
</p>
<a href="https://blog.dapr.io/posts/2021/10/05/join-us-for-daprcon-october-19th-20th-2021/" class="stretched-link"></a>
</div>
</div>
</div>
<br></br>
# <img src="/images/home-title.png" alt="Dapr Docs" width=400>
Welcome to the Dapr documentation site!
### Sections
{{% alert title="What is Dapr?" color="primary" %}}
Dapr is a portable, event-driven runtime that makes it easy for any developer to build resilient,
stateless and stateful applications that run on the cloud and edge and embraces the diversity of
languages and developer frameworks. Leveraging the benefits of a sidecar architecture, Dapr helps
you tackle the challenges that come with building microservices and keeps your code platform agnostic.
{{< button text="Get started" page="getting-started" >}}
{{% /alert %}}
### Start developing with Dapr
<div class="card-deck">
<div class="card">
<div class="card-body">
<h5 class="card-title"><b>Concepts</b></h5>
<p class="card-text">Learn about Dapr, including its main features and capabilities.</p>
<a href="{{< ref concepts >}}" class="stretched-link"></a>
</div>
</div>
<div class="card">
<div class="card-body">
<h5 class="card-title"><b>Getting started</b></h5>
@ -24,6 +43,26 @@ Welcome to the Dapr documentation site!
<a href="{{< ref getting-started >}}" class="stretched-link"></a>
</div>
</div>
<div class="card">
<div class="card-body">
<h5 class="card-title"><b>Quickstarts</b></h5>
<p class="card-text">A collection of tutorials with code samples to get you started quickly with Dapr.</p>
<a href="{{< ref quickstarts >}}" class="stretched-link"></a>
</div>
</div>
<div class="card">
<div class="card-body">
<h5 class="card-title"><b>Concepts</b></h5>
<p class="card-text">Learn about Dapr, including its main features and capabilities.</p>
<a href="{{< ref concepts >}}" class="stretched-link"></a>
</div>
</div>
</div>
### Learn more about Dapr
<div class="card-deck">
<div class="card">
<div class="card-body">
<h5 class="card-title"><b>Developing applications</b></h5>
@ -31,9 +70,13 @@ Welcome to the Dapr documentation site!
<a href="{{< ref developing-applications >}}" class="stretched-link"></a>
</div>
</div>
</div>
<br />
<div class="card-deck">
<div class="card">
<div class="card-body">
<h5 class="card-title"><b>Building blocks</b></h5>
<p class="card-text">Capabilities that solve common development challenges for distributed applications.</p>
<a href="{{< ref building-blocks-concept >}}" class="stretched-link"></a>
</div>
</div>
<div class="card">
<div class="card-body">
<h5 class="card-title"><b>Operations</b></h5>
@ -41,6 +84,12 @@ Welcome to the Dapr documentation site!
<a href="{{< ref operations >}}" class="stretched-link"></a>
</div>
</div>
</div>
### Additional info
<div class="card-deck">
<div class="card">
<div class="card-body">
<h5 class="card-title"><b>Reference</b></h5>
@ -58,64 +107,100 @@ Welcome to the Dapr documentation site!
</div>
### Tooling
### Tooling and resources
<div class="media">
<a class="pr-1" href="{{< ref ides >}}">
<img class="mr-3" src="/images/homepage/vscode.svg" alt="Visual studio code icon" width=40>
</a>
<div class="media-body">
<h5 class="mt-0"><b>IDE Integrations</b></h5>
<p>Learn how to get up and running with Dapr in your preferred integrated development environment.</p>
<div class="card-deck">
<div class="card">
<div class="card-body">
<h5 class="card-title">
<img src="/images/homepage/vscode.svg" alt="Visual studio code icon" width=40>
<b>IDE Integrations</b>
</h5>
<p class="card-text">
Learn how to get up and running with Dapr in your preferred integrated development environment.
</p>
<a href="{{< ref ides >}}" class="stretched-link"></a>
</div>
</div>
</div>
<div class="media">
<a class="pr-1" href="{{< ref sdks >}}">
<img class="mr-3" src="/images/homepage/code.svg" alt="Code icon" width=40>
</a>
<div class="media-body">
<h5 class="mt-0"><b>Language SDKs</b></h5>
<p>Create Dapr applications in your preferred language using the Dapr SDKs.</p>
<div class="media mt-3">
<a class="pr-3" href="{{< ref dotnet >}}">
<br>
<div class="card-deck">
<div class="card">
<div class="card-body">
<h5 class="card-title">
<img src="/images/homepage/code.svg" alt="Code icon" width=40>
<b>Language SDKs</b>
</h5>
<p class="card-text">
Create Dapr applications in your preferred language using the Dapr SDKs.
</p>
<a href="{{< ref sdks >}}" class="stretched-link"></a>
</div>
</div>
</div>
<br>
<div class="card-deck">
<div class="card">
<div class="card-body">
<h5 class="card-title">
<img src="/images/homepage/dotnet.png" alt=".NET logo" width=30>
</a>
<div class="media-body">
<h5 class="mt-0"><b>.NET</b></h5>
</div>
<b>.NET</b>
</h5>
<p class="card-text">
Learn more about the .NET SDK.
</p>
<a href="{{< ref dotnet >}}" class="stretched-link"></a>
</div>
<div class="media mt-3">
<a class="pr-3" href="{{< ref python >}}">
</div>
<div class="card">
<div class="card-body">
<h5 class="card-title">
<img src="/images/homepage/python.png" alt="Python logo" width=30>
</a>
<div class="media-body">
<h5 class="mt-0"><b>Python</b></h5>
</div>
</div>
<div class="media mt-3">
<a class="pr-4" href="{{< ref sdks >}}">
<img src="/images/homepage/java.png" alt="Java logo" width=20>
</a>
<div class="media-body">
<h5 class="mt-0"><b>Java</b></h5>
</div>
</div>
<div class="media mt-3">
<a class="pr-4" href="{{< ref go >}}">
<img src="/images/homepage/golang.svg" alt="Go logo" width=30>
</a>
<div class="media-body">
<h5 class="mt-0"><b>Go</b></h5>
</div>
</div>
<div class="media mt-3">
<a class="pr-4" href="{{< ref php >}}">
<img src="/images/homepage/php.png" alt="PHP logo" width=30>
</a>
<div class="media-body">
<h5 class="mt-0"><b>PHP</b></h5>
</div>
<b>Python</b>
</h5>
<p class="card-text">
Learn more about the Python SDK.
</p>
<a href="{{< ref python >}}" class="stretched-link"></a>
</div>
</div>
</div>
<br />
<br>
<div class="card-deck">
<div class="card">
<div class="card-body">
<h5 class="card-title">
<img src="/images/homepage/javalang.png" alt="Java logo" width=30>
<b>Java</b>
</h5>
<p class="card-text">
Learn more about the Java SDK.
</p>
<a href="{{< ref java >}}" class="stretched-link"></a>
</div>
</div>
<div class="card">
<div class="card-body">
<h5 class="card-title">
<img src="/images/homepage/golang.svg" alt="Go logo" width=30>
<b>Go</b>
</h5>
<p class="card-text">
Learn more about the Go SDK.
</p>
<a href="{{< ref go >}}" class="stretched-link"></a>
</div>
</div>
<div class="card">
<div class="card-body">
<h5 class="card-title">
<img src="/images/homepage/php.png" alt="PHP logo" width=30>
<b>PHP</b>
</h5>
<p class="card-text">
Learn more about the PHP SDK.
</p>
<a href="{{< ref php >}}" class="stretched-link"></a>
</div>
</div>
</div>

View File

@ -4,4 +4,13 @@ title: "Dapr concepts"
linkTitle: "Concepts"
weight: 10
description: "Learn about Dapr including its main features and capabilities"
---
---
Welcome to the Dapr concepts guide!
{{% alert title="Getting started with Dapr" color="primary" %}}
If you are ready to jump in and start developing with Dapr, please
visit the [getting started section]({{<ref getting-started>}}).
{{< button text="Install Dapr" page="getting-started" >}}
{{% /alert %}}

View File

@ -49,3 +49,9 @@ For a detailed list of all available arguments run `daprd --help` or see this [t
```bash
daprd --app-id myapp --enable-metrics
```
5. Listen to IPv4 and IPv6 loopback only
```bash
daprd --app-id myapp --dapr-listen-addresses '127.0.0.1,[::1]'
```

View File

@ -35,7 +35,7 @@ Every actor is defined as an instance of an actor type, identical to the way an
## Actor lifetime
Dapr actors are virtual, meaning that their lifetime is not tied to their in-memory representation. As a result, they do not need to be explicitly created or destroyed. The Dapr actors runtime automatically activates an actor the first time it receives a request for that actor ID. If an actor is not used for a period of time, the Dapr Actors runtime garbage-collects the in-memory object. It will also maintain knowledge of the actor's existence should it need to be reactivated later.
Dapr actors are virtual, meaning that their lifetime is not tied to their in-memory representation. As a result, they do not need to be explicitly created or destroyed. The Dapr actor runtime automatically activates an actor the first time it receives a request for that actor ID. If an actor is not used for a period of time, the Dapr actor runtime garbage-collects the in-memory object. It will also maintain knowledge of the actor's existence should it need to be reactivated later.
Invocation of actor methods and reminders reset the idle time, e.g. reminder firing will keep the actor active. Actor reminders fire whether an actor is active or inactive, if fired for inactive actor, it will activate the actor first. Actor timers do not reset the idle time, so timer firing will not keep the actor active. Timers only fire while the actor is active.
@ -77,11 +77,13 @@ POST/GET/PUT/DELETE http://localhost:3500/v1.0/actors/<actorType>/<actorId>/<met
You can provide any data for the actor method in the request body, and the response for the request would be in the response body which is the data from actor call.
Another, and perhaps more convenient, way of interacting with actors is via SDKs. Dapr currently supports actors SDKs in [.NET]({{< ref "dotnet-actors" >}}), [Java]({{< ref "java#actors" >}}), and [Python]({{< ref "python-actor" >}}).
Refer to [Dapr Actor Features]({{< ref howto-actors.md >}}) for more details.
### Concurrency
The Dapr Actors runtime provides a simple turn-based access model for accessing actor methods. This means that no more than one thread can be active inside an actor object's code at any time. Turn-based access greatly simplifies concurrent systems as there is no need for synchronization mechanisms for data access. It also means systems must be designed with special considerations for the single-threaded access nature of each actor instance.
The Dapr actor runtime provides a simple turn-based access model for accessing actor methods. This means that no more than one thread can be active inside an actor object's code at any time. Turn-based access greatly simplifies concurrent systems as there is no need for synchronization mechanisms for data access. It also means systems must be designed with special considerations for the single-threaded access nature of each actor instance.
A single actor instance cannot process more than one request at a time. An actor instance can cause a throughput bottleneck if it is expected to handle concurrent requests.
@ -94,9 +96,9 @@ As an enhancement to the base actors in dapr, reentrancy can now be enabled as a
### Turn-based access
A turn consists of the complete execution of an actor method in response to a request from other actors or clients, or the complete execution of a timer/reminder callback. Even though these methods and callbacks are asynchronous, the Dapr Actors runtime does not interleave them. A turn must be fully finished before a new turn is allowed. In other words, an actor method or timer/reminder callback that is currently executing must be fully finished before a new call to a method or callback is allowed. A method or callback is considered to have finished if the execution has returned from the method or callback and the task returned by the method or callback has finished. It is worth emphasizing that turn-based concurrency is respected even across different methods, timers, and callbacks.
A turn consists of the complete execution of an actor method in response to a request from other actors or clients, or the complete execution of a timer/reminder callback. Even though these methods and callbacks are asynchronous, the Dapr actor runtime does not interleave them. A turn must be fully finished before a new turn is allowed. In other words, an actor method or timer/reminder callback that is currently executing must be fully finished before a new call to a method or callback is allowed. A method or callback is considered to have finished if the execution has returned from the method or callback and the task returned by the method or callback has finished. It is worth emphasizing that turn-based concurrency is respected even across different methods, timers, and callbacks.
The Dapr actors runtime enforces turn-based concurrency by acquiring a per-actor lock at the beginning of a turn and releasing the lock at the end of the turn. Thus, turn-based concurrency is enforced on a per-actor basis and not across actors. Actor methods and timer/reminder callbacks can execute simultaneously on behalf of different actors.
The Dapr actor runtime enforces turn-based concurrency by acquiring a per-actor lock at the beginning of a turn and releasing the lock at the end of the turn. Thus, turn-based concurrency is enforced on a per-actor basis and not across actors. Actor methods and timer/reminder callbacks can execute simultaneously on behalf of different actors.
The following example illustrates the above concepts. Consider an actor type that implements two asynchronous methods (say, Method1 and Method2), a timer, and a reminder. The diagram below shows an example of a timeline for the execution of these methods and callbacks on behalf of two actors (ActorId1 and ActorId2) that belong to this actor type.

View File

@ -6,11 +6,11 @@ weight: 20
description: Learn more about the actor pattern
---
The Dapr actors runtime provides support for [virtual actors]({{< ref actors-overview.md >}}) through following capabilities:
The Dapr actor runtime provides support for [virtual actors]({{< ref actors-overview.md >}}) through following capabilities:
## Actor method invocation
You can interact with Dapr to invoke the actor method by calling HTTP/gRPC endpoint
You can interact with Dapr to invoke the actor method by calling HTTP/gRPC endpoint.
```html
POST/GET/PUT/DELETE http://localhost:3500/v1.0/actors/<actorType>/<actorId>/method/<method>
@ -20,6 +20,8 @@ You can provide any data for the actor method in the request body and the respon
Refer [api spec]({{< ref "actors_api.md#invoke-actor-method" >}}) for more details.
Alternatively, you can use the Dapr SDK in [.NET]({{< ref "dotnet-actors" >}}), [Java]({{< ref "java#actors" >}}), or [Python]({{< ref "python-actor" >}}).
## Actor state management
Actors can save state reliably using state management capability.
@ -31,27 +33,62 @@ To use actors, your state store must support multi-item transactions. This mean
Actors can schedule periodic work on themselves by registering either timers or reminders.
The functionality of timers and reminders is very similar. The main difference is that Dapr actor runtime is not retaining any information about timers after deactivation, while persisting the information about reminders using Dapr actor state provider.
This distintcion allows users to trade off between light-weight but stateless timers vs. more resource-demanding but stateful reminders.
The scheduling configuration of timers and reminders is identical, as summarized below:
---
`dueTime` is an optional parameter that sets time at which or time interval before the callback is invoked for the first time. If `dueTime` is omitted, the callback is invoked immediately after timer/reminder registration.
Supported formats:
- RFC3339 date format, e.g. `2020-10-02T15:00:00Z`
- time.Duration format, e.g. `2h30m`
- [ISO 8601 duration](https://en.wikipedia.org/wiki/ISO_8601#Durations) format, e.g. `PT2H30M`
---
`period` is an optional parameter that sets time interval between two consecutive callback invocations. When specified in `ISO 8601-1 duration` format, you can also configure the number of repetition in order to limit the total number of callback invocations.
If `period` is omitted, the callback will be invoked only once.
Supported formats:
- time.Duration format, e.g. `2h30m`
- [ISO 8601 duration](https://en.wikipedia.org/wiki/ISO_8601#Durations) format, e.g. `PT2H30M`, `R5/PT1M30S`
---
`ttl` is an optional parameter that sets time at which or time interval after which the timer/reminder will be expired and deleted. If `ttl` is omitted, no restrictions are applied.
Supported formats:
* RFC3339 date format, e.g. `2020-10-02T15:00:00Z`
* time.Duration format, e.g. `2h30m`
* [ISO 8601 duration](https://en.wikipedia.org/wiki/ISO_8601#Durations) format. Example: `PT2H30M`
---
The actor runtime validates correctess of the scheduling configuration and returns error on invalid input.
When you specify both the number of repetitions in `period` as well as `ttl`, the timer/reminder will be stopped when either condition is met.
### Actor timers
You can register a callback on actor to be executed based on a timer.
The Dapr actor runtime ensures that the callback methods respect the turn-based concurrency guarantees.This means that no other actor methods or timer/reminder callbacks will be in progress until this callback completes execution.
The Dapr actor runtime ensures that the callback methods respect the turn-based concurrency guarantees. This means that no other actor methods or timer/reminder callbacks will be in progress until this callback completes execution.
The next period of the timer starts after the callback completes execution. This implies that the timer is stopped while the callback is executing and is started when the callback finishes.
The Dapr actor runtime saves changes made to the actor's state when the callback finishes. If an error occurs in saving the state, that actor object is deactivated and a new instance will be activated.
The Dapr actors runtime saves changes made to the actor's state when the callback finishes. If an error occurs in saving the state, that actor object is deactivated and a new instance will be activated.
All timers are stopped when the actor is deactivated as part of garbage collection. No timer callbacks are invoked after that. Also, the Dapr actor runtime does not retain any information about the timers that were running before deactivation. It is up to the actor to register any timers that it needs when it is reactivated in the future.
All timers are stopped when the actor is deactivated as part of garbage collection. No timer callbacks are invoked after that. Also, the Dapr actors runtime does not retain any information about the timers that were running before deactivation. It is up to the actor to register any timers that it needs when it is reactivated in the future.
You can create a timer for an actor by calling the HTTP/gRPC request to Dapr.
You can create a timer for an actor by calling the HTTP/gRPC request to Dapr as shown below, or via Dapr SDK.
```md
POST/PUT http://localhost:3500/v1.0/actors/<actorType>/<actorId>/timers/<name>
```
The timer `duetime` and callback are specified in the request body. The due time represents when the timer will first fire after registration. The `period` represents how often the timer fires after that. A due time of 0 means to fire immediately. Negative due times and negative periods are invalid.
**Examples**
The following request body configures a timer with a `dueTime` of 9 seconds and a `period` of 3 seconds. This means it will first fire after 9 seconds, then every 3 seconds after that.
The timer parameters are specified in the request body.
The following request body configures a timer with a `dueTime` of 9 seconds and a `period` of 3 seconds. This means it will first fire after 9 seconds, then every 3 seconds after that.
```json
{
"dueTime":"0h0m9s0ms",
@ -59,11 +96,27 @@ The following request body configures a timer with a `dueTime` of 9 seconds and
}
```
The following request body configures a timer with a `dueTime` 0 seconds and a `period` of 3 seconds. This means it fires immediately after registration, then every 3 seconds after that.
The following request body configures a timer with a `period` of 3 seconds (in ISO 8601 duration format). It also limits the number of invocations to 10. This means it will fire 10 times: first, immediately after registration, then every 3 seconds after that.
```json
{
"dueTime":"0h0m0s0ms",
"period":"0h0m3s0ms"
"period":"R10/PT3S",
}
```
The following request body configures a timer with a `period` of 3 seconds (in ISO 8601 duration format) and a `ttl` of 20 seconds. This means it fires immediately after registration, then every 3 seconds after that for the duration of 20 seconds.
```json
{
"period":"PT3S",
"ttl":"20s"
}
```
The following request body configures a timer with a `dueTime` of 10 seconds, a `period` of 3 seconds, and a `ttl` of 10 seconds. It also limits the number of invocations to 4. This means it will first fire after 10 seconds, then every 3 seconds after that for the duration of 10 seconds, but no more than 4 times in total.
```json
{
"dueTime":"10s",
"period":"R4/PT3S",
"ttl":"10s"
}
```
@ -77,69 +130,15 @@ Refer [api spec]({{< ref "actors_api.md#invoke-timer" >}}) for more details.
### Actor reminders
Reminders are a mechanism to trigger *persistent* callbacks on an actor at specified times. Their functionality is similar to timers. But unlike timers, reminders are triggered under all circumstances until the actor explicitly unregisters them or the actor is explicitly deleted or the number in invocations is exhausted. Specifically, reminders are triggered across actor deactivations and failovers because the Dapr actors runtime persists the information about the actors' reminders using Dapr actor state provider.
Reminders are a mechanism to trigger *persistent* callbacks on an actor at specified times. Their functionality is similar to timers. But unlike timers, reminders are triggered under all circumstances until the actor explicitly unregisters them or the actor is explicitly deleted or the number in invocations is exhausted. Specifically, reminders are triggered across actor deactivations and failovers because the Dapr actor runtime persists the information about the actors' reminders using Dapr actor state provider.
You can create a persistent reminder for an actor by calling the Http/gRPC request to Dapr.
You can create a persistent reminder for an actor by calling the HTTP/gRPC request to Dapr as shown below, or via Dapr SDK.
```md
POST/PUT http://localhost:3500/v1.0/actors/<actorType>/<actorId>/reminders/<name>
```
The reminder `duetime` and callback can be specified in the request body. The due time represents when the reminder first fires after registration. The `period` represents how often the reminder will fire after that. A due time of 0 means to fire immediately. Negative due times and negative periods are invalid. To register a reminder that fires only once, set the period to an empty string.
The following request body configures a reminder with a `dueTime` 9 seconds and a `period` of 3 seconds. This means it will first fire after 9 seconds, then every 3 seconds after that.
```json
{
"dueTime":"0h0m9s0ms",
"period":"0h0m3s0ms"
}
```
The following request body configures a reminder with a `dueTime` 0 seconds and a `period` of 3 seconds. This means it will fire immediately after registration, then every 3 seconds after that.
```json
{
"dueTime":"0h0m0s0ms",
"period":"0h0m3s0ms"
}
```
The following request body configures a reminder with a `dueTime` 15 seconds and a `period` of empty string. This means it will first fire after 15 seconds, then never fire again.
```json
{
"dueTime":"0h0m15s0ms",
"period":""
}
```
[ISO 8601 duration](https://en.wikipedia.org/wiki/ISO_8601#Durations) can also be used to specify `period`. The following request body configures a reminder with a `dueTime` 0 seconds an `period` of 15 seconds.
```json
{
"dueTime":"0h0m0s0ms",
"period":"P0Y0M0W0DT0H0M15S"
}
```
The designators for zero are optional and the above `period` can be simplified to `PT15S`.
ISO 8601 specifies multiple recurrence formats but only the duration format is currently supported.
#### Reminders with repetitions
When configured with ISO 8601 durations, the `period` column also allows to specify number of times a reminder can run. The following request body will create a reminder that will execute for 5 number of times with a period of 15 seconds.
```json
{
"dueTime":"0h0m0s0ms",
"period":"R5/PT15S"
}
```
The number of repetitions i.e. the number of times the reminder is run should be a positive number.
**Example**
Watch this [video](https://www.youtube.com/watch?v=B_vkXqptpXY&t=1002s) for more information on using ISO 861 for Reminders
<div class="embed-responsive embed-responsive-16by9">
<iframe width="560" height="315" src="https://www.youtube.com/embed/B_vkXqptpXY?start=1003" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
The request structure for reminders is identical to those of actors. Please refer to the [actor timers examples]({{< ref "#actor-timers" >}}).
#### Retrieve actor reminder
@ -161,7 +160,7 @@ Refer [api spec]({{< ref "actors_api.md#invoke-reminder" >}}) for more details.
## Actor runtime configuration
You can configure the Dapr Actors runtime configuration to modify the default runtime behavior.
You can configure the Dapr actor runtime configuration to modify the default runtime behavior.
### Configuration parameters
- `actorIdleTimeout` - The timeout before deactivating an idle actor. Checks for timeouts occur every `actorScanInterval` interval. **Default: 60 minutes**

View File

@ -91,6 +91,20 @@ In order to tell Dapr that the event wasn't processed correctly in your applicat
res.status(500).send()
```
### Specifying a custom route
By default, incoming events will be sent to an HTTP endpoint that corresponds to the name of the input binding.
You can override this by setting the following metadata property:
```yaml
name: mybinding
spec:
type: binding.rabbitmq
metadata:
- name: route
value: /onevent
```
### Event delivery Guarantees
Event delivery guarantees are controlled by the binding implementation. Depending on the binding implementation, the event delivery can be exactly once or at least once.

View File

@ -489,6 +489,7 @@ Read about content types [here](#content-types), and about the [Cloud Events mes
## Next steps
- Try the [Pub/Sub quickstart sample](https://github.com/dapr/quickstarts/tree/master/pub-sub)
- Learn about [PubSub routing]({{< ref howto-route-messages >}})
- Learn about [topic scoping]({{< ref pubsub-scopes.md >}})
- Learn about [message time-to-live]({{< ref pubsub-message-ttl.md >}})
- Learn [how to configure Pub/Sub components with multiple namespaces]({{< ref pubsub-namespaces.md >}})

View File

@ -0,0 +1,519 @@
---
type: docs
title: "How-To: Route messages to different event handlers"
linkTitle: "How-To: Route events"
weight: 2100
description: "Learn how to route messages from a topic to different event handlers based on CloudEvent fields"
---
{{% alert title="Preview feature" color="warning" %}}
Pub/Sub message routing is currently in [preview]({{< ref preview-features.md >}}).
{{% /alert %}}
## Introduction
[Content-based routing](https://www.enterpriseintegrationpatterns.com/ContentBasedRouter.html) is a messaging pattern that utilizes a DSL instead of imperative application code. PubSub routing is an implementation of this pattern that allows developers to use expressions to route [CloudEvents](https://cloudevents.io) based on their contents to different URIs/paths and event handlers in your application. If no route matches, then an optional default route is used. This becomes useful as your applications expands to support multiple event versions, or special cases. Routing can be implemented with code; however, keeping routing rules external from the application can improve portability.
This feature is available to both the declarative and programmatic subscription approaches.
## Enable message routing
This is a preview feature. To enable it, add the `PubSub.Routing` feature entry to your application configuration like so:
```yaml
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
name: pubsubroutingconfig
spec:
features:
- name: PubSub.Routing
enabled: true
```
Learn more about enabling [preview features]({{<ref preview-features>}}).
## Declarative subscription
For declarative subscriptions, you must use `dapr.io/v2alpha1` as the `apiVersion`. Here is an example of `subscriptions.yaml` using routing.
```yaml
apiVersion: dapr.io/v2alpha1
kind: Subscription
metadata:
name: myevent-subscription
spec:
pubsubname: pubsub
topic: inventory
routes:
rules:
- match: event.type == "widget"
path: /widgets
- match: event.type == "gadget"
path: /gadgets
default: /products
scopes:
- app1
- app2
```
## Programmatic subscription
Alternatively, the programattic approach varies slightly in that the `routes` structure is returned instead of `route`. The JSON structure matches the declarative YAML.
{{< tabs Python Node "C#" Go PHP>}}
{{% codetab %}}
```python
import flask
from flask import request, jsonify
from flask_cors import CORS
import json
import sys
app = flask.Flask(__name__)
CORS(app)
@app.route('/dapr/subscribe', methods=['GET'])
def subscribe():
subscriptions = [
{
'pubsubname': 'pubsub',
'topic': 'inventory',
'routes': {
'rules': [
{
'match': 'event.type == "widget"',
'path': '/widgets'
},
{
'match': 'event.type == "gadget"',
'path': '/gadgets'
},
],
'default': '/products'
}
}]
return jsonify(subscriptions)
@app.route('/products', methods=['POST'])
def ds_subscriber():
print(request.json, flush=True)
return json.dumps({'success':True}), 200, {'ContentType':'application/json'}
app.run()
```
{{% /codetab %}}
{{% codetab %}}
```javascript
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
app.use(bodyParser.json({ type: 'application/*+json' }));
const port = 3000
app.get('/dapr/subscribe', (req, res) => {
res.json([
{
pubsubname: "pubsub",
topic: "inventory",
routes: {
rules: [
{
match: 'event.type == "widget"',
path: '/widgets'
},
{
match: 'event.type == "gadget"',
path: '/gadgets'
},
],
default: '/products'
}
}
]);
})
app.post('/products', (req, res) => {
console.log(req.body);
res.sendStatus(200);
});
app.listen(port, () => console.log(`consumer app listening on port ${port}!`))
```
{{% /codetab %}}
{{% codetab %}}
```csharp
[Topic("pubsub", "inventory", "event.type ==\"widget\"", 1)]
[HttpPost("widgets")]
public async Task<ActionResult<Stock>> HandleWidget(Widget widget, [FromServices] DaprClient daprClient)
{
// Logic
return stock;
}
[Topic("pubsub", "inventory", "event.type ==\"gadget\"", 2)]
[HttpPost("gadgets")]
public async Task<ActionResult<Stock>> HandleGadget(Gadget gadget, [FromServices] DaprClient daprClient)
{
// Logic
return stock;
}
[Topic("pubsub", "inventory")]
[HttpPost("products")]
public async Task<ActionResult<Stock>> HandleProduct(Product product, [FromServices] DaprClient daprClient)
{
// Logic
return stock;
}
```
{{% /codetab %}}
{{% codetab %}}
```golang
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"github.com/gorilla/mux"
)
const appPort = 3000
type subscription struct {
PubsubName string `json:"pubsubname"`
Topic string `json:"topic"`
Metadata map[string]string `json:"metadata,omitempty"`
Routes routes `json:"routes"`
}
type routes struct {
Rules []rule `json:"rules,omitempty"`
Default string `json:"default,omitempty"`
}
type rule struct {
Match string `json:"match"`
Path string `json:"path"`
}
// This handles /dapr/subscribe
func configureSubscribeHandler(w http.ResponseWriter, _ *http.Request) {
t := []subscription{
{
PubsubName: "pubsub",
Topic: "inventory",
Routes: routes{
Rules: []rule{
{
Match: `event.type == "widget"`,
Path: "/widgets",
},
{
Match: `event.type == "gadget"`,
Path: "/gadgets",
},
},
Default: "/products",
},
},
}
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(t)
}
func main() {
router := mux.NewRouter().StrictSlash(true)
router.HandleFunc("/dapr/subscribe", configureSubscribeHandler).Methods("GET")
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", appPort), router))
}
```
{{% /codetab %}}
{{% codetab %}}
```php
<?php
require_once __DIR__.'/vendor/autoload.php';
$app = \Dapr\App::create(configure: fn(\DI\ContainerBuilder $builder) => $builder->addDefinitions(['dapr.subscriptions' => [
new \Dapr\PubSub\Subscription(pubsubname: 'pubsub', topic: 'inventory', routes: (
rules: => [
('match': 'event.type == "widget"', path: '/widgets'),
('match': 'event.type == "gadget"', path: '/gadgets'),
]
default: '/products')),
]]));
$app->post('/products', function(
#[\Dapr\Attributes\FromBody]
\Dapr\PubSub\CloudEvent $cloudEvent,
\Psr\Log\LoggerInterface $logger
) {
$logger->alert('Received event: {event}', ['event' => $cloudEvent]);
return ['status' => 'SUCCESS'];
}
);
$app->start();
```
{{% /codetab %}}
{{< /tabs >}}
## Common Expression Language (CEL)
In these examples, depending on the type of the event (`event.type`), the application will be called on `/widgets`, `/gadgets` or `/products`. The expressions are written as [Common Expression Language (CEL)](https://github.com/google/cel-spec) where `event` represents the cloud event. Any of the attributes from the [CloudEvents core specification](https://github.com/cloudevents/spec/blob/v1.0.1/spec.md#required-attributes) can be referenced in the expression.
### Example expressions
Match "important" messages
```javascript
has(event.data.important) && event.data.important == true
```
Match deposits greater than $10000
```javascript
event.type == "deposit" && event.data.amount > 10000
```
Match multiple versions of a message
```javascript
event.type == "mymessage.v1"
```
```javascript
event.type == "mymessage.v2"
```
## CloudEvent attributes
For reference, the following attributes are from the CloudEvents specification.
### Event Data
#### data
As defined by the term Data, CloudEvents MAY include domain-specific information about the occurrence. When present, this information will be encapsulated within `data`.
- Description: The event payload. This specification does not place any restriction on the type of this information. It is encoded into a media format which is specified by the `datacontenttype` attribute (e.g. application/json), and adheres to the `dataschema` format when those respective attributes are present.
- Constraints:
- OPTIONAL
{{% alert title="Limitation" color="warning" %}}
Currently, it is only possible to access the attributes inside data if it is nested JSON values and not JSON escaped in a string.
{{% /alert %}}
### REQUIRED Attributes
The following attributes are REQUIRED to be present in all CloudEvents:
#### id
- Type: `String`
- Description: Identifies the event. Producers MUST ensure that `source` + `id`
is unique for each distinct event. If a duplicate event is re-sent (e.g. due
to a network error) it MAY have the same `id`. Consumers MAY assume that
Events with identical `source` and `id` are duplicates.
- Constraints:
- REQUIRED
- MUST be a non-empty string
- MUST be unique within the scope of the producer
- Examples:
- An event counter maintained by the producer
- A UUID
#### source
- Type: `URI-reference`
- Description: Identifies the context in which an event happened. Often this
will include information such as the type of the event source, the
organization publishing the event or the process that produced the event. The
exact syntax and semantics behind the data encoded in the URI is defined by
the event producer.
Producers MUST ensure that `source` + `id` is unique for each distinct event.
An application MAY assign a unique `source` to each distinct producer, which
makes it easy to produce unique IDs since no other producer will have the same
source. The application MAY use UUIDs, URNs, DNS authorities or an
application-specific scheme to create unique `source` identifiers.
A source MAY include more than one producer. In that case the producers MUST
collaborate to ensure that `source` + `id` is unique for each distinct event.
- Constraints:
- REQUIRED
- MUST be a non-empty URI-reference
- An absolute URI is RECOMMENDED
- Examples
- Internet-wide unique URI with a DNS authority.
- https://github.com/cloudevents
- mailto:cncf-wg-serverless@lists.cncf.io
- Universally-unique URN with a UUID:
- urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66
- Application-specific identifiers
- /cloudevents/spec/pull/123
- /sensors/tn-1234567/alerts
- 1-555-123-4567
#### specversion
- Type: `String`
- Description: The version of the CloudEvents specification which the event
uses. This enables the interpretation of the context. Compliant event
producers MUST use a value of `1.0` when referring to this version of the
specification.
Currently, this attribute will only have the 'major' and 'minor' version
numbers included in it. This allows for 'patch' changes to the specification
to be made without changing this property's value in the serialization.
Note: for 'release candidate' releases a suffix might be used for testing
purposes.
- Constraints:
- REQUIRED
- MUST be a non-empty string
#### type
- Type: `String`
- Description: This attribute contains a value describing the type of event
related to the originating occurrence. Often this attribute is used for
routing, observability, policy enforcement, etc. The format of this is
producer defined and might include information such as the version of the
`type` - see
[Versioning of CloudEvents in the Primer](https://github.com/cloudevents/spec/blob/v1.0.1/primer.md#versioning-of-cloudevents)
for more information.
- Constraints:
- REQUIRED
- MUST be a non-empty string
- SHOULD be prefixed with a reverse-DNS name. The prefixed domain dictates the
organization which defines the semantics of this event type.
- Examples
- com.github.pull_request.opened
- com.example.object.deleted.v2
### OPTIONAL Attributes
The following attributes are OPTIONAL to appear in CloudEvents. See the
[Notational Conventions](https://github.com/cloudevents/spec/blob/v1.0.1/spec.md#notational-conventions) section for more information
on the definition of OPTIONAL.
#### datacontenttype
- Type: `String` per [RFC 2046](https://tools.ietf.org/html/rfc2046)
- Description: Content type of `data` value. This attribute enables `data` to
carry any type of content, whereby format and encoding might differ from that
of the chosen event format. For example, an event rendered using the
[JSON envelope](https://github.com/cloudevents/spec/blob/v1.0.1/json-format.md#3-envelope) format might carry an XML payload
in `data`, and the consumer is informed by this attribute being set to
"application/xml". The rules for how `data` content is rendered for different
`datacontenttype` values are defined in the event format specifications; for
example, the JSON event format defines the relationship in
[section 3.1](https://github.com/cloudevents/spec/blob/v1.0.1/json-format.md#31-handling-of-data).
For some binary mode protocol bindings, this field is directly mapped to the
respective protocol's content-type metadata property. Normative rules for the
binary mode and the content-type metadata mapping can be found in the
respective protocol.
In some event formats the `datacontenttype` attribute MAY be omitted. For
example, if a JSON format event has no `datacontenttype` attribute, then it is
implied that the `data` is a JSON value conforming to the "application/json"
media type. In other words: a JSON-format event with no `datacontenttype` is
exactly equivalent to one with `datacontenttype="application/json"`.
When translating an event message with no `datacontenttype` attribute to a
different format or protocol binding, the target `datacontenttype` SHOULD be
set explicitly to the implied `datacontenttype` of the source.
- Constraints:
- OPTIONAL
- If present, MUST adhere to the format specified in
[RFC 2046](https://tools.ietf.org/html/rfc2046)
- For Media Type examples see
[IANA Media Types](http://www.iana.org/assignments/media-types/media-types.xhtml)
#### dataschema
- Type: `URI`
- Description: Identifies the schema that `data` adheres to. Incompatible
changes to the schema SHOULD be reflected by a different URI. See
[Versioning of CloudEvents in the Primer](https://github.com/cloudevents/spec/blob/v1.0.1/primer.md#versioning-of-cloudevents)
for more information.
- Constraints:
- OPTIONAL
- If present, MUST be a non-empty URI
#### subject
- Type: `String`
- Description: This describes the subject of the event in the context of the
event producer (identified by `source`). In publish-subscribe scenarios, a
subscriber will typically subscribe to events emitted by a `source`, but the
`source` identifier alone might not be sufficient as a qualifier for any
specific event if the `source` context has internal sub-structure.
Identifying the subject of the event in context metadata (opposed to only in
the `data` payload) is particularly helpful in generic subscription filtering
scenarios where middleware is unable to interpret the `data` content. In the
above example, the subscriber might only be interested in blobs with names
ending with '.jpg' or '.jpeg' and the `subject` attribute allows for
constructing a simple and efficient string-suffix filter for that subset of
events.
- Constraints:
- OPTIONAL
- If present, MUST be a non-empty string
- Example:
- A subscriber might register interest for when new blobs are created inside a
blob-storage container. In this case, the event `source` identifies the
subscription scope (storage container), the `type` identifies the "blob
created" event, and the `id` uniquely identifies the event instance to
distinguish separate occurrences of a same-named blob having been created;
the name of the newly created blob is carried in `subject`:
- `source`: https://example.com/storage/tenant/container
- `subject`: mynewfile.jpg
#### time
- Type: `Timestamp`
- Description: Timestamp of when the occurrence happened. If the time of the
occurrence cannot be determined then this attribute MAY be set to some other
time (such as the current time) by the CloudEvents producer, however all
producers for the same `source` MUST be consistent in this respect. In other
words, either they all use the actual time of the occurrence or they all use
the same algorithm to determine the value used.
- Constraints:
- OPTIONAL
- If present, MUST adhere to the format specified in
[RFC 3339](https://tools.ietf.org/html/rfc3339)
{{% alert title="Limitation" color="warning" %}}
Currently, comparisons to time (e.g. before or after "now") are not supported.
{{% /alert %}}
## Community call demo
Watch [this video](https://www.youtube.com/watch?v=QqJgRmbH82I&t=1063s) on how to use message routing with pub/sub:
<p class="embed-responsive embed-responsive-16by9">
<iframe width="688" height="430" src="https://www.youtube.com/embed/QqJgRmbH82I?start=1063" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</p>
## Next steps
- Try the [Pub/Sub routing sample](https://github.com/dapr/samples/tree/master/pub-sub-routing)
- Learn about [topic scoping]({{< ref pubsub-scopes.md >}})
- Learn about [message time-to-live]({{< ref pubsub-message-ttl.md >}})
- Learn [how to configure Pub/Sub components with multiple namespaces]({{< ref pubsub-namespaces.md >}})
- List of [pub/sub components]({{< ref setup-pubsub >}})
- Read the [API reference]({{< ref pubsub_api.md >}})

View File

@ -111,6 +111,32 @@ curl http://localhost:3500/v1.0/invoke/cart/method/add -X DELETE
```
Dapr puts any payload returned by the called service in the HTTP response's body.
### Additional URL formats
In order to avoid changing URL paths as much as possible, Dapr provides the following ways to call the service invocation API:
1. Change the address in the URL to `localhost:<dapr-http-port>`.
2. Add a `dapr-app-id` header to specify the ID of the target service, or alternatively pass the ID via HTTP Basic Auth: `http://dapr-app-id:<service-id>@localhost:3500/path`.
For example, the following command
```bash
curl http://localhost:3500/v1.0/invoke/cart/method/add
```
is equivalent to:
```bash
curl -H 'dapr-app-id: cart' 'http://localhost:3500/add' -X POST
```
or:
```bash
curl 'http://dapr-app-id:cart@localhost:3500/add' -X POST
```
{{% /codetab %}}
{{% codetab %}}

View File

@ -5,9 +5,12 @@ linkTitle: "How-To: Invoke with gRPC"
description: "Call between services using service invocation"
weight: 3000
---
{{% alert title="Preview feature" color="warning" %}}
gRPC proxying is currently in [preview]({{< ref preview-features.md >}}).
{{% /alert %}}
This article describe how to use Dapr to connect services using gRPC.
By using Dapr's gRPC proxying capability, you can use your existing proto based gRPC services and have the traffic go through the Dapr sidecar. Doing so yields the following [Dapr Service Invocation]({{< ref service-invocation-overview.md >}}) benefits to developers:
By using Dapr's gRPC proxying capability, you can use your existing proto based gRPC services and have the traffic go through the Dapr sidecar. Doing so yields the following [Dapr service invocation]({{< ref service-invocation-overview.md >}}) benefits to developers:
1. Mutual authentication
2. Tracing
@ -170,7 +173,7 @@ var call = client.SayHello(new HelloRequest { Name = "Darth Nihilus" }, metadata
{{% codetab %}}
```python
metadata = (('dapr-app-id', 'server'))
metadata = (('dapr-app-id', 'server'),)
response = stub.SayHello(request={ name: 'Darth Revan' }, metadata=metadata)
```
{{% /codetab %}}
@ -305,3 +308,10 @@ For more information on tracing and logs see the [observability]({{< ref observa
* [Service invocation overview]({{< ref service-invocation-overview.md >}})
* [Service invocation API specification]({{< ref service_invocation_api.md >}})
* [gRPC proxying community call video](https://youtu.be/B_vkXqptpXY?t=70)
## Community call demo
Watch this [video](https://youtu.be/B_vkXqptpXY?t=69) on how to use Dapr's gRPC proxying capability:
<div class="embed-responsive embed-responsive-16by9">
<iframe width="560" height="315" src="https://www.youtube.com/embed/B_vkXqptpXY?start=69" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>

View File

@ -0,0 +1,92 @@
---
type: docs
title: "How-To: Encrypt application state"
linkTitle: "How-To: Encrypt state"
weight: 450
description: "Automatically encrypt state and manage key rotations"
---
{{% alert title="Preview feature" color="warning" %}}
State store encryption is currently in [preview]({{< ref preview-features.md >}}).
{{% /alert %}}
## Introduction
Application state often needs to get encrypted at rest to provide stronger security in enterprise workloads or regulated environments. Dapr offers automatic client side encryption based on [AES256](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard).
In addition to automatic encryption, Dapr supports primary and secondary encryption keys to make it easier for developers and ops teams to enable a key rotation strategy.
This feature is supported by all Dapr state stores.
The encryption keys are fetched from a secret, and cannot be supplied as plaintext values on the `metadata` section.
## Enabling automatic encryption
1. Enable the state encryption preview feature using a standard [Dapr Configuration]({{< ref configuration-overview.md >}}):
```yaml
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
name: stateconfig
spec:
features:
- name: State.Encryption
enabled: true
```
2. Add the following `metadata` section to any Dapr supported state store:
```yaml
metadata:
- name: primaryEncryptionKey
secretKeyRef:
name: mysecret
key: mykey # key is optional.
```
For example, this is the full YAML of a Redis encrypted state store
```yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: statestore
spec:
type: state.redis
version: v1
metadata:
- name: redisHost
value: localhost:6379
- name: redisPassword
value: ""
- name: primaryEncryptionKey
secretKeyRef:
name: mysecret
key: mykey
```
You now have a Dapr state store that's configured to fetch the encryption key from a secret named `mysecret`, containing the actual encryption key in a key named `mykey`.
The actual encryption key *must* be an AES256 encryption key. Dapr will error and exit if the encryption key is invalid.
*Note that the secret store does not have to support keys*
## Key rotation
To support key rotation, Dapr provides a way to specify a secondary encryption key:
```yaml
metadata:
- name: primaryEncryptionKey
secretKeyRef:
name: mysecret
key: mykey
- name: secondaryEncryptionKey
secretKeyRef:
name: mysecret2
key: mykey2
```
When Dapr starts, it will fetch the secrets containing the encryption keys listed in the `metadata` section. Dapr knows which state item has been encrypted with which key automatically, as it appends the `secretKeyRef.name` field to the end of the actual state key.
To rotate a key, simply change the `primaryEncryptionKey` to point to a secret containing your new key, and move the old primary encryption key to the `secondaryEncryptionKey`. New data will be encrypted using the new key, and old data that's retrieved will be decrypted using the secondary key. Any updates to data items encrypted using the old key will be re-encrypted using the new key.

View File

@ -50,6 +50,12 @@ For stores that don't natively support ETags, it's expected that the correspondi
Read the [API reference]({{< ref state_api.md >}}) to learn how to set concurrency options.
### Automatic encryption
Dapr supports automatic client encryption of application state with support for key rotations. This is a preview feature and it is supported on all Dapr state stores.
For more info, read the [How-To: Encrypt application state]({{< ref howto-encrypt-state.md >}}) section.
### Consistency
Dapr supports both **strong consistency** and **eventual consistency**, with eventual consistency as the default behavior.
@ -104,6 +110,7 @@ The API for state management can be found in the [state management API reference
* [How-To: Save and get state]({{< ref howto-get-save-state.md >}})
* [How-To: Build a stateful service]({{< ref howto-stateful-service.md >}})
* [How-To: Share state between applications]({{< ref howto-share-state.md >}})
* [How-To: Encrypt application state]({{< ref howto-encrypt-state.md >}})
* Try out the [hello world quickstart](https://github.com/dapr/quickstarts/blob/master/hello-world/README.md) which shows how to use state management or try the samples in the [Dapr SDKs]({{< ref sdks >}})
* List of [state store components]({{< ref supported-state-stores.md >}})
* Read the [state management API reference]({{< ref state_api.md >}})

View File

@ -0,0 +1,407 @@
---
type: docs
title: "Authenticating to Azure"
linkTitle: "Authenticating to Azure"
description: "How to authenticate Azure components using Azure AD and/or Managed Identities"
aliases:
- "/operations/components/setup-secret-store/supported-secret-stores/azure-keyvault-managed-identity/"
- "/reference/components-reference/supported-secret-stores/azure-keyvault-managed-identity/"
---
## Common Azure authentication layer
Certain Azure components for Dapr offer support for the *common Azure authentication layer*, which enables applications to access data stored in Azure resources by authenticating with Azure AD. Thanks to this, administrators can leverage all the benefits of fine-tuned permissions with RBAC (Role-Based Access Control), and applications running on certain Azure services such as Azure VMs, Azure Kubernetes Service, or many Azure platform services can leverage [Managed Service Identities (MSI)](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview).
Some Azure components offer alternative authentication methods, such as systems based on "master keys" or "shared keys". Whenever possible, it is recommended that you authenticate your Dapr components using Azure AD for increased security and ease of management, as well as for the ability to leverage MSI if your app is running on supported Azure services.
> Currently, only a subset of Azure components for Dapr offer support for this authentication method. Over time, support will be expanded to all other Azure components for Dapr. You can track the progress of the work, component-by-component, on [this issue](https://github.com/dapr/components-contrib/issues/1103).
### About authentication with Azure AD
Azure AD is Azure's identity and access management (IAM) solution, which is used to authenticate and authorize users and services.
Azure AD is built on top of open standards such OAuth 2.0, which allows services (applications) to obtain access tokens to make requests to Azure services, including Azure Storage, Azure Key Vault, Cosmos DB, etc. In the Azure terminology, an application is also called a "Service Principal".
Many of the services listed above also support authentication using other systems, such as "master keys" or "shared keys". Although those are always valid methods to authenticate your application (and Dapr continues to support them, as explained in each component's reference page), using Azure AD when possible offers various benefits, including:
- The ability to leverage Managed Service Identities, which allow your application to authenticate with Azure AD, and obtain an access token to make requests to Azure services, without the need to use any credential. When your application is running on a supported Azure service (including, but not limited to, Azure VMs, Azure Kubernetes Service, Azure Web Apps, etc), an identity for your application can be assigned at the infrastructure level.
This way, your code does not have to deal with credentials of any kind, removing the challenge of safely managing credentials, allowing greater separation of concerns between development and operations teams and reducing the number of people with access to credentials, and lastly simplifying operational aspectsespecially when multiple environments are used.
- Using RBAC (Role-Based Access Control) with supported services (such as Azure Storage and Cosmos DB), permissions given to an application can be fine-tuned, for example allowing restricting access to a subset of data or making it read-only.
- Better auditing for access.
- Ability to authenticate using certificates (optional).
## Credentials metadata fields
To authenticate with Azure AD, you will need to add the following credentials as values in the metadata for your Dapr component (read the next section for how to create them). There are multiple options depending on the way you have chosen to pass the credentials to your Dapr service.
**Authenticating using client credentials:**
| Field | Required | Details | Example |
|---------------------|----------|--------------------------------------|----------------------------------------------|
| `azureTenantId` | Y | ID of the Azure AD tenant | `"cd4b2887-304c-47e1-b4d5-65447fdd542b"` |
| `azureClientId` | Y | Client ID (application ID) | `"c7dd251f-811f-4ba2-a905-acd4d3f8f08b"` |
| `azureClientSecret` | Y | Client secret (application password) | `"Ecy3XG7zVZK3/vl/a2NSB+a1zXLa8RnMum/IgD0E"` |
When running on Kubernetes, you can also use references to Kubernetes secrets for any or all of the values above.
**Authenticating using a PFX certificate:**
| Field | Required | Details | Example |
|--------|--------|--------|--------|
| `azureTenantId` | Y | ID of the Azure AD tenant | `"cd4b2887-304c-47e1-b4d5-65447fdd542b"` |
| `azureClientId` | Y | Client ID (application ID) | `"c7dd251f-811f-4ba2-a905-acd4d3f8f08b"` |
| `azureCertificate` | One of `azureCertificate` and `azureCertificateFile` | Certificate and private key (in PFX/PKCS#12 format) | `"-----BEGIN PRIVATE KEY-----\n MIIEvgI... \n -----END PRIVATE KEY----- \n -----BEGIN CERTIFICATE----- \n MIICoTC... \n -----END CERTIFICATE-----` |
| `azureCertificateFile` | One of `azureCertificate` and `azureCertificateFile` | Path to the PFX/PKCS#12 file containing the certificate and private key | `"/path/to/file.pem"` |
| `azureCertificatePassword` | N | Password for the certificate if encrypted | `"password"` |
When running on Kubernetes, you can also use references to Kubernetes secrets for any or all of the values above.
**Authenticating with Managed Service Identities (MSI):**
| Field | Required | Details | Example |
|-----------------|----------|----------------------------|------------------------------------------|
| `azureClientId` | N | Client ID (application ID) | `"c7dd251f-811f-4ba2-a905-acd4d3f8f08b"` |
Using MSI you're not required to specify any value, although you may optionally pass `azureClientId` if needed.
### Aliases
For backwards-compatibility reasons, the following values in the metadata are supported as aliases, although their use is discouraged.
| Metadata key | Aliases (supported but deprecated) |
|----------------------------|------------------------------------|
| `azureTenantId` | `spnTenantId`, `tenantId` |
| `azureClientId` | `spnClientId`, `clientId` |
| `azureClientSecret` | `spnClientSecret`, `clientSecret` |
| `azureCertificate` | `spnCertificate` |
| `azureCertificateFile` | `spnCertificateFile` |
| `azureCertificatePassword` | `spnCertificatePassword` |
## Generating a new Azure AD application and Service Principal
To start, create a new Azure AD application, which will also be used as Service Principal.
Prerequisites:
- [Azure Subscription](https://azure.microsoft.com/free/)
- [Azure CLI](https://docs.microsoft.com/cli/azure/install-azure-cli)
- [jq](https://stedolan.github.io/jq/download/)
- OpenSSL (included by default on all Linux and macOS systems, as well as on WSL)
- The scripts below are optimized for a bash or zsh shell
> If you haven't already, start by logging in to Azure using the Azure CLI:
>
> ```sh
> # Log in Azure
> az login
> # Set your default subscription
> az account set -s [your subscription id]
> ```
### Creating an Azure AD application
First, create the Azure AD application with:
```sh
# Friendly name for the application / Service Principal
APP_NAME="dapr-application"
# Create the app
APP_ID=$(az ad app create \
--display-name "${APP_NAME}" \
--available-to-other-tenants false \
--oauth2-allow-implicit-flow false \
| jq -r .appId)
```
{{< tabs "Client secret" "Certificate">}}
{{% codetab %}}
To create a **client secret**, then run this command. This will generate a random password based on the base64 charset and 40-characters long. Additionally, it will make the password valid for 2 years, before it will need to be rotated:
```sh
az ad app credential reset \
--id "${APP_ID}" \
--years 2 \
--password $(openssl rand -base64 30)
```
The ouput of the command above will be similar to this:
```json
{
"appId": "c7dd251f-811f-4ba2-a905-acd4d3f8f08b",
"name": "c7dd251f-811f-4ba2-a905-acd4d3f8f08b",
"password": "Ecy3XG7zVZK3/vl/a2NSB+a1zXLa8RnMum/IgD0E",
"tenant": "cd4b2887-304c-47e1-b4d5-65447fdd542b"
}
```
Take note of the values above, which you'll need to use in your Dapr components' metadata, to allow Dapr to authenticate with Azure:
- `appId` is the value for `azureClientId`
- `password` is the value for `azureClientSecret` (this was randomly-generated)
- `tenant` is the value for `azureTenantId`
{{% /codetab %}}
{{% codetab %}}
If you'd rather use a **PFX (PKCS#12) certificate**, run this command which will create a self-signed certificate:
```sh
az ad app credential reset \
--id "${APP_ID}" \
--create-cert
```
> Note: self-signed certificates are recommended for development only. For production, you should use certificates signed by a CA and imported with the `--cert` flag.
The output of the command above should look like:
```json
{
"appId": "c7dd251f-811f-4ba2-a905-acd4d3f8f08b",
"fileWithCertAndPrivateKey": "/Users/alessandro/tmpgtdgibk4.pem",
"name": "c7dd251f-811f-4ba2-a905-acd4d3f8f08b",
"password": null,
"tenant": "cd4b2887-304c-47e1-b4d5-65447fdd542b"
}
```
Take note of the values above, which you'll need to use in your Dapr components' metadata:
- `appId` is the value for `azureClientId`
- `tenant` is the value for `azureTenantId`
- The self-signed PFX certificate and private key are written in the file at the path specified in `fileWithCertAndPrivateKey`.
Use the contents of that file as `azureCertificate` (or write it to a file on the server and use `azureCertificateFile`)
> While the generated file has the `.pem` extension, it contains a certificate and private key encoded as PFX (PKCS#12).
{{% /codetab %}}
{{< /tabs >}}
### Creating a Service Principal
Once you have created an Azure AD application, create a Service Principal for that application, which will allow us to grant it access to Azure resources. Run:
```sh
SERVICE_PRINCIPAL_ID=$(az ad sp create \
--id "${APP_ID}" \
| jq -r .objectId)
echo "Service Principal ID: ${SERVICE_PRINCIPAL_ID}"
```
The output will be similar to:
```text
Service Principal ID: 1d0ccf05-5427-4b5e-8eb4-005ac5f9f163
```
Note that the value above is the ID of the **Service Principal** which is different from the ID of application in Azure AD (client ID)! The former is defined within an Azure tenant and is used to grant access to Azure resources to an application. The client ID instead is used by your application to authenticate. To sum things up:
- You'll use the client ID in Dapr manifests to configure authentication with Azure services
- You'll use the Service Principal ID to grant permissions to an application to access Azure resources
Keep in mind that the Service Principal that was just created does not have access to any Azure resource by default. Access will need to be granted to each resource as needed, as documented in the docs for the components.
> Note: this step is different from the [official documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) as the short-hand commands included there create a Service Principal that has broad read-write access to all Azure resources in your subscription.
> Not only doing that would grant our Service Principal more access than you are likely going to desire, but this also applies only to the Azure management plane (Azure Resource Manager, or ARM), which is irrelevant for Dapr anyways (all Azure components are designed to interact with the data plane of various services, and not ARM).
### Example usage in a Dapr component
In this example, you will set up an Azure Key Vault secret store component that uses Azure AD to authenticate.
{{< tabs "Self-Hosted" "Kubernetes">}}
{{% codetab %}}
To use a **client secret**, create a file called `azurekeyvault.yaml` in the components directory, filling in with the details from the above setup process:
```yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: azurekeyvault
namespace: default
spec:
type: secretstores.azure.keyvault
version: v1
metadata:
- name: vaultName
value: "[your_keyvault_name]"
- name: azureTenantId
value: "[your_tenant_id]"
- name: azureClientId
value: "[your_client_id]"
- name: azureClientSecret
value : "[your_client_secret]"
```
If you want to use a **certificate** saved on the local disk, instead, use:
```yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: azurekeyvault
namespace: default
spec:
type: secretstores.azure.keyvault
version: v1
metadata:
- name: vaultName
value: "[your_keyvault_name]"
- name: azureTenantId
value: "[your_tenant_id]"
- name: azureClientId
value: "[your_client_id]"
- name: azureCertificateFile
value : "[pfx_certificate_file_fully_qualified_local_path]"
```
{{% /codetab %}}
{{% codetab %}}
In Kubernetes, you store the client secret or the certificate into the Kubernetes Secret Store and then refer to those in the YAML file.
To use a **client secret**:
1. Create a Kubernetes secret using the following command:
```bash
kubectl create secret generic [your_k8s_secret_name] --from-literal=[your_k8s_secret_key]=[your_client_secret]
```
- `[your_client_secret]` is the application's client secret as generated above
- `[your_k8s_secret_name]` is secret name in the Kubernetes secret store
- `[your_k8s_secret_key]` is secret key in the Kubernetes secret store
2. Create an `azurekeyvault.yaml` component file.
The component yaml refers to the Kubernetes secretstore using `auth` property and `secretKeyRef` refers to the client secret stored in the Kubernetes secret store.
```yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: azurekeyvault
namespace: default
spec:
type: secretstores.azure.keyvault
version: v1
metadata:
- name: vaultName
value: "[your_keyvault_name]"
- name: azureTenantId
value: "[your_tenant_id]"
- name: azureClientId
value: "[your_client_id]"
- name: azureClientSecret
secretKeyRef:
name: "[your_k8s_secret_name]"
key: "[your_k8s_secret_key]"
auth:
secretStore: kubernetes
```
3. Apply the `azurekeyvault.yaml` component:
```bash
kubectl apply -f azurekeyvault.yaml
```
To use a **certificate**:
1. Create a Kubernetes secret using the following command:
```bash
kubectl create secret generic [your_k8s_secret_name] --from-file=[your_k8s_secret_key]=[pfx_certificate_file_fully_qualified_local_path]
```
- `[pfx_certificate_file_fully_qualified_local_path]` is the path to the PFX file you obtained earlier
- `[your_k8s_secret_name]` is secret name in the Kubernetes secret store
- `[your_k8s_secret_key]` is secret key in the Kubernetes secret store
2. Create an `azurekeyvault.yaml` component file.
The component yaml refers to the Kubernetes secretstore using `auth` property and `secretKeyRef` refers to the certificate stored in the Kubernetes secret store.
```yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: azurekeyvault
namespace: default
spec:
type: secretstores.azure.keyvault
version: v1
metadata:
- name: vaultName
value: "[your_keyvault_name]"
- name: azureTenantId
value: "[your_tenant_id]"
- name: azureClientId
value: "[your_client_id]"
- name: azureCertificate
secretKeyRef:
name: "[your_k8s_secret_name]"
key: "[your_k8s_secret_key]"
auth:
secretStore: kubernetes
```
3. Apply the `azurekeyvault.yaml` component:
```bash
kubectl apply -f azurekeyvault.yaml
```
{{% /codetab %}}
{{< /tabs >}}
## Using Managed Service Identities
Using MSI, authentication happens automatically by virtue of your application running on top of an Azure service that has an assigned identity. For example, when you create an Azure VM or an Azure Kubernetes Service cluster and choose to enable a managed identity for that, an Azure AD application is created for you and automatically assigned to the service. Your Dapr services can then leverage that identity to authenticate with Azure AD, transparently and without you having to specify any credential.
To get started with managed identities, first you need to assign an identity to a new or existing Azure resource. The instructions depend on the service use. Below are links to the official documentation:
- [Azure Kubernetes Service (AKS)](https://docs.microsoft.com/azure/aks/use-managed-identity)
- [Azure App Service](https://docs.microsoft.com/azure/app-service/overview-managed-identity) (including Azure Web Apps and Azure Functions)
- [Azure Virtual Machines (VM)](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/qs-configure-cli-windows-vm)
- [Azure Virtual Machines Scale Sets (VMSS)](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/qs-configure-cli-windows-vmss)
- [Azure Container Instance (ACI)](https://docs.microsoft.com/azure/container-instances/container-instances-managed-identity)
Other Azure application services may offer support for MSI; please check the documentation for those services to understand how to configure them.
After assigning a managed identity to your Azure resource, you will have credentials such as:
```json
{
"principalId": "<object-id>",
"tenantId": "<tenant-id>",
"type": "SystemAssigned",
"userAssignedIdentities": null
}
```
From the list above, take note of **`principalId`** which is the ID of the Service Principal that was created. You'll need that to grant access to Azure resources to your Service Principal.
## Support for other Azure environments
By default, Dapr components are configured to interact with Azure resources in the "public cloud". If your application is deployed to another cloud, such as Azure China, Azure Government, or Azure Germany, you can enable that for supported components by setting the `azureEnvironment` metadata property to one of the supported values:
- Azure public cloud (default): `"AZUREPUBLICCLOUD"`
- Azure China: `"AZURECHINACLOUD"`
- Azure Government: `"AZUREUSGOVERNMENTCLOUD"`
- Azure Germany: `"AZUREGERMANCLOUD"`
## References
- [Azure AD app credential: Azure CLI reference](https://docs.microsoft.com/cli/azure/ad/app/credential)
- [Azure Managed Service Identity (MSI) overview](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview)
- [Secrets building block]({{< ref secrets >}})
- [How-To: Retrieve a secret]({{< ref "howto-secrets.md" >}})
- [How-To: Reference secrets in Dapr components]({{< ref component-secrets.md >}})
- [Secrets API reference]({{< ref secrets_api.md >}})

View File

@ -0,0 +1,37 @@
---
type: docs
weight: 10000
title: "Use the Dapr CLI in a GitHub Actions workflow"
linkTitle: "GitHub Actions"
description: "Learn how to add the Dapr CLI to your GitHub Actions to deploy and manage Dapr in your environments."
---
Dapr can be integrated with GitHub Actions via the [Dapr tool installer](https://github.com/marketplace/actions/dapr-tool-installer) available in the GitHub Marketplace. This installer adds the Dapr CLI to your workflow, allowing you to deploy, manage, and upgrade Dapr across your environments.
## Overview
The `dapr/setup-dapr` action will install the specified version of the Dapr CLI on macOS, Linux and Windows runners. Once installed, you can run any [Dapr CLI command]({{< ref cli >}}) to manage your Dapr environments.
## Example
```yaml
- name: Install Dapr
uses: dapr/setup-dapr@v1
with:
version: '{{% dapr-latest-version long="true" %}}'
- name: Initialize Dapr
shell: pwsh
run: |
# Get the credentials to K8s to use with dapr init
az aks get-credentials --resource-group ${{ env.RG_NAME }} --name "${{ steps.azure-deployment.outputs.aksName }}"
# Initialize Dapr
# Group the Dapr init logs so these lines can be collapsed.
Write-Output "::group::Initialize Dapr"
dapr init --kubernetes --wait --runtime-version ${{ env.DAPR_VERSION }}
Write-Output "::endgroup::"
dapr status --kubernetes
working-directory: ./twitter-sentiment-processor/demos/demo3
```

View File

@ -11,6 +11,7 @@ Welcome to the Dapr getting started guide!
{{% alert title="Dapr Concepts" color="primary" %}}
If you are looking for an introductory overview of Dapr and learn more about basic Dapr terminology, it is recommended to visit the [concepts section]({{<ref concepts>}}).
{{< button text="Learn more" page="concepts" >}}
{{% /alert %}}
This guide will walk you through a series of steps to install, initialize and start using Dapr. The recommended way to get started with Dapr is to setup a local development environment (also referred to as [_self-hosted_ mode]({{< ref self-hosted >}})) which includes the Dapr CLI, Dapr sidecar binaries, and some default components that can help you start using Dapr quickly.
@ -23,3 +24,4 @@ The following steps in this guide are:
1. Explore Dapr quickstarts
{{< button text="First step: Install the Dapr CLI >>" page="install-dapr-cli" >}}
<br><br>

View File

@ -52,8 +52,8 @@ dapr --version
Output should look like this:
```
CLI version: 1.3.0
Runtime version: 1.3.0
CLI version: {{% dapr-latest-version cli="true" %}}
Runtime version: {{% dapr-latest-version long="true" %}}
```
### Step 4: Verify containers are running

View File

@ -17,11 +17,12 @@ The [Dapr Quickstarts](https://github.com/dapr/quickstarts/tree/v1.0.0) are a co
| Quickstart | Description |
|--------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [Hello World](https://github.com/dapr/quickstarts/tree/v1.3.0/hello-world) | Demonstrates how to run Dapr locally. Highlights service invocation and state management. |
| [Hello Kubernetes](https://github.com/dapr/quickstarts/tree/v1.3.0/hello-kubernetes) | Demonstrates how to run Dapr in Kubernetes. Highlights service invocation and state management. |
| [Distributed Calculator](https://github.com/dapr/quickstarts/tree/v1.3.0/distributed-calculator) | Demonstrates a distributed calculator application that uses Dapr services to power a React web app. Highlights polyglot (multi-language) programming, service invocation and state management. |
| [Pub/Sub](https://github.com/dapr/quickstarts/tree/v1.3.0/pub-sub) | Demonstrates how to use Dapr to enable pub-sub applications. Uses Redis as a pub-sub component. |
| [Bindings](https://github.com/dapr/quickstarts/tree/v1.3.0/bindings) | Demonstrates how to use Dapr to create input and output bindings to other components. Uses bindings to Kafka. |
| [Middleware](https://github.com/dapr/quickstarts/tree/v1.3.0/middleware) | Demonstrates use of Dapr middleware to enable OAuth 2.0 authorization. |
| [Observability](https://github.com/dapr/quickstarts/tree/v1.3.0/observability) | Demonstrates Dapr tracing capabilities. Uses Zipkin as a tracing component. |
| [Secret Store](https://github.com/dapr/quickstarts/tree/v1.3.0/secretstore) | Demonstrates the use of Dapr Secrets API to access secret stores. |
| [Hello World](https://github.com/dapr/quickstarts/tree/v1.4.0/hello-world) | Demonstrates how to run Dapr locally. Highlights service invocation and state management. |
| [Hello Kubernetes](https://github.com/dapr/quickstarts/tree/v1.4.0/hello-kubernetes) | Demonstrates how to run Dapr in Kubernetes. Highlights service invocation and state management. |
| [Distributed Calculator](https://github.com/dapr/quickstarts/tree/v1.4.0/distributed-calculator) | Demonstrates a distributed calculator application that uses Dapr services to power a React web app. Highlights polyglot (multi-language) programming, service invocation and state management. |
| [Pub/Sub](https://github.com/dapr/quickstarts/tree/v1.4.0/pub-sub) | Demonstrates how to use Dapr to enable pub-sub applications. Uses Redis as a pub-sub component. |
| [Bindings](https://github.com/dapr/quickstarts/tree/v1.4.0/bindings) | Demonstrates how to use Dapr to create input and output bindings to other components. Uses bindings to Kafka. |
| [Middleware](https://github.com/dapr/quickstarts/tree/v1.4.0/middleware) | Demonstrates use of Dapr middleware to enable OAuth 2.0 authorization. |
| [Observability](https://github.com/dapr/quickstarts/tree/v1.4.0/observability) | Demonstrates Dapr tracing capabilities. Uses Zipkin as a tracing component. |
| [Secret Store](https://github.com/dapr/quickstarts/tree/v1.4.0/secretstore) | Demonstrates the use of Dapr Secrets API to access secret stores. |

View File

@ -20,7 +20,7 @@ Go to [this]({{< ref "howto-secrets.md" >}}) link to see all the secret stores s
## Referencing secrets
While you have the option to use plain text secrets, this is not recommended for production:
While you have the option to use plain text secrets (like MyPassword), as shown in the yaml below for the `value` of `redisPassword`, this is not recommended for production:
```yml
apiVersion: dapr.io/v1alpha1
@ -38,7 +38,9 @@ spec:
value: MyPassword
```
Instead create the secret in your secret store and reference it in the component definition:
Instead create the secret in your secret store and reference it in the component definition. There are two cases for this shown below -- the "Secret contains an embedded key" and the "Secret is a string".
The "Secret contains an embedded key" case applies when there is a key embedded within the secret, i.e. the secret is **not** an entire connection string. This is shown in the following component definition yaml.
```yml
apiVersion: dapr.io/v1alpha1
@ -62,7 +64,30 @@ auth:
`SECRET_STORE_NAME` is the name of the configured [secret store component]({{< ref supported-secret-stores >}}). When running in Kubernetes and using a Kubernetes secret store, the field `auth.SecretStore` defaults to `kubernetes` and can be left empty.
The above component definition tells Dapr to extract a secret named `redis-secret` from the defined secret store and assign the value of the `redis-password` key in the secret to the `redisPassword` field in the Component.
The above component definition tells Dapr to extract a secret named `redis-secret` from the defined `secretStore` and assign the value associated with the `redis-password` key embedded in the secret to the `redisPassword` field in the component. One use of this case is when your code is constructing a connection string, for example putting together a URL, a secret, plus other information as necessary, into a string.
On the other hand, the below "Secret is a string" case applies when there is NOT a key embedded in the secret. Rather, the secret is just a string. Therefore, in the `secretKeyRef` section both the secret `name` and the secret `key` will be identical. This is the case when the secret itself is an entire connection string with no embedded key whose value needs to be extracted. Typically a connection string consists of connection information, some sort of secret to allow connection, plus perhaps other information and does not require a separate "secret". This case is shown in the below component definition yaml.
```yml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: servicec-inputq-azkvsecret-asbqueue
spec:
type: bindings.azure.servicebusqueues
version: v1
metadata:
-name: connectionString
secretKeyRef:
name: asbNsConnString
key: asbNsConnString
-name: queueName
value: servicec-inputq
auth:
secretStore: <SECRET_STORE_NAME>
```
The above "Secret is a string" case yaml tells Dapr to extract a connection string named `asbNsConnstring` from the defined `secretStore` and assign the value to the `connectionString` field in the component since there is no key embedded in the "secret" from the `secretStore` because it is a plain string. This requires the secret `name` and secret `key` to be identical.
## Example

View File

@ -9,7 +9,7 @@ description: "Control how many requests and events will invoke your application
A common scenario in distributed computing is to only allow for a given number of requests to execute concurrently.
Using Dapr, you can control how many requests and events will invoke your application simultaneously.
*Note that this rate limiing is guaranteed for every event that's coming from Dapr, meaning Pub/Sub events, direct invocation from other services, bindings events etc. Dapr can't enforce the concurrency policy on requests that are coming to your app externally.*
*Note that this rate limiting is guaranteed for every event that's coming from Dapr, meaning Pub/Sub events, direct invocation from other services, bindings events etc. Dapr can't enforce the concurrency policy on requests that are coming to your app externally.*
*Note that rate limiting per second can be achieved by using the **middleware.http.ratelimit** middleware. However, there is an imporant difference between the two approaches. The rate limit middlware is time bound and limits the number of requests per second, while the `app-max-concurrency` flag specifies the number of concurrent requests (and events) at any point of time. See [Rate limit middleware]({{< ref middleware-rate-limit.md >}}). *
@ -61,4 +61,4 @@ To set app-max-concurrency with the Dapr CLI for running on your local dev machi
dapr run --app-max-concurrency 1 --app-port 5000 python ./app.py
```
The above examples will effectively turn your app into a single concurrent service.
The above examples will effectively turn your app into a single concurrent service.

View File

@ -10,12 +10,6 @@ Access control enables the configuration of policies that restrict what operatio
An access control policy is specified in configuration and be applied to Dapr sidecar for the *called* application. Example access policies are shown below and access to the called app is based on the matched policy action. You can provide a default global action for all calling applications and if no access control policy is specified, the default behavior is to allow all calling applications to access to the called app.
Watch this [video](https://youtu.be/j99RN_nxExA?t=1108) on how to apply access control list for service invocation.
<div class="embed-responsive embed-responsive-16by9">
<iframe width="688" height="430" src="https://www.youtube.com/embed/j99RN_nxExA?start=1108" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
## Concepts
**TrustDomain** - A "trust domain" is a logical group to manage trust relationships. Every application is assigned a trust domain which can be specified in the access control list policy spec. If no policy spec is defined or an empty trust domain is specified, then a default value "public" is used. This trust domain is used to generate the identity of the application in the TLS cert.
@ -357,3 +351,10 @@ spec:
- name: python
image: dapriosamples/hello-k8s-python:edge
```
## Community call demo
Watch this [video](https://youtu.be/j99RN_nxExA?t=1108) on how to apply access control list for service invocation.
<div class="embed-responsive embed-responsive-16by9">
<iframe width="688" height="430" src="https://www.youtube.com/embed/j99RN_nxExA?start=1108" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>

View File

@ -12,7 +12,7 @@ description: >
## Prerequisites
- [Docker](https://docs.docker.com/install/)
- [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
- [kubectl](https://kubernetes.io/docs/tasks/tools/)
- [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest)
## Deploy an Azure Kubernetes Service cluster

View File

@ -8,7 +8,7 @@ description: "Setup a Google Kubernetes Engine cluster"
### Prerequisites
- [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
- [kubectl](https://kubernetes.io/docs/tasks/tools/)
- [Google Cloud SDK](https://cloud.google.com/sdk)
## Create a new cluster

View File

@ -12,7 +12,7 @@ description: >
## Prerequisites
- [Docker](https://docs.docker.com/install/)
- [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
- [kubectl](https://kubernetes.io/docs/tasks/tools/)
- [Minikube](https://minikube.sigs.k8s.io/docs/start/)
> Note: For Windows, enable Virtualization in BIOS and [install Hyper-V](https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/quick-start/enable-hyper-v)

View File

@ -15,7 +15,7 @@ For more information on what is deployed to your Kubernetes cluster read the [Ku
## Prerequisites
- Install [Dapr CLI]({{< ref install-dapr-cli.md >}})
- Install [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
- Install [kubectl](https://kubernetes.io/docs/tasks/tools/)
- Kubernetes cluster (see below if needed)
### Create cluster
@ -122,7 +122,7 @@ The latest Dapr helm chart no longer supports Helm v2. Please migrate from Helm
```bash
helm upgrade --install dapr dapr/dapr \
--version=1.2 \
--version={{% dapr-latest-version short="true" %}} \
--namespace dapr-system \
--create-namespace \
--wait
@ -132,7 +132,7 @@ The latest Dapr helm chart no longer supports Helm v2. Please migrate from Helm
```bash
helm upgrade --install dapr dapr/dapr \
--version=1.2 \
--version={{% dapr-latest-version short="true" %}} \
--namespace dapr-system \
--create-namespace \
--set global.ha.enabled=true \

View File

@ -11,15 +11,15 @@ description: "Follow these steps to upgrade Dapr on Kubernetes and ensure a smoo
- [Dapr CLI]({{< ref install-dapr-cli.md >}})
- [Helm 3](https://github.com/helm/helm/releases) (if using Helm)
## Upgrade existing cluster to 1.3.0
## Upgrade existing cluster to {{% dapr-latest-version long="true" %}}
There are two ways to upgrade the Dapr control plane on a Kubernetes cluster using either the Dapr CLI or Helm.
### Dapr CLI
The example below shows how to upgrade to version 1.3.0:
The example below shows how to upgrade to version {{% dapr-latest-version long="true" %}}:
```bash
dapr upgrade -k --runtime-version=1.3.0
dapr upgrade -k --runtime-version={{% dapr-latest-version long="true" %}}
```
You can provide all the available Helm chart configurations using the Dapr CLI.
@ -43,7 +43,7 @@ To resolve this issue please run the follow command to upgrade the CustomResourc
kubectl replace -f https://raw.githubusercontent.com/dapr/dapr/5a15b3e0f093d2d0938b12f144c7047474a290fe/charts/dapr/crds/configuration.yaml
```
Then proceed with the `dapr upgrade --runtime-version 1.3.0 -k` command as above.
Then proceed with the `dapr upgrade --runtime-version {{% dapr-latest-version long="true" %}} -k` command as above.
### Helm

View File

@ -25,11 +25,11 @@ description: "Follow these steps to upgrade Dapr in self-hosted mode and ensure
dapr init
```
1. Ensure you are using the latest version of Dapr (v1.3) with:
1. Ensure you are using the latest version of Dapr (v{{% dapr-latest-version long="true" %}})) with:
```bash
$ dapr --version
CLI version: 1.3
Runtime version: 1.3
CLI version: {{% dapr-latest-version short="true" %}}
Runtime version: {{% dapr-latest-version short="true" %}}
```

View File

@ -9,7 +9,7 @@ description: "How to install Fluentd, Elastic Search, and Kibana to search logs
## Prerequisites
- Kubernetes (> 1.14)
- [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
- [kubectl](https://kubernetes.io/docs/tasks/tools/)
- [Helm 3](https://helm.sh/)
## Install Elastic search and Kibana

View File

@ -10,7 +10,7 @@ description: "Enable Dapr metrics and logs with Azure Monitor for Azure Kubernet
- [Azure Kubernetes Service](https://docs.microsoft.com/en-us/azure/aks/)
- [Enable Azure Monitor For containers in AKS](https://docs.microsoft.com/en-us/azure/azure-monitor/insights/container-insights-overview)
- [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
- [kubectl](https://kubernetes.io/docs/tasks/tools/)
- [Helm 3](https://helm.sh/)
## Enable Prometheus metric scrape using config map

View File

@ -67,7 +67,7 @@ Once Prometheus is running, you'll be able to visit its dashboard by visiting `h
### Prerequisites
- Kubernetes (> 1.14)
- [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
- [kubectl](https://kubernetes.io/docs/tasks/tools/)
- [Helm 3](https://helm.sh/)
### Install Prometheus

View File

@ -9,8 +9,10 @@ Preview features in Dapr are considered experimental when they are first release
## Current preview features
| Description | Setting | Documentation |
|-------------|---------|---------------|
| Preview feature that enables Actors to be called multiple times in the same call chain allowing call backs between actors. | Actor.Reentrancy | [Actor reentrancy]({{<ref actor-reentrancy>}}) |
| Preview feature that allows Actor reminders to be partitioned across multiple keys in the underlying statestore in order to improve scale and performance. | Actor.TypeMetadata | [How-To: Partition Actor Reminders]({{< ref "howto-actors.md#partitioning-reminders" >}}) |
| Preview feature that enables you to call endpoints using service invocation on gRPC services through Dapr via gRPC proxying, without requiring the use of Dapr SDKs. | proxy.grpc | [How-To: Invoke services using gRPC]({{<ref howto-invoke-services-grpc>}}) |
| Feature | Description | Setting | Documentation |
| ---------- |-------------|---------|---------------|
| **Actor reentrancy** | Enables actors to be called multiple times in the same call chain allowing call backs between actors. | `Actor.Reentrancy` | [Actor reentrancy]({{<ref actor-reentrancy>}}) |
| **Partition actor reminders** | Allows actor reminders to be partitioned across multiple keys in the underlying statestore in order to improve scale and performance. | `Actor.TypeMetadata` | [How-To: Partition Actor Reminders]({{< ref "howto-actors.md#partitioning-reminders" >}}) |
| **gRPC proxying** | Enables calling endpoints using service invocation on gRPC services through Dapr via gRPC proxying, without requiring the use of Dapr SDKs. | `proxy.grpc` | [How-To: Invoke services using gRPC]({{<ref howto-invoke-services-grpc>}}) |
| **State store encryption** | Enables automatic client side encryption for state stores | `State.Encryption` | [How-To: Encrypt application state]({{<ref howto-encrypt-state>}}) |
| **Pub/Sub routing** | Allow the use of expressions to route cloud events to different URIs/paths and event handlers in your application. | `PubSub.Routing` | [How-To: Publish a message and subscribe to a topic]({{<ref howto-route-messages>}}) |

View File

@ -31,15 +31,20 @@ The table below shows the versions of Dapr releases that have been tested togeth
| Release date | Runtime | CLI | SDKs | Dashboard | Status |
|--------------------|:--------:|:--------|---------|---------|---------|
| Feb 17th 2021 | 1.0.0</br>| 1.0.0 | Java 1.0.0 </br>Go 1.0.0 </br>PHP 1.0.0 </br>Python 1.0.0 </br>.NET 1.0.0 | 0.6.0 | Unsupported |
| Mar 4th 2021 | 1.0.1</br>| 1.0.1 | Java 1.0.2 </br>Go 1.0.0 </br>PHP 1.0.0 </br>Python 1.0.0 </br>.NET 1.0.0 | 0.6.0 | Unsupported |
| Apr 1st 2021 | 1.1.0</br> | 1.1.0 | Java 1.0.2 </br>Go 1.1.0 </br>PHP 1.0.0 </br>Python 1.1.0 </br>.NET 1.1.0 | 0.6.0 | Unsupported |
| Apr 6th 2021 | 1.1.1</br> | 1.1.0 | Java 1.0.2 </br>Go 1.1.0 </br>PHP 1.0.0 </br>Python 1.1.0 </br>.NET 1.1.0 | 0.6.0 | Unsupported |
| Apr 16th 2021 | 1.1.2</br> | 1.1.0 | Java 1.0.2 </br>Go 1.1.0 </br>PHP 1.0.0 </br>Python 1.1.0 </br>.NET 1.1.0 | 0.6.0 | Unsupported |
| May 26th 2021 | 1.2.0</br> | 1.2.0 | Java 1.1.0 </br>Go 1.1.0 </br>PHP 1.1.0 </br>Python 1.1.0 </br>.NET 1.2.0 | 0.6.0 | Supported |
| June 16th 2021 | 1.2.1</br> | 1.2.0 | Java 1.1.0 </br>Go 1.1.0 </br>PHP 1.1.0 </br>Python 1.1.0 </br>.NET 1.2.0 | 0.6.0 | Supported |
| June 16th 2021 | 1.2.2</br> | 1.2.0 | Java 1.1.0 </br>Go 1.1.0 </br>PHP 1.1.0 </br>Python 1.1.0 </br>.NET 1.2.0 | 0.6.0 | Supported |
| July 26th 2021 | 1.3</br> | 1.3.0 | Java 1.2.0 </br>Go 1.2.0 </br>PHP 1.1.0 </br>Python 1.2.0 </br>.NET 1.3.0 | 0.7.0 | Supported (current) |
| Feb 17th 2021 | 1.0.0</br> | 1.0.0 | Java 1.0.0 </br>Go 1.0.0 </br>PHP 1.0.0 </br>Python 1.0.0 </br>.NET 1.0.0 | 0.6.0 | Unsupported |
| Mar 4th 2021 | 1.0.1</br> | 1.0.1 | Java 1.0.2 </br>Go 1.0.0 </br>PHP 1.0.0 </br>Python 1.0.0 </br>.NET 1.0.0 | 0.6.0 | Unsupported |
| Apr 1st 2021 | 1.1.0</br> | 1.1.0 | Java 1.0.2 </br>Go 1.1.0 </br>PHP 1.0.0 </br>Python 1.1.0 </br>.NET 1.1.0 | 0.6.0 | Unsupported |
| Apr 6th 2021 | 1.1.1</br> | 1.1.0 | Java 1.0.2 </br>Go 1.1.0 </br>PHP 1.0.0 </br>Python 1.1.0 </br>.NET 1.1.0 | 0.6.0 | Unsupported |
| Apr 16th 2021 | 1.1.2</br> | 1.1.0 | Java 1.0.2 </br>Go 1.1.0 </br>PHP 1.0.0 </br>Python 1.1.0 </br>.NET 1.1.0 | 0.6.0 | Unsupported |
| May 26th 2021 | 1.2.0</br> | 1.2.0 | Java 1.1.0 </br>Go 1.1.0 </br>PHP 1.1.0 </br>Python 1.1.0 </br>.NET 1.2.0 | 0.6.0 | Unsupported |
| Jun 16th 2021 | 1.2.1</br> | 1.2.0 | Java 1.1.0 </br>Go 1.1.0 </br>PHP 1.1.0 </br>Python 1.1.0 </br>.NET 1.2.0 | 0.6.0 | Unsupported |
| Jun 16th 2021 | 1.2.2</br> | 1.2.0 | Java 1.1.0 </br>Go 1.1.0 </br>PHP 1.1.0 </br>Python 1.1.0 </br>.NET 1.2.0 | 0.6.0 | Unsupported |
| Jul 26th 2021 | 1.3</br> | 1.3.0 | Java 1.2.0 </br>Go 1.2.0 </br>PHP 1.1.0 </br>Python 1.2.0 </br>.NET 1.3.0 | 0.7.0 | Supported |
| Sep 14th 2021 | 1.3.1</br> | 1.3.0 | Java 1.2.0 </br>Go 1.2.0 </br>PHP 1.1.0 </br>Python 1.2.0 </br>.NET 1.3.0 | 0.7.0 | Supported |
| Sep 15th 2021 | 1.4</br> | 1.4.0 | Java 1.3.0 </br>Go 1.3.0 </br>PHP 1.2.0 </br>Python 1.3.0 </br>.NET 1.4.0 | 0.8.0 | Supported |
| Sep 22nd 2021 | 1.4.1</br> | 1.4.0 | Java 1.3.0 </br>Go 1.3.0 </br>PHP 1.2.0 </br>Python 1.3.0 </br>.NET 1.4.0 | 0.8.0 | Supported
| Sep 24th 2021 | 1.4.2</br> | 1.4.0 | Java 1.3.0 </br>Go 1.3.0 </br>PHP 1.2.0 </br>Python 1.3.0 </br>.NET 1.4.0 | 0.8.0 | Supported |
| Oct 7th 2021 | 1.4.3</br> | 1.4.0 | Java 1.3.0 </br>Go 1.3.0 </br>PHP 1.2.0 </br>Python 1.3.0 </br>.NET 1.4.0 | 0.8.0 | Supported (current) |
## Upgrade paths
After the 1.0 release of the runtime there may be situations where it is necessary to explicitly upgrade through an additional release to reach the desired target. For example an upgrade from v1.0 to v1.2 may need go pass through v1.1
@ -52,10 +57,17 @@ General guidance on upgrading can be found for [self hosted mode]({{<ref self-ho
|--------------------------|-----------------------|------------------------- |
| 1.0.0 or 1.0.1 | N/A | 1.1.2 |
| | 1.1.2 | 1.2.2 |
| | 1.2.2 | 1.3.0 |
| | 1.2.2 | 1.3.1 |
| | 1.3.1 | 1.4.3 |
| 1.1.0 to 1.1.2 | N/A | 1.2.2 |
| | 1.2.2 | 1.3.0 |
| 1.2.0 to 1.2.2 | N/A | 1.3.0 |
| | 1.2.2 | 1.3.1 |
| | 1.3.1 | 1.4.3 |
| 1.2.0 to 1.2.2 | N/A | 1.3.1 |
| | 1.3.1 | 1.4.3 |
| 1.3.0 | N/A | 1.3.1 |
| | 1.3.1 | 1.4.3 |
| 1.3.1 | N/A | 1.4.3 |
| 1.4.0 to 1.4.2 | N/A | 1.4.3 |
## Feature and deprecations
There is a process for announcing feature deprecations. Deprecations are applied two (2) releases after the release in which they were announced. For example Feature X is announced to be deprecated in the 1.0.0 release notes and will then be removed in 1.2.0.

View File

@ -95,14 +95,14 @@ Code | Description
### Examples
```shell
curl http://localhost:3500/v1.0/secrets/vault/db-secret \
curl http://localhost:3500/v1.0/secrets/vault/db-secret
```
```shell
curl http://localhost:3500/v1.0/secrets/vault/db-secret?metadata.version_id=15&metadata.version_stage=AAA \
curl http://localhost:3500/v1.0/secrets/vault/db-secret?metadata.version_id=15&metadata.version_stage=AAA
```
> Note, in case of deploying into namespace other than default`, the above query will also have to include the namespace metadata (e.g. `production` below)
> Note, in case of deploying into namespace other than default, the above query will also have to include the namespace metadata (e.g. `production` below)
```shell
curl http://localhost:3500/v1.0/secrets/vault/db-secret?metadata.version_id=15&?metadata.namespace=production
@ -165,7 +165,7 @@ Code | Description
### Examples
```shell
curl http://localhost:3500/v1.0/secrets/vault/bulk \
curl http://localhost:3500/v1.0/secrets/vault/bulk
```
```json

View File

@ -39,6 +39,7 @@ This table is meant to help users understand the equivalent options for running
| `--version` | `--version` | `-v` | not supported | Prints the runtime version |
| not supported | not supported | | `dapr.io/enabled` | Setting this paramater to true injects the Dapr sidecar into the pod |
| not supported | not supported | | `dapr.io/api-token-secret` | Tells Dapr which Kubernetes secret to use for token based API authentication. By default this is not set |
| `--dapr-listen-addresses` | not supported | | `dapr.io/sidecar-listen-addresses` | Comma separated list of IP addresses that sidecar will listen to. Defaults to all in standalone mode. Defaults to `[::1],127.0.0.1` in Kubernetes. To listen to all IPv4 addresses, use `0.0.0.0`. To listen to all IPv6 addresses, use `[::]`.
| not supported | not supported | | `dapr.io/sidecar-cpu-limit` | Maximum amount of CPU that the Dapr sidecar can use. See valid values [here](https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/quota-memory-cpu-namespace/). By default this is not set
| not supported | not supported | | `dapr.io/sidecar-memory-limit` | Maximum amount of Memory that the Dapr sidecar can use. See valid values [here](https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/quota-memory-cpu-namespace/). By default this is not set
| not supported | not supported | | `dapr.io/sidecar-cpu-request` | Amount of CPU that the Dapr sidecar requests. See valid values [here](https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/quota-memory-cpu-namespace/). By default this is not set

View File

@ -23,6 +23,7 @@ dapr dashboard [flags]
| Name | Environment Variable | Default | Description |
|------|----------------------|---------|-------------|
| `--address`, `-a` | | `localhost` | Address to listen on. Only accepts IP address or localhost as a value |
| `--help`, `-h` | | | Prints this help message |
| `--kubernetes`, `-k` | | `false` | Opens Dapr dashboard in local browser via local proxy to Kubernetes cluster |
| `--namespace`, `-n` | | `dapr-system` | The namespace where Dapr dashboard is running |
@ -46,6 +47,11 @@ dapr dashboard -p 9999
dapr dashboard -k
```
### Port forward to dashboard service running in Kubernetes on all addresses on a specified port
```bash
dapr dashboard -k -p 9999 --address 0.0.0.0
```
### Port forward to dashboard service running in Kubernetes on a specified port
```bash
dapr dashboard -k -p 9999

View File

@ -50,6 +50,7 @@ Table captions:
|------|:----------------:|:-----------------:|--------| ------ |----------|
| [Alibaba Cloud DingTalk]({{< ref alicloud-dingtalk.md >}}) | ✅ | ✅ | Alpha | v1 | 1.2 |
| [Alibaba Cloud OSS]({{< ref alicloudoss.md >}}) | | ✅ | Alpha | v1 | 1.0 |
| [Alibaba Cloud Tablestore]({{< ref alicloudtablestore.md >}}) | | ✅ | Alpha | v1 | 1.4 |
### Amazon Web Services (AWS)
@ -57,6 +58,7 @@ Table captions:
|------|:----------------:|:-----------------:|--------| ------ |----------|
| [AWS DynamoDB]({{< ref dynamodb.md >}}) | | ✅ | Alpha | v1 | 1.0 |
| [AWS S3]({{< ref s3.md >}}) | | ✅ | Alpha | v1 | 1.0 |
| [AWS SES]({{< ref ses.md >}}) | | ✅ | Alpha | v1 | 1.4 |
| [AWS SNS]({{< ref sns.md >}}) | | ✅ | Alpha | v1 | 1.0 |
| [AWS SQS]({{< ref sqs.md >}}) | ✅ | ✅ | Alpha | v1 | 1.0 |
| [AWS Kinesis]({{< ref kinesis.md >}}) | ✅ | ✅ | Alpha | v1 | 1.0 |

View File

@ -0,0 +1,143 @@
---
type: docs
title: "Alibaba Cloud Tablestore binding spec"
linkTitle: "Alibaba Cloud Tablestore"
description: "Detailed documentation on the Alibaba Tablestore binding component"
aliases:
- "/operations/components/setup-bindings/supported-bindings/alicloudtablestore/"
---
## Component format
To setup an Alibaba Cloud Tablestore binding create a component of type `bindings.alicloud.tablestore`. See [this guide]({{< ref "howto-bindings.md#1-create-a-binding" >}}) on how to create and apply a secretstore configuration. See this guide on [referencing secrets]({{< ref component-secrets.md >}}) to retrieve and use the secret with Dapr components.
```yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: mytablestore
namespace: default
spec:
type: bindings.alicloud.tablestore
version: v1
metadata:
- name: endpoint
value: "[endpoint]"
- name: accessKeyID
value: "[key-id]"
- name: accessKey
value: "[access-key]"
- name: instanceName
value: "[instance]"
- name: tableName
value: "[table]"
- name: endpoint
value: "[endpoint]"
```
{{% alert title="Warning" color="warning" %}}
The above example uses secrets as plain strings. It is recommended to use a secret store for the secrets as described [here]({{< ref component-secrets.md >}}).
{{% /alert %}}
## Spec metadata fields
| Field | Required | Binding support | Details | Example |
|---------------|----------|---------|---------|---------|
| `endpoint` | Y | Output | Alicloud Tablestore endpoint. | https://tablestore-cn-hangzhou.aliyuncs.com
| `accessKeyID` | Y | Output | Access key ID credential. |
| `accessKey` | Y | Output | Access key credential. |
| `instanceName` | Y | Output | Name of the instance. |
| `tableName` | Y | Output | Name of the table. |
## Binding support
This component supports **output binding** with the following operations:
- `create`: [Create object](#create-object)
### Create object
To perform a create object operation, invoke the binding with a `POST` method and the following JSON body:
```json
{
"operation": "create",
"data": "YOUR_CONTENT",
"metadata": {
"primaryKeys": "pk1"
}
}
```
{{% alert title="Note" color="primary" %}}
Note the `metadata.primaryKeys` field is mandatory.
{{% /alert %}}
### Delete object
To perform a delete object operation, invoke the binding with a `POST` method and the following JSON body:
```json
{
"operation": "delete",
"metadata": {
"primaryKeys": "pk1",
"columnToGet": "name,age,date"
},
"data": {
"pk1": "data1"
}
}
```
{{% alert title="Note" color="primary" %}}
Note the `metadata.primaryKeys` field is mandatory.
{{% /alert %}}
### List objects
To perform a list objects operation, invoke the binding with a `POST` method and the following JSON body:
```json
{
"operation": "delete",
"metadata": {
"primaryKeys": "pk1",
"columnToGet": "name,age,date"
},
"data": {
"pk1": "data1",
"pk2": "data2"
}
}
```
{{% alert title="Note" color="primary" %}}
Note the `metadata.primaryKeys` field is mandatory.
{{% /alert %}}
### Get object
To perform a get object operation, invoke the binding with a `POST` method and the following JSON body:
```json
{
"operation": "delete",
"metadata": {
"primaryKeys": "pk1"
},
"data": {
"pk1": "data1"
}
}
```
{{% alert title="Note" color="primary" %}}
Note the `metadata.primaryKeys` field is mandatory.
{{% /alert %}}
## Related links
- [Bindings building block]({{< ref bindings >}})
- [How-To: Use bindings to interface with external resources]({{< ref howto-bindings.md >}})
- [Bindings API reference]({{< ref bindings_api.md >}})

View File

@ -44,6 +44,10 @@ spec:
value: https://www.googleapis.com/robot/v1/metadata/x509/<project-name>.iam.gserviceaccount.com
- name: private_key
value: PRIVATE KEY
- name: decodeBase64
value: <bool>
- name: encodeBase64
value: <bool>
```
{{% alert title="Warning" color="warning" %}}
@ -65,12 +69,17 @@ The above example uses secrets as plain strings. It is recommended to use a secr
| token_uri | Y | Output | Google account token uri | `https://oauth2.googleapis.com/token`
| auth_provider_x509_cert_url | Y | Output | GCP credentials cert url | `https://www.googleapis.com/oauth2/v1/certs`
| client_x509_cert_url | Y | Output | GCP credentials project x509 cert url | `https://www.googleapis.com/robot/v1/metadata/x509/<PROJECT_NAME>.iam.gserviceaccount.com`
| decodeBase64 | N | Output | Configuration to decode base64 file content before saving to bucket storage. (In case of saving a file with binary content). `true` is the only allowed positive value. Other positive variations like `"True", "1"` are not acceptable. Defaults to `false` | `true`, `false` |
| encodeBase64 | N | Output | Configuration to encode base64 file content before return the content. (In case of opening a file with binary content). `true` is the only allowed positive value. Other positive variations like `"True", "1"` are not acceptable. Defaults to `false` | `true`, `false` |
## Binding support
This component supports **output binding** with the following operations:
- `create`
- `create` : [Create file](#create-file)
- `get` : [Get file](#get-file)
- `delete` : [Delete file](#delete-file)
- `list`: [List file](#list-files)
### Create file
@ -84,10 +93,11 @@ To perform a create operation, invoke the GCP Storage Bucket binding with a `POS
"data": "YOUR_CONTENT"
}
```
The metadata parameters are:
- `key` - (optional) the name of the object
- `decodeBase64` - (optional) configuration to decode base64 file content before saving to storage
#### Examples
##### Save text to a random generated UUID file
{{< tabs Windows Linux >}}
@ -113,14 +123,14 @@ To perform a create operation, invoke the GCP Storage Bucket binding with a `POS
{{% codetab %}}
```bash
curl -d "{ \"operation\": \"create\", \"data\": \"Hello World\", \"metadata\": { \"name\": \"my-test-file.txt\" } }" \
curl -d "{ \"operation\": \"create\", \"data\": \"Hello World\", \"metadata\": { \"key\": \"my-test-file.txt\" } }" \
http://localhost:<dapr-port>/v1.0/bindings/<binding-name>
```
{{% /codetab %}}
{{% codetab %}}
```bash
curl -d '{ "operation": "create", "data": "Hello World", "metadata": { "name": "my-test-file.txt" } }' \
curl -d '{ "operation": "create", "data": "Hello World", "metadata": { "key": "my-test-file.txt" } }' \
http://localhost:<dapr-port>/v1.0/bindings/<binding-name>
```
{{% /codetab %}}
@ -138,19 +148,175 @@ Then you can upload it as you would normally:
{{% codetab %}}
```bash
curl -d "{ \"operation\": \"create\", \"data\": \"(YOUR_FILE_CONTENTS)\", \"metadata\": { \"name\": \"my-test-file.jpg\" } }" http://localhost:<dapr-port>/v1.0/bindings/<binding-name>
curl -d "{ \"operation\": \"create\", \"data\": \"(YOUR_FILE_CONTENTS)\", \"metadata\": { \"key\": \"my-test-file.jpg\" } }" http://localhost:<dapr-port>/v1.0/bindings/<binding-name>
```
{{% /codetab %}}
{{% codetab %}}
```bash
curl -d '{ "operation": "create", "data": "$(cat my-test-file.jpg)", "metadata": { "name": "my-test-file.jpg" } }' \
curl -d '{ "operation": "create", "data": "$(cat my-test-file.jpg)", "metadata": { "key": "my-test-file.jpg" } }' \
http://localhost:<dapr-port>/v1.0/bindings/<binding-name>
```
{{% /codetab %}}
{{< /tabs >}}
#### Response
The response body will contain the following JSON:
```json
{
"objectURL":"https://storage.googleapis.com/<your bucket>/<key>",
}
```
### Get object
To perform a get file operation, invoke the GCP bucket binding with a `POST` method and the following JSON body:
```json
{
"operation": "get",
"metadata": {
"key": "my-test-file.txt"
}
}
```
The metadata parameters are:
- `key` - the name of the object
- `encodeBase64` - (optional) configuration to encode base64 file content before return the content.
#### Example
{{< tabs Windows Linux >}}
{{% codetab %}}
```bash
curl -d '{ \"operation\": \"get\", \"metadata\": { \"key\": \"my-test-file.txt\" }}' http://localhost:<dapr-port>/v1.0/bindings/<binding-name>
```
{{% /codetab %}}
{{% codetab %}}
```bash
curl -d '{ "operation": "get", "metadata": { "key": "my-test-file.txt" }}' \
http://localhost:<dapr-port>/v1.0/bindings/<binding-name>
```
{{% /codetab %}}
{{< /tabs >}}
#### Response
The response body contains the value stored in the object.
### Delete object
To perform a delete object operation, invoke the GCP bucket binding with a `POST` method and the following JSON body:
```json
{
"operation": "delete",
"metadata": {
"key": "my-test-file.txt"
}
}
```
The metadata parameters are:
- `key` - the name of the object
#### Examples
##### Delete object
{{< tabs Windows Linux >}}
{{% codetab %}}
```bash
curl -d '{ \"operation\": \"delete\", \"metadata\": { \"key\": \"my-test-file.txt\" }}' http://localhost:<dapr-port>/v1.0/bindings/<binding-name>
```
{{% /codetab %}}
{{% codetab %}}
```bash
curl -d '{ "operation": "delete", "metadata": { "key": "my-test-file.txt" }}' \
http://localhost:<dapr-port>/v1.0/bindings/<binding-name>
```
{{% /codetab %}}
{{< /tabs >}}
#### Response
An HTTP 204 (No Content) and empty body will be retuned if successful.
### List objects
To perform a list object operation, invoke the S3 binding with a `POST` method and the following JSON body:
```json
{
"operation": "list",
"data": {
"maxResults": 10,
"prefix": "file",
"delimiter": "i0FvxAn2EOEL6"
}
}
```
The data parameters are:
- `maxResults` - (optional) sets the maximum number of keys returned in the response. By default the action returns up to 1,000 key names. The response might contain fewer keys but will never contain more.
- `prefix` - (optional) it can be used to filter objects starting with prefix.
- `delimiter` - (optional) it can be used to restrict the results to only the kobjects in the given "directory". Without the delimiter, the entire tree under the prefix is returned
#### Response
The response body contains the list of found objects.
The list of objects will be returned as JSON array in the following form:
```json
[
{
"Bucket": "<your bucket>",
"Name": "02WGzEdsUWNlQ",
"ContentType": "image/png",
"ContentLanguage": "",
"CacheControl": "",
"EventBasedHold": false,
"TemporaryHold": false,
"RetentionExpirationTime": "0001-01-01T00:00:00Z",
"ACL": null,
"PredefinedACL": "",
"Owner": "",
"Size": 5187,
"ContentEncoding": "",
"ContentDisposition": "",
"MD5": "aQdLBCYV0BxA51jUaxc3pQ==",
"CRC32C": 1058633505,
"MediaLink": "https://storage.googleapis.com/download/storage/v1/b/<your bucket>/o/02WGzEdsUWNlQ?generation=1631553155678071&alt=media",
"Metadata": null,
"Generation": 1631553155678071,
"Metageneration": 1,
"StorageClass": "STANDARD",
"Created": "2021-09-13T17:12:35.679Z",
"Deleted": "0001-01-01T00:00:00Z",
"Updated": "2021-09-13T17:12:35.679Z",
"CustomerKeySHA256": "",
"KMSKeyName": "",
"Prefix": "",
"Etag": "CPf+mpK5/PICEAE="
}
]
```
## Related links
- [Basic schema for a Dapr component]({{< ref component-schema >}})

View File

@ -70,6 +70,8 @@ The above example uses secrets as plain strings. It is recommended to use a secr
## Binding support
This component supports both **input and output** binding interfaces.
This component supports **output binding** with the following operations:
- `create`

View File

@ -52,6 +52,7 @@ spec:
| authRequired | Y | Input/Output | Enable [SASL](https://en.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer) authentication with the Kafka brokers. | `"true"`, `"false"` |
| saslUsername | N | Input/Output | The SASL username used for authentication. Only required if `authRequired` is set to `"true"`. | `"adminuser"` |
| saslPassword | N | Input/Output | The SASL password used for authentication. Can be `secretKeyRef` to use a [secret reference]({{< ref component-secrets.md >}}). Only required if `authRequired` is set to `"true"`. | `""`, `"KeFg23!"` |
| initialOffset | N | The initial offset to use if no offset was previously committed. Should be "newest" or "oldest". Defaults to "newest". | `"oldest"` |
| maxMessageBytes | N | Input/Output | The maximum size in bytes allowed for a single Kafka message. Defaults to 1024. | `2048` |
## Binding support

View File

@ -38,6 +38,8 @@ spec:
value: false
- name: maxPriority
value: 5
- name: contentType
value: "text/plain"
```
{{% alert title="Warning" color="warning" %}}
@ -56,6 +58,7 @@ The above example uses secrets as plain strings. It is recommended to use a secr
| prefetchCount | N | Input | Set the [Channel Prefetch Setting (QoS)](https://www.rabbitmq.com/confirms.html#channel-qos-prefetch). If this parameter is omiited, QoS would set value to 0 as no limit | `0` |
| exclusive | N | Input/Output | Determines whether the topic will be an exclusive topic or not. Defaults to `"false"` | `"true"`, `"false"` |
| maxPriority| N | Input/Output | Parameter to set the [priority queue](https://www.rabbitmq.com/priority.html). If this parameter is omitted, queue will be created as a general queue instead of a priority queue. Value between 1 and 255. See [also](#specifying-a-priority-per-message) | `"1"`, `"10"` |
| contentType | N | Input/Output | The content type of the message. Defaults to "text/plain". | `"text/plain"`, `"application/cloudevent+json"` and so on |
## Binding support
This component supports both **input and output** binding interfaces.

View File

@ -40,25 +40,26 @@ The above example uses secrets as plain strings. It is recommended to use a secr
|--------------------|:--------:|------------|-----|---------|
| redisHost | Y | Output | The Redis host address | `"localhost:6379"` |
| redisPassword | Y | Output | The Redis password | `"password"` |
| redisUsername | N | Output | Username for Redis host. Defaults to empty. Make sure your redis server version is 6 or above, and have created acl rule correctly. | `"username"` |
| enableTLS | N | Output | If the Redis instance supports TLS with public certificates it can be configured to enable or disable TLS. Defaults to `"false"` | `"true"`, `"false"` |
| failover | N | Property to enabled failover configuration. Needs sentinalMasterName to be set. Defaults to `"false"` | `"true"`, `"false"`
| sentinelMasterName | N | The sentinel master name. See [Redis Sentinel Documentation](https://redis.io/topics/sentinel) | `""`, `"127.0.0.1:6379"`
| redeliverInterval | N | The interval between checking for pending messages to redelivery. Defaults to `"60s"`. `"0"` disables redelivery. | `"30s"`
| processingTimeout | N | The amount time a message must be pending before attempting to redeliver it. Defaults to `"15s"`. `"0"` disables redelivery. | `"30s"`
| redisType | N | The type of redis. There are two valid values, one is `"node"` for single node mode, the other is `"cluster"` for redis cluster mode. Defaults to `"node"`. | `"cluster"`
| redisDB | N | Database selected after connecting to redis. If `"redisType"` is `"cluster"` this option is ignored. Defaults to `"0"`. | `"0"`
| redisMaxRetries | N | Maximum number of times to retry commands before giving up. Default is to not retry failed commands. | `"5"`
| redisMinRetryInterval | N | Minimum backoff for redis commands between each retry. Default is `"8ms"`; `"-1"` disables backoff. | `"8ms"`
| redisMaxRetryInterval | N | Maximum backoff for redis commands between each retry. Default is `"512ms"`;`"-1"` disables backoff. | `"5s"`
| dialTimeout | N | Dial timeout for establishing new connections. Defaults to `"5s"`. | `"5s"`
| readTimeout | N | Timeout for socket reads. If reached, redis commands will fail with a timeout instead of blocking. Defaults to `"3s"`, `"-1"` for no timeout. | `"3s"`
| writeTimeout | N | Timeout for socket writes. If reached, redis commands will fail with a timeout instead of blocking. Defaults is readTimeout. | `"3s"`
| poolSize | N | Maximum number of socket connections. Default is 10 connections per every CPU as reported by runtime.NumCPU. | `"20"`
| poolTimeout | N | Amount of time client waits for a connection if all connections are busy before returning an error. Default is readTimeout + 1 second. | `"5s"`
| maxConnAge | N | Connection age at which the client retires (closes) the connection. Default is to not close aged connections. | `"30m"`
| minIdleConns | N | Minimum number of idle connections to keep open in order to avoid the performance degradation associated with creating new connections. Defaults to `"0"`. | `"2"`
| idleCheckFrequency | N | Frequency of idle checks made by idle connections reaper. Default is `"1m"`. `"-1"` disables idle connections reaper. | `"-1"`
| idleTimeout | N | Amount of time after which the client closes idle connections. Should be less than server's timeout. Default is `"5m"`. `"-1"` disables idle timeout check. | `"10m"`
| failover | N | Output | Property to enabled failover configuration. Needs sentinalMasterName to be set. Defaults to `"false"` | `"true"`, `"false"`
| sentinelMasterName | N | Output | The sentinel master name. See [Redis Sentinel Documentation](https://redis.io/topics/sentinel) | `""`, `"127.0.0.1:6379"`
| redeliverInterval | N | Output | The interval between checking for pending messages to redelivery. Defaults to `"60s"`. `"0"` disables redelivery. | `"30s"`
| processingTimeout | N | Output | The amount time a message must be pending before attempting to redeliver it. Defaults to `"15s"`. `"0"` disables redelivery. | `"30s"`
| redisType | N | Output | The type of redis. There are two valid values, one is `"node"` for single node mode, the other is `"cluster"` for redis cluster mode. Defaults to `"node"`. | `"cluster"`
| redisDB | N | Output | Database selected after connecting to redis. If `"redisType"` is `"cluster"` this option is ignored. Defaults to `"0"`. | `"0"`
| redisMaxRetries | N | Output | Maximum number of times to retry commands before giving up. Default is to not retry failed commands. | `"5"`
| redisMinRetryInterval | N | Output | Minimum backoff for redis commands between each retry. Default is `"8ms"`; `"-1"` disables backoff. | `"8ms"`
| redisMaxRetryInterval | N | Output | Maximum backoff for redis commands between each retry. Default is `"512ms"`;`"-1"` disables backoff. | `"5s"`
| dialTimeout | N | Output | Dial timeout for establishing new connections. Defaults to `"5s"`. | `"5s"`
| readTimeout | N | Output | Timeout for socket reads. If reached, redis commands will fail with a timeout instead of blocking. Defaults to `"3s"`, `"-1"` for no timeout. | `"3s"`
| writeTimeout | N | Output | Timeout for socket writes. If reached, redis commands will fail with a timeout instead of blocking. Defaults is readTimeout. | `"3s"`
| poolSize | N | Output | Maximum number of socket connections. Default is 10 connections per every CPU as reported by runtime.NumCPU. | `"20"`
| poolTimeout | N | Output | Amount of time client waits for a connection if all connections are busy before returning an error. Default is readTimeout + 1 second. | `"5s"`
| maxConnAge | N | Output | Connection age at which the client retires (closes) the connection. Default is to not close aged connections. | `"30m"`
| minIdleConns | N | Output | Minimum number of idle connections to keep open in order to avoid the performance degradation associated with creating new connections. Defaults to `"0"`. | `"2"`
| idleCheckFrequency | N | Output | Frequency of idle checks made by idle connections reaper. Default is `"1m"`. `"-1"` disables idle connections reaper. | `"-1"`
| idleTimeout | N | Output | Amount of time after which the client closes idle connections. Should be less than server's timeout. Default is `"5m"`. `"-1"` disables idle timeout check. | `"10m"`
## Binding support

View File

@ -33,6 +33,10 @@ spec:
value: *****************
- name: sessionToken
value: mysession
- name: decodeBase64
value: <bool>
- name: encodeBase64
value: <bool>
```
{{% alert title="Warning" color="warning" %}}
@ -48,13 +52,18 @@ The above example uses secrets as plain strings. It is recommended to use a secr
| accessKey | Y | Output | The AWS Access Key to access this resource | `"key"` |
| secretKey | Y | Output | The AWS Secret Access Key to access this resource | `"secretAccessKey"` |
| sessionToken | N | Output | The AWS session token to use | `"sessionToken"` |
| decodeBase64 | N | Output | Configuration to decode base64 file content before saving to bucket storage. (In case of saving a file with binary content). `true` is the only allowed positive value. Other positive variations like `"True", "1"` are not acceptable. Defaults to `false` | `true`, `false` |
| encodeBase64 | N | Output | Configuration to encode base64 file content before return the content. (In case of opening a file with binary content). `true` is the only allowed positive value. Other positive variations like `"True", "1"` are not acceptable. Defaults to `false` | `true`, `false` |
## Binding support
This component supports **output binding** with the following operations:
- `create`
- `create` : [Create file](#create-file)
- `get` : [Get file](#get-file)
- `delete` : [Delete file](#delete-file)
- `list`: [List file](#list-files)
### Create file
@ -70,8 +79,6 @@ To perform a create operation, invoke the AWS S3 binding with a `POST` method an
```
#### Examples
##### Save text to a random generated UUID file
{{< tabs Windows Linux >}}
@ -111,10 +118,33 @@ To perform a create operation, invoke the AWS S3 binding with a `POST` method an
{{< /tabs >}}
##### Save a file to a object
##### Upload a file
To upload a file, encode it as Base64 and let the Binding know to deserialize it:
To upload a file, pass the file contents as the data payload; you may want to encode this in e.g. Base64 for binary content.
```yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: <NAME>
namespace: <NAMESPACE>
spec:
type: bindings.aws.s3
version: v1
metadata:
- name: bucket
value: mybucket
- name: region
value: us-west-2
- name: accessKey
value: *****************
- name: secretKey
value: *****************
- name: sessionToken
value: mysession
- name: decodeBase64
value: <bool>
```
Then you can upload it as you would normally:
@ -122,19 +152,172 @@ Then you can upload it as you would normally:
{{% codetab %}}
```bash
curl -d "{ \"operation\": \"create\", \"data\": \"(YOUR_FILE_CONTENTS)\", \"metadata\": { \"key\": \"my-test-file.jpg\" } }" http://localhost:<dapr-port>/v1.0/bindings/<binding-name>
curl -d "{ \"operation\": \"create\", \"data\": \"YOUR_BASE_64_CONTENT\", \"metadata\": { \"key\": \"my-test-file.jpg\" } }" http://localhost:<dapr-port>/v1.0/bindings/<binding-name>
```
{{% /codetab %}}
{{% codetab %}}
```bash
curl -d '{ "operation": "create", "data": "$(cat my-test-file.jpg)", "metadata": { "key": "my-test-file.jpg" } }' \
curl -d '{ "operation": "create", "data": "YOUR_BASE_64_CONTENT", "metadata": { "key": "my-test-file.jpg" } }' \
http://localhost:<dapr-port>/v1.0/bindings/<binding-name>
```
{{% /codetab %}}
{{< /tabs >}}
#### Response
The response body will contain the following JSON:
```json
{
"location":"https://<your bucket>.s3.<your region>.amazonaws.com/<key>",
"versionID":"<version ID if Bucket Versioning is enabled"
}
```
### Get object
To perform a get file operation, invoke the AWS S3 binding with a `POST` method and the following JSON body:
```json
{
"operation": "get",
"metadata": {
"key": "my-test-file.txt"
}
}
```
The metadata parameters are:
- `key` - the name of the object
#### Example
{{< tabs Windows Linux >}}
{{% codetab %}}
```bash
curl -d '{ \"operation\": \"get\", \"metadata\": { \"key\": \"my-test-file.txt\" }}' http://localhost:<dapr-port>/v1.0/bindings/<binding-name>
```
{{% /codetab %}}
{{% codetab %}}
```bash
curl -d '{ "operation": "get", "metadata": { "key": "my-test-file.txt" }}' \
http://localhost:<dapr-port>/v1.0/bindings/<binding-name>
```
{{% /codetab %}}
{{< /tabs >}}
#### Response
The response body contains the value stored in the object.
### Delete object
To perform a delete object operation, invoke the AWS S3 binding with a `POST` method and the following JSON body:
```json
{
"operation": "delete",
"metadata": {
"key": "my-test-file.txt"
}
}
```
The metadata parameters are:
- `key` - the name of the object
#### Examples
##### Delete object
{{< tabs Windows Linux >}}
{{% codetab %}}
```bash
curl -d '{ \"operation\": \"delete\", \"metadata\": { \"key\": \"my-test-file.txt\" }}' http://localhost:<dapr-port>/v1.0/bindings/<binding-name>
```
{{% /codetab %}}
{{% codetab %}}
```bash
curl -d '{ "operation": "delete", "metadata": { "key": "my-test-file.txt" }}' \
http://localhost:<dapr-port>/v1.0/bindings/<binding-name>
```
{{% /codetab %}}
{{< /tabs >}}
#### Response
An HTTP 204 (No Content) and empty body will be retuned if successful.
### List objects
To perform a list object operation, invoke the S3 binding with a `POST` method and the following JSON body:
```json
{
"operation": "list",
"data": {
"maxResults": 10,
"prefix": "file",
"marker": "hvlcCQFSOD5TD",
"delimiter": "i0FvxAn2EOEL6"
}
}
```
The data parameters are:
- `maxResults` - (optional) sets the maximum number of keys returned in the response. By default the action returns up to 1,000 key names. The response might contain fewer keys but will never contain more.
- `prefix` - (optional) limits the response to keys that begin with the specified prefix.
- `marker` - (optional) marker is where you want Amazon S3 to start listing from. Amazon S3 starts listing after this specified key. Marker can be any key in the bucket.
The marker value may then be used in a subsequent call to request the next set of list items.
- `delimiter` - (optional) A delimiter is a character you use to group keys.
#### Response
The response body contains the list of found objects.
The list of objects will be returned as JSON array in the following form:
```json
{
"CommonPrefixes": null,
"Contents": [
{
"ETag": "\"7e94cc9b0f5226557b05a7c2565dd09f\"",
"Key": "hpNdFUxruNuwm",
"LastModified": "2021-08-16T06:44:14Z",
"Owner": {
"DisplayName": "owner name",
"ID": "owner id"
},
"Size": 6916,
"StorageClass": "STANDARD"
}
],
"Delimiter": "",
"EncodingType": null,
"IsTruncated": true,
"Marker": "hvlcCQFSOD5TD",
"MaxKeys": 1,
"Name": "mybucketdapr",
"NextMarker": "hzaUPWjmvyi9W",
"Prefix": ""
}
```
## Related links
- [Basic schema for a Dapr component]({{< ref component-schema >}})

View File

@ -0,0 +1,105 @@
---
type: docs
title: "AWS SES binding spec"
linkTitle: "AWS SES"
description: "Detailed documentation on the AWS SES binding component"
aliases:
- "/operations/components/setup-bindings/supported-bindings/ses/"
---
## Component format
To setup AWS binding create a component of type `bindings.aws.ses`. See [this guide]({{< ref "howto-bindings.md#1-create-a-binding" >}}) on how to create and apply a binding configuration.
See [Authenticating to AWS]({{< ref authenticating-aws.md >}}) for information about authentication-related attributes
```yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: ses
namespace: default
spec:
type: bindings.aws.ses
version: v1
metadata:
- name: accessKey
value: *****************
- name: secretKey
value: *****************
- name: region
value: "eu-west-1"
- name: sessionToken
value: mysession
- name: emailFrom
value: "sender@example.com"
- name: emailTo
value: "receiver@example.com"
- name: emailCc
value: "cc@example.com"
- name: emailBcc
value: "bcc@example.com"
- name: subject
value: "subject"
```
{{% alert title="Warning" color="warning" %}}
The above example uses secrets as plain strings. It is recommended to use a secret store for the secrets as described [here]({{< ref component-secrets.md >}}).
{{% /alert %}}
## Spec metadata fields
| Field | Required | Binding support | Details | Example |
|--------------------|:--------:|------------|-----|---------|
| region | Y | Output | The specific AWS region | `"eu-west-1"` |
| accessKey | Y | Output | The AWS Access Key to access this resource | `"key"` |
| secretKey | Y | Output | The AWS Secret Access Key to access this resource | `"secretAccessKey"` |
| sessionToken | N | Output | The AWS session token to use | `"sessionToken"` |
| emailFrom | N | Output | If set, this specifies the email address of the sender. See [also](#example-request) | `"me@example.com"` |
| emailTo | N | Output | If set, this specifies the email address of the receiver. See [also](#example-request) | `"me@example.com"` |
| emailCc | N | Output | If set, this specifies the email address to CC in. See [also](#example-request) | `"me@example.com"` |
| emailBcc | N | Output | If set, this specifies email address to BCC in. See [also](#example-request) | `"me@example.com"` |
| subject | N | Output | If set, this specifies the subject of the email message. See [also](#example-request) | `"subject of mail"` |
## Binding support
This component supports **output binding** with the following operations:
- `create`
## Example request
You can specify any of the following optional metadata properties with each request:
- `emailFrom`
- `emailTo`
- `emailCc`
- `emailBcc`
- `subject`
When sending an email, the metadata in the configuration and in the request is combined. The combined set of metadata must contain at least the `emailFrom`, `emailTo`, `emailCc`, `emailBcc` and `subject` fields.
The `emailTo`, `emailCc` and `emailBcc` fields can contain multiple email addresses separated by a semicolon.
Example:
```json
{
"operation": "create",
"metadata": {
"emailTo": "dapr-smtp-binding@example.net",
"emailCc": "cc1@example.net",
"subject": "Email subject"
},
"data": "Testing Dapr SMTP Binding"
}
```
The `emailTo`, `emailCc` and `emailBcc` fields can contain multiple email addresses separated by a semicolon.
## Related links
- [Basic schema for a Dapr component]({{< ref component-schema >}})
- [Bindings building block]({{< ref bindings >}})
- [How-To: Trigger application with input binding]({{< ref howto-triggers.md >}})
- [How-To: Use bindings to interface with external resources]({{< ref howto-bindings.md >}})
- [Bindings API reference]({{< ref bindings_api.md >}})

View File

@ -30,6 +30,8 @@ spec:
value: "myqueue"
- name: ttlInSeconds
value: "60"
- name: decodeBase64
value: "false"
```
{{% alert title="Warning" color="warning" %}}
@ -44,6 +46,7 @@ The above example uses secrets as plain strings. It is recommended to use a secr
| storageAccessKey | Y | Input/Output | The Azure Storage access key | `"accessKey"` |
| queue | Y | Input/Output | The name of the Azure Storage queue | `"myqueue"` |
| ttlInSeconds | N | Output | Parameter to set the default message time to live. If this parameter is omitted, messages will expire after 10 minutes. See [also](#specifying-a-ttl-per-message) | `"60"` |
| decodeBase64 | N | Output | Configuration to decode base64 file content before saving to Blob Storage. (In case of saving a file with binary content). `true` is the only allowed positive value. Other positive variations like `"True", "1"` are not acceptable. Defaults to `false` | `true`, `false` |
## Binding support

View File

@ -26,6 +26,8 @@ Table captions:
| [Hazelcast]({{< ref setup-hazelcast.md >}}) | Alpha | v1 | 1.0 |
| [MQTT]({{< ref setup-mqtt.md >}}) | Alpha | v1 | 1.0 |
| [NATS Streaming]({{< ref setup-nats-streaming.md >}}) | Beta | v1 | 1.0 |
| [In Memory]({{< ref setup-inmemory.md >}}) | Alpha | v1 | 1.4 |
| [JetStream]({{< ref setup-jetstream.md >}}) | Alpha | v1 | 1.4 |
| [Pulsar]({{< ref setup-pulsar.md >}}) | Alpha | v1 | 1.0 |
| [RabbitMQ]({{< ref setup-rabbitmq.md >}}) | Alpha | v1 | 1.0 |
| [Redis Streams]({{< ref setup-redis-pubsub.md >}}) | GA | v1 | 1.0 |

View File

@ -49,6 +49,7 @@ spec:
| authRequired | Y | Enable [SASL](https://en.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer) authentication with the Kafka brokers. | `"true"`, `"false"`
| saslUsername | N | The SASL username used for authentication. Only required if `authRequired` is set to `"true"`. | `"adminuser"`
| saslPassword | N | The SASL password used for authentication. Can be `secretKeyRef` to use a [secret reference]({{< ref component-secrets.md >}}). Only required if `authRequired` is set to `"true"`. | `""`, `"KeFg23!"`
| initialOffset | N | The initial offset to use if no offset was previously committed. Should be "newest" or "oldest". Defaults to "newest". | `"oldest"`
| maxMessageBytes | N | The maximum size in bytes allowed for a single Kafka message. Defaults to 1024. | `2048`
## Per-call metadata fields

View File

@ -84,6 +84,40 @@ The above example uses secrets as plain strings. It is recommended to use a secr
| publishMaxRetries | N | The max number of retries for when Azure Service Bus responds with "too busy" in order to throttle messages. Defaults: `5` | `5`
| publishInitialRetryInternalInMs | N | Time in milliseconds for the initial exponential backoff when Azure Service Bus throttle messages. Defaults: `500` | `500`
## Message metadata
Azure Service Bus messages extend the Dapr message format with additional contextual metadata. Some metadata fields are set by Azure Service Bus itself (read-only) and others can be set by the client when publishing a message.
### Sending a message with metadata
To set Azure Service Bus metadata when sending a message, set the query parameters on the HTTP request or the gRPC metadata as documented [here](https://docs.dapr.io/reference/api/pubsub_api/#metadata).
- `metadata.MessageId`
- `metadata.CorrelationId`
- `metadata.SessionId`
- `metadata.Label`
- `metadata.ReplyTo`
- `metadata.PartitionKey`
- `metadata.To`
- `metadata.ContentType`
- `metadata.ScheduledEnqueueTimeUtc`
- `metadata.ReplyToSessionId`
> **NOTE:** The `metadata.MessageId` property does not set the `id` property of the cloud event and should be treated in isolation.
### Receiving a message with metadata
When Dapr calls your application, it will attach Azure Service Bus message metadata to the request using either HTTP headers or gRPC metadata.
In addition to the [settable metadata listed above](#sending-a-message-with-metadata), you can also access the following read-only message metadata.
- `metadata.DeliveryCount`
- `metadata.LockedUntilUtc`
- `metadata.LockToken`
- `metadata.EnqueuedTimeUtc`
- `metadata.SequenceNumber`
To find out more details on the purpose of any of these metadata properties, please refer to [the official Azure Service Bus documentation](https://docs.microsoft.com/en-us/rest/api/servicebus/message-headers-and-properties#message-headers).
## Create an Azure Service Bus
Follow the instructions [here](https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-quickstart-topics-subscriptions-portal) on setting up Azure Service Bus Topics.

View File

@ -46,6 +46,8 @@ spec:
value: <PRIVATE_KEY> # replace x509 cert
- name: disableEntityManagement
value: "false"
- name: enableMessageOrdering
value: "false"
```
{{% alert title="Warning" color="warning" %}}
The above example uses secrets as plain strings. It is recommended to use a secret store for the secrets as described [here]({{< ref component-secrets.md >}}).
@ -67,6 +69,11 @@ The above example uses secrets as plain strings. It is recommended to use a secr
| authProviderX509CertUrl | N | If using explicit credentials, this field should contain the `auth_provider_x509_cert_url` field from the service account json | `https://www.googleapis.com/oauth2/v1/certs`
| clientX509CertUrl | N | If using explicit credentials, this field should contain the `client_x509_cert_url` field from the service account json | `https://www.googleapis.com/robot/v1/metadata/x509/myserviceaccount%40myproject.iam.gserviceaccount.com`
| disableEntityManagement | N | When set to `"true"`, topics and subscriptions do not get created automatically. Default: `"false"` | `"true"`, `"false"`
| enableMessageOrdering | N | When set to `"true"`, subscribed messages will be received in order, depending on publishing and permissions configuration. | `"true"`, `"false"`
{{% alert title="Warning" color="warning" %}}
If `enableMessageOrdering` is set to "true", the roles/viewer or roles/pubsub.viewer role will be required on the service account in order to guarantee ordering in cases where order tokens are not embedded in the messages. If this role is not given, or the call to Subscription.Config() fails for any other reason, ordering by embedded order tokens will still function correctly.
{{% /alert %}}
## Create a GCP Pub/Sub
You can use either "explicit" or "implicit" credentials to configure access to your GCP pubsub instance. If using explicit, most fields are required. Implicit relies on dapr running under a Kubernetes service account (KSA) mapped to a Google service account (GSA) which has the necessary permissions to access pubsub. In implicit mode, only the `projectId` attribute is needed, all other are optional.

View File

@ -0,0 +1,28 @@
---
type: docs
title: "In Memory"
linkTitle: "In Memory"
description: "Detailed documentation on the In Memory pubsub component"
aliases:
- "/operations/components/setup-pubsub/supported-pubsub/setup-inmemory/"
---
The In Memory pub/sub component is useful for development purposes and works inside of a single machine boundary.
## Component format
```yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: pubsub
namespace: default
spec:
type: pubsub.in-memory
version: v1
```
## Related links
- [Basic schema for a Dapr component]({{< ref component-schema >}}) in the Related links section
- Read [this guide]({{< ref "howto-publish-subscribe.md#step-2-publish-a-topic" >}}) for instructions on configuring pub/sub components
- [Pub/Sub building block]({{< ref pubsub >}})

View File

@ -0,0 +1,97 @@
---
type: docs
title: "JetStream"
linkTitle: "JetStream"
description: "Detailed documentation on the NATS JetStream component"
aliases:
- "/operations/components/setup-pubsub/supported-pubsub/setup-jetstream/"
---
## Component format
To setup JetStream pubsub create a component of type `pubsub.jetstream`. See
[this guide]({{< ref
"howto-publish-subscribe.md#step-1-setup-the-pubsub-component" >}}) on how to
create and apply a pubsub configuration.
```yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: jetstream-pubsub
namespace: default
spec:
type: pubsub.jetstream
version: v1
metadata:
- name: natsURL
value: "nats://localhost:4222"
- name: name
value: "connection name"
- name: durableName
value: "consumer durable name"
- name: queueGroupName
value: "queue group name"
- name: startSequence
value: 1
- name: startTime # in Unix format
value: 1630349391
- name: deliverAll
value: false
- name: flowControl
value: false
```
## Spec metadata fields
| Field | Required | Details | Example |
|----------------|:--------:|---------|---------|
| natsURL | Y | NATS server address URL | "`nats://localhost:4222`"|
| name | N | NATS connection name | `"my-conn-name"`|
| durableName | N | [Durable name] | `"my-durable"` |
| queueGroupName | N | Queue group name | `"my-queue"` |
| startSequence | N | [Start Sequence] | `1` |
| startTime | N | [Start Time] in Unix format | `1630349391` |
| deliverAll | N | Set deliver all as [Replay Policy] | `true` |
| flowControl | N | [Flow Control] | `true` |
## Create a NATS server
{{< tabs "Self-Hosted" "Kubernetes">}}
{{% codetab %}}
You can run a NATS Server with JetStream enabled locally using Docker:
```bash
docker run -d -p 4222:4222 nats:latest -js
```
You can then interact with the server using the client port: `localhost:4222`.
{{% /codetab %}}
{{% codetab %}}
Install NATS JetStream on Kubernetes by using the [helm](https://github.com/nats-io/k8s/tree/main/helm/charts/nats#jetstream):
```bash
helm repo add nats https://nats-io.github.io/k8s/helm/charts/
helm install my-nats nats/nats
```
This installs a single NATS server into the `default` namespace. To interact
with NATS, find the service with: `kubectl get svc my-nats`.
{{% /codetab %}}
{{< /tabs >}}
## Related links
- [Basic schema for a Dapr component]({{< ref component-schema >}})
- Read [this guide]({{< ref "howto-publish-subscribe.md#step-2-publish-a-topic" >}}) for instructions on configuring pub/sub components
- [Pub/Sub building block]({{< ref pubsub >}})
- [JetStream Documentation](https://docs.nats.io/jetstream/jetstream)
- [NATS CLI](https://github.com/nats-io/natscli)
[Durable Name]: https://docs.nats.io/jetstream/concepts/consumers#durable-name
[Start Sequence]: https://docs.nats.io/jetstream/concepts/consumers#deliverbystartsequence
[Start Time]: https://docs.nats.io/jetstream/concepts/consumers#deliverbystarttime
[Replay Policy]: https://docs.nats.io/jetstream/concepts/consumers#replaypolicy
[Flow Control]: https://docs.nats.io/jetstream/concepts/consumers#flowcontrol

View File

@ -54,6 +54,11 @@ spec:
The above example uses secrets as plain strings. It is recommended to use a secret store for the secrets as described [here]({{< ref component-secrets.md >}}).
{{% /alert %}}
{{% alert title="Warning" color="warning" %}}
NATS Streaming has been [deprecated](https://github.com/nats-io/nats-streaming-server/#warning--deprecation-notice-warning).
Please consider using [NATS JetStream]({{< ref setup-jetstream >}}) going forward.
{{% /alert %}}
## Spec metadata fields
| Field | Required | Details | Example |
@ -111,3 +116,4 @@ For example, if installing using the example above, the NATS Streaming address w
- [Basic schema for a Dapr component]({{< ref component-schema >}})
- Read [this guide]({{< ref "howto-publish-subscribe.md#step-2-publish-a-topic" >}}) for instructions on configuring pub/sub components
- [Pub/Sub building block]({{< ref pubsub >}})
- [NATS Streaming Deprecation Notice](https://github.com/nats-io/nats-streaming-server/#warning--deprecation-notice-warning)

View File

@ -41,6 +41,7 @@ The above example uses secrets as plain strings. It is recommended to use a secr
|--------------------|:--------:|---------|---------|
| redisHost | Y | Connection-string for the redis host. If `"redisType"` is `"cluster"` it can be multiple hosts separated by commas or just a single host | `localhost:6379`, `redis-master.default.svc.cluster.local:6379`
| redisPassword | Y | Password for Redis host. No Default. Can be `secretKeyRef` to use a secret reference | `""`, `"KeFg23!"`
| redisUsername | N | Username for Redis host. Defaults to empty. Make sure your redis server version is 6 or above, and have created acl rule correctly. | `""`, `"default"`
| consumerID | N | The consumer group ID | `"myGroup"`
| enableTLS | N | If the Redis instance supports TLS with public certificates, can be configured to be enabled or disabled. Defaults to `"false"` | `"true"`, `"false"`
| redeliverInterval | N | The interval between checking for pending messages to redelivery. Defaults to `"60s"`. `"0"` disables redelivery. | `"30s"`

View File

@ -45,5 +45,4 @@ Table captions:
| Name | Status | Component version | Since |
|---------------------------------------------------------------------------------------|--------| ---- |--------------|
| [Azure Key Vault w/ Managed Identity]({{< ref azure-keyvault-managed-identity.md >}}) | Alpha | v1 | 1.0 |
| [Azure Key Vault]({{< ref azure-keyvault.md >}}) | GA | v1 | 1.0 |

View File

@ -1,167 +0,0 @@
---
type: docs
title: "Azure Key Vault with Managed Identities on Kubernetes"
linkTitle: "Azure Key Vault w/ Managed Identity"
description: How to configure Azure Key Vault and Kubernetes to use Azure Managed Identities to access secrets
aliases:
- "/operations/components/setup-secret-store/supported-secret-stores/azure-keyvault-managed-identity/"
---
## Component format
To setup Azure Key Vault secret store with Managed Identies create a component of type `secretstores.azure.keyvault`. See [this guide]({{< ref "setup-secret-store.md#apply-the-configuration" >}}) on how to create and apply a secretstore configuration. See this guide on [referencing secrets]({{< ref component-secrets.md >}}) to retrieve and use the secret with Dapr components.
In Kubernetes mode, you store the certificate for the service principal into the Kubernetes Secret Store and then enable Azure Key Vault secret store with this certificate in Kubernetes secretstore.
The component yaml uses the name of your key vault and the Client ID of the managed identity to setup the secret store.
```yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: azurekeyvault
namespace: default
spec:
type: secretstores.azure.keyvault
version: v1
metadata:
- name: vaultName
value: [your_keyvault_name]
- name: spnClientId
value: [your_managed_identity_client_id]
```
{{% alert title="Warning" color="warning" %}}
The above example uses secrets as plain strings. It is recommended to use a local secret store such as [Kubernetes secret store]({{< ref kubernetes-secret-store.md >}}) or a [local file]({{< ref file-secret-store.md >}}) to bootstrap secure key storage.
{{% /alert %}}
## Spec metadata fields
| Field | Required | Details | Example |
|--------------------|:--------:|-------------------------------------------------------------------------|---------------------|
| vaultName | Y | The name of the Azure Key Vault | `"mykeyvault"` |
| spnClientId | Y | Your managed identity client Id | `"yourId"` |
## Setup Managed Identity and Azure Key Vault
### Prerequisites
- [Azure Subscription](https://azure.microsoft.com/en-us/free/)
- [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest)
### Steps
1. Login to Azure and set the default subscription
```bash
# Log in Azure
az login
# Set your subscription to the default subscription
az account set -s [your subscription id]
```
2. Create an Azure Key Vault in a region
```bash
az keyvault create --location [region] --name [your keyvault] --resource-group [your resource group]
```
3. Create the managed identity(Optional)
This step is required only if the AKS Cluster is provisoned without the flag "--enable-managed-identity". If the cluster is provisioned with managed identity, than it is suggested to use the autogenerated managed identity that is associated to the Resource Group MC_*.
```bash
$identity = az identity create -g [your resource group] -n [your managed identity name] -o json | ConvertFrom-Json
```
Below is the command to retrieve the managed identity in the autogenerated scenario:
```bash
az aks show -g <AKSResourceGroup> -n <AKSClusterName>
```
For more detail about the roles to assign to integrate AKS with Azure Services [Role Assignment](https://azure.github.io/aad-pod-identity/docs/getting-started/role-assignment/).
4. Retrieve Managed Identity ID
The two main scenario are:
- Service Principal, in this case the Resource Group is the one in which is deployed the AKS Service Cluster
```bash
$clientId= az aks show -g <AKSResourceGroup> -n <AKSClusterName> --query servicePrincipalProfile.clientId -otsv
```
- Managed Identity, in this case the Resource Group is the one in which is deployed the AKS Service Cluster
```bash
$clientId= az aks show -g <AKSResourceGroup> -n <AKSClusterName> --query identityProfile.kubeletidentity.clientId -otsv
```
5. Assign the Reader role to the managed identity
For AKS cluster, the cluster resource group refers to the resource group with a MC_ prefix, which contains all of the infrastructure resources associated with the cluster like VM/VMSS.
```bash
az role assignment create --role "Reader" --assignee $clientId --scope /subscriptions/[your subscription id]/resourcegroups/[your resource group]
```
6. Assign the Managed Identity Operator role to the AKS Service Principal
Refer to previous step about the Resource Group to use and which identity to assign
```bash
az role assignment create --role "Managed Identity Operator" --assignee $clientId --scope /subscriptions/[your subscription id]/resourcegroups/[your resource group]
az role assignment create --role "Virtual Machine Contributor" --assignee $clientId --scope /subscriptions/[your subscription id]/resourcegroups/[your resource group]
```
7. Add a policy to the Key Vault so the managed identity can read secrets
```bash
az keyvault set-policy --name [your keyvault] --spn $clientId --secret-permissions get list
```
8. Enable AAD Pod Identity on AKS
```bash
kubectl apply -f https://raw.githubusercontent.com/Azure/aad-pod-identity/master/deploy/infra/deployment-rbac.yaml
# For AKS clusters, deploy the MIC and AKS add-on exception by running -
kubectl apply -f https://raw.githubusercontent.com/Azure/aad-pod-identity/master/deploy/infra/mic-exception.yaml
```
9. Configure the Azure Identity and AzureIdentityBinding yaml
Save the following yaml as azure-identity-config.yaml:
```yaml
apiVersion: "aadpodidentity.k8s.io/v1"
kind: AzureIdentity
metadata:
name: [your managed identity name]
spec:
type: 0
resourceID: [your managed identity id]
clientID: [your managed identity Client ID]
---
apiVersion: "aadpodidentity.k8s.io/v1"
kind: AzureIdentityBinding
metadata:
name: [your managed identity name]-identity-binding
spec:
azureIdentity: [your managed identity name]
selector: [your managed identity selector]
```
10. Deploy the azure-identity-config.yaml:
```yaml
kubectl apply -f azure-identity-config.yaml
```
## References
- [Azure CLI Keyvault CLI](https://docs.microsoft.com/en-us/cli/azure/keyvault?view=azure-cli-latest#az-keyvault-create)
- [Create an Azure service principal with Azure CLI](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli?view=azure-cli-latest)
- [AAD Pod Identity](https://github.com/Azure/aad-pod-identity)
- [Secrets building block]({{< ref secrets >}})
- [How-To: Retrieve a secret]({{< ref "howto-secrets.md" >}})
- [How-To: Reference secrets in Dapr components]({{< ref component-secrets.md >}})
- [Secrets API reference]({{< ref secrets_api.md >}})

View File

@ -7,10 +7,6 @@ aliases:
- "/operations/components/setup-secret-store/supported-secret-stores/azure-keyvault/"
---
{{% alert title="Note" color="primary" %}}
Azure Managed Identity can be used for Azure Key Vault access on Kubernetes. Instructions [here]({{< ref azure-keyvault-managed-identity.md >}}).
{{% /alert %}}
## Component format
To setup Azure Key Vault secret store create a component of type `secretstores.azure.keyvault`. See [this guide]({{< ref "setup-secret-store.md#apply-the-configuration" >}}) on how to create and apply a secretstore configuration. See this guide on [referencing secrets]({{< ref component-secrets.md >}}) to retrieve and use the secret with Dapr components.
@ -37,158 +33,91 @@ spec:
- name: spnCertificateFile
value : "[pfx_certificate_file_fully_qualified_local_path]"
```
{{% alert title="Warning" color="warning" %}}
The above example uses secrets as plain strings. It is recommended to use a local secret store such as [Kubernetes secret store]({{< ref kubernetes-secret-store.md >}}) or a [local file]({{< ref file-secret-store.md >}}) to bootstrap secure key storage.
{{% /alert %}}
## Spec metadata fields
## Authenticating with Azure AD
### Self-Hosted
The Azure Key Vault secret store component supports authentication with Azure AD only. Before you enable this component, make sure you've read the [Authenticating to Azure]({{< ref authenticating-azure.md >}}) document and created an Azure AD application (also called Service Principal). Alternatively, make sure you have created a managed identity for your application platform.
## Spec metadata fields
| Field | Required | Details | Example |
|--------------------|:--------:|---------|---------|
| vaultName | Y | The name of the Azure Key Vault. If you only provide a name, it will covert to `[your_keyvault_name].vault.azure.net` in Dapr. If your URL uses another suffix, please provide the entire URI, such as `test.vault.azure.cn`. | `"mykeyvault"`, `"mykeyvault.value.azure.cn"`
| spnTenantId | Y | Service Principal Tenant Id | `"spnTenantId"`
| spnClientId | Y | Service Principal App Id | `"spnAppId"`
| spnCertificateFile | Y | PFX certificate file path. <br></br> For Windows the `[pfx_certificate_file_fully_qualified_local_path]` value must use escaped backslashes, i.e. double backslashes. For example `"C:\\folder1\\folder2\\certfile.pfx"`. <br></br> For Linux you can use single slashes. For example `"/folder1/folder2/certfile.pfx"`. <br></br> See [configure the component](#configure-the-component) for more details | `"C:\\folder1\\folder2\\certfile.pfx"`, `"/folder1/folder2/certfile.pfx"`
| `vaultName` | Y | The name of the Azure Key Vault | `"mykeyvault"` |
| `azureEnvironment` | N | Optional name for the Azure environment if using a different Azure cloud | `"AZUREPUBLICCLOUD"` (default value), `"AZURECHINACLOUD"`, `"AZUREUSGOVERNMENTCLOUD"`, `"AZUREGERMANCLOUD"` |
Additionally, you must provide the authentication fields as explained in the [Authenticating to Azure]({{< ref authenticating-azure.md >}}) document.
### Kubernetes
| Field | Required | Details | Example |
|----------------|:--------:|---------|---------|
| vaultName | Y | The name of the Azure Key Vault | `"mykeyvault"`
| spnTenantId | Y | Service Principal Tenant Id | `"spnTenantId"`
| spnClientId | Y | Service Principal App Id | `"spnAppId"`
| spnCertificate | Y | PKCS 12 encoded bytes of the certificate. See [configure the component](#configure-the-component) for details on encoding this in a Kubernetes secret. | `secretKeyRef: ...` <br /> See [configure the component](#configure-the-component) for more information.
## Setup Key Vault and service principal
## Create the Azure Key Vault and authorize the Service Principal
### Prerequisites
- [Azure Subscription](https://azure.microsoft.com/en-us/free/)
- [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest)
- [Azure Subscription](https://azure.microsoft.com/free/)
- [Azure CLI](https://docs.microsoft.com/cli/azure/install-azure-cli)
- [jq](https://stedolan.github.io/jq/download/)
- The scripts below are optimized for a bash or zsh shell
Make sure you have followed the steps in the [Authenticating to Azure]({{< ref authenticating-azure.md >}}) document to create an Azure AD application (also called Service Principal). You will need the following values:
- `SERVICE_PRINCIPAL_ID`: the ID of the Service Principal that you created for a given application
### Steps
1. Login to Azure and set the default subscription
1. Set a variable with the Service Principal that you created:
```bash
# Log in Azure
az login
```sh
SERVICE_PRINCIPAL_ID="[your_service_principal_object_id]"
```
# Set your subscription to the default subscription
az account set -s [your subscription id]
```
2. Set a variable with the location where to create all resources:
2. Create an Azure Key Vault in a region
```sh
LOCATION="[your_location]"
```
```bash
az keyvault create --location [region] --name [your_keyvault] --resource-group [your resource group]
```
(You can get the full list of options with: `az account list-locations --output tsv`)
3. Create a service principal
3. Create a Resource Group, giving it any name you'd like:
Create a service principal with a new certificate and store the 1-year certificate inside your keyvault's certificate vault. You can skip this step if you want to use an existing service principal for keyvault instead of creating new one
```sh
RG_NAME="[resource_group_name]"
RG_ID=$(az group create \
--name "${RG_NAME}" \
--location "${LOCATION}" \
| jq -r .id)
```
```bash
az ad sp create-for-rbac --name [your_service_principal_name] --create-cert --cert [certificate_name] --keyvault [your_keyvault] --skip-assignment --years 1
4. Create an Azure Key Vault (that uses Azure RBAC for authorization):
{
"appId": "a4f90000-0000-0000-0000-00000011d000",
"displayName": "[your_service_principal_name]",
"name": "http://[your_service_principal_name]",
"password": null,
"tenant": "34f90000-0000-0000-0000-00000011d000"
}
```
```sh
KEYVAULT_NAME="[key_vault_name]"
az keyvault create \
--name "${KEYVAULT_NAME}" \
--enable-rbac-authorization true \
--resource-group "${RG_NAME}" \
--location "${LOCATION}"
```
**Save both the appId and tenant from the output which will be used in the next step**
5. Using RBAC, assign a role to the Azure AD application so it can access the Key Vault.
In this case, assign the "Key Vault Crypto Officer" role, which has broad access; other more restrictive roles can be used as well, depending on your application.
4. Get the Object Id for [your_service_principal_name]
```bash
az ad sp show --id [service_principal_app_id]
{
...
"objectId": "[your_service_principal_object_id]",
"objectType": "ServicePrincipal",
...
}
```
5. Grant the service principal the GET permission to your Azure Key Vault
```bash
az keyvault set-policy --name [your_keyvault] --object-id [your_service_principal_object_id] --secret-permissions get
```
Now that your service principal has access to your keyvault you are ready to configure the secret store component to use secrets stored in your keyvault to access other components securely.
6. Download the certificate in PFX format from your Azure Key Vault either using the Azure portal or the Azure CLI:
- **Using the Azure portal:**
Go to your key vault on the Azure portal and navigate to the *Certificates* tab under *Settings*. Find the certificate that was created during the service principal creation, named [certificate_name] and click on it.
Click *Download in PFX/PEM format* to download the certificate.
- **Using the Azure CLI:**
```bash
az keyvault secret download --vault-name [your_keyvault] --name [certificate_name] --encoding base64 --file [certificate_name].pfx
```
```sh
az role assignment create \
--assignee "${SERVICE_PRINCIPAL_ID}" \
--role "Key Vault Crypto Officer" \
--scope "${RG_ID}/providers/Microsoft.KeyVault/vaults/${KEYVAULT_NAME}"
```
## Configure the component
{{< tabs "Self-Hosted" "Kubernetes">}}
{{% codetab %}}
1. Copy downloaded PFX cert from your Azure Keyvault into your components directory or a secure location on your local disk
2. Create a file called `azurekeyvault.yaml` in the components directory
```yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: azurekeyvault
namespace: default
spec:
type: secretstores.azure.keyvault
version: v1
metadata:
- name: vaultName
value: [your_keyvault_name]
- name: spnTenantId
value: "[your_service_principal_tenant_id]"
- name: spnClientId
value: "[your_service_principal_app_id]"
- name: spnCertificateFile
value : "[pfx_certificate_file_fully_qualified_local_path]"
```
Fill in the metadata fields with your Key Vault details from the above setup process.
{{% /codetab %}}
{{% codetab %}}
In Kubernetes, you store the certificate for the service principal into the Kubernetes Secret Store and then enable Azure Key Vault secret store with this certificate in Kubernetes secretstore.
1. Create a kubernetes secret using the following command:
```bash
kubectl create secret generic [your_k8s_spn_secret_name] --from-file=[your_k8s_spn_secret_key]=[pfx_certificate_file_fully_qualified_local_path]
```
- `[pfx_certificate_file_fully_qualified_local_path]` is the path of PFX cert file you downloaded above
- `[your_k8s_spn_secret_name]` is secret name in Kubernetes secret store
- `[your_k8s_spn_secret_key]` is secret key in Kubernetes secret store
2. Create a `azurekeyvault.yaml` component file
The component yaml refers to the Kubernetes secretstore using `auth` property and `secretKeyRef` refers to the certificate stored in Kubernetes secret store.
To use a **client secret**, create a file called `azurekeyvault.yaml` in the components directory, filling in with the Azure AD application that you created following the [Authenticating to Azure]({{< ref authenticating-azure.md >}}) document:
```yaml
apiVersion: dapr.io/v1alpha1
@ -201,32 +130,142 @@ spec:
version: v1
metadata:
- name: vaultName
value: [your_keyvault_name]
- name: spnTenantId
value: "[your_service_principal_tenant_id]"
- name: spnClientId
value: "[your_service_principal_app_id]"
- name: spnCertificate
secretKeyRef:
name: [your_k8s_spn_secret_name]
key: [your_k8s_spn_secret_key]
auth:
secretStore: kubernetes
value: "[your_keyvault_name]"
- name: azureTenantId
value: "[your_tenant_id]"
- name: azureClientId
value: "[your_client_id]"
- name: azureClientSecret
value : "[your_client_secret]"
```
3. Apply `azurekeyvault.yaml` component
If you want to use a **certificate** saved on the local disk, instead, use this template, filling in with details of the Azure AD application that you created following the [Authenticating to Azure]({{< ref authenticating-azure.md >}}) document:
```bash
kubectl apply -f azurekeyvault.yaml
```yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: azurekeyvault
namespace: default
spec:
type: secretstores.azure.keyvault
version: v1
metadata:
- name: vaultName
value: "[your_keyvault_name]"
- name: azureTenantId
value: "[your_tenant_id]"
- name: azureClientId
value: "[your_client_id]"
- name: azureCertificateFile
value : "[pfx_certificate_file_fully_qualified_local_path]"
```
{{% /codetab %}}
{{% codetab %}}
In Kubernetes, you store the client secret or the certificate into the Kubernetes Secret Store and then refer to those in the YAML file. You will need the details of the Azure AD application that was created following the [Authenticating to Azure]({{< ref authenticating-azure.md >}}) document.
To use a **client secret**:
1. Create a Kubernetes secret using the following command:
```bash
kubectl create secret generic [your_k8s_secret_name] --from-literal=[your_k8s_secret_key]=[your_client_secret]
```
- `[your_client_secret]` is the application's client secret as generated above
- `[your_k8s_secret_name]` is secret name in the Kubernetes secret store
- `[your_k8s_secret_key]` is secret key in the Kubernetes secret store
2. Create an `azurekeyvault.yaml` component file.
The component yaml refers to the Kubernetes secretstore using `auth` property and `secretKeyRef` refers to the client secret stored in the Kubernetes secret store.
```yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: azurekeyvault
namespace: default
spec:
type: secretstores.azure.keyvault
version: v1
metadata:
- name: vaultName
value: "[your_keyvault_name]"
- name: azureTenantId
value: "[your_tenant_id]"
- name: azureClientId
value: "[your_client_id]"
- name: azureClientSecret
secretKeyRef:
name: "[your_k8s_secret_name]"
key: "[your_k8s_secret_key]"
auth:
secretStore: kubernetes
```
3. Apply the `azurekeyvault.yaml` component:
```bash
kubectl apply -f azurekeyvault.yaml
```
To use a **certificate**:
1. Create a Kubernetes secret using the following command:
```bash
kubectl create secret generic [your_k8s_secret_name] --from-file=[your_k8s_secret_key]=[pfx_certificate_file_fully_qualified_local_path]
```
- `[pfx_certificate_file_fully_qualified_local_path]` is the path of PFX file you obtained earlier
- `[your_k8s_secret_name]` is secret name in the Kubernetes secret store
- `[your_k8s_secret_key]` is secret key in the Kubernetes secret store
2. Create an `azurekeyvault.yaml` component file.
The component yaml refers to the Kubernetes secretstore using `auth` property and `secretKeyRef` refers to the certificate stored in the Kubernetes secret store.
```yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: azurekeyvault
namespace: default
spec:
type: secretstores.azure.keyvault
version: v1
metadata:
- name: vaultName
value: "[your_keyvault_name]"
- name: azureTenantId
value: "[your_tenant_id]"
- name: azureClientId
value: "[your_client_id]"
- name: azureCertificate
secretKeyRef:
name: "[your_k8s_secret_name]"
key: "[your_k8s_secret_key]"
auth:
secretStore: kubernetes
```
3. Apply the `azurekeyvault.yaml` component:
```bash
kubectl apply -f azurekeyvault.yaml
```
{{% /codetab %}}
{{< /tabs >}}
## References
- [Azure CLI Keyvault CLI](https://docs.microsoft.com/en-us/cli/azure/keyvault?view=azure-cli-latest#az-keyvault-create)
- [Create an Azure service principal with Azure CLI](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli?view=azure-cli-latest)
- [Authenticating to Azure]({{< ref authenticating-azure.md >}})
- [Azure CLI: keyvault commands](https://docs.microsoft.com/en-us/cli/azure/keyvault?view=azure-cli-latest#az-keyvault-create)
- [Secrets building block]({{< ref secrets >}})
- [How-To: Retrieve a secret]({{< ref "howto-secrets.md" >}})
- [How-To: Reference secrets in Dapr components]({{< ref component-secrets.md >}})

View File

@ -31,6 +31,8 @@ spec:
value: [path to the JSON file]
- name: nestedSeparator
value: ":"
- name: multiValued
value: "false"
```
## Spec metadata fields
@ -38,11 +40,12 @@ spec:
| Field | Required | Details | Example |
|--------------------|:--------:|-------------------------------------------------------------------------|--------------------------|
| secretsFile | Y | The path to the file where secrets are stored | `"path/to/file.json"` |
| nestedSeparator | N | Used by the store when flattening the JSON hierarchy to a map. Defaults to `":"` | `":"` |
| nestedSeparator | N | Used by the store when flattening the JSON hierarchy to a map. Defaults to `":"` | `":"`
| multiValued | N | Allows one level of multi-valued key/value pairs before flattening JSON hierarchy. Defaults to `"false"` | `"true"` |
## Setup JSON file to hold the secrets
Given the following json:
Given the following JSON loaded from `secretsFile`:
```json
{
@ -54,7 +57,7 @@ Given the following json:
}
```
The store will load the file and create a map with the following key value pairs:
If `multiValued` is `"false"`, the store will load the file and create a map with the following key value pairs:
| flattened key | value |
| --- | --- |
@ -62,7 +65,49 @@ The store will load the file and create a map with the following key value pairs
|"connectionStrings:sql" | "your sql connection string" |
|"connectionStrings:mysql"| "your mysql connection string" |
Use the flattened key (`connectionStrings:sql`) to access the secret.
Use the flattened key (`connectionStrings:sql`) to access the secret. The following JSON map returned:
```json
{
"connectionStrings:sql": "your sql connection string"
}
```
If `multiValued` is `"true"`, you would instead use the top level key. In this example, `connectionStrings` would return the following map:
```json
{
"sql": "your sql connection string",
"mysql": "your mysql connection string"
}
```
Nested structures after the top level will be flattened. In this example, `connectionStrings` would return the following map:
JSON from `secretsFile`:
```json
{
"redisPassword": "your redis password",
"connectionStrings": {
"mysql": {
"username": "your mysql username",
"password": "your mysql password"
}
}
}
```
Response:
```json
{
"mysql:username": "your mysql username",
"mysql:password": "your mysql password"
}
```
This is useful in order to mimic secret stores like Vault or Kubernetes that return multiple key/value pairs per secret key.
## Related links
- [Secrets building block]({{< ref secrets >}})

View File

@ -9,8 +9,7 @@ aliases:
## Component format
To setup Azure Blobstorage state store create a component of type `state.azure.blobstorage`. See [this guide]({{< ref "howto-get-save-state.md#step-1-setup-a-state-store" >}}) on how to create and apply a state store configuration.
To setup the Azure Blob Storage state store create a component of type `state.azure.blobstorage`. See [this guide]({{< ref "howto-get-save-state.md#step-1-setup-a-state-store" >}}) on how to create and apply a state store configuration.
```yaml
apiVersion: dapr.io/v1alpha1
@ -23,42 +22,105 @@ spec:
version: v1
metadata:
- name: accountName
value: <REPLACE-WITH-ACCOUNT-NAME>
value: "[your_account_name]"
- name: accountKey
value: <REPLACE-WITH-ACCOUNT-KEY>
value: "[your_account_key]"
- name: containerName
value: <REPLACE-WITH-CONTAINER-NAME>
value: "[your_container_name]"
```
{{% alert title="Warning" color="warning" %}}
The above example uses secrets as plain strings. It is recommended to use a secret store for the secrets as described [here]({{< ref component-secrets.md >}}).
{{% /alert %}}
## Spec metadata fields
| Field | Required | Details | Example |
|--------------------|:--------:|---------|---------|
| accountName | Y | The storage account name | `"mystorageaccount"`.
| accountKey | Y | Primary or secondary storage key | `"key"`
| accountKey | Y (unless using Azure AD) | Primary or secondary storage key | `"key"`
| containerName | Y | The name of the container to be used for Dapr state. The container will be created for you if it doesn't exist | `"container"`
| ContentType | N | The blobs content type | `"text/plain"`
| `azureEnvironment` | N | Optional name for the Azure environment if using a different Azure cloud | `"AZUREPUBLICCLOUD"` (default value), `"AZURECHINACLOUD"`, `"AZUREUSGOVERNMENTCLOUD"`, `"AZUREGERMANCLOUD"`
| ContentType | N | The blob's content type | `"text/plain"`
| ContentMD5 | N | The blob's MD5 hash | `"vZGKbMRDAnMs4BIwlXaRvQ=="`
| ContentEncoding | N | The blob's content encoding | `"UTF-8"`
| ContentLanguage | N | The blob's content language | `"en-us"`
| ContentDisposition | N | The blob's content disposition. Conveys additional information about how to process the response payload | `"attachment"`
| CacheControl | N | The blob's cache control | `"no-cache"`
## Setup Azure Blobstorage
## Setup Azure Blob Storage
[Follow the instructions](https://docs.microsoft.com/en-us/azure/storage/common/storage-account-create?tabs=azure-portal) from the Azure documentation on how to create an Azure Storage Account.
If you wish to create a container for Dapr to use, you can do so beforehand. However, Blob Storage state provider will create one for you automatically if it doesn't exist.
If you wish to create a container for Dapr to use, you can do so beforehand. However, the Blob Storage state provider will create one for you automatically if it doesn't exist.
In order to setup Azure Blob Storage as a state store, you will need the following properties:
- **AccountName**: The storage account name. For example: **mystorageaccount**.
- **AccountKey**: Primary or secondary storage key.
- **ContainerName**: The name of the container to be used for Dapr state. The container will be created for you if it doesn't exist.
- **accountName**: The storage account name. For example: **mystorageaccount**.
- **accountKey**: Primary or secondary storage account key.
- **containerName**: The name of the container to be used for Dapr state. The container will be created for you if it doesn't exist.
### Authenticating with Azure AD
This component supports authentication with Azure AD as an alternative to use account keys. Whenever possible, it is recommended that you use Azure AD for authentication in production systems, to take advantage of better security, fine-tuned access control, and the ability to use managed identities for apps running on Azure.
> The following scripts are optimized for a bash or zsh shell and require the following apps installed:
>
> - [Azure CLI](https://docs.microsoft.com/cli/azure/install-azure-cli)
> - [jq](https://stedolan.github.io/jq/download/)
>
> You must also be authenticated with Azure in your Azure CLI.
1. To get started with using Azure AD for authenticating the Blob Storage state store component, make sure you've created an Azure AD application and a Service Principal as explained in the [Authenticating to Azure]({{< ref authenticating-azure.md >}}) document.
Once done, set a variable with the ID of the Service Principal that you created:
```sh
SERVICE_PRINCIPAL_ID="[your_service_principal_object_id]"
```
2. Set the following variables with the name of your Azure Storage Account and the name of the Resource Group where it's located:
```sh
STORAGE_ACCOUNT_NAME="[your_storage_account_name]"
RG_NAME="[your_resource_group_name]"
```
3. Using RBAC, assign a role to our Service Principal so it can access data inside the Storage Account.
In this case, you are assigning the "Storage blob Data Contributor" role, which has broad access; other more restrictive roles can be used as well, depending on your application.
```sh
RG_ID=$(az group show --resource-group ${RG_NAME} | jq -r ".id")
az role assignment create \
--assignee "${SERVICE_PRINCIPAL_ID}" \
--role "Storage blob Data Contributor" \
--scope "${RG_ID}/providers/Microsoft.Storage/storageAccounts/${STORAGE_ACCOUNT_NAME}"
```
When authenticating your component using Azure AD, the `accountKey` field is not required. Instead, please specify the required credentials in the component's metadata (if any) according to the [Authenticating to Azure]({{< ref authenticating-azure.md >}}) document.
For example:
```yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: <NAME>
namespace: <NAMESPACE>
spec:
type: state.azure.blobstorage
version: v1
metadata:
- name: accountName
value: "[your_account_name]"
- name: containerName
value: "[your_container_name]"
- name: azureTenantId
value: "[your_tenant_id]"
- name: azureClientId
value: "[your_client_id]"
- name: azureClientSecret
value : "[your_client_secret]"
```
## Apply the configuration
@ -66,16 +128,17 @@ In order to setup Azure Blob Storage as a state store, you will need the followi
To apply Azure Blob Storage state store to Kubernetes, use the `kubectl` CLI:
```
```sh
kubectl apply -f azureblob.yaml
```
### Running locally
To run locally, create a `components` dir containing the YAML file and provide the path to the `dapr run` command with the flag `--components-path`.
This state store creates a blob file in the container and puts raw state inside it.
For example, the following operation coming from service called `myservice`
For example, the following operation coming from service called `myservice`:
```shell
curl -X POST http://localhost:3500/v1.0/state \
@ -88,13 +151,14 @@ curl -X POST http://localhost:3500/v1.0/state \
]'
```
creates the blob file in the containter with `key` as filename and `value` as the contents of file.
This creates the blob file in the container with `key` as filename and `value` as the contents of file.
## Concurrency
Azure Blob Storage state concurrency is achieved by using `ETag`s according to [the Azure Blob Storage documentation](https://docs.microsoft.com/en-us/azure/storage/common/storage-concurrency#managing-concurrency-in-blob-storage).
## Related links
- [Basic schema for a Dapr component]({{< ref component-schema >}})
- Read [this guide]({{< ref "howto-get-save-state.md#step-2-save-and-retrieve-a-single-state" >}}) for instructions on configuring state store components
- [State management building block]({{< ref state-management >}})

View File

@ -39,6 +39,10 @@ spec:
The above example uses secrets as plain strings. It is recommended to use a secret store for the secrets as described [here]({{< ref component-secrets.md >}}).
{{% /alert %}}
## Primary Key
In order to use DynamoDB as a Dapr state store, the table must have a primary key named `key`.
## Spec metadata fields
| Field | Required | Details | Example |

View File

@ -35,6 +35,8 @@ spec:
value: # Optional
- name: maxRetryBackoff
value: # Optional
- name: ttlInSeconds
value: <int> # Optional
```
**TLS:** If the Redis instance supports TLS with public certificates it can be configured to enable or disable TLS `true` or `false`.
@ -58,6 +60,7 @@ If you wish to use Redis as an actor store, append the following to the yaml.
|--------------------|:--------:|---------|---------|
| redisHost | Y | Connection-string for the redis host | `localhost:6379`, `redis-master.default.svc.cluster.local:6379`
| redisPassword | Y | Password for Redis host. No Default. Can be `secretKeyRef` to use a secret reference | `""`, `"KeFg23!"`
| redisUsername | N | Username for Redis host. Defaults to empty. Make sure your redis server version is 6 or above, and have created acl rule correctly. | `""`, `"default"`
| consumerID | N | The consumer group ID | `"myGroup"`
| enableTLS | N | If the Redis instance supports TLS with public certificates, can be configured to be enabled or disabled. Defaults to `"false"` | `"true"`, `"false"`
| maxRetries | N | Maximum number of retries before giving up. Defaults to `3` | `5`, `10`
@ -81,6 +84,7 @@ If you wish to use Redis as an actor store, append the following to the yaml.
| idleCheckFrequency | N | Frequency of idle checks made by idle connections reaper. Default is `"1m"`. `"-1"` disables idle connections reaper. | `"-1"`
| idleTimeout | N | Amount of time after which the client closes idle connections. Should be less than server's timeout. Default is `"5m"`. `"-1"` disables idle timeout check. | `"10m"`
| actorStateStore | N | Consider this state store for actors. Defaults to `"false"` | `"true"`, `"false"`
| ttlInSeconds | N | Allows specifying a default Time-to-live (TTL) in seconds that will be applied to every state store request unless TTL is explicitly defined via the [request metadata]({{< ref "state-store-ttl.md" >}}). | `600`
## Setup Redis

View File

@ -25,7 +25,7 @@ spec:
- name: connectionString
value: <REPLACE-WITH-CONNECTION-STRING> # Required.
- name: tableName
value: <REPLACE-WITH-TABLE-NAME> # Required.
value: <REPLACE-WITH-TABLE-NAME> # Optional. defaults to "state"
- name: keyType
value: <REPLACE-WITH-KEY-TYPE> # Optional. defaults to "string"
- name: keyLength
@ -41,7 +41,7 @@ spec:
The above example uses secrets as plain strings. It is recommended to use a secret store for the secrets as described [here]({{< ref component-secrets.md >}}).
{{% /alert %}}
If you wish to use Redis as an [actor state store]({{< ref "state_api.md#configuring-state-store-for-actors" >}}), append the following to the yaml.
If you wish to use SQL server as an [actor state store]({{< ref "state_api.md#configuring-state-store-for-actors" >}}), append the following to the yaml.
```yaml
- name: actorStateStore
@ -52,8 +52,8 @@ If you wish to use Redis as an [actor state store]({{< ref "state_api.md#configu
| Field | Required | Details | Example |
|--------------------|:--------:|---------|---------|
| connectionString | Y | The connection string used to connect | `"Server=myServerName\myInstanceName;Database=myDataBase;User Id=myUsername;Password=myPassword;"`
| tableName | Y | The name of the table to use. Alpha-numeric with underscores | `"table_name"`
| connectionString | Y | The connection string used to connect. If the connection string contains the database it must already exist. If the database is omitted a default database named `"Dapr"` is created. | `"Server=myServerName\myInstanceName;Database=myDataBase;User Id=myUsername;Password=myPassword;"`
| tableName | N | The name of the table to use. Alpha-numeric with underscores. Defaults to `"state"` | `"table_name"`
| keyType | N | The type of key used. Defaults to `"string"` | `"string"`
| keyLength | N | The max length of key. Used along with `"string"` keytype. Defaults to `"200"` | `"200"`
| schema | N | The schema to use. Defaults to `"dbo"` | `"dapr"`,`"dbo"`
@ -69,7 +69,7 @@ If you wish to use Redis as an [actor state store]({{< ref "state_api.md#configu
In order to setup SQL Server as a state store, you need the following properties:
- **Connection String**: the SQL Server connection string. For example: server=localhost;user id=sa;password=your-password;port=1433;database=mydatabase;
- **Connection String**: The SQL Server connection string. For example: server=localhost;user id=sa;password=your-password;port=1433;database=mydatabase;
- **Schema**: The database schema to use (default=dbo). Will be created if does not exist
- **Table Name**: The database table name. Will be created if does not exist
- **Indexed Properties**: Optional properties from json data which will be indexed and persisted as individual column

View File

@ -0,0 +1,62 @@
<style>
.feedback--title {
margin-top: 3rem;
}
.feedback--answer {
display: inline-block;
}
.feedback--answer-no {
margin-left: 1em;
}
.feedback--response {
display: none;
margin-top: 1em;
}
.feedback--response__visible {
display: block;
}
</style>
<div class="d-print-none">
<h2 class="feedback--title">Feedback</h2>
<p class="feedback--question">Was this page helpful?</p>
<button class="btn btn-primary mb-4 feedback--answer feedback--answer-yes">Yes</button>
<button class="btn btn-primary mb-4 feedback--answer feedback--answer-no">No</button>
<p class="feedback--response feedback--response-yes">
{{ .yes | safeHTML }}
</p>
<p class="feedback--response feedback--response-no">
{{ .no | safeHTML }}
</p>
</div>
<script>
const yesButton = document.querySelector('.feedback--answer-yes');
const noButton = document.querySelector('.feedback--answer-no');
const yesResponse = document.querySelector('.feedback--response-yes');
const noResponse = document.querySelector('.feedback--response-no');
const disableButtons = () => {
yesButton.disabled = true;
noButton.disabled = true;
};
const sendFeedback = (value) => {
if (typeof ga !== 'function') return;
const args = {
command: 'send',
hitType: 'event',
category: 'Helpful',
action: 'click',
label: window.location.pathname,
value: value
};
ga(args.command, args.hitType, args.category, args.action, args.label, args.value);
};
yesButton.addEventListener('click', () => {
yesResponse.classList.add('feedback--response__visible');
disableButtons();
sendFeedback(1);
});
noButton.addEventListener('click', () => {
noResponse.classList.add('feedback--response__visible');
disableButtons();
sendFeedback(0);
});
</script>

View File

@ -0,0 +1 @@
{{- if .Get "short" }}1.4{{ else if .Get "long" }}1.4.3{{ else if .Get "cli" }}1.4.0{{ else }}1.4.3{{ end -}}

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

@ -0,0 +1,6 @@
{
"globalHeaders": {
"X-Frame-Options": "DENY"
}
}

1
sdkdocs/js Submodule

@ -0,0 +1 @@
Subproject commit 1e23f32eafdebe571db6e19717cf5317f09a5402