From d34ca506b0003143d6e101dd04340495785e4a00 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Wed, 25 Jan 2023 19:54:18 -0600 Subject: [PATCH 01/38] start dapr run -f docs Signed-off-by: Hannah Hunter --- .../local-development/multi-app-dapr-run.md | 71 ++++++++++++++++++ .../support/support-preview-features.md | 1 + .../static/images/multi-app-structure.png | Bin 0 -> 13627 bytes 3 files changed, 72 insertions(+) create mode 100644 daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run.md create mode 100644 daprdocs/static/images/multi-app-structure.png diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run.md new file mode 100644 index 000000000..0006debd9 --- /dev/null +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run.md @@ -0,0 +1,71 @@ +--- +type: docs +title: Run multiple applications with one command +linkTitle: Multi-app Dapr Run +weight: 2000 +description: Learn the scenarios around running multiple applications with one Dapr command +--- + +{{% alert title="Note" color="primary" %}} + Multi-app `dapr run` is currently a preview feature only supported in Linux/MacOS. +{{% /alert %}} + +Let's say you want to run several applications in local mode while being able to replication the production scenario. While in Kubernets mode, you'd be able to use helm/deployment YAML files, self-hosted mode required you to: + +- Run multiple `dapr run` commands +- Keep track of all ports opened +- Remember the resources folders and configuration files that each application refers to +- Recall all of the additional flags you used to tweak the `dapr run` command behavior (`--app-health-check-path`, `--dapr-grpc-port`, `--unix-domain-socket`, etc.) + +With the Multi-app Dapr Run feature, you can easily start multiple Dapr applications in self-hosted mode using a single `dapr run -f` command. + +## How does it work? + +Currently, upon running [`dapr init`]({{< ref install-dapr-selfhost.md >}}), Dapr initializes in the `~/.dapr/` directory on Linux, where the default configurations and resources are stored. + +For running multiple applications, `dapr init` will initialize the following `~/.dapr/` directory structure: + + + +When developing multiple applications, each **app directory** can have a `.dapr` folder, which contains a `config.yaml` file and a `resources` directory. If the `.dapr` directory is not present within the app directory, the default `~/.dapr/resources/` and `~/.dapr/config.yaml` locations are used. + +> This change does not impact the `bin` folder, where the Dapr CLI looks for the `daprd` and `dashboard` binaries. That remains at `~/.dapr/bin/`. + +### The `config.yaml` file + +When you execute `dapr run -f`, Dapr parses the `config.yaml` file initialized with `dapr init`. The following example includes the configurations you can customize to your applications: + +```yaml + +version: 1 +common: (optional) + resources_dir: ./app/components # any dapr resources to be shared across apps + env: # any environment variable shared among apps + - DEBUG: true +apps: + - app_id: webapp ## required + app_dir: ./webapp/ ## required + resources_dir: ./webapp/components # (optional) can be default by convention too, ignore if dir is not found. + config_file: ./webapp/config.yaml # (optional) can be default by convention too, ignore if file is not found. + app_protocol: HTTP + app_port: 8080 + app_health_check_path: "/healthz" # All _ converted to - for all properties defined under daprd section + command: ["python3" "app.py"] + - app_id: backend + app_dir: ./backend/ + app_protocol: GRPC + app_port: 3000 + unix_domain_socket: "/tmp/test-socket" + env: + - DEBUG: false + command: ["./backend"] +``` + +### Precedence rules + + +## Scenario + +todo + +## Next steps \ No newline at end of file diff --git a/daprdocs/content/en/operations/support/support-preview-features.md b/daprdocs/content/en/operations/support/support-preview-features.md index 224d2e065..6b0da1ccc 100644 --- a/daprdocs/content/en/operations/support/support-preview-features.md +++ b/daprdocs/content/en/operations/support/support-preview-features.md @@ -20,3 +20,4 @@ For CLI there is no explicit opt-in, just the version that this was first made a | **App Middleware** | Allow middleware components to be executed when making service-to-service calls | N/A | [App Middleware]({{}}) | v1.9 | | **App health checks** | Allows configuring app health checks | `AppHealthCheck` | [App health checks]({{}}) | v1.9 | | **Pluggable components** | Allows creating self-hosted gRPC-based components written in any language that supports gRPC. The following component APIs are supported: State stores, Pub/sub, Bindings | N/A | [Pluggable components concept]({{}})| v1.9 | +| **Multi-app Run** | Configure multiple Dapr applications from a single configuration file and run from a single command | `dapr run -f` | [Multi-app Dapr Run]({{< ref multi-app-dapr-run.md >}}) | v1.10 | diff --git a/daprdocs/static/images/multi-app-structure.png b/daprdocs/static/images/multi-app-structure.png new file mode 100644 index 0000000000000000000000000000000000000000..e2647461a4b3c8019e0aa31954328aa6d3fd627a GIT binary patch literal 13627 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 Date: Fri, 27 Jan 2023 14:37:26 -0600 Subject: [PATCH 02/38] pull template into another file Signed-off-by: Hannah Hunter --- .../local-development/multi-app-dapr-run.md | 71 --------------- .../multi-app-dapr-run/_index.md | 7 ++ .../multi-app-dapr-run/multi-app-overview.md | 63 +++++++++++++ .../multi-app-dapr-run/multi-app-template.md | 90 +++++++++++++++++++ daprdocs/content/en/reference/cli/dapr-run.md | 1 + 5 files changed, 161 insertions(+), 71 deletions(-) delete mode 100644 daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run.md create mode 100644 daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/_index.md create mode 100644 daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md create mode 100644 daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run.md deleted file mode 100644 index 0006debd9..000000000 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -type: docs -title: Run multiple applications with one command -linkTitle: Multi-app Dapr Run -weight: 2000 -description: Learn the scenarios around running multiple applications with one Dapr command ---- - -{{% alert title="Note" color="primary" %}} - Multi-app `dapr run` is currently a preview feature only supported in Linux/MacOS. -{{% /alert %}} - -Let's say you want to run several applications in local mode while being able to replication the production scenario. While in Kubernets mode, you'd be able to use helm/deployment YAML files, self-hosted mode required you to: - -- Run multiple `dapr run` commands -- Keep track of all ports opened -- Remember the resources folders and configuration files that each application refers to -- Recall all of the additional flags you used to tweak the `dapr run` command behavior (`--app-health-check-path`, `--dapr-grpc-port`, `--unix-domain-socket`, etc.) - -With the Multi-app Dapr Run feature, you can easily start multiple Dapr applications in self-hosted mode using a single `dapr run -f` command. - -## How does it work? - -Currently, upon running [`dapr init`]({{< ref install-dapr-selfhost.md >}}), Dapr initializes in the `~/.dapr/` directory on Linux, where the default configurations and resources are stored. - -For running multiple applications, `dapr init` will initialize the following `~/.dapr/` directory structure: - - - -When developing multiple applications, each **app directory** can have a `.dapr` folder, which contains a `config.yaml` file and a `resources` directory. If the `.dapr` directory is not present within the app directory, the default `~/.dapr/resources/` and `~/.dapr/config.yaml` locations are used. - -> This change does not impact the `bin` folder, where the Dapr CLI looks for the `daprd` and `dashboard` binaries. That remains at `~/.dapr/bin/`. - -### The `config.yaml` file - -When you execute `dapr run -f`, Dapr parses the `config.yaml` file initialized with `dapr init`. The following example includes the configurations you can customize to your applications: - -```yaml - -version: 1 -common: (optional) - resources_dir: ./app/components # any dapr resources to be shared across apps - env: # any environment variable shared among apps - - DEBUG: true -apps: - - app_id: webapp ## required - app_dir: ./webapp/ ## required - resources_dir: ./webapp/components # (optional) can be default by convention too, ignore if dir is not found. - config_file: ./webapp/config.yaml # (optional) can be default by convention too, ignore if file is not found. - app_protocol: HTTP - app_port: 8080 - app_health_check_path: "/healthz" # All _ converted to - for all properties defined under daprd section - command: ["python3" "app.py"] - - app_id: backend - app_dir: ./backend/ - app_protocol: GRPC - app_port: 3000 - unix_domain_socket: "/tmp/test-socket" - env: - - DEBUG: false - command: ["./backend"] -``` - -### Precedence rules - - -## Scenario - -todo - -## Next steps \ No newline at end of file diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/_index.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/_index.md new file mode 100644 index 000000000..afbced2f8 --- /dev/null +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/_index.md @@ -0,0 +1,7 @@ +--- +type: docs +title: "Multi-app support" +linkTitle: "Multi-app support" +weight: 300 +description: "Support for running multiple Dapr applications with one command" +--- \ No newline at end of file diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md new file mode 100644 index 000000000..8af743ad3 --- /dev/null +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md @@ -0,0 +1,63 @@ +--- +type: docs +title: Run multiple applications with one command +linkTitle: Multi-app Dapr Run +weight: 1000 +description: Learn the scenarios around running multiple applications with one Dapr command +--- + +{{% alert title="Note" color="primary" %}} + Multi-app `dapr run -f` is currently a preview feature only supported in Linux/MacOS. +{{% /alert %}} + +Let's say you want to run several applications locally to test them together, similar to a production scenario. With a local Kubernetes cluster, you'd be able to do this with helm/deployment YAML files. You'd also have to build them as containers and set up Kubernetes, which can add some complexity. + +Instead, you simply want to run them as local executables in self-hosted mode. However, self-hosted mode requires you to: + +- Run multiple `dapr run` commands +- Keep track of all ports opened (you cannot have duplicate ports for different applications)- Remember the resources folders and configuration files that each application refers to +- Recall all of the additional flags you used to tweak the `dapr run` command behavior (`--app-health-check-path`, `--dapr-grpc-port`, `--unix-domain-socket`, etc.) + +With Multi-app Run, you can easily start multiple applications in self-hosted mode using a single `dapr run -f` command. + +## Multi-app template file + +When you execute `dapr run -f`, Dapr parses the multi-app template file initialized with `dapr init`. By default, this template file is called `dapr.yaml`. + +You can customize the template file by executing `dapr run -f ./.yaml`. + +The following `dapr.yaml` example includes some of the configurations you can customize to your applications. For a more in-depth example and explanation of variables, see [Multi-app template]({{< ref multi-app-template.md >}}). + +```yaml +version: 1 +apps: + - appDirPath: ../../../apps/processor/ + appPort: 9081 + daprHTTPPort: 3510 + command: ["go","run", "app.go"] + - appID: emit-metrics + appDirPath: ../../../apps/emit-metrics/ + daprHTTPPort: 3511 + env: + DAPR_HOST_ADD: localhost + command: ["go","run", "app.go"] +``` + + +## How does it work? + +When running [`dapr init`]({{< ref install-dapr-selfhost.md >}}), this initializes a directory where the default configurations and resources are stored. + +For running multiple applications, `dapr init` will initialize the following `~/.dapr/` directory structure: + + + +When developing multiple applications, each **app directory** can have a `.dapr` folder, which contains a `config.yaml` file and a `resources` directory. If the `.dapr` directory is not present within the app directory, the default `~/.dapr/resources/` and `~/.dapr/config.yaml` locations are used. + +> This change does not impact the `bin` folder, where the Dapr CLI looks for the `daprd` and `dashboard` binaries. That remains at `~/.dapr/bin/`. + + +### Precedence rules + + +## Next steps \ No newline at end of file diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md new file mode 100644 index 000000000..14a733e7e --- /dev/null +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md @@ -0,0 +1,90 @@ +--- +type: docs +title: Multi-app template file +linkTitle: Multi-app template +weight: 2000 +description: Unpack the multi-app template file and its variables +--- + +{{% alert title="Note" color="primary" %}} + Multi-app `dapr run -f` is currently a preview feature only supported in Linux/MacOS. +{{% /alert %}} + +The multi-app template file is a single YAML configuration file that you can use to configure multiple applications alongside a Dapr sidecar. Execute the following command for Dapr to parse the multi-app template file, named `dapr.yaml` by default: + +```cmd +dapr run -f +``` + +To name the multi-app template file something other than `dapr.yaml`, run: + +```cmd +dapr run -f ./.yaml +``` + +The multi-app template file can include any of the following parameters. + +```yaml +version: 1 +common: # optional section for variables shared across apps + resourcesPath: ./app/components # any dapr resources to be shared across apps + env: # any environment variable shared across apps + - DEBUG: true +apps: + - appID: webapp # required + appDirPath: ./webapp/ # required + resourcesPath: ./webapp/components # (optional) can be default by convention + configFilePath: ./webapp/config.yaml # (optional) can be default by convention too, ignore if file is not found. + appProtocol: HTTP + appPort: 8080 + appHealthCheckPath: "/healthz" # All _ converted to - for all properties defined under daprd section + command: ["python3" "app.py"] + - appID: backend + appDirPath: ./backend/ + appProtocol: GRPC + appPort: 3000 + unixDomainSocket: "/tmp/test-socket" + env: + - DEBUG: false + command: ["./backend"] +``` + +## Parameters + + +| Parameter | Required | Details | Example | +|--------------------------|:--------:|--------|---------| +| `appID` | Y | Your application's app ID | `webapp`, `backend` | +| `appDirPath` | Y | Path to the your application | `./webapp/`, `./backend/` | +| `resourcesPath` | N | Path to your Dapr resources. Can be default by convention; ignore if directory isn't found | `./app/components`, `./webapp/components` | +| `configFilePath` | N | Path to your application's configuration file | `./webapp/config.yaml` | +| `appProtocol` | N | Application protocol | `HTTP`, `GRPC` | +| `appPort` | N | Designated port for your application | `8080`, `3000` | +| `daprHTTPPort` | N | Dapr HTTP port | | +| `daprGRPCPort` | N | Dapr GRPC port | | +| `daprInternalGRPCPort` | N | | | +| `metricsPort` | N | | | +| `unixDomainSocket` | N | Path to the Unix Domain Socket | `/tmp/test-socket` | +| `profilePort` | N | | | +| `enableProfiling` | N | | | +| `apiListenAddresses` | N | Dapr API listen addresses | | +| `logLevel` | N | | | +| `appMaxConcurrency` | N | | | +| `placementHostAddress` | N | | | +| `appSSL` | N | | | +| `daprHTTPMaxRequestSize` | N | | | +| `daprHTTPReadBufferSize` | N | | | +| `enableAppHealthCheck` | N | Enable the app health check on the application | `true`, `false` | +| `appHealthCheckPath` | N | Path to the health check file | `/healthz` | +| `appHealthProbeInterval` | N | App health check interval time range | | +| `appHealthProbeTimeout` | N | When the app health check will timeout | | +| `appHealthThreshold` | N | | | +| `enableApiLogging` | N | | | +| `daprPath` | N | Dapr install path | | +| `env` | N | Map to environment variable; environment variables applied per application will overwrite environment variables shared across applications | `DEBUG`, `DAPR_HOST_ADD` | + +## Scenario + +todo + +## Next steps \ No newline at end of file diff --git a/daprdocs/content/en/reference/cli/dapr-run.md b/daprdocs/content/en/reference/cli/dapr-run.md index 995211012..acf0ba8ae 100644 --- a/daprdocs/content/en/reference/cli/dapr-run.md +++ b/daprdocs/content/en/reference/cli/dapr-run.md @@ -35,6 +35,7 @@ dapr run [flags] [command] | `--dapr-http-port` | `DAPR_HTTP_PORT` | `3500` | The HTTP port for Dapr to listen on | | `--enable-profiling` | | `false` | Enable "pprof" profiling via an HTTP endpoint | | `--help`, `-h` | | | Print the help message | +| `--run-file`, `-f` | | Linux/Mac: `$HOME/.dapr/dapr.yaml` | Run multiple applications at once via the multi-app template file | | `--image` | | | Use a custom Docker image. Format is `repository/image` for Docker Hub, or `example.com/repository/image` for a custom registry. | | `--log-level` | | `info` | The log verbosity. Valid values are: `debug`, `info`, `warn`, `error`, `fatal`, or `panic` | | `--enable-api-logging` | | `false` | Enable the logging of all API calls from application to Dapr | From 190e5ffad92b890278fe1fcacd144420857404dc Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Fri, 27 Jan 2023 17:07:22 -0600 Subject: [PATCH 03/38] notes from mark Signed-off-by: Hannah Hunter --- .../multi-app-dapr-run/multi-app-overview.md | 35 ++++++++++++++++--- .../multi-app-dapr-run/multi-app-template.md | 2 +- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md index 8af743ad3..249fa74d3 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md @@ -1,7 +1,7 @@ --- type: docs title: Run multiple applications with one command -linkTitle: Multi-app Dapr Run +linkTitle: Multi-app Run weight: 1000 description: Learn the scenarios around running multiple applications with one Dapr command --- @@ -20,7 +20,7 @@ Instead, you simply want to run them as local executables in self-hosted mode. With Multi-app Run, you can easily start multiple applications in self-hosted mode using a single `dapr run -f` command. -## Multi-app template file +## Multi-app Run template file When you execute `dapr run -f`, Dapr parses the multi-app template file initialized with `dapr init`. By default, this template file is called `dapr.yaml`. @@ -44,20 +44,45 @@ apps: ``` -## How does it work? +## Multi-app Run defaults -When running [`dapr init`]({{< ref install-dapr-selfhost.md >}}), this initializes a directory where the default configurations and resources are stored. -For running multiple applications, `dapr init` will initialize the following `~/.dapr/` directory structure: + + +This is the directory structure that you can use, where these are optional When developing multiple applications, each **app directory** can have a `.dapr` folder, which contains a `config.yaml` file and a `resources` directory. If the `.dapr` directory is not present within the app directory, the default `~/.dapr/resources/` and `~/.dapr/config.yaml` locations are used. +1 Go to root .dapr/resources and throw eerything in there and assume all apps will use that directory - all using the same resources path +- point to one place with convention +2 each application can have a different default resources path that you put in application directory +- point to separate places (per app) with convention +3 if you want to call it something other than .dapr, and be explicit about it, you can +- point to different places with whatever names you choose + > This change does not impact the `bin` folder, where the Dapr CLI looks for the `daprd` and `dashboard` binaries. That remains at `~/.dapr/bin/`. +Under .dapr/log folder locally: +app.log - application logs +daprd.log + +Even if you've decided to have a different resources folder, it will still have the logs there ### Precedence rules +## Try it out + + +## Watch the demo + +Watch [this video for an overview on pub/sub multi-tenancy](https://youtu.be/eK463jugo0c?t=1188): + + + + + + ## Next steps \ No newline at end of file diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md index 14a733e7e..864dfb317 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md @@ -33,7 +33,7 @@ common: # optional section for variables shared across apps apps: - appID: webapp # required appDirPath: ./webapp/ # required - resourcesPath: ./webapp/components # (optional) can be default by convention + resourcesPath: ./webapp/resources # (optional) can be default by convention configFilePath: ./webapp/config.yaml # (optional) can be default by convention too, ignore if file is not found. appProtocol: HTTP appPort: 8080 From 5c8a60e8b3c2100341d8e4e0dad01b2aadbb6e1b Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Fri, 27 Jan 2023 18:39:41 -0600 Subject: [PATCH 04/38] updates to wording Signed-off-by: Hannah Hunter --- .../multi-app-dapr-run/multi-app-overview.md | 37 +++++++++---------- .../multi-app-dapr-run/multi-app-template.md | 8 ++-- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md index 249fa74d3..6bedfbf70 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md @@ -20,7 +20,7 @@ Instead, you simply want to run them as local executables in self-hosted mode. With Multi-app Run, you can easily start multiple applications in self-hosted mode using a single `dapr run -f` command. -## Multi-app Run template file +## Multi-app run template file When you execute `dapr run -f`, Dapr parses the multi-app template file initialized with `dapr init`. By default, this template file is called `dapr.yaml`. @@ -43,32 +43,32 @@ apps: command: ["go","run", "app.go"] ``` +## Approaches for using multi-app run -## Multi-app Run defaults +You have several options when using multi-app run. +### Point to one location (with convention) +When developing multiple applications, each app directory can have a `.dapr` folder, which contains a `config.yaml` file and a `resources` directory. Otherwise, if the `.dapr` directory is not present within the app directory, the default `~/.dapr/resources/` and `~/.dapr/config.yaml` locations are used. +You can set all of your applications and resources at the `~/.dapr` root. This is helpful when all applications share the same resources path. -This is the directory structure that you can use, where these are optional +### Point to separate locations (with convention) - +If you decide to add a `.dapr` directory in each app directory, with a `/resources` directory and `config.yaml` file, you can specify different resources paths for each application. This approach remains within convention by using the default `.dapr` -When developing multiple applications, each **app directory** can have a `.dapr` folder, which contains a `config.yaml` file and a `resources` directory. If the `.dapr` directory is not present within the app directory, the default `~/.dapr/resources/` and `~/.dapr/config.yaml` locations are used. +### Point to separate locations (custom) -1 Go to root .dapr/resources and throw eerything in there and assume all apps will use that directory - all using the same resources path -- point to one place with convention -2 each application can have a different default resources path that you put in application directory -- point to separate places (per app) with convention -3 if you want to call it something other than .dapr, and be explicit about it, you can -- point to different places with whatever names you choose +You can also name each app directory's `.dapr` directory something other than `.dapr`, like `mymagicapp`, `webapp`, or `backend`. This helps if you'd like to be explicit about resource or application directory paths. -> This change does not impact the `bin` folder, where the Dapr CLI looks for the `daprd` and `dashboard` binaries. That remains at `~/.dapr/bin/`. +## Logs -Under .dapr/log folder locally: -app.log - application logs -daprd.log +Logs are included by default within each app directory and are tracked in the following locations under `.dapr/logs`: -Even if you've decided to have a different resources folder, it will still have the logs there +- `app.log` +- `daprd.log` + +Even if you've decided to rename your resources folder to something other than `.dapr`, the logs will remain there. ### Precedence rules @@ -78,10 +78,7 @@ Even if you've decided to have a different resources folder, it will still have ## Watch the demo -Watch [this video for an overview on pub/sub multi-tenancy](https://youtu.be/eK463jugo0c?t=1188): - - - +Watch [this video for an overview on multi-app run](https://youtu.be/s1p9MNl4VGo?t=2456): diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md index 864dfb317..ae89bf73e 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md @@ -32,15 +32,15 @@ common: # optional section for variables shared across apps - DEBUG: true apps: - appID: webapp # required - appDirPath: ./webapp/ # required - resourcesPath: ./webapp/resources # (optional) can be default by convention - configFilePath: ./webapp/config.yaml # (optional) can be default by convention too, ignore if file is not found. + appDirPath: .dapr/webapp/ # required + resourcesPath: .dapr/resources # (optional) can be default by convention + configFilePath: .dapr/config.yaml # (optional) can be default by convention too, ignore if file is not found. appProtocol: HTTP appPort: 8080 appHealthCheckPath: "/healthz" # All _ converted to - for all properties defined under daprd section command: ["python3" "app.py"] - appID: backend - appDirPath: ./backend/ + appDirPath: .dapr/backend/ appProtocol: GRPC appPort: 3000 unixDomainSocket: "/tmp/test-socket" From 89dbc9ab6825f0ba7c095539151660f1b6585f1f Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Fri, 27 Jan 2023 18:48:58 -0600 Subject: [PATCH 05/38] capitalization consistency; add overview to title Signed-off-by: Hannah Hunter --- .../multi-app-dapr-run/multi-app-overview.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md index 6bedfbf70..16ae25dcd 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md @@ -1,7 +1,7 @@ --- type: docs title: Run multiple applications with one command -linkTitle: Multi-app Run +linkTitle: Multi-app Run overview weight: 1000 description: Learn the scenarios around running multiple applications with one Dapr command --- @@ -20,7 +20,7 @@ Instead, you simply want to run them as local executables in self-hosted mode. With Multi-app Run, you can easily start multiple applications in self-hosted mode using a single `dapr run -f` command. -## Multi-app run template file +## Multi-app Run template file When you execute `dapr run -f`, Dapr parses the multi-app template file initialized with `dapr init`. By default, this template file is called `dapr.yaml`. @@ -43,9 +43,9 @@ apps: command: ["go","run", "app.go"] ``` -## Approaches for using multi-app run +## Approaches for using Multi-app Run -You have several options when using multi-app run. +You have several options when using Multi-app Run. ### Point to one location (with convention) @@ -78,7 +78,7 @@ Even if you've decided to rename your resources folder to something other than ` ## Watch the demo -Watch [this video for an overview on multi-app run](https://youtu.be/s1p9MNl4VGo?t=2456): +Watch [this video for an overview on Multi-app Run](https://youtu.be/s1p9MNl4VGo?t=2456): From 4a2440dbc63506a0de1117b22ea0f6db17a5887c Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Fri, 27 Jan 2023 18:51:01 -0600 Subject: [PATCH 06/38] typo Signed-off-by: Hannah Hunter --- .../local-development/multi-app-dapr-run/multi-app-template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md index ae89bf73e..1b3425c75 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md @@ -1,7 +1,7 @@ --- type: docs title: Multi-app template file -linkTitle: Multi-app template +linkTitle: Multi-app Run template weight: 2000 description: Unpack the multi-app template file and its variables --- From 716d75f2cb718f332cc0b1c09d6d9a699fe995eb Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Mon, 30 Jan 2023 09:44:57 -0600 Subject: [PATCH 07/38] update per Mark review Signed-off-by: Hannah Hunter --- .../multi-app-dapr-run/_index.md | 4 +- .../multi-app-dapr-run/multi-app-overview.md | 53 ++++++++-------- .../multi-app-dapr-run/multi-app-template.md | 63 ++++++++++--------- .../support/support-preview-features.md | 2 +- daprdocs/content/en/reference/cli/dapr-run.md | 2 +- 5 files changed, 65 insertions(+), 59 deletions(-) diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/_index.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/_index.md index afbced2f8..8474af033 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/_index.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/_index.md @@ -1,7 +1,7 @@ --- type: docs -title: "Multi-app support" -linkTitle: "Multi-app support" +title: "Multi-app run" +linkTitle: "Multi-app run" weight: 300 description: "Support for running multiple Dapr applications with one command" --- \ No newline at end of file diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md index 16ae25dcd..01f28ae86 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md @@ -1,13 +1,13 @@ --- type: docs -title: Run multiple applications with one command -linkTitle: Multi-app Run overview +title: Multi-app Run (MapR) overview +linkTitle: MapR overview weight: 1000 -description: Learn the scenarios around running multiple applications with one Dapr command +description: Learn the scenarios around running multiple applications with one CLI command --- {{% alert title="Note" color="primary" %}} - Multi-app `dapr run -f` is currently a preview feature only supported in Linux/MacOS. + MapR (Multi-app Run using `dapr run -f`) is currently a preview feature only supported in Linux/MacOS. {{% /alert %}} Let's say you want to run several applications locally to test them together, similar to a production scenario. With a local Kubernetes cluster, you'd be able to do this with helm/deployment YAML files. You'd also have to build them as containers and set up Kubernetes, which can add some complexity. @@ -15,23 +15,25 @@ Let's say you want to run several applications locally to test them together, si Instead, you simply want to run them as local executables in self-hosted mode. However, self-hosted mode requires you to: - Run multiple `dapr run` commands -- Keep track of all ports opened (you cannot have duplicate ports for different applications)- Remember the resources folders and configuration files that each application refers to +- Keep track of all ports opened (you cannot have duplicate ports for different applications). +- Remember the resources folders and configuration files that each application refers to. - Recall all of the additional flags you used to tweak the `dapr run` command behavior (`--app-health-check-path`, `--dapr-grpc-port`, `--unix-domain-socket`, etc.) -With Multi-app Run, you can easily start multiple applications in self-hosted mode using a single `dapr run -f` command. +With Multi-app Run, you can start multiple applications in self-hosted mode using a single `dapr run -f` command using a template file. The template file describes how to start multiple applications as if you had run many separate CLI `run`commands. By default, this template file is called `dapr.yaml`. -## Multi-app Run template file +## MapR template file -When you execute `dapr run -f`, Dapr parses the multi-app template file initialized with `dapr init`. By default, this template file is called `dapr.yaml`. +When you execute `dapr run -f`, uses the multi-app template file to run all the applications. -You can customize the template file by executing `dapr run -f ./.yaml`. +You can name template file with preferred name other than the default. For example `dapr run -f ./.yaml`. -The following `dapr.yaml` example includes some of the configurations you can customize to your applications. For a more in-depth example and explanation of variables, see [Multi-app template]({{< ref multi-app-template.md >}}). +The following `dapr.yaml` example includes some of the template properties you can customize for your applications. In the example, you can simultaneously launch 2 applications with app IDs of `processor` and `emit-metrics`. ```yaml version: 1 apps: - - appDirPath: ../../../apps/processor/ + - appID: processor + appDirPath: ../../../apps/processor/ appPort: 9081 daprHTTPPort: 3510 command: ["go","run", "app.go"] @@ -43,23 +45,25 @@ apps: command: ["go","run", "app.go"] ``` -## Approaches for using Multi-app Run +For a more in-depth example and explanation of the template properties, see [Multi-app template]({{< ref multi-app-template.md >}}). -You have several options when using Multi-app Run. +## Locations for resources and configuration files -### Point to one location (with convention) +You have options on where to place your applications' resources and configuration files when using MapR. + +### Point to one file location (with convention) + +You can set all of your applications resources and configurations at the `~/.dapr` root. This is helpful when all applications share the same resources path, like when testing on a local machine. + +### Separate file locations for each application (with convention) When developing multiple applications, each app directory can have a `.dapr` folder, which contains a `config.yaml` file and a `resources` directory. Otherwise, if the `.dapr` directory is not present within the app directory, the default `~/.dapr/resources/` and `~/.dapr/config.yaml` locations are used. -You can set all of your applications and resources at the `~/.dapr` root. This is helpful when all applications share the same resources path. - -### Point to separate locations (with convention) - If you decide to add a `.dapr` directory in each app directory, with a `/resources` directory and `config.yaml` file, you can specify different resources paths for each application. This approach remains within convention by using the default `.dapr` ### Point to separate locations (custom) -You can also name each app directory's `.dapr` directory something other than `.dapr`, like `mymagicapp`, `webapp`, or `backend`. This helps if you'd like to be explicit about resource or application directory paths. +You can also name each app directory's `.dapr` directory something other than `.dapr`, such as, `webapp`, or `backend`. This helps if you'd like to be explicit about resource or application directory paths. ## Logs @@ -68,18 +72,17 @@ Logs are included by default within each app directory and are tracked in the fo - `app.log` - `daprd.log` -Even if you've decided to rename your resources folder to something other than `.dapr`, the logs will remain there. - -### Precedence rules - +Even if you've decided to rename your resources folder to something other than `.dapr`, the logs file are written to `.dapr` folder. ## Try it out ## Watch the demo -Watch [this video for an overview on Multi-app Run](https://youtu.be/s1p9MNl4VGo?t=2456): +Watch [this video for an overview on MapR](https://youtu.be/s1p9MNl4VGo?t=2456): -## Next steps \ No newline at end of file +## Next steps + +[Unpack the MapR template file and its properties]({{< ref multi-app-template.md >}}) \ No newline at end of file diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md index 1b3425c75..e1f1b206e 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md @@ -1,28 +1,30 @@ --- type: docs -title: Multi-app template file -linkTitle: Multi-app Run template +title: MapR template file +linkTitle: MapR template weight: 2000 -description: Unpack the multi-app template file and its variables +description: Unpack the MapR template file and its properties --- {{% alert title="Note" color="primary" %}} - Multi-app `dapr run -f` is currently a preview feature only supported in Linux/MacOS. + MapR (Multi-app Run using `dapr run -f`) is currently a preview feature only supported in Linux/MacOS. {{% /alert %}} -The multi-app template file is a single YAML configuration file that you can use to configure multiple applications alongside a Dapr sidecar. Execute the following command for Dapr to parse the multi-app template file, named `dapr.yaml` by default: +The MapR template file is a YAML file that you can use to run multiple applications at once. Execute the following CLI command to read the MapR template file, named `dapr.yaml` by default: ```cmd +// the template file needs to be called `dapr.yaml` by default + dapr run -f ``` -To name the multi-app template file something other than `dapr.yaml`, run: +If the MapR template file is named something other than `dapr.yaml`, run: ```cmd dapr run -f ./.yaml ``` -The multi-app template file can include any of the following parameters. +The MapR template file can include the following properties. Below is an example template showing two applications that are configured with some of the properties. ```yaml version: 1 @@ -49,42 +51,43 @@ apps: command: ["./backend"] ``` -## Parameters +## Template properties + +The properties for the MapR template align with the `dapr run` CLI flags, [listed in the CLI reference documentation]({{< ref run.md >}}). -| Parameter | Required | Details | Example | +| Properties | Required | Details | Example | |--------------------------|:--------:|--------|---------| -| `appID` | Y | Your application's app ID | `webapp`, `backend` | -| `appDirPath` | Y | Path to the your application | `./webapp/`, `./backend/` | +| `appID` | Y | Application's app ID | `webapp`, `backend` | +| `appDirPath` | Y | Path to the your application code | `./webapp/`, `./backend/` | | `resourcesPath` | N | Path to your Dapr resources. Can be default by convention; ignore if directory isn't found | `./app/components`, `./webapp/components` | | `configFilePath` | N | Path to your application's configuration file | `./webapp/config.yaml` | -| `appProtocol` | N | Application protocol | `HTTP`, `GRPC` | -| `appPort` | N | Designated port for your application | `8080`, `3000` | +| `appProtocol` | N | The protocol Dapr uses to talk to the application. | `HTTP`, `GRPC` | +| `appPort` | N | The port your application is listening on | `8080`, `3000` | | `daprHTTPPort` | N | Dapr HTTP port | | | `daprGRPCPort` | N | Dapr GRPC port | | | `daprInternalGRPCPort` | N | | | -| `metricsPort` | N | | | -| `unixDomainSocket` | N | Path to the Unix Domain Socket | `/tmp/test-socket` | -| `profilePort` | N | | | -| `enableProfiling` | N | | | +| `metricsPort` | N | The port that Dapr sends its metrics information to | | +| `unixDomainSocket` | N | Path to a unix domain socket dir mount. If specified, communication with the Dapr sidecar uses unix domain sockets for lower latency and greater throughput when compared to using TCP ports. Not available on Windows. | `/tmp/test-socket` | +| `profilePort` | N | The port for the profile server to listen on | | +| `enableProfiling` | N | Enable profiling via an HTTP endpoint | | | `apiListenAddresses` | N | Dapr API listen addresses | | -| `logLevel` | N | | | -| `appMaxConcurrency` | N | | | +| `logLevel` | N | The log verbosity. | | +| `appMaxConcurrency` | N | The concurrency level of the application; default is unlimited | | | `placementHostAddress` | N | | | -| `appSSL` | N | | | -| `daprHTTPMaxRequestSize` | N | | | -| `daprHTTPReadBufferSize` | N | | | +| `appSSL` | N | Enable https when Dapr invokes the application | | +| `daprHTTPMaxRequestSize` | N | Max size of the request body in MB. | | +| `daprHTTPReadBufferSize` | N | Max size of the HTTP read buffer in KB. This also limits the maximum size of HTTP headers. The default 4 KB | | | `enableAppHealthCheck` | N | Enable the app health check on the application | `true`, `false` | | `appHealthCheckPath` | N | Path to the health check file | `/healthz` | -| `appHealthProbeInterval` | N | App health check interval time range | | -| `appHealthProbeTimeout` | N | When the app health check will timeout | | -| `appHealthThreshold` | N | | | -| `enableApiLogging` | N | | | +| `appHealthProbeInterval` | N | Interval to probe for the health of the app in seconds + | | +| `appHealthProbeTimeout` | N | Timeout for app health probes in milliseconds | | +| `appHealthThreshold` | N | Number of consecutive failures for the app to be considered unhealthy | | +| `enableApiLogging` | N | Enable the logging of all API calls from application to Dapr | | | `daprPath` | N | Dapr install path | | | `env` | N | Map to environment variable; environment variables applied per application will overwrite environment variables shared across applications | `DEBUG`, `DAPR_HOST_ADD` | -## Scenario +## Next steps -todo - -## Next steps \ No newline at end of file +[Try out the MapR template using the Distributed Calculator tutorial] \ No newline at end of file diff --git a/daprdocs/content/en/operations/support/support-preview-features.md b/daprdocs/content/en/operations/support/support-preview-features.md index 6b0da1ccc..769ee842a 100644 --- a/daprdocs/content/en/operations/support/support-preview-features.md +++ b/daprdocs/content/en/operations/support/support-preview-features.md @@ -20,4 +20,4 @@ For CLI there is no explicit opt-in, just the version that this was first made a | **App Middleware** | Allow middleware components to be executed when making service-to-service calls | N/A | [App Middleware]({{}}) | v1.9 | | **App health checks** | Allows configuring app health checks | `AppHealthCheck` | [App health checks]({{}}) | v1.9 | | **Pluggable components** | Allows creating self-hosted gRPC-based components written in any language that supports gRPC. The following component APIs are supported: State stores, Pub/sub, Bindings | N/A | [Pluggable components concept]({{}})| v1.9 | -| **Multi-app Run** | Configure multiple Dapr applications from a single configuration file and run from a single command | `dapr run -f` | [Multi-app Dapr Run]({{< ref multi-app-dapr-run.md >}}) | v1.10 | +| **MapR** | Configure multiple Dapr applications from a single configuration file and run from a single command | `dapr run -f` | [MapR]({{< ref multi-app-dapr-run.md >}}) | v1.10 | diff --git a/daprdocs/content/en/reference/cli/dapr-run.md b/daprdocs/content/en/reference/cli/dapr-run.md index acf0ba8ae..af82c3b35 100644 --- a/daprdocs/content/en/reference/cli/dapr-run.md +++ b/daprdocs/content/en/reference/cli/dapr-run.md @@ -35,7 +35,7 @@ dapr run [flags] [command] | `--dapr-http-port` | `DAPR_HTTP_PORT` | `3500` | The HTTP port for Dapr to listen on | | `--enable-profiling` | | `false` | Enable "pprof" profiling via an HTTP endpoint | | `--help`, `-h` | | | Print the help message | -| `--run-file`, `-f` | | Linux/Mac: `$HOME/.dapr/dapr.yaml` | Run multiple applications at once via the multi-app template file | +| `--run-file`, `-f` | | Linux/Mac: `$HOME/.dapr/dapr.yaml` | Run multiple applications at once using a multi-app run (MapR) template file | | `--image` | | | Use a custom Docker image. Format is `repository/image` for Docker Hub, or `example.com/repository/image` for a custom registry. | | `--log-level` | | `info` | The log verbosity. Valid values are: `debug`, `info`, `warn`, `error`, `fatal`, or `panic` | | `--enable-api-logging` | | `false` | Enable the logging of all API calls from application to Dapr | From 238b8987f58a3390a0980ba236de6446bc90b950 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Mon, 30 Jan 2023 10:05:46 -0600 Subject: [PATCH 08/38] fix link Signed-off-by: Hannah Hunter --- .../local-development/multi-app-dapr-run/_index.md | 4 ++-- .../multi-app-dapr-run/multi-app-template.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/_index.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/_index.md index 8474af033..c85773ab1 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/_index.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/_index.md @@ -1,7 +1,7 @@ --- type: docs -title: "Multi-app run" -linkTitle: "Multi-app run" +title: "Multi-app Run (MapR)" +linkTitle: "Multi-app Run (MapR)" weight: 300 description: "Support for running multiple Dapr applications with one command" --- \ No newline at end of file diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md index e1f1b206e..63ff2c344 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md @@ -53,7 +53,7 @@ apps: ## Template properties -The properties for the MapR template align with the `dapr run` CLI flags, [listed in the CLI reference documentation]({{< ref run.md >}}). +The properties for the MapR template align with the `dapr run` CLI flags, [listed in the CLI reference documentation]({{< ref "dapr-run.md#flags" >}}). | Properties | Required | Details | Example | From 0164ee6f33f9329f8b8f43b410e10774c4ee1e34 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Mon, 30 Jan 2023 10:42:48 -0600 Subject: [PATCH 09/38] update internal grpc port table entry Signed-off-by: Hannah Hunter --- .../local-development/multi-app-dapr-run/multi-app-template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md index 63ff2c344..b77fafa41 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md @@ -66,7 +66,7 @@ The properties for the MapR template align with the `dapr run` CLI flags, [liste | `appPort` | N | The port your application is listening on | `8080`, `3000` | | `daprHTTPPort` | N | Dapr HTTP port | | | `daprGRPCPort` | N | Dapr GRPC port | | -| `daprInternalGRPCPort` | N | | | +| `daprInternalGRPCPort` | N | gRPC port for the Dapr Internal API to listen on; used when parsing the value from a local DNS component | | | `metricsPort` | N | The port that Dapr sends its metrics information to | | | `unixDomainSocket` | N | Path to a unix domain socket dir mount. If specified, communication with the Dapr sidecar uses unix domain sockets for lower latency and greater throughput when compared to using TCP ports. Not available on Windows. | `/tmp/test-socket` | | `profilePort` | N | The port for the profile server to listen on | | From 1a6564f7fbd62b92edcd088433c933876358d9f5 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Tue, 31 Jan 2023 16:02:16 -0600 Subject: [PATCH 10/38] remove weird comment in example Signed-off-by: Hannah Hunter --- .../local-development/multi-app-dapr-run/multi-app-template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md index b77fafa41..37e2727f9 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md @@ -39,7 +39,7 @@ apps: configFilePath: .dapr/config.yaml # (optional) can be default by convention too, ignore if file is not found. appProtocol: HTTP appPort: 8080 - appHealthCheckPath: "/healthz" # All _ converted to - for all properties defined under daprd section + appHealthCheckPath: "/healthz" command: ["python3" "app.py"] - appID: backend appDirPath: .dapr/backend/ From caaa1e7c7d6f2f352d2ec7d9e50d5d187ac9de62 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Thu, 2 Feb 2023 11:32:59 -0600 Subject: [PATCH 11/38] pravin review Signed-off-by: Hannah Hunter --- .../multi-app-dapr-run/multi-app-overview.md | 9 +++------ .../multi-app-dapr-run/multi-app-template.md | 8 +++++--- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md index 01f28ae86..734834286 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md @@ -67,16 +67,13 @@ You can also name each app directory's `.dapr` directory something other than `. ## Logs -Logs are included by default within each app directory and are tracked in the following locations under `.dapr/logs`: +Logs for application and `daprd` are captured in separate files. These log files are created automatically under `.dapr/logs` directory under each app director. These log file names follow the below pattern: -- `app.log` -- `daprd.log` +- `_app_.log` (file name format for app's log) +- `_daprd_.log` (file name format for `daprd` log) Even if you've decided to rename your resources folder to something other than `.dapr`, the logs file are written to `.dapr` folder. -## Try it out - - ## Watch the demo Watch [this video for an overview on MapR](https://youtu.be/s1p9MNl4VGo?t=2456): diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md index 37e2727f9..65fff9a6d 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md @@ -33,7 +33,7 @@ common: # optional section for variables shared across apps env: # any environment variable shared across apps - DEBUG: true apps: - - appID: webapp # required + - appID: webapp appDirPath: .dapr/webapp/ # required resourcesPath: .dapr/resources # (optional) can be default by convention configFilePath: .dapr/config.yaml # (optional) can be default by convention too, ignore if file is not found. @@ -58,8 +58,8 @@ The properties for the MapR template align with the `dapr run` CLI flags, [liste | Properties | Required | Details | Example | |--------------------------|:--------:|--------|---------| -| `appID` | Y | Application's app ID | `webapp`, `backend` | | `appDirPath` | Y | Path to the your application code | `./webapp/`, `./backend/` | +| `appID` | N | Application's app ID. If not provided, will be derived from `appDirPath` | `webapp`, `backend` | | `resourcesPath` | N | Path to your Dapr resources. Can be default by convention; ignore if directory isn't found | `./app/components`, `./webapp/components` | | `configFilePath` | N | Path to your application's configuration file | `./webapp/config.yaml` | | `appProtocol` | N | The protocol Dapr uses to talk to the application. | `HTTP`, `GRPC` | @@ -90,4 +90,6 @@ The properties for the MapR template align with the `dapr run` CLI flags, [liste ## Next steps -[Try out the MapR template using the Distributed Calculator tutorial] \ No newline at end of file +Watch [this video for an overview on MapR](https://youtu.be/s1p9MNl4VGo?t=2456): + + From 9b12a599c8bfc1670af253ec10447d2c2a8ea89a Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Fri, 3 Feb 2023 10:33:52 -0600 Subject: [PATCH 12/38] updates per mukundand and pravin Signed-off-by: Hannah Hunter --- .../multi-app-dapr-run/multi-app-overview.md | 16 ++--- .../multi-app-dapr-run/multi-app-template.md | 58 +++++++++++++++++-- 2 files changed, 61 insertions(+), 13 deletions(-) diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md index 734834286..b5b8c7b3c 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md @@ -23,7 +23,7 @@ With Multi-app Run, you can start multiple applications in self-hosted mode usin ## MapR template file -When you execute `dapr run -f`, uses the multi-app template file to run all the applications. +When you execute `dapr run -f .`, it uses the multi-app template file (named `dapr.yaml`) present in the current directory to run all the applications. You can name template file with preferred name other than the default. For example `dapr run -f ./.yaml`. @@ -33,12 +33,12 @@ The following `dapr.yaml` example includes some of the template properties you c version: 1 apps: - appID: processor - appDirPath: ../../../apps/processor/ + appDirPath: ../apps/processor/ appPort: 9081 daprHTTPPort: 3510 command: ["go","run", "app.go"] - appID: emit-metrics - appDirPath: ../../../apps/emit-metrics/ + appDirPath: ../apps/emit-metrics/ daprHTTPPort: 3511 env: DAPR_HOST_ADD: localhost @@ -57,9 +57,9 @@ You can set all of your applications resources and configurations at the `~/.dap ### Separate file locations for each application (with convention) -When developing multiple applications, each app directory can have a `.dapr` folder, which contains a `config.yaml` file and a `resources` directory. Otherwise, if the `.dapr` directory is not present within the app directory, the default `~/.dapr/resources/` and `~/.dapr/config.yaml` locations are used. +When using MapR, each application directory can have a `.dapr` folder, which contains a `config.yaml` file and a `resources` directory. Otherwise, if the `.dapr` directory is not present within the app directory, the default `~/.dapr/resources/` and `~/.dapr/config.yaml` locations are used. -If you decide to add a `.dapr` directory in each app directory, with a `/resources` directory and `config.yaml` file, you can specify different resources paths for each application. This approach remains within convention by using the default `.dapr` +If you decide to add a `.dapr` directory in each application directory, with a `/resources` directory and `config.yaml` file, you can specify different resources paths for each application. This approach remains within convention by using the default `~/.dapr`. ### Point to separate locations (custom) @@ -67,12 +67,12 @@ You can also name each app directory's `.dapr` directory something other than `. ## Logs -Logs for application and `daprd` are captured in separate files. These log files are created automatically under `.dapr/logs` directory under each app director. These log file names follow the below pattern: +Logs for application and `daprd` are captured in separate files. These log files are created automatically under `.dapr/logs` directory under each application directory (`appDirPath` in the template). These log file names follow the pattern seen below: -- `_app_.log` (file name format for app's log) +- `_app_.log` (file name format for `app` log) - `_daprd_.log` (file name format for `daprd` log) -Even if you've decided to rename your resources folder to something other than `.dapr`, the logs file are written to `.dapr` folder. +Even if you've decided to rename your resources folder to something other than `.dapr`, the log files are written only to the `.dapr/logs` folder (created in the application directory). ## Watch the demo diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md index 65fff9a6d..4a22f188b 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md @@ -1,7 +1,7 @@ --- type: docs -title: MapR template file -linkTitle: MapR template +title: "How to: Use the MapR template file" +linkTitle: "How to: Use the MapR template" weight: 2000 description: Unpack the MapR template file and its properties --- @@ -10,20 +10,59 @@ description: Unpack the MapR template file and its properties MapR (Multi-app Run using `dapr run -f`) is currently a preview feature only supported in Linux/MacOS. {{% /alert %}} -The MapR template file is a YAML file that you can use to run multiple applications at once. Execute the following CLI command to read the MapR template file, named `dapr.yaml` by default: +The MapR template file is a YAML file that you can use to run multiple applications at once. In this guide, you'll learn how to: +- Use the multi-app template +- View started applications +- Stop the multi-app template +- Stucture the multi-app template file + +## Use the multi-app template + +You can use the multi-app template file in one of the following two ways: + +### Execute by providing a directory path + +When you provide a directory path, the CLI will try to locate the MapR template file, named `dapr.yaml` by default in the directory. If the file is not found, the CLI will return an error. + +Execute the following CLI command to read the MapR template file, named `dapr.yaml` by default: ```cmd // the template file needs to be called `dapr.yaml` by default -dapr run -f +dapr run -f ``` -If the MapR template file is named something other than `dapr.yaml`, run: +### Execute by providing a file path + +If the MapR template file is named something other than `dapr.yaml`, then you can provide the relative or absolute file path to the command: ```cmd dapr run -f ./.yaml ``` +## View the started applications + +Once the multi-app template is running, you can view the started applications with the following command: + +```cmd +dapr list +``` + +## Stop the multi-app template + +Stop the multi-app run template anytime with either of the following commands: + +```cmd +dapr stop -f +``` +or: + +```cmd +dapr stop -f dapr.yaml +``` + +## Template file structure + The MapR template file can include the following properties. Below is an example template showing two applications that are configured with some of the properties. ```yaml @@ -51,6 +90,15 @@ apps: command: ["./backend"] ``` +{{% alert title="Important" color="warning" %}} +The following rules apply for all the paths present in the template file: + - If the path is absolute, it is used as is. + - All relative paths under comman section should be provided relative to the template file path. + - `appDirPath` under apps section should be provided relative to the template file path. + - All relative paths under app section should be provided relative to the appDirPath. + +{{% /alert %}} + ## Template properties The properties for the MapR template align with the `dapr run` CLI flags, [listed in the CLI reference documentation]({{< ref "dapr-run.md#flags" >}}). From d8dabf43093ac3f03963abb809be57611cbbb5c6 Mon Sep 17 00:00:00 2001 From: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> Date: Fri, 3 Feb 2023 14:58:33 -0600 Subject: [PATCH 13/38] [Pluggable components] Error handling documentation (#3067) * initial draft of error handling table Signed-off-by: Hannah Hunter * add go examples Signed-off-by: Hannah Hunter * remove code brackets Signed-off-by: Hannah Hunter * typo Signed-off-by: Hannah Hunter * Update daprdocs/content/en/developing-applications/develop-components/pluggable-components/develop-pluggable.md Co-authored-by: Marcos Candeia Signed-off-by: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> * add .net code examples, annotations example, marcos review Signed-off-by: Hannah Hunter * add note about nuget package Signed-off-by: Hannah Hunter * updates from tiago and marcos Signed-off-by: Hannah Hunter * remove paragraph Signed-off-by: Hannah Hunter * make more clear that pluggable components are in same pod Signed-off-by: Hannah Hunter * Update daprdocs/content/en/operations/components/pluggable-components-registration.md Co-authored-by: Marcos Candeia Signed-off-by: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> * editing other example per marcos Signed-off-by: Hannah Hunter --------- Signed-off-by: Hannah Hunter Signed-off-by: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> Co-authored-by: Marcos Candeia --- .../pluggable-components/develop-pluggable.md | 197 +++++++++++++++++- .../pluggable-components-registration.md | 46 +++- 2 files changed, 236 insertions(+), 7 deletions(-) diff --git a/daprdocs/content/en/developing-applications/develop-components/pluggable-components/develop-pluggable.md b/daprdocs/content/en/developing-applications/develop-components/pluggable-components/develop-pluggable.md index e3f92b1e5..d25ff95d7 100644 --- a/daprdocs/content/en/developing-applications/develop-components/pluggable-components/develop-pluggable.md +++ b/daprdocs/content/en/developing-applications/develop-components/pluggable-components/develop-pluggable.md @@ -1,7 +1,7 @@ --- type: docs title: "How to: Implement pluggable components" -linkTitle: "Pluggable components" +linkTitle: "Implement pluggable components" weight: 1100 description: "Learn how to author and implement pluggable components" --- @@ -105,6 +105,201 @@ After generating the above state store example's service scaffolding code using This concrete implementation and auxiliary code are the **core** of your pluggable component. They define how your component behaves when handling gRPC requests from Dapr. +## Returning semantic errors + +Returning semantic errors are also part of the pluggable component protocol. The component must return specific gRPC codes that have semantic meaning for the user application, those errors are used to a variety of situations from concurrency requirements to informational only. + +| Error | gRPC error code | Source component | Description | +| ------------------------ | ------------------------------- | ---------------- | ----------- | +| ETag Mismatch | `codes.FailedPrecondition` | State store | Error mapping to meet concurrency requirements | +| ETag Invalid | `codes.InvalidArgument` | State store | | +| Bulk Delete Row Mismatch | `codes.Internal` | State store | | + +Learn more about concurrency requirements in the [State Management overview]({{< ref "state-management-overview.md#concurrency" >}}). + +The following examples demonstrate how to return an error in your own pluggable component, changing the messages to suit your needs. + +{{< tabs ".NET" "Java" "Go" >}} + +{{% codetab %}} + +> **Important:** In order to use .NET for error mapping, first install the [`Google.Api.CommonProtos` NuGet package](https://www.nuget.org/packages/Google.Api.CommonProtos/). + +**Etag Mismatch** + +```csharp +var badRequest = new BadRequest(); +var des = "The ETag field provided does not match the one in the store"; +badRequest.FieldViolations.Add(    + new Google.Rpc.BadRequest.Types.FieldViolation +    {        + Field = "etag", + Description = des +    }); + +var baseStatusCode = Grpc.Core.StatusCode.FailedPrecondition; +var status = new Google.Rpc.Status{    + Code = (int)baseStatusCode +}; + +status.Details.Add(Google.Protobuf.WellKnownTypes.Any.Pack(badRequest)); + +var metadata = new Metadata(); +metadata.Add("grpc-status-details-bin", status.ToByteArray()); +throw new RpcException(new Grpc.Core.Status(baseStatusCode, "fake-err-msg"), metadata); +``` + +**Etag Invalid** + +```csharp +var badRequest = new BadRequest(); +var des = "The ETag field must only contain alphanumeric characters"; +badRequest.FieldViolations.Add( + new Google.Rpc.BadRequest.Types.FieldViolation + { + Field = "etag", + Description = des + }); + +var baseStatusCode = Grpc.Core.StatusCode.InvalidArgument; +var status = new Google.Rpc.Status +{ + Code = (int)baseStatusCode +}; + +status.Details.Add(Google.Protobuf.WellKnownTypes.Any.Pack(badRequest)); + +var metadata = new Metadata(); +metadata.Add("grpc-status-details-bin", status.ToByteArray()); +throw new RpcException(new Grpc.Core.Status(baseStatusCode, "fake-err-msg"), metadata); +``` + +**Bulk Delete Row Mismatch** + +```csharp +var errorInfo = new Google.Rpc.ErrorInfo(); + +errorInfo.Metadata.Add("expected", "100"); +errorInfo.Metadata.Add("affected", "99"); + +var baseStatusCode = Grpc.Core.StatusCode.Internal; +var status = new Google.Rpc.Status{ +    Code = (int)baseStatusCode +}; + +status.Details.Add(Google.Protobuf.WellKnownTypes.Any.Pack(errorInfo)); + +var metadata = new Metadata(); +metadata.Add("grpc-status-details-bin", status.ToByteArray()); +throw new RpcException(new Grpc.Core.Status(baseStatusCode, "fake-err-msg"), metadata); +``` + +{{% /codetab %}} + + +{{% codetab %}} + +Just like the [Dapr Java SDK](https://github.com/tmacam/dapr-java-sdk/), the Java Pluggable Components SDK uses [Project Reactor](https://projectreactor.io/), which provides an asynchronous API for Java. + +Errors can be returned directly by: +1. Calling the `.error()` method in the `Mono` or `Flux` that your method returns +1. Providing the appropriate exception as parameter. + +You can also raise an exception, as long as it is captured and fed back to your resulting `Mono` or `Flux`. + +**ETag Mismatch** + +```java +final Status status = Status.newBuilder() + .setCode(io.grpc.Status.Code.FAILED_PRECONDITION.value()) + .setMessage("fake-err-msg-for-etag-mismatch") + .addDetails(Any.pack(BadRequest.FieldViolation.newBuilder() + .setField("etag") + .setDescription("The ETag field provided does not match the one in the store") + .build())) + .build(); +return Mono.error(StatusProto.toStatusException(status)); +``` + +**ETag Invalid** + +```java +final Status status = Status.newBuilder() + .setCode(io.grpc.Status.Code.INVALID_ARGUMENT.value()) + .setMessage("fake-err-msg-for-invalid-etag") + .addDetails(Any.pack(BadRequest.FieldViolation.newBuilder() + .setField("etag") + .setDescription("The ETag field must only contain alphanumeric characters") + .build())) + .build(); +return Mono.error(StatusProto.toStatusException(status)); +``` + +**Bulk Delete Row Mismatch** + +```java +final Status status = Status.newBuilder() + .setCode(io.grpc.Status.Code.INTERNAL.value()) + .setMessage("fake-err-msg-for-bulk-delete-row-mismatch") + .addDetails(Any.pack(ErrorInfo.newBuilder() + .putAllMetadata(Map.ofEntries( + Map.entry("affected", "99"), + Map.entry("expected", "100") + )) + .build())) + .build(); +return Mono.error(StatusProto.toStatusException(status)); +``` + +{{% /codetab %}} + + +{{% codetab %}} + +**ETag Mismatch** + +```go +st := status.New(codes.FailedPrecondition, "fake-err-msg") +desc := "The ETag field provided does not match the one in the store" +v := &errdetails.BadRequest_FieldViolation{ + Field: etagField, + Description: desc, +} +br := &errdetails.BadRequest{} +br.FieldViolations = append(br.FieldViolations, v) +st, err := st.WithDetails(br) +``` + +**ETag Invalid** + +```go +st := status.New(codes.InvalidArgument, "fake-err-msg") +desc := "The ETag field must only contain alphanumeric characters" +v := &errdetails.BadRequest_FieldViolation{ + Field: etagField, + Description: desc, +} +br := &errdetails.BadRequest{} +br.FieldViolations = append(br.FieldViolations, v) +st, err := st.WithDetails(br) +``` + +**Bulk Delete Row Mismatch** + +```go +st := status.New(codes.Internal, "fake-err-msg") +br := &errdetails.ErrorInfo{} +br.Metadata = map[string]string{ + affected: "99", + expected: "100", +} +st, err := st.WithDetails(br) +``` + +{{% /codetab %}} + +{{< /tabs >}} + ## Next steps - Get started with developing .NET pluggable component using this [sample code](https://github.com/dapr/samples/tree/master/pluggable-components-dotnet-template) diff --git a/daprdocs/content/en/operations/components/pluggable-components-registration.md b/daprdocs/content/en/operations/components/pluggable-components-registration.md index 06a4b6a2e..15e7fdbc8 100644 --- a/daprdocs/content/en/operations/components/pluggable-components-registration.md +++ b/daprdocs/content/en/operations/components/pluggable-components-registration.md @@ -132,7 +132,7 @@ Follow the steps provided in the [Deploy Dapr on a Kubernetes cluster]({{< ref k ## Add the pluggable component container in your deployments -When running in Kubernetes mode, pluggable components are deployed as containers in the same pod as your application. +Pluggable components are deployed as containers **in the same pod** as your application. Since pluggable components are backed by [Unix Domain Sockets][uds], make the socket created by your pluggable component accessible by Dapr runtime. Configure the deployment spec to: @@ -140,7 +140,7 @@ Since pluggable components are backed by [Unix Domain Sockets][uds], make the so 2. Hint to Dapr the mounted Unix socket volume location 3. Attach volume to your pluggable component container -Below is an example of a deployment that configures a pluggable component: +In the following example, your configured pluggable component is deployed as a container within the same pod as your application container. ```yaml apiVersion: apps/v1 @@ -167,17 +167,51 @@ spec: - name: dapr-unix-domain-socket emptyDir: {} containers: - ### --------------------- YOUR APPLICATION CONTAINER GOES HERE ----------- - ## - ### --------------------- YOUR APPLICATION CONTAINER GOES HERE ----------- - ### This is the pluggable component container. + containers: + ### --------------------- YOUR APPLICATION CONTAINER GOES HERE ----------- + - name: app + image: YOUR_APP_IMAGE:YOUR_APP_IMAGE_VERSION + ### --------------------- YOUR PLUGGABLE COMPONENT CONTAINER GOES HERE ----------- - name: component + image: YOUR_IMAGE_GOES_HERE:YOUR_IMAGE_VERSION volumeMounts: # required, the sockets volume mount - name: dapr-unix-domain-socket mountPath: /tmp/dapr-components-sockets image: YOUR_IMAGE_GOES_HERE:YOUR_IMAGE_VERSION ``` +Alternatively, you can annotate your pods, telling Dapr which containers within that pod are pluggable components, like in the example below: + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: app + labels: + app: app +spec: + replicas: 1 + selector: + matchLabels: + app: app + template: + metadata: + labels: + app: app + annotations: + dapr.io/pluggable-components: "component" ## the name of the pluggable component container separated by `,`, e.g "componentA,componentB". + dapr.io/app-id: "my-app" + dapr.io/enabled: "true" + spec: + containers: + ### --------------------- YOUR APPLICATION CONTAINER GOES HERE ----------- + - name: app + image: YOUR_APP_IMAGE:YOUR_APP_IMAGE_VERSION + ### --------------------- YOUR PLUGGABLE COMPONENT CONTAINER GOES HERE ----------- + - name: component + image: YOUR_IMAGE_GOES_HERE:YOUR_IMAGE_VERSION +``` + Before applying the deployment, let's add one more configuration: the component spec. ## Define a component From c408e460ee5d3bb2e807b1ed3f2ba0329ec4f284 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Fri, 3 Feb 2023 16:04:43 -0600 Subject: [PATCH 14/38] remove mapr Signed-off-by: Hannah Hunter --- .../multi-app-dapr-run/_index.md | 4 ++-- .../multi-app-dapr-run/multi-app-overview.md | 16 +++++++------- .../multi-app-dapr-run/multi-app-template.md | 22 +++++++++---------- .../en/getting-started/quickstarts/_index.md | 1 - .../support/support-preview-features.md | 2 +- daprdocs/content/en/reference/cli/dapr-run.md | 2 +- 6 files changed, 23 insertions(+), 24 deletions(-) diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/_index.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/_index.md index c85773ab1..aecd74114 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/_index.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/_index.md @@ -1,7 +1,7 @@ --- type: docs -title: "Multi-app Run (MapR)" -linkTitle: "Multi-app Run (MapR)" +title: "Multi-app Run" +linkTitle: "Multi-app Run" weight: 300 description: "Support for running multiple Dapr applications with one command" --- \ No newline at end of file diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md index b5b8c7b3c..f2f3fd654 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md @@ -1,13 +1,13 @@ --- type: docs -title: Multi-app Run (MapR) overview -linkTitle: MapR overview +title: Multi-app Run overview +linkTitle: Multi-App Run overview weight: 1000 description: Learn the scenarios around running multiple applications with one CLI command --- {{% alert title="Note" color="primary" %}} - MapR (Multi-app Run using `dapr run -f`) is currently a preview feature only supported in Linux/MacOS. + Multi-App Run is currently a preview feature only supported in Linux/MacOS. {{% /alert %}} Let's say you want to run several applications locally to test them together, similar to a production scenario. With a local Kubernetes cluster, you'd be able to do this with helm/deployment YAML files. You'd also have to build them as containers and set up Kubernetes, which can add some complexity. @@ -21,7 +21,7 @@ Instead, you simply want to run them as local executables in self-hosted mode. With Multi-app Run, you can start multiple applications in self-hosted mode using a single `dapr run -f` command using a template file. The template file describes how to start multiple applications as if you had run many separate CLI `run`commands. By default, this template file is called `dapr.yaml`. -## MapR template file +## Multi-App Run template file When you execute `dapr run -f .`, it uses the multi-app template file (named `dapr.yaml`) present in the current directory to run all the applications. @@ -49,7 +49,7 @@ For a more in-depth example and explanation of the template properties, see [Mul ## Locations for resources and configuration files -You have options on where to place your applications' resources and configuration files when using MapR. +You have options on where to place your applications' resources and configuration files when using Multi-App Run. ### Point to one file location (with convention) @@ -57,7 +57,7 @@ You can set all of your applications resources and configurations at the `~/.dap ### Separate file locations for each application (with convention) -When using MapR, each application directory can have a `.dapr` folder, which contains a `config.yaml` file and a `resources` directory. Otherwise, if the `.dapr` directory is not present within the app directory, the default `~/.dapr/resources/` and `~/.dapr/config.yaml` locations are used. +When using Multi-App Run, each application directory can have a `.dapr` folder, which contains a `config.yaml` file and a `resources` directory. Otherwise, if the `.dapr` directory is not present within the app directory, the default `~/.dapr/resources/` and `~/.dapr/config.yaml` locations are used. If you decide to add a `.dapr` directory in each application directory, with a `/resources` directory and `config.yaml` file, you can specify different resources paths for each application. This approach remains within convention by using the default `~/.dapr`. @@ -76,10 +76,10 @@ Even if you've decided to rename your resources folder to something other than ` ## Watch the demo -Watch [this video for an overview on MapR](https://youtu.be/s1p9MNl4VGo?t=2456): +Watch [this video for an overview on Multi-App Run](https://youtu.be/s1p9MNl4VGo?t=2456): ## Next steps -[Unpack the MapR template file and its properties]({{< ref multi-app-template.md >}}) \ No newline at end of file +[Unpack the Multi-App Run template file and its properties]({{< ref multi-app-template.md >}}) \ No newline at end of file diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md index 4a22f188b..fa0d7dd4f 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md @@ -1,16 +1,16 @@ --- type: docs -title: "How to: Use the MapR template file" -linkTitle: "How to: Use the MapR template" +title: "How to: Use the Multi-App Run template file" +linkTitle: "How to: Use the Multi-App Run template" weight: 2000 -description: Unpack the MapR template file and its properties +description: Unpack the Multi-App Run template file and its properties --- {{% alert title="Note" color="primary" %}} - MapR (Multi-app Run using `dapr run -f`) is currently a preview feature only supported in Linux/MacOS. + Multi-App Run is currently a preview feature only supported in Linux/MacOS. {{% /alert %}} -The MapR template file is a YAML file that you can use to run multiple applications at once. In this guide, you'll learn how to: +The Multi-App Run template file is a YAML file that you can use to run multiple applications at once. In this guide, you'll learn how to: - Use the multi-app template - View started applications - Stop the multi-app template @@ -22,9 +22,9 @@ You can use the multi-app template file in one of the following two ways: ### Execute by providing a directory path -When you provide a directory path, the CLI will try to locate the MapR template file, named `dapr.yaml` by default in the directory. If the file is not found, the CLI will return an error. +When you provide a directory path, the CLI will try to locate the Multi-App Run template file, named `dapr.yaml` by default in the directory. If the file is not found, the CLI will return an error. -Execute the following CLI command to read the MapR template file, named `dapr.yaml` by default: +Execute the following CLI command to read the Multi-App Run template file, named `dapr.yaml` by default: ```cmd // the template file needs to be called `dapr.yaml` by default @@ -34,7 +34,7 @@ dapr run -f ### Execute by providing a file path -If the MapR template file is named something other than `dapr.yaml`, then you can provide the relative or absolute file path to the command: +If the Multi-App Run template file is named something other than `dapr.yaml`, then you can provide the relative or absolute file path to the command: ```cmd dapr run -f ./.yaml @@ -63,7 +63,7 @@ dapr stop -f dapr.yaml ## Template file structure -The MapR template file can include the following properties. Below is an example template showing two applications that are configured with some of the properties. +The Multi-App Run template file can include the following properties. Below is an example template showing two applications that are configured with some of the properties. ```yaml version: 1 @@ -101,7 +101,7 @@ The following rules apply for all the paths present in the template file: ## Template properties -The properties for the MapR template align with the `dapr run` CLI flags, [listed in the CLI reference documentation]({{< ref "dapr-run.md#flags" >}}). +The properties for the Multi-App Run template align with the `dapr run` CLI flags, [listed in the CLI reference documentation]({{< ref "dapr-run.md#flags" >}}). | Properties | Required | Details | Example | @@ -138,6 +138,6 @@ The properties for the MapR template align with the `dapr run` CLI flags, [liste ## Next steps -Watch [this video for an overview on MapR](https://youtu.be/s1p9MNl4VGo?t=2456): +Watch [this video for an overview on Multi-App Run](https://youtu.be/s1p9MNl4VGo?t=2456): diff --git a/daprdocs/content/en/getting-started/quickstarts/_index.md b/daprdocs/content/en/getting-started/quickstarts/_index.md index 4e47d39e4..727b9a17b 100644 --- a/daprdocs/content/en/getting-started/quickstarts/_index.md +++ b/daprdocs/content/en/getting-started/quickstarts/_index.md @@ -29,4 +29,3 @@ Hit the ground running with our Dapr quickstarts, complete with code samples aim | [Secrets Management]({{< ref secrets-quickstart.md >}}) | Securely fetch secrets. | | [Configuration]({{< ref configuration-quickstart.md >}}) | Get configuration items and subscribe for configuration updates. | | [Resiliency]({{< ref resiliency >}}) | Define and apply fault-tolerance policies to your Dapr API requests. | - diff --git a/daprdocs/content/en/operations/support/support-preview-features.md b/daprdocs/content/en/operations/support/support-preview-features.md index e17636760..ec474b0f4 100644 --- a/daprdocs/content/en/operations/support/support-preview-features.md +++ b/daprdocs/content/en/operations/support/support-preview-features.md @@ -19,5 +19,5 @@ For CLI there is no explicit opt-in, just the version that this was first made a | **App Middleware** | Allow middleware components to be executed when making service-to-service calls | N/A | [App Middleware]({{}}) | v1.9 | | **App health checks** | Allows configuring app health checks | `AppHealthCheck` | [App health checks]({{}}) | v1.9 | | **Pluggable components** | Allows creating self-hosted gRPC-based components written in any language that supports gRPC. The following component APIs are supported: State stores, Pub/sub, Bindings | N/A | [Pluggable components concept]({{}})| v1.9 | -| **MapR** | Configure multiple Dapr applications from a single configuration file and run from a single command | `dapr run -f` | [MapR]({{< ref multi-app-dapr-run.md >}}) | v1.10 | +| **Multi-App Run** | Configure multiple Dapr applications from a single configuration file and run from a single command | `dapr run -f` | [Multi-App Run]({{< ref multi-app-dapr-run.md >}}) | v1.10 | | **Workflows** | Author workflows as code to automate and orchestrate tasks within your application, like messaging, state management, and failure handling | N/A | [Workflows concept]({{< ref "components-concept#workflows" >}})| v1.10 | \ No newline at end of file diff --git a/daprdocs/content/en/reference/cli/dapr-run.md b/daprdocs/content/en/reference/cli/dapr-run.md index 67e23a240..9191741f4 100644 --- a/daprdocs/content/en/reference/cli/dapr-run.md +++ b/daprdocs/content/en/reference/cli/dapr-run.md @@ -34,7 +34,7 @@ dapr run [flags] [command] | `--dapr-http-port` | `DAPR_HTTP_PORT` | `3500` | The HTTP port for Dapr to listen on | | `--enable-profiling` | | `false` | Enable "pprof" profiling via an HTTP endpoint | | `--help`, `-h` | | | Print the help message | -| `--run-file`, `-f` | | Linux/Mac: `$HOME/.dapr/dapr.yaml` | Run multiple applications at once using a multi-app run (MapR) template file | +| `--run-file`, `-f` | | Linux/Mac: `$HOME/.dapr/dapr.yaml` | Run multiple applications at once using a Multi-App Run template file | | `--image` | | | Use a custom Docker image. Format is `repository/image` for Docker Hub, or `example.com/repository/image` for a custom registry. | | `--log-level` | | `info` | The log verbosity. Valid values are: `debug`, `info`, `warn`, `error`, `fatal`, or `panic` | | `--enable-api-logging` | | `false` | Enable the logging of all API calls from application to Dapr | From 23eafed4698fb8e4a15b8e56214861275a43faba Mon Sep 17 00:00:00 2001 From: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> Date: Fri, 3 Feb 2023 17:51:37 -0600 Subject: [PATCH 15/38] remove --image-registry from preview features table (#3136) Signed-off-by: Hannah Hunter --- .../content/en/operations/support/support-preview-features.md | 1 - 1 file changed, 1 deletion(-) diff --git a/daprdocs/content/en/operations/support/support-preview-features.md b/daprdocs/content/en/operations/support/support-preview-features.md index 650c7f169..66af5f2cc 100644 --- a/daprdocs/content/en/operations/support/support-preview-features.md +++ b/daprdocs/content/en/operations/support/support-preview-features.md @@ -15,7 +15,6 @@ For CLI there is no explicit opt-in, just the version that this was first made a | Feature | Description | Setting | Documentation | Version introduced | | ---------- |-------------|---------|---------------|-----------------| -| **`--image-registry`** flag in Dapr CLI| In self-hosted mode, you can set this flag to specify any private registry to pull the container images required to install Dapr| N/A | [CLI `init` command reference]({{< ref "dapr-init.md#self-hosted-environment" >}}) | v1.7 | | **App Middleware** | Allow middleware components to be executed when making service-to-service calls | N/A | [App Middleware]({{< ref "middleware.md#app-middleware" >}}) | v1.9 | | **App health checks** | Allows configuring app health checks | `AppHealthCheck` | [App health checks]({{< ref "app-health.md" >}}) | v1.9 | | **Pluggable components** | Allows creating self-hosted gRPC-based components written in any language that supports gRPC. The following component APIs are supported: State stores, Pub/sub, Bindings | N/A | [Pluggable components concept]({{< ref "components-concept#pluggable-components" >}})| v1.9 | From 6602c68775e0e1ce996a565fbc3abbed087097d7 Mon Sep 17 00:00:00 2001 From: Yaron Schneider Date: Fri, 3 Feb 2023 17:20:23 -0800 Subject: [PATCH 16/38] Add metrics regex docs (#3126) * add metrics regex Signed-off-by: yaron2 * Update daprdocs/content/en/operations/monitoring/metrics/metrics-overview.md Co-authored-by: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> Signed-off-by: Yaron Schneider --------- Signed-off-by: yaron2 Signed-off-by: Yaron Schneider Co-authored-by: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> --- .../monitoring/metrics/metrics-overview.md | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/daprdocs/content/en/operations/monitoring/metrics/metrics-overview.md b/daprdocs/content/en/operations/monitoring/metrics/metrics-overview.md index f3091c237..bfe21154e 100644 --- a/daprdocs/content/en/operations/monitoring/metrics/metrics-overview.md +++ b/daprdocs/content/en/operations/monitoring/metrics/metrics-overview.md @@ -72,6 +72,30 @@ spec: enabled: false ``` +## High cardinality metrics + +Depending on your use case, some metrics emitted by Dapr might contain values that have a high cardinality. This might cause increased memory usage for the Dapr process/container and incur expensive egress costs in certain cloud environments. To mitigate this issue, you can set regular expressions for every metric exposed by the Dapr sidecar. [See a list of all Dapr metrics](https://github.com/dapr/dapr/blob/master/docs/development/dapr-metrics.md). + +The following example shows how to apply a regular expression for the label `method` in the metric `dapr_runtime_service_invocation_req_sent_total`: + +```yaml +apiVersion: dapr.io/v1alpha1 +kind: Configuration +metadata: + name: daprConfig +spec: + metric: + enabled: true + rules: + - name: dapr_runtime_service_invocation_req_sent_total + labels: + - name: method + regex: + "orders/": "orders/.+" +``` + +When this configuration is applied, a recorded metric with the `method` label of `orders/a746dhsk293972nz` will be replaced with `orders/`. + ## References * [Howto: Run Prometheus locally]({{< ref prometheus.md >}}) From a54c403e7901eff7379a397b794f0f3db1b46ea4 Mon Sep 17 00:00:00 2001 From: Bert Verstraete Date: Sat, 4 Feb 2023 02:22:10 +0100 Subject: [PATCH 17/38] Expand component metadata templating docs (#3070) * Expand component metadata templating docs - Add info on {namespace} and {appId} template - Reference metadata templating on Kafka component docs Signed-off-by: VerstraeteBert * Update daprdocs/content/en/reference/components-reference/supported-pubsub/setup-apache-kafka.md Co-authored-by: Mark Fussell Signed-off-by: Bert Verstraete * Update daprdocs/content/en/reference/components-reference/supported-bindings/kafka.md Co-authored-by: Mark Fussell Signed-off-by: Bert Verstraete * Fix broken link Co-authored-by: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> Signed-off-by: Bert Verstraete --------- Signed-off-by: VerstraeteBert Signed-off-by: Mark Fussell Signed-off-by: Bert Verstraete Co-authored-by: Mark Fussell Co-authored-by: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> --- .../en/operations/components/component-schema.md | 16 +++++++++++----- .../supported-bindings/kafka.md | 3 +++ .../supported-pubsub/setup-apache-kafka.md | 5 ++++- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/daprdocs/content/en/operations/components/component-schema.md b/daprdocs/content/en/operations/components/component-schema.md index d87ac4017..bf60364cd 100644 --- a/daprdocs/content/en/operations/components/component-schema.md +++ b/daprdocs/content/en/operations/components/component-schema.md @@ -42,9 +42,18 @@ spec: | spec.ignoreErrors | N | Tells the Dapr sidecar to continue initialization if the component fails to load. Default is false | `false` | **spec.metadata** | - | **A key/value pair of component specific configuration. See your component definition for fields**| -### Special metadata values +### Templated metadata values -Metadata values can contain a `{uuid}` tag that is replaced with a randomly generate UUID when the Dapr sidecar starts up. A new UUID is generated on every start up. It can be used, for example, to have a pod on Kubernetes with multiple application instances consuming a [shared MQTT subscription]({{< ref "setup-mqtt3.md" >}}). Below is an example of using the `{uuid}` tag. +Metadata values can contain template tags that are resolved on Dapr sidecar startup. The table below shows the current templating tags that can be used in components. + +| Tag | Details | Example use case | +|-------------|--------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| {uuid} | Randomly generated UUIDv4 | When you need a unique identifier in self-hosted mode; for example, multiple application instances consuming a [shared MQTT subscription]({{< ref "setup-mqtt3.md" >}}) | +| {podName} | Name of the pod containing the Dapr sidecar | Use to have a persisted behavior, where the ConsumerID does not change on restart when using StatefulSets in Kubernetes | +| {namespace} | Namespace where the Dapr sidecar resides combined with its appId | Using a shared `clientId` when multiple application instances consume a Kafka topic in Kubernetes | +| {appID} | The configured `appID` of the resource containing the Dapr sidecar | Having a shared `clientId` when multiple application instances consumer a Kafka topic in self-hosted mode | + +Below is an example of using the `{uuid}` tag in an MQTT pubsub component. Note that multiple template tags can be used in a single metadata value. ```yaml apiVersion: dapr.io/v1alpha1 @@ -67,9 +76,6 @@ spec: value: "false" ``` -The consumerID metadata values can also contain a `{podName}` tag that is replaced with the Kubernetes POD's name when the Dapr sidecar starts up. This can be used to have a persisted behavior where the ConsumerID does not change on restart when using StatefulSets in Kubernetes. - - ## Further reading - [Components concept]({{< ref components-concept.md >}}) - [Reference secrets in component definitions]({{< ref component-secrets.md >}}) diff --git a/daprdocs/content/en/reference/components-reference/supported-bindings/kafka.md b/daprdocs/content/en/reference/components-reference/supported-bindings/kafka.md index 152cfb6a0..9e0234fe8 100644 --- a/daprdocs/content/en/reference/components-reference/supported-bindings/kafka.md +++ b/daprdocs/content/en/reference/components-reference/supported-bindings/kafka.md @@ -11,6 +11,9 @@ aliases: To setup Kafka binding create a component of type `bindings.kafka`. See [this guide]({{< ref "howto-bindings.md#1-create-a-binding" >}}) on how to create and apply a binding configuration. For details on using `secretKeyRef`, see the guide on [how to reference secrets in components]({{< ref component-secrets.md >}}). +All component metadata field values can carry [templated metadata values]({{< ref "component-schema.md#templated-metadata-values" >}}), which are resolved on Dapr sidecar startup. +For example, you can choose to use `{namespace}` as the `consumerGroup`, to enable using the same `appId` in different namespaces using the same topics as described in [this article]({{< ref "howto-namespace.md#with-namespace-consumer-groups">}}). + ```yaml apiVersion: dapr.io/v1alpha1 kind: Component diff --git a/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-apache-kafka.md b/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-apache-kafka.md index a18b8c261..b1b0efab6 100644 --- a/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-apache-kafka.md +++ b/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-apache-kafka.md @@ -11,6 +11,9 @@ aliases: To setup Apache Kafka pubsub create a component of type `pubsub.kafka`. See [this guide]({{< ref "howto-publish-subscribe.md#step-1-setup-the-pubsub-component" >}}) on how to create and apply a pubsub configuration. For details on using `secretKeyRef`, see the guide on [how to reference secrets in components]({{< ref component-secrets.md >}}). +All component metadata field values can carry [templated metadata values]({{< ref "component-schema.md#templated-metadata-values" >}}), which are resolved on Dapr sidecar startup. +For example, you can choose to use `{namespace}` as the `consumerGroup` to enable using the same `appId` in different namespaces using the same topics as described in [this article]({{< ref "howto-namespace.md#with-namespace-consumer-groups">}}). + ```yaml apiVersion: dapr.io/v1alpha1 kind: Component @@ -23,7 +26,7 @@ spec: - name: brokers # Required. Kafka broker connection setting value: "dapr-kafka.myapp.svc.cluster.local:9092" - name: consumerGroup # Optional. Used for input bindings. - value: "group1" + value: "{namespace}" - name: clientID # Optional. Used as client tracing ID by Kafka brokers. value: "my-dapr-app-id" - name: authType # Required. From 1c979a94d5fd368c3d855aa09cc210c3069267a4 Mon Sep 17 00:00:00 2001 From: Ryan Lettieri Date: Sun, 5 Feb 2023 16:15:52 -0700 Subject: [PATCH 18/38] Adding in description for managing workflows Signed-off-by: Ryan Lettieri --- .../workflow/howto-manage-workflow.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/daprdocs/content/en/developing-applications/building-blocks/workflow/howto-manage-workflow.md b/daprdocs/content/en/developing-applications/building-blocks/workflow/howto-manage-workflow.md index 57f94591a..69c49edb5 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/workflow/howto-manage-workflow.md +++ b/daprdocs/content/en/developing-applications/building-blocks/workflow/howto-manage-workflow.md @@ -16,7 +16,21 @@ Now that you've [set up the workflow and its activities in your application]({{< Manage your workflow within your code. In the `OrderProcessingWorkflow` example from the [Author a workflow]({{< ref "howto-author-workflow.md#write-the-workflow" >}}) guide, the workflow is registered in the code. You can then start, terminate, and get information about the workflow: ```csharp +string orderId = "exampleOrderId"; +string workflowComponent = "dapr"; +string workflowName = "OrderProcessingWorkflow"; +OrderPayload input = new OrderPayload("Paperclips", 99.95); +Dictionary workflowOptions; // This is an optional parameter +CancellationToken cts = CancellationToken.None; +// Start the workflow. This returns back a "WorkflowReference" which contains the instanceID for the particular workflow instance. +WorkflowReference startResponse = await daprClient.StartWorkflowAsync(orderId, workflowComponent, workflowName, input, workflowOptions, cts); + +// Get information on the workflow. This response will contain information such as the status of the workflow, when it started, and more! +GetWorkflowResponse getResponse = await daprClient.GetWorkflowAsync(orderId, workflowComponent, workflowName); + +// Terminate the workflow +await daprClient.TerminateWorkflowAsync(instanceId, workflowComponent); ``` {{% /codetab %}} From 2b08c5b7fdb14a3f6fa7cb2d4a0aaefa0061412d Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Mon, 6 Feb 2023 11:43:31 -0600 Subject: [PATCH 19/38] updates per mukundan Signed-off-by: Hannah Hunter --- .../multi-app-dapr-run/_index.md | 4 ++-- .../multi-app-dapr-run/multi-app-overview.md | 10 +++++----- .../multi-app-dapr-run/multi-app-template.md | 16 +++++++++------- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/_index.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/_index.md index aecd74114..09a3cd5d7 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/_index.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/_index.md @@ -1,7 +1,7 @@ --- type: docs -title: "Multi-app Run" -linkTitle: "Multi-app Run" +title: "Multi-App Run" +linkTitle: "Multi-App Run" weight: 300 description: "Support for running multiple Dapr applications with one command" --- \ No newline at end of file diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md index f2f3fd654..24b3c9c99 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-overview.md @@ -1,9 +1,9 @@ --- type: docs -title: Multi-app Run overview +title: Multi-App Run overview linkTitle: Multi-App Run overview weight: 1000 -description: Learn the scenarios around running multiple applications with one CLI command +description: Run multiple applications with one CLI command --- {{% alert title="Note" color="primary" %}} @@ -19,7 +19,7 @@ Instead, you simply want to run them as local executables in self-hosted mode. - Remember the resources folders and configuration files that each application refers to. - Recall all of the additional flags you used to tweak the `dapr run` command behavior (`--app-health-check-path`, `--dapr-grpc-port`, `--unix-domain-socket`, etc.) -With Multi-app Run, you can start multiple applications in self-hosted mode using a single `dapr run -f` command using a template file. The template file describes how to start multiple applications as if you had run many separate CLI `run`commands. By default, this template file is called `dapr.yaml`. +With Multi-App Run, you can start multiple applications in self-hosted mode using a single `dapr run -f` command using a template file. The template file describes how to start multiple applications as if you had run many separate CLI `run`commands. By default, this template file is called `dapr.yaml`. ## Multi-App Run template file @@ -27,7 +27,7 @@ When you execute `dapr run -f .`, it uses the multi-app template file (named `da You can name template file with preferred name other than the default. For example `dapr run -f ./.yaml`. -The following `dapr.yaml` example includes some of the template properties you can customize for your applications. In the example, you can simultaneously launch 2 applications with app IDs of `processor` and `emit-metrics`. +The following example includes some of the template properties you can customize for your applications. In the example, you can simultaneously launch 2 applications with app IDs of `processor` and `emit-metrics`. ```yaml version: 1 @@ -82,4 +82,4 @@ Watch [this video for an overview on Multi-App Run](https://youtu.be/s1p9MNl4VGo ## Next steps -[Unpack the Multi-App Run template file and its properties]({{< ref multi-app-template.md >}}) \ No newline at end of file +[Learn the Multi-App Run template file structure and its properties]({{< ref multi-app-template.md >}}) \ No newline at end of file diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md index fa0d7dd4f..ce943f01b 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md @@ -27,7 +27,7 @@ When you provide a directory path, the CLI will try to locate the Multi-App Run Execute the following CLI command to read the Multi-App Run template file, named `dapr.yaml` by default: ```cmd -// the template file needs to be called `dapr.yaml` by default +# the template file needs to be called `dapr.yaml` by default if a directory path is given dapr run -f ``` @@ -37,7 +37,7 @@ dapr run -f If the Multi-App Run template file is named something other than `dapr.yaml`, then you can provide the relative or absolute file path to the command: ```cmd -dapr run -f ./.yaml +dapr run -f ./path/to/.yaml ``` ## View the started applications @@ -53,12 +53,14 @@ dapr list Stop the multi-app run template anytime with either of the following commands: ```cmd +# the template file needs to be called `dapr.yaml` by default if a directory path is given + dapr stop -f ``` or: ```cmd -dapr stop -f dapr.yaml +dapr stop -f ./path/to/.yaml ``` ## Template file structure @@ -72,16 +74,16 @@ common: # optional section for variables shared across apps env: # any environment variable shared across apps - DEBUG: true apps: - - appID: webapp - appDirPath: .dapr/webapp/ # required + - appID: webapp # optional + appDirPath: .dapr/webapp/ # REQUIRED resourcesPath: .dapr/resources # (optional) can be default by convention configFilePath: .dapr/config.yaml # (optional) can be default by convention too, ignore if file is not found. appProtocol: HTTP appPort: 8080 appHealthCheckPath: "/healthz" command: ["python3" "app.py"] - - appID: backend - appDirPath: .dapr/backend/ + - appID: backend # optional + appDirPath: .dapr/backend/ # REQUIRED appProtocol: GRPC appPort: 3000 unixDomainSocket: "/tmp/test-socket" From 30a1c865518ffe2d63e9a5212d427b940038b068 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Tue, 7 Feb 2023 08:22:14 -0600 Subject: [PATCH 20/38] add to dapr stop doc and update metadata table Signed-off-by: Hannah Hunter --- .../multi-app-dapr-run/multi-app-template.md | 2 +- daprdocs/content/en/reference/cli/dapr-stop.md | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md index ce943f01b..a0ef21650 100644 --- a/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md +++ b/daprdocs/content/en/developing-applications/local-development/multi-app-dapr-run/multi-app-template.md @@ -135,7 +135,7 @@ The properties for the Multi-App Run template align with the `dapr run` CLI flag | `appHealthProbeTimeout` | N | Timeout for app health probes in milliseconds | | | `appHealthThreshold` | N | Number of consecutive failures for the app to be considered unhealthy | | | `enableApiLogging` | N | Enable the logging of all API calls from application to Dapr | | -| `daprPath` | N | Dapr install path | | +| `runtimePath` | N | Dapr runtime install path | | | `env` | N | Map to environment variable; environment variables applied per application will overwrite environment variables shared across applications | `DEBUG`, `DAPR_HOST_ADD` | ## Next steps diff --git a/daprdocs/content/en/reference/cli/dapr-stop.md b/daprdocs/content/en/reference/cli/dapr-stop.md index 2f9a47d00..c5fe074b1 100644 --- a/daprdocs/content/en/reference/cli/dapr-stop.md +++ b/daprdocs/content/en/reference/cli/dapr-stop.md @@ -21,10 +21,11 @@ dapr stop [flags] ### Flags -| Name | Environment Variable | Default | Description | -| ---------------- | -------------------- | ------- | -------------------------------- | -| `--app-id`, `-a` | `APP_ID` | | The application id to be stopped | -| `--help`, `-h` | | | Print this help message | +| Name | Environment Variable | Default | Description | +| -------------------- | -------------------- | ------- | -------------------------------- | +| `--app-id`, `-a` | `APP_ID` | | The application id to be stopped | +| `--help`, `-h` | | | Print this help message | +| `--run-file`, `-f` | | | Stop running multiple applications at once using a Multi-App Run template file | ### Examples From ffe2f31dfd7af00c9a610a6469a31d6769f1f57c Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Tue, 7 Feb 2023 08:43:12 -0600 Subject: [PATCH 21/38] add runtime path flag to dapr run doc Signed-off-by: Hannah Hunter --- daprdocs/content/en/reference/cli/dapr-run.md | 1 + 1 file changed, 1 insertion(+) diff --git a/daprdocs/content/en/reference/cli/dapr-run.md b/daprdocs/content/en/reference/cli/dapr-run.md index 9191741f4..9f47c6924 100644 --- a/daprdocs/content/en/reference/cli/dapr-run.md +++ b/daprdocs/content/en/reference/cli/dapr-run.md @@ -29,6 +29,7 @@ dapr run [flags] [command] | `--app-protocol`, `-P` | | `http` | The protocol Dapr uses to talk to the application. Valid values are: `http` or `grpc` | | `--app-ssl` | | `false` | Enable https when Dapr invokes the application | | `--resources-path`, `-d` | | Linux/Mac: `$HOME/.dapr/components`
Windows: `%USERPROFILE%\.dapr\components` | The path for components directory | +| `runtimePath` | | | Dapr runtime install path | | `--config`, `-c` | | Linux/Mac: `$HOME/.dapr/config.yaml`
Windows: `%USERPROFILE%\.dapr\config.yaml` | Dapr configuration file | | `--dapr-grpc-port` | `DAPR_GRPC_PORT` | `50001` | The gRPC port for Dapr to listen on | | `--dapr-http-port` | `DAPR_HTTP_PORT` | `3500` | The HTTP port for Dapr to listen on | From cc14a4e6f0d7fd3912d513848d061112a4951174 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Tue, 7 Feb 2023 08:50:50 -0600 Subject: [PATCH 22/38] update to snake case in dapr run Signed-off-by: Hannah Hunter --- daprdocs/content/en/reference/cli/dapr-run.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daprdocs/content/en/reference/cli/dapr-run.md b/daprdocs/content/en/reference/cli/dapr-run.md index 9f47c6924..0ebfb51db 100644 --- a/daprdocs/content/en/reference/cli/dapr-run.md +++ b/daprdocs/content/en/reference/cli/dapr-run.md @@ -29,7 +29,7 @@ dapr run [flags] [command] | `--app-protocol`, `-P` | | `http` | The protocol Dapr uses to talk to the application. Valid values are: `http` or `grpc` | | `--app-ssl` | | `false` | Enable https when Dapr invokes the application | | `--resources-path`, `-d` | | Linux/Mac: `$HOME/.dapr/components`
Windows: `%USERPROFILE%\.dapr\components` | The path for components directory | -| `runtimePath` | | | Dapr runtime install path | +| `runtime-path` | | | Dapr runtime install path | | `--config`, `-c` | | Linux/Mac: `$HOME/.dapr/config.yaml`
Windows: `%USERPROFILE%\.dapr\config.yaml` | Dapr configuration file | | `--dapr-grpc-port` | `DAPR_GRPC_PORT` | `50001` | The gRPC port for Dapr to listen on | | `--dapr-http-port` | `DAPR_HTTP_PORT` | `3500` | The HTTP port for Dapr to listen on | From e90e505145ef6fc388ee3750d5cf48a6a9cccdf3 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Tue, 7 Feb 2023 08:53:21 -0600 Subject: [PATCH 23/38] add alpha state and availability to dapr stop Signed-off-by: Hannah Hunter --- daprdocs/content/en/reference/cli/dapr-stop.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daprdocs/content/en/reference/cli/dapr-stop.md b/daprdocs/content/en/reference/cli/dapr-stop.md index c5fe074b1..0bb20213f 100644 --- a/daprdocs/content/en/reference/cli/dapr-stop.md +++ b/daprdocs/content/en/reference/cli/dapr-stop.md @@ -25,7 +25,7 @@ dapr stop [flags] | -------------------- | -------------------- | ------- | -------------------------------- | | `--app-id`, `-a` | `APP_ID` | | The application id to be stopped | | `--help`, `-h` | | | Print this help message | -| `--run-file`, `-f` | | | Stop running multiple applications at once using a Multi-App Run template file | +| `--run-file`, `-f` | | | Stop running multiple applications at once using a Multi-App Run template file. Currently in [alpha]({{< ref "support-preview-features.md" >}}) and only availale in Linux/MacOS | ### Examples From 101d55db8ef72b60ff417e1d555b3f6e5d99f2ca Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Tue, 7 Feb 2023 08:54:27 -0600 Subject: [PATCH 24/38] also add note about alpha and linux/macos to dapr run Signed-off-by: Hannah Hunter --- daprdocs/content/en/reference/cli/dapr-run.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daprdocs/content/en/reference/cli/dapr-run.md b/daprdocs/content/en/reference/cli/dapr-run.md index 0ebfb51db..f1b15f462 100644 --- a/daprdocs/content/en/reference/cli/dapr-run.md +++ b/daprdocs/content/en/reference/cli/dapr-run.md @@ -35,7 +35,7 @@ dapr run [flags] [command] | `--dapr-http-port` | `DAPR_HTTP_PORT` | `3500` | The HTTP port for Dapr to listen on | | `--enable-profiling` | | `false` | Enable "pprof" profiling via an HTTP endpoint | | `--help`, `-h` | | | Print the help message | -| `--run-file`, `-f` | | Linux/Mac: `$HOME/.dapr/dapr.yaml` | Run multiple applications at once using a Multi-App Run template file | +| `--run-file`, `-f` | | Linux/MacOS: `$HOME/.dapr/dapr.yaml` | Run multiple applications at once using a Multi-App Run template file. Currently in [alpha]({{< ref "support-preview-features.md" >}}) and only availale in Linux/MacOS | | `--image` | | | Use a custom Docker image. Format is `repository/image` for Docker Hub, or `example.com/repository/image` for a custom registry. | | `--log-level` | | `info` | The log verbosity. Valid values are: `debug`, `info`, `warn`, `error`, `fatal`, or `panic` | | `--enable-api-logging` | | `false` | Enable the logging of all API calls from application to Dapr | From 3ff4313d117021ee8d1893f6097a1bf1ccdfc6b7 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Tue, 7 Feb 2023 09:05:09 -0600 Subject: [PATCH 25/38] nit Signed-off-by: Hannah Hunter --- daprdocs/content/en/reference/cli/dapr-run.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daprdocs/content/en/reference/cli/dapr-run.md b/daprdocs/content/en/reference/cli/dapr-run.md index f1b15f462..9973a128c 100644 --- a/daprdocs/content/en/reference/cli/dapr-run.md +++ b/daprdocs/content/en/reference/cli/dapr-run.md @@ -29,7 +29,7 @@ dapr run [flags] [command] | `--app-protocol`, `-P` | | `http` | The protocol Dapr uses to talk to the application. Valid values are: `http` or `grpc` | | `--app-ssl` | | `false` | Enable https when Dapr invokes the application | | `--resources-path`, `-d` | | Linux/Mac: `$HOME/.dapr/components`
Windows: `%USERPROFILE%\.dapr\components` | The path for components directory | -| `runtime-path` | | | Dapr runtime install path | +| `--runtime-path` | | | Dapr runtime install path | | `--config`, `-c` | | Linux/Mac: `$HOME/.dapr/config.yaml`
Windows: `%USERPROFILE%\.dapr\config.yaml` | Dapr configuration file | | `--dapr-grpc-port` | `DAPR_GRPC_PORT` | `50001` | The gRPC port for Dapr to listen on | | `--dapr-http-port` | `DAPR_HTTP_PORT` | `3500` | The HTTP port for Dapr to listen on | From b0bf194c810af5b71c49723b7421b6c3cda070f7 Mon Sep 17 00:00:00 2001 From: "Alessandro (Ale) Segala" <43508+ItalyPaleAle@users.noreply.github.com> Date: Tue, 7 Feb 2023 19:48:35 -0800 Subject: [PATCH 26/38] Docs for SQLite state store (#3099) * Docs for SQLite state store Fixes #3085 Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> * Update daprdocs/content/en/reference/components-reference/supported-state-stores/setup-sqlite.md Co-authored-by: Mark Fussell Signed-off-by: Alessandro (Ale) Segala <43508+ItalyPaleAle@users.noreply.github.com> * Explain relative paths Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> Signed-off-by: Alessandro (Ale) Segala <43508+ItalyPaleAle@users.noreply.github.com> * Clarify that URI options require the `file:` prefix Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> * Add note for in-memory DBs Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> --------- Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> Signed-off-by: Alessandro (Ale) Segala <43508+ItalyPaleAle@users.noreply.github.com> Co-authored-by: Mark Fussell Co-authored-by: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> --- .../supported-state-stores/setup-sqlite.md | 86 +++++++++++++++++++ .../data/components/state_stores/generic.yaml | 11 +++ 2 files changed, 97 insertions(+) create mode 100644 daprdocs/content/en/reference/components-reference/supported-state-stores/setup-sqlite.md diff --git a/daprdocs/content/en/reference/components-reference/supported-state-stores/setup-sqlite.md b/daprdocs/content/en/reference/components-reference/supported-state-stores/setup-sqlite.md new file mode 100644 index 000000000..1415e0d8b --- /dev/null +++ b/daprdocs/content/en/reference/components-reference/supported-state-stores/setup-sqlite.md @@ -0,0 +1,86 @@ +--- +type: docs +title: "SQLite" +linkTitle: "SQLite" +description: Detailed information on the SQLite state store component +aliases: + - "/operations/components/setup-state-store/supported-state-stores/setup-sqlite/" +--- + +This component allows using SQLite 3 as state store for Dapr. + +> The component is currently compiled with SQLite version 3.40.1. + +## Create a Dapr component + +Create a file called `sqlite.yaml`, paste the following, and replace the `` value with your connection string, which is the path to a file on disk. + +If you want to also configure SQLite to store actors, add the `actorStateStore` option as in the example below. + +```yaml +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: +spec: + type: state.sqlite + version: v1 + metadata: + # Connection string + - name: connectionString + value: "data.db" + # Timeout for database operations, in seconds (optional) + #- name: timeoutInSeconds + # value: 20 + # Name of the table where to store the state (optional) + #- name: tableName + # value: "state" + # Cleanup interval in seconds, to remove expired rows (optional) + #- name: cleanupIntervalInSeconds + # value: 3600 + # Uncomment this if you wish to use SQLite as a state store for actors (optional) + #- name: actorStateStore + # value: "true" +``` + +## Spec metadata fields + +| Field | Required | Details | Example | +|--------------------|:--------:|---------|---------| +| `connectionString` | Y | The connection string for the SQLite database. See below for more details. | `"path/to/data.db"`, `"file::memory:?cache=shared"` +| `timeoutInSeconds` | N | Timeout, in seconds, for all database operations. Defaults to `20` | `30` +| `tableName` | N | Name of the table where the data is stored. Defaults to `state`. | `"state"` +| `cleanupIntervalInSeconds` | N | Interval, in seconds, to clean up rows with an expired TTL. Default: `3600` (i.e. 1 hour). Setting this to values <=0 disables the periodic cleanup. | `1800`, `-1` +| `actorStateStore` | N | Consider this state store for actors. Defaults to `"false"` | `"true"`, `"false"` + +The **`connectionString`** parameter configures how to open the SQLite database. + +- Normally, this is the path to a file on disk, relative to the current working directory, or absolute. For example: `"data.db"` (relative to the working directory) or `"/mnt/data/mydata.db"`. +- The path is interpreted by the SQLite library, so it's possible to pass additional options to the SQLite driver using "URI options" if the path begins with `file:`. For example: `"file:path/to/data.db?mode=ro"` opens the database at path `path/to/data.db` in read-only mode. [Refer to the SQLite documentation for all supported URI options](https://www.sqlite.org/uri.html). +- The special case `":memory:"` launches the component backed by an in-memory SQLite database. This database is not persisted on disk, not shared across multiple Dapr instances, and all data is lost when the Dapr sidecar is stopped. When using an in-memory database, you should always set the `?cache=shared` URI option: `"file::memory:?cache=shared"` + +## Advanced + +### TTLs and cleanups + +This state store supports [Time-To-Live (TTL)]({{< ref state-store-ttl.md >}}) for records stored with Dapr. When storing data using Dapr, you can set the `ttlInSeconds` metadata property to indicate when the data should be considered "expired". + +Because SQLite doesn't have built-in support for TTLs, this is implemented in Dapr by adding a column in the state table indicating when the data is to be considered "expired". Records that are "expired" are not returned to the caller, even if they're still physically stored in the database. A background "garbage collector" periodically scans the state table for expired rows and deletes them. + +The `cleanupIntervalInSeconds` metadata property sets the expired records deletion interval, which defaults to 3600 seconds (that is, 1 hour). + +- Longer intervals require less frequent scans for expired rows, but can require storing expired records for longer, potentially requiring more storage space. If you plan to store many records in your state table, with short TTLs, consider setting `cleanupIntervalInSeconds` to a smaller value, for example `300` (300 seconds, or 5 minutes). +- If you do not plan to use TTLs with Dapr and the SQLite state store, you should consider setting `cleanupIntervalInSeconds` to a value <= 0 (e.g. `0` or `-1`) to disable the periodic cleanup and reduce the load on the database. + +The `expiration_time` column in the state table, where the expiration date for records is stored, **does not have an index by default**, so each periodic cleanup must perform a full-table scan. If you have a table with a very large number of records, and only some of them use a TTL, you may find it useful to create an index on that column. Assuming that your state table name is `state` (the default), you can use this query: + +```sql +CREATE INDEX idx_expiration_time + ON state (expiration_time); +``` + +## 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 >}}) diff --git a/daprdocs/data/components/state_stores/generic.yaml b/daprdocs/data/components/state_stores/generic.yaml index 5f8506cae..9a6ef7d0e 100644 --- a/daprdocs/data/components/state_stores/generic.yaml +++ b/daprdocs/data/components/state_stores/generic.yaml @@ -163,6 +163,17 @@ etag: false ttl: false query: false +- component: SQLite + link: setup-sqlite + state: Beta + version: v1 + since: "1.10" + features: + crud: true + transactions: true + etag: true + ttl: true + query: false - component: Zookeeper link: setup-zookeeper state: Alpha From efcb297f17733e6746820d5227b5502445f9066f Mon Sep 17 00:00:00 2001 From: Mukundan Sundararajan <65565396+mukundansundar@users.noreply.github.com> Date: Wed, 8 Feb 2023 09:30:12 +0530 Subject: [PATCH 27/38] Kafka bulk support documentation (#3071) * add initial docs for kafka bulk support Signed-off-by: Mukundan Sundararajan <65565396+mukundansundar@users.noreply.github.com> * address review comments Signed-off-by: Mukundan Sundararajan <65565396+mukundansundar@users.noreply.github.com> --------- Signed-off-by: Mukundan Sundararajan <65565396+mukundansundar@users.noreply.github.com> --- .../supported-pubsub/setup-apache-kafka.md | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-apache-kafka.md b/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-apache-kafka.md index b1b0efab6..1d844e945 100644 --- a/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-apache-kafka.md +++ b/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-apache-kafka.md @@ -111,7 +111,7 @@ spec: value: 200ms - name: version # Optional. value: 0.10.2.0 - - name: disableTls + - name: disableTls value: "true" ``` @@ -201,13 +201,13 @@ spec: #### OAuth2 or OpenID Connect -Setting `authType` to `oidc` enables SASL authentication via the **OAUTHBEARER** mechanism. This supports specifying a bearer token from an external OAuth2 or [OIDC](https://en.wikipedia.org/wiki/OpenID) identity provider. Currently, only the **client_credentials** grant is supported. +Setting `authType` to `oidc` enables SASL authentication via the **OAUTHBEARER** mechanism. This supports specifying a bearer token from an external OAuth2 or [OIDC](https://en.wikipedia.org/wiki/OpenID) identity provider. Currently, only the **client_credentials** grant is supported. -Configure `oidcTokenEndpoint` to the full URL for the identity provider access token endpoint. +Configure `oidcTokenEndpoint` to the full URL for the identity provider access token endpoint. -Set `oidcClientID` and `oidcClientSecret` to the client credentials provisioned in the identity provider. +Set `oidcClientID` and `oidcClientSecret` to the client credentials provisioned in the identity provider. -If `caCert` is specified in the component configuration, the certificate is appended to the system CA trust for verifying the identity provider certificate. Similarly, if `skipVerify` is specified in the component configuration, verification will also be skipped when accessing the identity provider. +If `caCert` is specified in the component configuration, the certificate is appended to the system CA trust for verifying the identity provider certificate. Similarly, if `skipVerify` is specified in the component configuration, verification will also be skipped when accessing the identity provider. By default, the only scope requested for the token is `openid`; it is **highly** recommended that additional scopes be specified via `oidcScopes` in a comma-separated list and validated by the Kafka broker. If additional scopes are not used to narrow the validity of the access token, a compromised Kafka broker could replay the token to access other services as the Dapr clientID. @@ -296,6 +296,19 @@ auth: secretStore: ``` +## Sending and receiving multiple messages + +Apache Kafka component supports sending and receiving multiple messages in a single operation using the bulk Pub/sub API. + +### Configuring bulk subscribe + +When subscribing to a topic, you can configure `bulkSubscribe` options. Refer to [Subscription methods]({{< ref subscription-methods >}}) for more details. Learn more about [the bulk subscribe API]({{< ref pubsub-bulk.md >}}). + +| Configuration | Default | +|----------|---------| +| `maxBulkAwaitDurationMs` | `10000` (10s) | +| `maxBulkSubCount` | `80` | + ## Per-call metadata fields ### Partition Key From cb8395cd9d014c5e396c9bd2713c25f316f9b6c7 Mon Sep 17 00:00:00 2001 From: Bernd Verst Date: Tue, 7 Feb 2023 20:02:13 -0800 Subject: [PATCH 28/38] deprecate twitter (#3145) Signed-off-by: Bernd Verst --- .../components-reference/supported-bindings/twitter.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/daprdocs/content/en/reference/components-reference/supported-bindings/twitter.md b/daprdocs/content/en/reference/components-reference/supported-bindings/twitter.md index 8bfc6fdf4..0e1c57a70 100644 --- a/daprdocs/content/en/reference/components-reference/supported-bindings/twitter.md +++ b/daprdocs/content/en/reference/components-reference/supported-bindings/twitter.md @@ -7,6 +7,10 @@ aliases: - "/operations/components/setup-bindings/supported-bindings/twitter/" --- +{{% alert title="Deprecation notice" color="warning" %}} +The Twitter binding component has been deprecated and will be removed in a future release. See [this GitHub issue](https://github.com/dapr/components-contrib/issues/2503) for details. +{{% /alert %}} + ## Component format To setup Twitter binding create a component of type `bindings.twitter`. See [this guide]({{< ref "howto-bindings.md#1-create-a-binding" >}}) on how to create and apply a binding configuration. From cfb47e9db7811a19294d455dc238bef40fc74359 Mon Sep 17 00:00:00 2001 From: "Alessandro (Ale) Segala" <43508+ItalyPaleAle@users.noreply.github.com> Date: Tue, 7 Feb 2023 22:09:32 -0800 Subject: [PATCH 29/38] Docs for ServiceInvocationStreaming feature flag (#3102) * Docs for ServiceInvocationStreaming feature flag Fixes #3096 Also removes the Resiliency feature flag from the table Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> * Future note Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> * Added diagram Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> * Update daprdocs/content/en/operations/support/support-preview-features.md Co-authored-by: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> Signed-off-by: Alessandro (Ale) Segala <43508+ItalyPaleAle@users.noreply.github.com> --------- Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> Signed-off-by: Alessandro (Ale) Segala <43508+ItalyPaleAle@users.noreply.github.com> Co-authored-by: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> --- .../support/support-preview-features.md | 30 ++++++++++++++++-- .../images/service-invocation-simple.webp | Bin 0 -> 38786 bytes 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 daprdocs/static/images/service-invocation-simple.webp diff --git a/daprdocs/content/en/operations/support/support-preview-features.md b/daprdocs/content/en/operations/support/support-preview-features.md index e8f1e5867..ab4c93d40 100644 --- a/daprdocs/content/en/operations/support/support-preview-features.md +++ b/daprdocs/content/en/operations/support/support-preview-features.md @@ -14,9 +14,35 @@ For CLI there is no explicit opt-in, just the version that this was first made a ## Current preview features | Feature | Description | Setting | Documentation | Version introduced | -| ---------- |-------------|---------|---------------|-----------------| | **App Middleware** | Allow middleware components to be executed when making service-to-service calls | N/A | [App Middleware]({{}}) | v1.9 | +| **Streaming for HTTP service invocation** | Enables (partial) support for using streams in HTTP service invocation; see below for more details. | `ServiceInvocationStreaming` | [Details]({{< ref "support-preview-features.md#streaming-for-http-service-invocation" >}}) | v1.10 | | **App health checks** | Allows configuring app health checks | `AppHealthCheck` | [App health checks]({{}}) | v1.9 | | **Pluggable components** | Allows creating self-hosted gRPC-based components written in any language that supports gRPC. The following component APIs are supported: State stores, Pub/sub, Bindings | N/A | [Pluggable components concept]({{}})| v1.9 | | **Multi-App Run** | Configure multiple Dapr applications from a single configuration file and run from a single command | `dapr run -f` | [Multi-App Run]({{< ref multi-app-dapr-run.md >}}) | v1.10 | -| **Workflows** | Author workflows as code to automate and orchestrate tasks within your application, like messaging, state management, and failure handling | N/A | [Workflows concept]({{< ref "components-concept#workflows" >}})| v1.10 | \ No newline at end of file +| **Workflows** | Author workflows as code to automate and orchestrate tasks within your application, like messaging, state management, and failure handling | N/A | [Workflows concept]({{< ref "components-concept#workflows" >}})| v1.10 | + +### Streaming for HTTP service invocation + +Running Dapr with the `ServiceInvocationStreaming` feature flag enables partial support for handling data as a stream in HTTP service invocation. This can offer improvements in performance and memory utilization when using Dapr to invoke another service using HTTP with large request or response bodies. + +The table below summarizes the current state of support for streaming in HTTP service invocation in Dapr, including the impact of enabling `ServiceInvocationStreaming`, in the example where "app A" is invoking "app B" using Dapr. There are six steps in the data flow, with various levels of support for handling data as a stream: + +Diagram showing the steps of service invocation described in the table below + +| Step | Handles data as a stream | Dapr 1.10 | Dapr 1.10 with
`ServiceInvocationStreaming` | +|:---:|---|:---:|:---:| +| 1 | Request: "App A" to "Dapr sidecar A | | | +| 2 | Request: "Dapr sidecar A" to "Dapr sidecar B | | | +| 3 | Request: "Dapr sidecar B" to "App B" | | | +| 4 | Response: "App B" to "Dapr sidecar B" | | | +| 5 | Response: "Dapr sidecar B" to "Dapr sidecar A | | | +| 6 | Response: "Dapr sidecar A" to "App A | | | + +Important notes: + +- `ServiceInvocationStreaming` needs to be applied on caller sidecars only. + In the example above, streams are used for HTTP service invocation if `ServiceInvocationStreaming` is applied to the configuration of "app A" and its Dapr sidecar, regardless of whether the feature flag is enabled for "app B" and its sidecar. +- When `ServiceInvocationStreaming` is enabled, you should make sure that all services your app invokes using Dapr ("app B") are updated to Dapr 1.10, even if `ServiceInvocationStreaming` is not enabled for those sidecars. + Invoking an app using Dapr 1.9 or older is still possible, but those calls may fail if you have applied a Dapr Resiliency policy with retries enabled. + +> Full support for streaming for HTTP service invocation will be completed in a future Dapr version. diff --git a/daprdocs/static/images/service-invocation-simple.webp b/daprdocs/static/images/service-invocation-simple.webp new file mode 100644 index 0000000000000000000000000000000000000000..a4fbc7ba3af3a593d81ee41660006bca83c476cb GIT binary patch literal 38786 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 literal 0 HcmV?d00001 From bc48a091046b9b0ef202120de9be8d8c610ff141 Mon Sep 17 00:00:00 2001 From: "Alessandro (Ale) Segala" <43508+ItalyPaleAle@users.noreply.github.com> Date: Tue, 7 Feb 2023 22:51:01 -0800 Subject: [PATCH 30/38] Add docs for `pubsub.azure.servicebus.queues` component and update metadata for all other Service Bus components (#3097) * Add docs for `pubsub.azure.servicebus.queues` component and update metadata for all other Service Bus components Fixes #2912 Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> * Updated per review feedback Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> --------- Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> --- .../supported-bindings/servicebusqueues.md | 70 +++++--- ...us.md => setup-azure-servicebus-queues.md} | 58 +++--- .../setup-azure-servicebus-topics.md | 166 ++++++++++++++++++ daprdocs/data/components/pubsub/azure.yaml | 12 +- 4 files changed, 251 insertions(+), 55 deletions(-) rename daprdocs/content/en/reference/components-reference/supported-pubsub/{setup-azure-servicebus.md => setup-azure-servicebus-queues.md} (63%) create mode 100644 daprdocs/content/en/reference/components-reference/supported-pubsub/setup-azure-servicebus-topics.md diff --git a/daprdocs/content/en/reference/components-reference/supported-bindings/servicebusqueues.md b/daprdocs/content/en/reference/components-reference/supported-bindings/servicebusqueues.md index f33bfceeb..8e5bab356 100644 --- a/daprdocs/content/en/reference/components-reference/supported-bindings/servicebusqueues.md +++ b/daprdocs/content/en/reference/components-reference/supported-bindings/servicebusqueues.md @@ -23,25 +23,39 @@ spec: version: v1 metadata: - name: connectionString # Required when not using Azure Authentication. - value: "Endpoint=sb://************" + value: "Endpoint=sb://{ServiceBusNamespace}.servicebus.windows.net/;SharedAccessKeyName={PolicyName};SharedAccessKey={Key};EntityPath={ServiceBus}" - name: queueName value: queue1 - # - name: ttlInSeconds # Optional - # value: 86400 - # - name: maxRetriableErrorsPerSec # Optional + # - name: timeoutInSec # Optional + # value: 60 + # - name: handlerTimeoutInSec # Optional + # value: 60 + # - name: disableEntityManagement # Optional + # value: "false" + # - name: maxDeliveryCount # Optional + # value: 3 + # - name: lockDurationInSec # Optional + # value: 60 + # - name: lockRenewalInSec # Optional + # value: 20 + # - name: maxActiveMessages # Optional + # value: 10000 + # - name: maxConcurrentHandlers # Optional # value: 10 + # - name: defaultMessageTimeToLiveInSec # Optional + # value: 10 + # - name: autoDeleteOnIdleInSec # Optional + # value: 3600 # - name: minConnectionRecoveryInSec # Optional # value: 2 # - name: maxConnectionRecoveryInSec # Optional # value: 300 - # - name: maxActiveMessages # Optional - # value: 1 - # - name: maxConcurrentHandlers # Optional - # value: 1 - # - name: lockRenewalInSec # Optional - # value: 20 - # - name: timeoutInSec # Optional - # value: 60 + # - name: maxRetriableErrorsPerSec # Optional + # value: 10 + # - name: publishMaxRetries # Optional + # value: 5 + # - name: publishInitialRetryIntervalInMs # Optional + # value: 500 ``` {{% 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 >}}). @@ -52,16 +66,26 @@ The above example uses secrets as plain strings. It is recommended to use a secr | Field | Required | Binding support | Details | Example | |--------------------|:--------:|-----------------|----------|---------| | `connectionString` | Y | Input/Output | The Service Bus connection string. Required unless using Azure AD authentication. | `"Endpoint=sb://************"` | -| `namespaceName`| N | Input/Output | Parameter to set the address of the Service Bus namespace, as a fully-qualified domain name. Required if using Azure AD authentication. | `"namespace.servicebus.windows.net"` | | `queueName` | Y | Input/Output | The Service Bus queue name. Queue names are case-insensitive and will always be forced to lowercase. | `"queuename"` | -| `ttlInSeconds` | N | Output | Parameter to set the default message [time to live](https://docs.microsoft.com/azure/service-bus-messaging/message-expiration). If this parameter is omitted, messages will expire after 14 days. See [also](#specifying-a-ttl-per-message) | `86400` | -| `maxRetriableErrorsPerSec` | N | Input | Maximum number of retriable errors that are processed per second. If a message fails to be processed with a retriable error, the component adds a delay before it starts processing another message, to avoid immediately re-processing messages that have failed. Default: `10` | `10` | +| `timeoutInSec` | N | Input/Output | Timeout for all invocations to the Azure Service Bus endpoint, in seconds. *Note that this option impacts network calls and it's unrelated to the TTL applies to messages*. Default: `60` | `60` | +| `namespaceName`| N | Input/Output | Parameter to set the address of the Service Bus namespace, as a fully-qualified domain name. Required if using Azure AD authentication. | `"namespace.servicebus.windows.net"` | +| `disableEntityManagement` | N | Input/Output | When set to true, queues and subscriptions do not get created automatically. Default: `"false"` | `"true"`, `"false"` +| `lockDurationInSec` | N | Input/Output | Defines the length in seconds that a message will be locked for before expiring. Used during subscription creation only. Default set by server. | `30` +| `autoDeleteOnIdleInSec` | N | Input/Output | Time in seconds to wait before auto deleting idle subscriptions. Used during subscription creation only. Default: `0` (disabled) | `3600` +| `defaultMessageTimeToLiveInSec` | N | Input/Output | Default message time to live, in seconds. Used during subscription creation only. | `10` +| `maxDeliveryCount` | N | Input/Output | Defines the number of attempts the server will make to deliver a message. Used during subscription creation only. Default set by server. | `10` +| `minConnectionRecoveryInSec` | N | Input/Output | Minimum interval (in seconds) to wait before attempting to reconnect to Azure Service Bus in case of a connection failure. Default: `2` | `5` +| `maxConnectionRecoveryInSec` | N | Input/Output | Maximum interval (in seconds) to wait before attempting to reconnect to Azure Service Bus in case of a connection failure. After each attempt, the component waits a random number of seconds, increasing every time, between the minimum and the maximum. Default: `300` (5 minutes) | `600` +| `maxActiveMessages` | N | Defines the maximum number of messages to be processing or in the buffer at once. This should be at least as big as the maximum concurrent handlers. Default: `1` | `1` +| `handlerTimeoutInSec`| N | Input | Timeout for invoking the app's handler. Default: `0` (no timeout) | `30` | `minConnectionRecoveryInSec` | N | Input | Minimum interval (in seconds) to wait before attempting to reconnect to Azure Service Bus in case of a connection failure. Default: `2` | `5` | | `maxConnectionRecoveryInSec` | N | Input | Maximum interval (in seconds) to wait before attempting to reconnect to Azure Service Bus in case of a connection failure. After each attempt, the binding waits a random number of seconds, increasing every time, between the minimum and the maximum. Default: `300` (5 minutes) | `600` | -| `maxActiveMessages` | N |Defines the maximum number of messages to be processing or in the buffer at once. This should be at least as big as the maximum concurrent handlers. Default: `1` | `1` -| `maxConcurrentHandlers` | N |Defines the maximum number of concurrent message handlers. Default: `1`. | `1` -| `lockRenewalInSec` | N |Defines the frequency at which buffered message locks will be renewed. Default: `20`. | `20` -| `timeoutInSec` | N | Input/Output | Timeout for all invocations to the Azure Service Bus endpoint, in seconds. *Note that this option impacts network calls and it's unrelated to the TTL applies to messages*. Default: `60` | `60` | +| `lockRenewalInSec` | N | Input | Defines the frequency at which buffered message locks will be renewed. Default: `20`. | `20` +| `maxActiveMessages` | N | Input | Defines the maximum number of messages to be processing or in the buffer at once. This should be at least as big as the maximum concurrent handlers. Default: `1` | `2000` +| `maxConcurrentHandlers` | N | Input | Defines the maximum number of concurrent message handlers; set to `0` for unlimited. Default: `1` | `10` +| `maxRetriableErrorsPerSec` | N | Input | Maximum number of retriable errors that are processed per second. If a message fails to be processed with a retriable error, the component adds a delay before it starts processing another message, to avoid immediately re-processing messages that have failed. Default: `10` | `10` +| `publishMaxRetries` | N | Output | The max number of retries for when Azure Service Bus responds with "too busy" in order to throttle messages. Defaults: `5` | `5` +| `publishInitialRetryIntervalInMs` | N | Output | Time in milliseconds for the initial exponential backoff when Azure Service Bus throttle messages. Defaults: `500` | `500` ### Azure Active Directory (AAD) authentication @@ -100,15 +124,13 @@ This component supports both **input and output** binding interfaces. This component supports **output binding** with the following operations: -- `create` +- `create`: publishes a message to the specified queue ## Specifying a TTL per message -Time to live can be defined on queue level (as illustrated above) or at the message level. The value defined at message level overwrites any value set at queue level. +Time to live can be defined on a per-queue level (as illustrated above) or at the message level. The value defined at message level overwrites any value set at the queue level. -To set time to live at message level use the `metadata` section in the request body during the binding invocation. - -The field name is `ttlInSeconds`. +To set time to live at message level use the `metadata` section in the request body during the binding invocation: the field name is `ttlInSeconds`. {{< tabs "Linux">}} diff --git a/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-azure-servicebus.md b/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-azure-servicebus-queues.md similarity index 63% rename from daprdocs/content/en/reference/components-reference/supported-pubsub/setup-azure-servicebus.md rename to daprdocs/content/en/reference/components-reference/supported-pubsub/setup-azure-servicebus-queues.md index aeddc47a6..59ecf2f6b 100644 --- a/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-azure-servicebus.md +++ b/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-azure-servicebus-queues.md @@ -1,14 +1,18 @@ --- type: docs -title: "Azure Service Bus" -linkTitle: "Azure Service Bus" -description: "Detailed documentation on the Azure Service Bus pubsub component" +title: "Azure Service Bus Queues" +linkTitle: "Azure Service Bus Queues" +description: "Detailed documentation on the Azure Service Bus Queues pubsub component" aliases: - - "/operations/components/setup-pubsub/supported-pubsub/setup-azure-servicebus/" + - "/operations/components/setup-pubsub/supported-pubsub/setup-azure-servicebus-queues/" --- ## Component format -To setup Azure Service Bus pubsub create a component of type `pubsub.azure.servicebus`. See [this guide]({{< ref "howto-publish-subscribe.md#step-1-setup-the-pubsub-component" >}}) on how to create and apply a pubsub configuration. + +To setup Azure Service Bus Queues pubsub create a component of type `pubsub.azure.servicebus.queues`. See [this guide]({{< ref "howto-publish-subscribe.md#step-1-setup-the-pubsub-component" >}}) on how to create and apply a pubsub configuration. + +> This component uses queues on Azure Service Bus; see the official documentation for the differences between [topics and queues](https://learn.microsoft.com/azure/service-bus-messaging/service-bus-queues-topics-subscriptions). +> For using topics, see the [Azure Service Bus Topics pubsub component]({{< ref "setup-azure-servicebus-topics" >}}). ### Connection String Authentication @@ -18,13 +22,12 @@ kind: Component metadata: name: servicebus-pubsub spec: - type: pubsub.azure.servicebus + type: pubsub.azure.servicebus.queues version: v1 metadata: - - name: connectionString # Required when not using Azure Authentication. + # Required when not using Azure AD Authentication + - name: connectionString value: "Endpoint=sb://{ServiceBusNamespace}.servicebus.windows.net/;SharedAccessKeyName={PolicyName};SharedAccessKey={Key};EntityPath={ServiceBus}" - # - name: consumerID # Optional: defaults to the app's own ID - # value: "{identifier}" # - name: timeoutInSec # Optional # value: 60 # - name: handlerTimeoutInSec # Optional @@ -53,12 +56,10 @@ spec: # value: 10 # - name: publishMaxRetries # Optional # value: 5 - # - name: publishInitialRetryInternalInMs # Optional + # - name: publishInitialRetryIntervalInMs # Optional # value: 500 ``` -> __NOTE:__ The above settings are shared across all topics that use this component. - {{% 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 %}} @@ -67,28 +68,27 @@ The above example uses secrets as plain strings. It is recommended to use a secr | Field | Required | Details | Example | |--------------------|:--------:|---------|---------| -| `connectionString` | Y | Shared access policy connection-string for the Service Bus. Required unless using Azure AD authentication. | "`Endpoint=sb://{ServiceBusNamespace}.servicebus.windows.net/;SharedAccessKeyName={PolicyName};SharedAccessKey={Key};EntityPath={ServiceBus}`" +| `connectionString` | Y | Shared access policy connection string for the Service Bus. Required unless using Azure AD authentication. | See example above | `namespaceName`| N | Parameter to set the address of the Service Bus namespace, as a fully-qualified domain name. Required if using Azure AD authentication. | `"namespace.servicebus.windows.net"` | -| `consumerID` | N | Consumer ID a.k.a consumer tag organizes one or more consumers into a group. Consumers with the same consumer ID work as one virtual consumer, i.e. a message is processed only once by one of the consumers in the group. If the consumer ID is not set, the dapr runtime will set it to the dapr application ID. | | `timeoutInSec` | N | Timeout for sending messages and for management operations. Default: `60` |`30` | `handlerTimeoutInSec`| N | Timeout for invoking the app's handler. Default: `60` | `30` -| `disableEntityManagement` | N | When set to true, topics and subscriptions do not get created automatically. Default: `"false"` | `"true"`, `"false"` -| `maxDeliveryCount` | N |Defines the number of attempts the server will make to deliver a message. Default set by server| `10` -| `lockDurationInSec` | N |Defines the length in seconds that a message will be locked for before expiring. Default set by server | `30` -| `lockRenewalInSec` | N |Defines the frequency at which buffered message locks will be renewed. Default: `20`. | `20` -| `maxActiveMessages` | N |Defines the maximum number of messages to be processing or in the buffer at once. This should be at least as big as the maximum concurrent handlers. Default: `10000` | `2000` -| `maxConcurrentHandlers` | N |Defines the maximum number of concurrent message handlers. | `10` -| `defaultMessageTimeToLiveInSec` | N |Default message time to live. | `10` -| `autoDeleteOnIdleInSec` | N |Time in seconds to wait before auto deleting idle subscriptions. | `3600` +| `lockRenewalInSec` | N | Defines the frequency at which buffered message locks will be renewed. Default: `20`. | `20` +| `maxActiveMessages` | N | Defines the maximum number of messages to be processing or in the buffer at once. This should be at least as big as the maximum concurrent handlers. Default: `1000` | `2000` +| `maxConcurrentHandlers` | N | Defines the maximum number of concurrent message handlers. Default: `0` (unlimited) | `10` +| `disableEntityManagement` | N | When set to true, queues and subscriptions do not get created automatically. Default: `"false"` | `"true"`, `"false"` +| `defaultMessageTimeToLiveInSec` | N | Default message time to live, in seconds. Used during subscription creation only. | `10` +| `autoDeleteOnIdleInSec` | N | Time in seconds to wait before auto deleting idle subscriptions. Used during subscription creation only. Default: `0` (disabled) | `3600` +| `maxDeliveryCount` | N | Defines the number of attempts the server will make to deliver a message. Used during subscription creation only. Default set by server. | `10` +| `lockDurationInSec` | N | Defines the length in seconds that a message will be locked for before expiring. Used during subscription creation only. Default set by server. | `30` | `minConnectionRecoveryInSec` | N | Minimum interval (in seconds) to wait before attempting to reconnect to Azure Service Bus in case of a connection failure. Default: `2` | `5` | `maxConnectionRecoveryInSec` | N | Maximum interval (in seconds) to wait before attempting to reconnect to Azure Service Bus in case of a connection failure. After each attempt, the component waits a random number of seconds, increasing every time, between the minimum and the maximum. Default: `300` (5 minutes) | `600` | `maxRetriableErrorsPerSec` | N | Maximum number of retriable errors that are processed per second. If a message fails to be processed with a retriable error, the component adds a delay before it starts processing another message, to avoid immediately re-processing messages that have failed. Default: `10` | `10` | `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` +| `publishInitialRetryIntervalInMs` | N | Time in milliseconds for the initial exponential backoff when Azure Service Bus throttle messages. Defaults: `500` | `500` ### Azure Active Directory (AAD) authentication -The Azure Service Bus pubsub component supports authentication using all Azure Active Directory mechanisms, including Managed Identities. For further information and the relevant component metadata fields to provide depending on the choice of AAD authentication mechanism, see the [docs for authenticating to Azure]({{< ref authenticating-azure.md >}}). +The Azure Service Bus Queues pubsub component supports authentication using all Azure Active Directory mechanisms, including Managed Identities. For further information and the relevant component metadata fields to provide depending on the choice of AAD authentication mechanism, see the [docs for authenticating to Azure]({{< ref authenticating-azure.md >}}). #### Example Configuration @@ -98,7 +98,7 @@ kind: Component metadata: name: servicebus-pubsub spec: - type: pubsub.azure.servicebus + type: pubsub.azure.servicebus.queues version: v1 metadata: - name: namespaceName @@ -132,7 +132,7 @@ To set Azure Service Bus metadata when sending a message, set the query paramete - `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. +> **Note:** The `metadata.MessageId` property does not set the `id` property of the cloud event returned by Dapr and should be treated in isolation. ### Receiving a message with metadata @@ -147,11 +147,11 @@ In addition to the [settable metadata listed above](#sending-a-message-with-meta 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/rest/api/servicebus/message-headers-and-properties#message-headers). -> Note that all times are populated by the server and are not adjusted for clock skews. +> Note: that all times are populated by the server and are not adjusted for clock skews. -## Create an Azure Service Bus +## Create an Azure Service Bus broker for queues -Follow the instructions [here](https://docs.microsoft.com/azure/service-bus-messaging/service-bus-quickstart-topics-subscriptions-portal) on setting up Azure Service Bus Topics. +Follow the instructions [here](https://learn.microsoft.com/azure/service-bus-messaging/service-bus-quickstart-portal) on setting up Azure Service Bus Queues. ## Related links diff --git a/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-azure-servicebus-topics.md b/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-azure-servicebus-topics.md new file mode 100644 index 000000000..b72fedbf4 --- /dev/null +++ b/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-azure-servicebus-topics.md @@ -0,0 +1,166 @@ +--- +type: docs +title: "Azure Service Bus Topics" +linkTitle: "Azure Service Bus Topics" +description: "Detailed documentation on the Azure Service Bus Topics pubsub component" +aliases: + - "/operations/components/setup-pubsub/supported-pubsub/setup-azure-servicebus-topics/" + - "/operations/components/setup-pubsub/supported-pubsub/setup-azure-servicebus/" +--- + +## Component format + +To setup Azure Service Bus Topics pubsub create a component of type `pubsub.azure.servicebus.topics`. See [this guide]({{< ref "howto-publish-subscribe.md#step-1-setup-the-pubsub-component" >}}) on how to create and apply a pubsub configuration. + +> This component uses topics on Azure Service Bus; see the official documentation for the differences between [topics and queues](https://learn.microsoft.com/azure/service-bus-messaging/service-bus-queues-topics-subscriptions). +> For using queues, see the [Azure Service Bus Queues pubsub component]({{< ref "setup-azure-servicebus-queues" >}}). + +### Connection String Authentication + +```yaml +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: servicebus-pubsub +spec: + type: pubsub.azure.servicebus.topics + version: v1 + metadata: + # Required when not using Azure AD Authentication + - name: connectionString + value: "Endpoint=sb://{ServiceBusNamespace}.servicebus.windows.net/;SharedAccessKeyName={PolicyName};SharedAccessKey={Key};EntityPath={ServiceBus}" + # - name: consumerID # Optional: defaults to the app's own ID + # value: "{identifier}" + # - name: timeoutInSec # Optional + # value: 60 + # - name: handlerTimeoutInSec # Optional + # value: 60 + # - name: disableEntityManagement # Optional + # value: "false" + # - name: maxDeliveryCount # Optional + # value: 3 + # - name: lockDurationInSec # Optional + # value: 60 + # - name: lockRenewalInSec # Optional + # value: 20 + # - name: maxActiveMessages # Optional + # value: 10000 + # - name: maxConcurrentHandlers # Optional + # value: 10 + # - name: defaultMessageTimeToLiveInSec # Optional + # value: 10 + # - name: autoDeleteOnIdleInSec # Optional + # value: 3600 + # - name: minConnectionRecoveryInSec # Optional + # value: 2 + # - name: maxConnectionRecoveryInSec # Optional + # value: 300 + # - name: maxRetriableErrorsPerSec # Optional + # value: 10 + # - name: publishMaxRetries # Optional + # value: 5 + # - name: publishInitialRetryIntervalInMs # Optional + # value: 500 +``` + +> __NOTE:__ The above settings are shared across all topics that use this component. + +{{% 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 | +|--------------------|:--------:|---------|---------| +| `connectionString` | Y | Shared access policy connection string for the Service Bus. Required unless using Azure AD authentication. | See example above +| `namespaceName`| N | Parameter to set the address of the Service Bus namespace, as a fully-qualified domain name. Required if using Azure AD authentication. | `"namespace.servicebus.windows.net"` | +| `consumerID` | N | Consumer ID (a.k.a consumer tag) organizes one or more consumers into a group. Consumers with the same consumer ID work as one virtual consumer, i.e. a message is processed only once by one of the consumers in the group. If the consumer ID is not set, the dapr runtime will set it to the dapr application ID. | +| `timeoutInSec` | N | Timeout for sending messages and for management operations. Default: `60` |`30` +| `handlerTimeoutInSec`| N | Timeout for invoking the app's handler. Default: `60` | `30` +| `lockRenewalInSec` | N | Defines the frequency at which buffered message locks will be renewed. Default: `20`. | `20` +| `maxActiveMessages` | N | Defines the maximum number of messages to be processing or in the buffer at once. This should be at least as big as the maximum concurrent handlers. Default: `1000` | `2000` +| `maxConcurrentHandlers` | N | Defines the maximum number of concurrent message handlers. Default: `0` (unlimited) | `10` +| `disableEntityManagement` | N | When set to true, queues and subscriptions do not get created automatically. Default: `"false"` | `"true"`, `"false"` +| `defaultMessageTimeToLiveInSec` | N | Default message time to live, in seconds. Used during subscription creation only. | `10` +| `autoDeleteOnIdleInSec` | N | Time in seconds to wait before auto deleting idle subscriptions. Used during subscription creation only. Default: `0` (disabled) | `3600` +| `maxDeliveryCount` | N | Defines the number of attempts the server will make to deliver a message. Used during subscription creation only. Default set by server. | `10` +| `lockDurationInSec` | N | Defines the length in seconds that a message will be locked for before expiring. Used during subscription creation only. Default set by server. | `30` +| `minConnectionRecoveryInSec` | N | Minimum interval (in seconds) to wait before attempting to reconnect to Azure Service Bus in case of a connection failure. Default: `2` | `5` +| `maxConnectionRecoveryInSec` | N | Maximum interval (in seconds) to wait before attempting to reconnect to Azure Service Bus in case of a connection failure. After each attempt, the component waits a random number of seconds, increasing every time, between the minimum and the maximum. Default: `300` (5 minutes) | `600` +| `maxRetriableErrorsPerSec` | N | Maximum number of retriable errors that are processed per second. If a message fails to be processed with a retriable error, the component adds a delay before it starts processing another message, to avoid immediately re-processing messages that have failed. Default: `10` | `10` +| `publishMaxRetries` | N | The max number of retries for when Azure Service Bus responds with "too busy" in order to throttle messages. Defaults: `5` | `5` +| `publishInitialRetryIntervalInMs` | N | Time in milliseconds for the initial exponential backoff when Azure Service Bus throttle messages. Defaults: `500` | `500` + +### Azure Active Directory (AAD) authentication + +The Azure Service Bus Topics pubsub component supports authentication using all Azure Active Directory mechanisms, including Managed Identities. For further information and the relevant component metadata fields to provide depending on the choice of AAD authentication mechanism, see the [docs for authenticating to Azure]({{< ref authenticating-azure.md >}}). + +#### Example Configuration + +```yaml +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: servicebus-pubsub +spec: + type: pubsub.azure.servicebus.topics + version: v1 + metadata: + - name: namespaceName + # Required when using Azure Authentication. + # Must be a fully-qualified domain name + value: "servicebusnamespace.servicebus.windows.net" + - name: azureTenantId + value: "***" + - name: azureClientId + value: "***" + - name: azureClientSecret + value: "***" +``` + +## 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 returned by Dapr 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/rest/api/servicebus/message-headers-and-properties#message-headers). + +> Note: that all times are populated by the server and are not adjusted for clock skews. + +## Create an Azure Service Bus broker for topics + +Follow the instructions [here](https://docs.microsoft.com/azure/service-bus-messaging/service-bus-quickstart-topics-subscriptions-portal) on setting up Azure Service Bus Topics. + +## Related links + +- [Basic schema for a Dapr component]({{< ref component-schema >}}) +- [Pub/Sub building block]({{< ref pubsub >}}) +- Read [this guide]({{< ref "howto-publish-subscribe.md#step-2-publish-a-topic" >}}) for instructions on configuring pub/sub components diff --git a/daprdocs/data/components/pubsub/azure.yaml b/daprdocs/data/components/pubsub/azure.yaml index e278829af..44cb1a410 100644 --- a/daprdocs/data/components/pubsub/azure.yaml +++ b/daprdocs/data/components/pubsub/azure.yaml @@ -6,11 +6,19 @@ features: bulkPublish: true bulkSubscribe: false -- component: Azure Service Bus - link: setup-azure-servicebus +- component: Azure Service Bus Topics + link: setup-azure-servicebus-topics state: Stable version: v1 since: "1.0" features: bulkPublish: true bulkSubscribe: true +- component: Azure Service Bus Queues + link: setup-azure-servicebus-queues + state: Beta + version: v1 + since: "1.10" + features: + bulkPublish: true + bulkSubscribe: true From 1c5944be9b30e46fa2daedb05f9617e6cf208b39 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Wed, 8 Feb 2023 16:38:07 -0600 Subject: [PATCH 31/38] pull in dotnet docs updates Signed-off-by: Hannah Hunter --- sdkdocs/dotnet | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdkdocs/dotnet b/sdkdocs/dotnet index 52b82d7ce..bc3ec80e4 160000 --- a/sdkdocs/dotnet +++ b/sdkdocs/dotnet @@ -1 +1 @@ -Subproject commit 52b82d7ce6599822a37d2528379f5ca146e286bb +Subproject commit bc3ec80e4a187269abeb46e698464d5f0a9a018a From 00e18258f4a7df74a03ad98831cdf10413a02196 Mon Sep 17 00:00:00 2001 From: "Alessandro (Ale) Segala" <43508+ItalyPaleAle@users.noreply.github.com> Date: Wed, 8 Feb 2023 15:51:56 -0800 Subject: [PATCH 32/38] Updated docs for MQTT components (#3115) * Updated docs for MQTT components Fixes #3072 Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> * Update daprdocs/content/en/reference/components-reference/supported-bindings/mqtt3.md Co-authored-by: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> Signed-off-by: Alessandro (Ale) Segala <43508+ItalyPaleAle@users.noreply.github.com> --------- Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> Signed-off-by: Alessandro (Ale) Segala <43508+ItalyPaleAle@users.noreply.github.com> Co-authored-by: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> --- .../supported-bindings/mqtt3.md | 108 +++++++++--------- .../supported-pubsub/setup-mqtt3.md | 106 ++++++++--------- 2 files changed, 107 insertions(+), 107 deletions(-) diff --git a/daprdocs/content/en/reference/components-reference/supported-bindings/mqtt3.md b/daprdocs/content/en/reference/components-reference/supported-bindings/mqtt3.md index 9e4824d83..9e3c43d84 100644 --- a/daprdocs/content/en/reference/components-reference/supported-bindings/mqtt3.md +++ b/daprdocs/content/en/reference/components-reference/supported-bindings/mqtt3.md @@ -21,18 +21,19 @@ spec: type: bindings.mqtt3 version: v1 metadata: - - name: url - value: "tcp://[username][:password]@host.domain[:port]" - - name: topic - value: "mytopic" - - name: qos - value: 1 - - name: retain - value: "false" - - name: cleanSession - value: "true" - - name: backOffMaxRetries - value: "0" + - name: url + value: "tcp://[username][:password]@host.domain[:port]" + - name: topic + value: "mytopic" + - name: consumerID + value: "myapp" + # Optional + - name: retain + value: "false" + - name: cleanSession + value: "false" + - name: backOffMaxRetries + value: "0" ``` {{% alert title="Warning" color="warning" %}} @@ -43,20 +44,19 @@ The above example uses secrets as plain strings. It is recommended to use a secr | Field | Required | Binding support | Details | Example | |--------------------|:--------:|---------|---------|---------| -| url | Y | Input/Output | Address of the MQTT broker. Can be `secretKeyRef` to use a secret reference.
Use the **`tcp://`** URI scheme for non-TLS communication.
Use the **`ssl://`** URI scheme for TLS communication. | `"tcp://[username][:password]@host.domain[:port]"` -| topic | Y | Input/Output | The topic to listen on or send events to. | `"mytopic"` | -| consumerID | N | Input/Output | The client ID used to connect to the MQTT broker. Defaults to the Dapr app ID. | `"myMqttClientApp"` -| qos | N | Input/Output | Indicates the Quality of Service Level (QoS) of the message. Defaults to `0`. |`1` -| retain | N | Input/Output | Defines whether the message is saved by the broker as the last known good value for a specified topic. Defaults to `"false"`. | `"true"`, `"false"` -| cleanSession | N | Input/Output | Sets the `clean_session` flag in the connection message to the MQTT broker if `"true"`. Defaults to `"true"`. | `"true"`, `"false"` -| caCert | Required for using TLS | Input/Output | Certificate Authority (CA) certificate in PEM format for verifying server TLS certificates. | `"-----BEGIN CERTIFICATE-----\n\n-----END CERTIFICATE-----"` -| clientCert | Required for using TLS | Input/Output | TLS client certificate in PEM format. Must be used with `clientKey`. | `"-----BEGIN CERTIFICATE-----\n\n-----END CERTIFICATE-----"` -| clientKey | Required for using TLS | Input/Output | TLS client key in PEM format. Must be used with `clientCert`. Can be `secretKeyRef` to use a secret reference. | `"-----BEGIN RSA PRIVATE KEY-----\n\n-----END RSA PRIVATE KEY-----"` -| backOffMaxRetries | N | Input | The maximum number of retries to process the message before returning an error. Defaults to `"0"`, which means that no retries will be attempted. `"-1"` can be specified to indicate that messages should be retried indefinitely until they are successfully processed or the application is shutdown. The component will wait 5 seconds between retries. | `"3"` +| `url` | Y | Input/Output | Address of the MQTT broker. Can be `secretKeyRef` to use a secret reference.
Use the **`tcp://`** URI scheme for non-TLS communication.
Use the **`ssl://`** URI scheme for TLS communication. | `"tcp://[username][:password]@host.domain[:port]"` +| `topic` | Y | Input/Output | The topic to listen on or send events to. | `"mytopic"` | +| `consumerID` | Y | Input/Output | The client ID used to connect to the MQTT broker. | `"myMqttClientApp"` +| `retain` | N | Input/Output | Defines whether the message is saved by the broker as the last known good value for a specified topic. Defaults to `"false"`. | `"true"`, `"false"` +| `cleanSession` | N | Input/Output | Sets the `clean_session` flag in the connection message to the MQTT broker if `"true"`. Defaults to `"false"`. | `"true"`, `"false"` +| `caCert` | Required for using TLS | Input/Output | Certificate Authority (CA) certificate in PEM format for verifying server TLS certificates. | See example below +| `clientCert` | Required for using TLS | Input/Output | TLS client certificate in PEM format. Must be used with `clientKey`. | See example below +| `clientKey` | Required for using TLS | Input/Output | TLS client key in PEM format. Must be used with `clientCert`. Can be `secretKeyRef` to use a secret reference. | See example below +| `backOffMaxRetries` | N | Input | The maximum number of retries to process the message before returning an error. Defaults to `"0"`, which means that no retries will be attempted. `"-1"` can be specified to indicate that messages should be retried indefinitely until they are successfully processed or the application is shutdown. The component will wait 5 seconds between retries. | `"3"` ### Communication using TLS -To configure communication using TLS, ensure that the MQTT broker (e.g. mosquitto) is configured to support certificates and provide the `caCert`, `clientCert`, `clientKey` metadata in the component configuration. For example: +To configure communication using TLS, ensure that the MQTT broker (e.g. emqx) is configured to support certificates and provide the `caCert`, `clientCert`, `clientKey` metadata in the component configuration. For example: ```yaml apiVersion: dapr.io/v1alpha1 @@ -67,35 +67,41 @@ spec: type: bindings.mqtt3 version: v1 metadata: - - name: url - value: "ssl://host.domain[:port]" - - name: topic - value: "topic1" - - name: qos - value: 1 - - name: retain - value: "false" - - name: cleanSession - value: "false" - - name: backoffMaxRetries - value: "0" - - name: caCert - value: ${{ myLoadedCACert }} - - name: clientCert - value: ${{ myLoadedClientCert }} - - name: clientKey - secretKeyRef: - name: myMqttClientKey - key: myMqttClientKey -auth: - secretStore: + - name: url + value: "ssl://host.domain[:port]" + - name: topic + value: "topic1" + - name: consumerID + value: "myapp" + # TLS configuration + - name: caCert + value: | + -----BEGIN CERTIFICATE----- + ... + -----END CERTIFICATE----- + - name: clientCert + value: | + -----BEGIN CERTIFICATE----- + ... + -----END CERTIFICATE----- + - name: clientKey + secretKeyRef: + name: myMqttClientKey + key: myMqttClientKey + # Optional + - name: retain + value: "false" + - name: cleanSession + value: "false" + - name: backoffMaxRetries + value: "0" ``` -Note that while the `caCert` and `clientCert` values may not be secrets, they can be referenced from a Dapr secret store as well for convenience. +> Note that while the `caCert` and `clientCert` values may not be secrets, they can be referenced from a Dapr secret store as well for convenience. ### Consuming a shared topic -When consuming a shared topic, each consumer must have a unique identifier. By default, the application ID is used to uniquely identify each consumer and publisher. In self-hosted mode, invoking each `dapr run` with a different application ID is sufficient to have them consume from the same shared topic. However, on Kubernetes, multiple instances of an application pod will share the same application ID, prohibiting all instances from consuming the same topic. To overcome this, configure the component's `consumerID` metadata with a `{uuid}` tag, which will give each instance a randomly generated `consumerID` value on start up. For example: +When consuming a shared topic, each consumer must have a unique identifier. If running multiple instances of an application, you configure the component's `consumerID` metadata with a `{uuid}` tag, which will give each instance a randomly generated `consumerID` value on start up. For example: ```yaml apiVersion: dapr.io/v1alpha1 @@ -113,12 +119,10 @@ spec: value: "tcp://admin:public@localhost:1883" - name: topic value: "topic1" - - name: qos - value: 1 - name: retain value: "false" - name: cleanSession - value: "false" + value: "true" - name: backoffMaxRetries value: "0" ``` @@ -127,13 +131,15 @@ 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 %}} +> In this case, the value of the consumer ID is random every time Dapr restarts, so you should set `cleanSession` to `true` as well. + ## Binding support This component supports both **input and output** binding interfaces. This component supports **output binding** with the following operations: -- `create` +- `create`: publishes a new message ## Set topic per-request diff --git a/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-mqtt3.md b/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-mqtt3.md index abcb08314..966806841 100644 --- a/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-mqtt3.md +++ b/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-mqtt3.md @@ -21,16 +21,15 @@ spec: type: pubsub.mqtt3 version: v1 metadata: - - name: url - value: "tcp://[username][:password]@host.domain[:port]" - - name: qos - value: 1 - - name: retain - value: "false" - - name: cleanSession - value: "false" - - name: backOffMaxRetries - value: "0" + - name: url + value: "tcp://[username][:password]@host.domain[:port]" + # Optional + - name: retain + value: "false" + - name: cleanSession + value: "false" + - name: qos + value: "1" ``` {{% alert title="Warning" color="warning" %}} @@ -41,18 +40,18 @@ The above example uses secrets as plain strings. It is recommended to use a secr | Field | Required | Details | Example | |--------------------|:--------:|---------|---------| -| url | Y | Address of the MQTT broker. Can be `secretKeyRef` to use a secret reference.
Use the **`tcp://`** URI scheme for non-TLS communication.
Use the **`ssl://`** URI scheme for TLS communication. | `"tcp://[username][:password]@host.domain[:port]"` -| consumerID | N | The client ID used to connect to the MQTT broker for the consumer connection. Defaults to the Dapr app ID.
Note: if `producerID` is not set, `-consumer` is appended to this value for the consumer connection | `"myMqttClientApp"` -| producerID | N | The client ID used to connect to the MQTT broker for the producer connection. Defaults to `{consumerID}-producer`. | `"myMqttProducerApp"` -| qos | N | Indicates the Quality of Service Level (QoS) of the message ([more info](https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels/)). Defaults to `1`. |`0`, `1`, `2` -| retain | N | Defines whether the message is saved by the broker as the last known good value for a specified topic. Defaults to `"false"`. | `"true"`, `"false"` -| cleanSession | N | Sets the `clean_session` flag in the connection message to the MQTT broker if `"true"` ([more info](http://www.steves-internet-guide.com/mqtt-clean-sessions-example/)). Defaults to `"false"`. | `"true"`, `"false"` -| caCert | Required for using TLS | Certificate Authority (CA) certificate in PEM format for verifying server TLS certificates. | `"-----BEGIN CERTIFICATE-----\n\n-----END CERTIFICATE-----"` -| clientCert | Required for using TLS | TLS client certificate in PEM format. Must be used with `clientKey`. | `"-----BEGIN CERTIFICATE-----\n\n-----END CERTIFICATE-----"` -| clientKey | Required for using TLS | TLS client key in PEM format. Must be used with `clientCert`. Can be `secretKeyRef` to use a secret reference. | `"-----BEGIN RSA PRIVATE KEY-----\n\n-----END RSA PRIVATE KEY-----"` +| `url` | Y | Address of the MQTT broker. Can be `secretKeyRef` to use a secret reference.
Use the **`tcp://`** URI scheme for non-TLS communication.
Use the **`ssl://`** URI scheme for TLS communication. | `"tcp://[username][:password]@host.domain[:port]"` +| `consumerID` | N | The client ID used to connect to the MQTT broker. Defaults to the Dapr app ID. | `"myMqttClientApp"` +| `retain` | N | Defines whether the message is saved by the broker as the last known good value for a specified topic. Defaults to `"false"`. | `"true"`, `"false"` +| `cleanSession` | N | Sets the `clean_session` flag in the connection message to the MQTT broker if `"true"` ([more info](http://www.steves-internet-guide.com/mqtt-clean-sessions-example/)). Defaults to `"false"`. | `"true"`, `"false"` +| `caCert` | Required for using TLS | Certificate Authority (CA) certificate in PEM format for verifying server TLS certificates. | See example below +| `clientCert` | Required for using TLS | TLS client certificate in PEM format. Must be used with `clientKey`. | See example below +| `clientKey` | Required for using TLS | TLS client key in PEM format. Must be used with `clientCert`. Can be `secretKeyRef` to use a secret reference. | See example below +| `qos` | N | Indicates the Quality of Service Level (QoS) of the message ([more info](https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels/)). Defaults to `1`. |`0`, `1`, `2` + ### Communication using TLS -To configure communication using TLS, ensure that the MQTT broker (e.g. mosquitto) is configured to support certificates and provide the `caCert`, `clientCert`, `clientKey` metadata in the component configuration. For example: +To configure communication using TLS, ensure that the MQTT broker (e.g. emqx) is configured to support certificates and provide the `caCert`, `clientCert`, `clientKey` metadata in the component configuration. For example: ```yaml apiVersion: dapr.io/v1alpha1 @@ -63,26 +62,30 @@ spec: type: pubsub.mqtt3 version: v1 metadata: - - name: url - value: "ssl://host.domain[:port]" - - name: qos - value: 1 - - name: retain - value: "false" - - name: cleanSession - value: "false" - - name: backoffMaxRetries - value: "0" - - name: caCert - value: ${{ myLoadedCACert }} - - name: clientCert - value: ${{ myLoadedClientCert }} - - name: clientKey - secretKeyRef: - name: myMqttClientKey - key: myMqttClientKey -auth: - secretStore: + - name: url + value: "ssl://host.domain[:port]" + # TLS configuration + - name: caCert + value: | + -----BEGIN CERTIFICATE----- + ... + -----END CERTIFICATE----- + - name: clientCert + value: | + -----BEGIN CERTIFICATE----- + ... + -----END CERTIFICATE----- + - name: clientKey + secretKeyRef: + name: myMqttClientKey + key: myMqttClientKey + # Optional + - name: retain + value: "false" + - name: cleanSession + value: "false" + - name: qos + value: 1 ``` Note that while the `caCert` and `clientCert` values may not be secrets, they can be referenced from a Dapr secret store as well for convenience. @@ -102,36 +105,34 @@ spec: metadata: - name: consumerID value: "{uuid}" + - name: cleanSession + value: "true" - name: url value: "tcp://admin:public@localhost:1883" - name: qos value: 1 - name: retain value: "false" - - name: cleanSession - value: "true" - - name: backoffMaxRetries - value: "0" ``` {{% 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 %}} -Note that in the case, the value of the consumer ID is random every time Dapr restarts, so we are setting `cleanSession` to true as well. +Note that in the case, the value of the consumer ID is random every time Dapr restarts, so you should set `cleanSession` to `true` as well. ## Create a MQTT3 broker {{< tabs "Self-Hosted" "Kubernetes">}} {{% codetab %}} -You can run a MQTT broker [locally using Docker](https://hub.docker.com/_/eclipse-mosquitto): +You can run a MQTT broker like emqx [locally using Docker](https://hub.docker.com/_/emqx): ```bash -docker run -d -p 1883:1883 -p 9001:9001 --name mqtt eclipse-mosquitto:1.6 +docker run -d -p 1883:1883 --name mqtt emqx:latest ``` -You can then interact with the server using the client port: `mqtt://localhost:1883` +You can then interact with the server using the client port: `tcp://localhost:1883` {{% /codetab %}} {{% codetab %}} @@ -156,15 +157,12 @@ spec: spec: containers: - name: mqtt - image: eclipse-mosquitto:1.6 + image: emqx:latest imagePullPolicy: IfNotPresent ports: - name: default containerPort: 1883 protocol: TCP - - name: websocket - containerPort: 9001 - protocol: TCP --- apiVersion: v1 kind: Service @@ -181,10 +179,6 @@ spec: targetPort: default name: default protocol: TCP - - port: 9001 - targetPort: websocket - name: websocket - protocol: TCP ``` You can then interact with the server using the client port: `tcp://mqtt-broker.default.svc.cluster.local:1883` From c8a84f6cb78a5d384298e2a5a8eecd95f5e03fc2 Mon Sep 17 00:00:00 2001 From: "Alessandro (Ale) Segala" <43508+ItalyPaleAle@users.noreply.github.com> Date: Wed, 8 Feb 2023 15:52:21 -0800 Subject: [PATCH 33/38] Updated docs for proxying of streaming gRPC (#3112) * Updated docs for proxying of streaming gRPC Fixes #3065 Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> * Add note about resiliency Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> Signed-off-by: Alessandro (Ale) Segala <43508+ItalyPaleAle@users.noreply.github.com> --------- Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> Signed-off-by: Alessandro (Ale) Segala <43508+ItalyPaleAle@users.noreply.github.com> Co-authored-by: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> --- .../howto-invoke-services-grpc.md | 92 +++++++++++++++++-- 1 file changed, 83 insertions(+), 9 deletions(-) diff --git a/daprdocs/content/en/developing-applications/building-blocks/service-invocation/howto-invoke-services-grpc.md b/daprdocs/content/en/developing-applications/building-blocks/service-invocation/howto-invoke-services-grpc.md index f1f9a2116..e1b05d8fb 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/service-invocation/howto-invoke-services-grpc.md +++ b/daprdocs/content/en/developing-applications/building-blocks/service-invocation/howto-invoke-services-grpc.md @@ -7,7 +7,8 @@ weight: 3000 --- 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 @@ -16,11 +17,11 @@ By using Dapr's gRPC proxying capability, you can use your existing proto based 5. Network level resiliency 6. API token based authentication +Dapr allows proxying all kinds of gRPC invocations, including unary and [stream-based](#proxying-of-streaming-rpcs) ones. + ## Step 1: Run a gRPC server -The following example is taken from the [hello world grpc-go example](https://github.com/grpc/grpc-go/tree/master/examples/helloworld). - -Note this example is in Go, but applies to all programming languages supported by gRPC. +The following example is taken from the ["hello world" grpc-go example](https://github.com/grpc/grpc-go/tree/master/examples/helloworld). Although this example is in Go, the same concepts apply to all programming languages supported by gRPC. ```go package main @@ -175,7 +176,7 @@ response = service.sayHello({ 'name': 'Darth Bane' }, metadata) {{% codetab %}} ```c++ grpc::ClientContext context; -context.AddMetadata("dapr-app-id", "Darth Sidious"); +context.AddMetadata("dapr-app-id", "server"); ``` {{% /codetab %}} @@ -191,7 +192,7 @@ dapr run --app-id client --dapr-grpc-port 50007 -- go run main.go If you're running Dapr locally with Zipkin installed, open the browser at `http://localhost:9411` and view the traces between the client and server. -## Deploying to Kubernetes +### Deploying to Kubernetes Set the following Dapr annotations on your deployment: @@ -241,15 +242,88 @@ The example above showed you how to directly invoke a different service running For more information on tracing and logs see the [observability]({{< ref observability-concept.md >}}) article. - ## Related Links +## Proxying of streaming RPCs + +When using Dapr to proxy streaming RPC calls using gRPC, you must set an additional metadata option `dapr-stream` with value `true`. + +For example: + +{{< tabs Go Java Dotnet Python JavaScript Ruby "C++">}} + +{{% codetab %}} +```go +ctx = metadata.AppendToOutgoingContext(ctx, "dapr-app-id", "server") +ctx = metadata.AppendToOutgoingContext(ctx, "dapr-stream", "true") +``` +{{% /codetab %}} + +{{% codetab %}} +```java +Metadata headers = new Metadata(); +Metadata.Key jwtKey = Metadata.Key.of("dapr-app-id", "server"); +Metadata.Key jwtKey = Metadata.Key.of("dapr-stream", "true"); +``` +{{% /codetab %}} + +{{% codetab %}} +```csharp +var metadata = new Metadata +{ + { "dapr-app-id", "server" }, + { "dapr-stream", "true" } +}; +``` +{{% /codetab %}} + +{{% codetab %}} +```python +metadata = (('dapr-app-id', 'server'), ('dapr-stream', 'true'),) +``` +{{% /codetab %}} + +{{% codetab %}} +```javascript +const metadata = new grpc.Metadata(); +metadata.add('dapr-app-id', 'server'); +metadata.add('dapr-stream', 'true'); +``` +{{% /codetab %}} + +{{% codetab %}} +```ruby +metadata = { 'dapr-app-id' : 'server' } +metadata = { 'dapr-stream' : 'true' } +``` +{{% /codetab %}} + +{{% codetab %}} +```c++ +grpc::ClientContext context; +context.AddMetadata("dapr-app-id", "server"); +context.AddMetadata("dapr-stream", "true"); +``` +{{% /codetab %}} + +{{< /tabs >}} + +### Streaming gRPCs and Resiliency + +When proxying streaming gRPCs, due to their long-lived nature, [resiliency]({{< ref "resiliency-overview.md" >}}) policies are applied on the "initial handshake" only. As a consequence: + +- If the stream is interrupted after the initial handshake, it will not be automatically re-established by Dapr. Your application will be notified that the stream has ended, and will need to recreate it. +- Retry policies only impact the initial connection "handshake". If your resiliency policy includes retries, Dapr will detect failures in establishing the initial connection to the target app and will retry until it succeeds (or until the number of retries defined in the policy is exhausted). +- Likewise, timeouts defined in resiliency policies only apply to the initial "handshake". After the connection has been established, timeouts do not impact the stream anymore. + +## Related Links * [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:
- -
\ No newline at end of file + + From 3e5af6cd3a97547fb83ff968b5ce55284fd47a97 Mon Sep 17 00:00:00 2001 From: "Alessandro (Ale) Segala" <43508+ItalyPaleAle@users.noreply.github.com> Date: Wed, 8 Feb 2023 15:58:00 -0800 Subject: [PATCH 34/38] Document new metadata option readBody for middleware.http.opa (#3098) Fixes #2865 Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> --- .../supported-middleware/middleware-opa.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/daprdocs/content/en/reference/components-reference/supported-middleware/middleware-opa.md b/daprdocs/content/en/reference/components-reference/supported-middleware/middleware-opa.md index 217e1bf83..62bf76922 100644 --- a/daprdocs/content/en/reference/components-reference/supported-middleware/middleware-opa.md +++ b/daprdocs/content/en/reference/components-reference/supported-middleware/middleware-opa.md @@ -7,7 +7,7 @@ aliases: - /developing-applications/middleware/supported-middleware/middleware-opa/ --- -The Open Policy Agent (OPA) [HTTP middleware]({{< ref middleware.md >}}) applys [OPA Policies](https://www.openpolicyagent.org/) to incoming Dapr HTTP requests. This can be used to apply reusable authorization policies to app endpoints. +The Open Policy Agent (OPA) [HTTP middleware]({{< ref middleware.md >}}) applies [OPA Policies](https://www.openpolicyagent.org/) to incoming Dapr HTTP requests. This can be used to apply reusable authorization policies to app endpoints. ## Component format @@ -30,6 +30,11 @@ spec: - name: defaultStatus value: 403 + # `readBody` controls whether the middleware reads the entire request body in-memory and make it + # availble for policy decisions. + - name: readBody + value: "false" + # `rego` is the open policy agent policy to evaluate. required # The policy package must be http and the policy must set data.http.allow - name: rego @@ -66,15 +71,16 @@ spec: } ``` -You can prototype and experiment with policies using the [official opa playground](https://play.openpolicyagent.org). For example, [you can find the example policy above here](https://play.openpolicyagent.org/p/oRIDSo6OwE). +You can prototype and experiment with policies using the [official OPA playground](https://play.openpolicyagent.org). For example, [you can find the example policy above here](https://play.openpolicyagent.org/p/oRIDSo6OwE). ## Spec metadata fields | Field | Details | Example | |--------|---------|---------| -| rego | The Rego policy language | See above | -| defaultStatus | The status code to return for denied responses | `"https://accounts.google.com"`, `"https://login.salesforce.com"` -| includedHeaders | A comma-separated set of case-insensitive headers to include in the request input. Request headers are not passed to the policy by default. Include to receive incoming request headers in the input | `"x-my-custom-header, x-jwt-header"` +| `rego` | The Rego policy language | See above | +| `defaultStatus` | The status code to return for denied responses | `"https://accounts.google.com"`, `"https://login.salesforce.com"` +| `readBody` | If set to `true` (the default value), the body of each request is read fully in-memory and can be used to make policy decisions. If your policy doesn't depend on inspecting the request body, consider disabling this (setting to `false`) for significant performance improvements. | `"false"` +| `includedHeaders` | A comma-separated set of case-insensitive headers to include in the request input. Request headers are not passed to the policy by default. Include to receive incoming request headers in the input | `"x-my-custom-header, x-jwt-header"` ## Dapr configuration @@ -193,6 +199,7 @@ allow = { "allow": true, "additional_headers": { "X-JWT-Payload": payload } } { ``` ### Result structure + ```go type Result bool // or From a40d382086296e085e07a73b8bd71a8502e491e3 Mon Sep 17 00:00:00 2001 From: "Alessandro (Ale) Segala" <43508+ItalyPaleAle@users.noreply.github.com> Date: Wed, 8 Feb 2023 15:59:43 -0800 Subject: [PATCH 35/38] Updated docs for `logging.apiLogging.obfuscateURLs` config option (#3122) * Updated docs for `logging.apiLogging.obfuscateURLs` config option Fixes #3117 Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> Signed-off-by: Alessandro (Ale) Segala <43508+ItalyPaleAle@users.noreply.github.com> --------- Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> Signed-off-by: Alessandro (Ale) Segala <43508+ItalyPaleAle@users.noreply.github.com> Co-authored-by: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> --- .../configuration/configuration-overview.md | 2 ++ .../api-logs-troubleshooting.md | 24 +++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/daprdocs/content/en/operations/configuration/configuration-overview.md b/daprdocs/content/en/operations/configuration/configuration-overview.md index 6edfa5b84..bed33cadc 100644 --- a/daprdocs/content/en/operations/configuration/configuration-overview.md +++ b/daprdocs/content/en/operations/configuration/configuration-overview.md @@ -117,6 +117,7 @@ The `logging` section under the `Configuration` spec contains the following prop logging: apiLogging: enabled: false + obfuscateURLs: false omitHealthChecks: false ``` @@ -125,6 +126,7 @@ The following table lists the properties for logging: | Property | Type | Description | |--------------|--------|-------------| | `apiLogging.enabled` | boolean | The default value for the `--enable-api-logging` flag for `daprd` (and the corresponding `dapr.io/enable-api-logging` annotation): the value set in the Configuration spec is used as default unless a `true` or `false` value is passed to each Dapr Runtime. Default: `false`. +| `apiLogging.obfuscateURLs` | boolean | When enabled, obfuscates the values of URLs in HTTP API logs (if enabled), logging the abstract route name rather than the full path being invoked, which could contain Personal Identifiable Information (PII). Default: `false`. | `apiLogging.omitHealthChecks` | boolean | If `true`, calls to health check endpoints (e.g. `/v1.0/healthz`) are not logged when API logging is enabled. This is useful if those calls are adding a lot of noise in your logs. Default: `false` See [logging documentation]({{< ref "logs.md" >}}) for more information. diff --git a/daprdocs/content/en/operations/troubleshooting/api-logs-troubleshooting.md b/daprdocs/content/en/operations/troubleshooting/api-logs-troubleshooting.md index 6d124098d..f8b4af585 100644 --- a/daprdocs/content/en/operations/troubleshooting/api-logs-troubleshooting.md +++ b/daprdocs/content/en/operations/troubleshooting/api-logs-troubleshooting.md @@ -40,11 +40,11 @@ $ dapr run --enable-api-logging -- node myapp.js ℹ️ Starting Dapr with id order-processor on port 56730 ✅ You are up and running! Both Dapr and your app logs will appear here. ..... -INFO[0000] HTTP API Called app_id=order-processor instance=mypc method="POST /v1.0/state/{name}" scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge +INFO[0000] HTTP API Called app_id=order-processor instance=mypc method="POST /v1.0/state/mystate" scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge == APP == INFO:root:Saving Order: {'orderId': '483'} -INFO[0000] HTTP API Called app_id=order-processor instance=mypc method="GET /v1.0/state/{name}/{key}" scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge +INFO[0000] HTTP API Called app_id=order-processor instance=mypc method="GET /v1.0/state/mystate/key123" scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge == APP == INFO:root:Getting Order: {'orderId': '483'} -INFO[0000] HTTP API Called app_id=order-processor instance=mypc method="DELETE /v1.0/state/{name}" scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge +INFO[0000] HTTP API Called app_id=order-processor instance=mypc method="DELETE /v1.0/state/mystate" scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge == APP == INFO:root:Deleted Order: {'orderId': '483'} INFO[0000] HTTP API Called app_id=order-processor instance=mypc method="PUT /v1.0/metadata/cliPID" scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge ``` @@ -68,7 +68,7 @@ See the kubernetes API logs by executing the below command. kubectl logs daprd -n ``` -The example below show `info` level API logging in Kubernetes. +The example below show `info` level API logging in Kubernetes (with [URL obfuscation](#obfuscate-urls-in-http-api-logging) enabled). ```bash time="2022-03-16T18:32:02.487041454Z" level=info msg="HTTP API Called" method="POST /v1.0/invoke/{id}/method/{method:*}" app_id=invoke-caller instance=invokecaller-f4f949886-cbnmt scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge @@ -98,6 +98,22 @@ logging: enabled: true ``` +### Obfuscate URLs in HTTP API logging + +By default, logs for API calls in the HTTP endpoints include the full URL being invoked (for example, `POST /v1.0/invoke/directory/method/user-123`), which could contain Personal Identifiable Information (PII). + +To reduce the risk of PII being accidentally included in API logs (when enabled), Dapr can instead log the abstract route being invoked (for example, `POST /v1.0/invoke/{id}/method/{method:*}`). This can help ensuring compliance with privacy regulations such as GDPR. + +To enable obfuscation of URLs in Dapr's HTTP API logs, set `logging.apiLogging.obfuscateURLs` to `true`. For example: + +```yaml +logging: + apiLogging: + obfuscateURLs: true +``` + +Logs emitted by the Dapr gRPC APIs are not impacted by this configuration option, as they only include the name of the method invoked and no arguments. + ### Omit health checks from API logging When API logging is enabled, all calls to the Dapr API server are logged, including those to health check endpoints (e.g. `/v1.0/healthz`). Depending on your environment, this may generate multiple log lines per minute and could create unwanted noise. From a50eb9d53c2aac432bf5f1bf319be6213a667959 Mon Sep 17 00:00:00 2001 From: Bernd Verst Date: Wed, 8 Feb 2023 20:07:50 -0800 Subject: [PATCH 36/38] Storage Queues Binding improvements (#3154) Signed-off-by: Bernd Verst --- .../supported-bindings/storagequeues.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/daprdocs/content/en/reference/components-reference/supported-bindings/storagequeues.md b/daprdocs/content/en/reference/components-reference/supported-bindings/storagequeues.md index b9d2113c1..5e0d89330 100644 --- a/daprdocs/content/en/reference/components-reference/supported-bindings/storagequeues.md +++ b/daprdocs/content/en/reference/components-reference/supported-bindings/storagequeues.md @@ -31,8 +31,12 @@ spec: # value: "60" # - name: decodeBase64 # value: "false" +# - name: encodeBase64 +# value: "false" # - name: endpoint # value: "http://127.0.0.1:10001" +# - name: visibilityTimeout +# value: "30s" ``` {{% alert title="Warning" color="warning" %}} @@ -47,8 +51,10 @@ The above example uses secrets as plain strings. It is recommended to use a secr | `accountKey` | Y* | Input/Output | The access key of the Azure Storage account. Only required when not using Azure AD authentication. | `"access-key"` | | `queueName` | 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` | +| `decodeBase64` | N | Output | Configuration to decode base64 file content before saving to Storage Queues. (In case of saving a file with binary content). Defaults to `false` | `true`, `false` | +| `encodeBase64` | N | Output | If enabled base64 encodes the data payload before uploading to Azure storage queues. Default `false`. | `true`, `false` | | `endpoint` | N | Input/Output | Optional custom endpoint URL. This is useful when using the [Azurite emulator](https://github.com/Azure/azurite) or when using custom domains for Azure Storage (although this is not officially supported). The endpoint must be the full base URL, including the protocol (`http://` or `https://`), the IP or FQDN, and optional port. | `"http://127.0.0.1:10001"` or `"https://accountName.queue.example.com"` | +| `visibilityTimeout` | N | Input | Allows setting a custom queue visibility timeout to avoid immediate retrying of recently failed messages. Defaults to 30 seconds. | "100s" | ### Azure Active Directory (Azure AD) authentication From 69de6d430fcde00e9d59cdb8e457de2193eae666 Mon Sep 17 00:00:00 2001 From: Bernd Verst Date: Wed, 8 Feb 2023 20:18:39 -0800 Subject: [PATCH 37/38] Firestore noindex option (#3146) Signed-off-by: Bernd Verst --- .../supported-state-stores/setup-firestore.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/daprdocs/content/en/reference/components-reference/supported-state-stores/setup-firestore.md b/daprdocs/content/en/reference/components-reference/supported-state-stores/setup-firestore.md index 63cbbe079..9c489bbf1 100644 --- a/daprdocs/content/en/reference/components-reference/supported-state-stores/setup-firestore.md +++ b/daprdocs/content/en/reference/components-reference/supported-state-stores/setup-firestore.md @@ -43,6 +43,8 @@ spec: value: # Required. - name: entity_kind value: # Optional. default: "DaprState" + - name: noindex + value: # Optional. default: "false" ``` {{% alert title="Warning" color="warning" %}} @@ -63,6 +65,7 @@ The above example uses secrets as plain strings. It is recommended to use a secr | auth_provider_x509_cert_url | Y | The auth provider certificate URL | `"https://www.googleapis.com/oauth2/v1/certs"` | client_x509_cert_url | Y | The client certificate URL | `"https://www.googleapis.com/robot/v1/metadata/x509/x"` | entity_kind | N | The entity name in Filestore. Defaults to `"DaprState"` | `"DaprState"` +| noindex | N | Whether to disable indexing of state entities. Use this setting if you encounter Firestore index size limitations. Defaults to `"false"` | `"true"` ## Setup GCP Firestore From 8ac50eb1fdb2f000252cf40c1df2875560da6146 Mon Sep 17 00:00:00 2001 From: "Alessandro (Ale) Segala" <43508+ItalyPaleAle@users.noreply.github.com> Date: Wed, 8 Feb 2023 21:19:41 -0800 Subject: [PATCH 38/38] Updated docs for Event Grid for Dapr 1.10 (#3152) * Updated docs for Event Grid for Dapr 1.10 Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Mark Fussell Signed-off-by: Alessandro (Ale) Segala <43508+ItalyPaleAle@users.noreply.github.com> --------- Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> Signed-off-by: Alessandro (Ale) Segala <43508+ItalyPaleAle@users.noreply.github.com> Co-authored-by: Mark Fussell --- .../supported-bindings/eventgrid.md | 156 +++++++++++------- 1 file changed, 100 insertions(+), 56 deletions(-) diff --git a/daprdocs/content/en/reference/components-reference/supported-bindings/eventgrid.md b/daprdocs/content/en/reference/components-reference/supported-bindings/eventgrid.md index a7f9a3c99..f0469b7bb 100644 --- a/daprdocs/content/en/reference/components-reference/supported-bindings/eventgrid.md +++ b/daprdocs/content/en/reference/components-reference/supported-bindings/eventgrid.md @@ -9,9 +9,9 @@ aliases: ## Component format -To setup Azure Event Grid binding create a component of type `bindings.azure.eventgrid`. See [this guide]({{< ref "howto-bindings.md#1-create-a-binding" >}}) on how to create and apply a binding configuration. +To setup an Azure Event Grid binding create a component of type `bindings.azure.eventgrid`. See [this guide]({{< ref "howto-bindings.md#1-create-a-binding" >}}) on how to create and apply a binding configuration. -See [this](https://docs.microsoft.com/azure/event-grid/) for Azure Event Grid documentation. +See [this](https://docs.microsoft.com/azure/event-grid/) for the documentation for Azure Event Grid. ```yml apiVersion: dapr.io/v1alpha1 @@ -22,29 +22,30 @@ spec: type: bindings.azure.eventgrid version: v1 metadata: - # Required Input Binding Metadata - - name: tenantId - value: "[AzureTenantId]" - - name: subscriptionId - value: "[AzureSubscriptionId]" - - name: clientId - value: "[ClientId]" - - name: clientSecret - value: "[ClientSecret]" - - name: subscriberEndpoint - value: "[SubscriberEndpoint]" - - name: handshakePort - value: [HandshakePort] - - name: scope - value: "[Scope]" - # Optional Input Binding Metadata - - name: eventSubscriptionName - value: "[EventSubscriptionName]" # Required Output Binding Metadata - name: accessKey value: "[AccessKey]" - name: topicEndpoint value: "[TopicEndpoint]" + # Required Input Binding Metadata + - name: azureTenantId + value: "[AzureTenantId]" + - name: azureSubscriptionId + value: "[AzureSubscriptionId]" + - name: azureClientId + value: "[ClientId]" + - name: azureClientSecret + value: "[ClientSecret]" + - name: subscriberEndpoint + value: "[SubscriberEndpoint]" + - name: handshakePort + # Make sure to pass this as a string, with quotes around the value + value: "[HandshakePort]" + - name: scope + value: "[Scope]" + # Optional Input Binding Metadata + - name: eventSubscriptionName + value: "[EventSubscriptionName]" ``` {{% alert title="Warning" color="warning" %}} @@ -55,57 +56,99 @@ The above example uses secrets as plain strings. It is recommended to use a secr | Field | Required | Binding support | Details | Example | |--------------------|:--------:|------------|-----|---------| -| tenantId | Y | Input | The Azure tenant id in which this Event Grid Event Subscription should be created | `"tenentID"` | -| subscriptionId | Y | Input | The Azure subscription id in which this Event Grid Event Subscription should be created | `"subscriptionId"` | -| clientId | Y | Input | The client id that should be used by the binding to create or update the Event Grid Event Subscription | `"clientId"` | -| clientSecret | Y | Input | The client id that should be used by the binding to create or update the Event Grid Event Subscription | `"clientSecret"` | -| subscriberEndpoint | Y | Input | The https endpoint in which Event Grid will handshake and send Cloud Events. If you aren't re-writing URLs on ingress, it should be in the form of: `https://[YOUR HOSTNAME]/api/events` If testing on your local machine, you can use something like [ngrok](https://ngrok.com) to create a public endpoint. | `"https://[YOUR HOSTNAME]/api/events"` | -| handshakePort | Y | Input | The container port that the input binding will listen on for handshakes and events | `"9000"` | -| scope | Y | Input | The identifier of the resource to which the event subscription needs to be created or updated. See [here](#scope) for more details | `"/subscriptions/{subscriptionId}/"` | -| eventSubscriptionName | N | Input | The name of the event subscription. Event subscription names must be between 3 and 64 characters in length and should use alphanumeric letters only | `"name"` | -| accessKey | Y | Output | The Access Key to be used for publishing an Event Grid Event to a custom topic | `"accessKey"` | -| topicEndpoint | Y | Output | The topic endpoint in which this output binding should publish events | `"topic-endpoint"` | +| `accessKey` | Y | Output | The Access Key to be used for publishing an Event Grid Event to a custom topic | `"accessKey"` | +| `topicEndpoint` | Y | Output | The topic endpoint in which this output binding should publish events | `"topic-endpoint"` | +| `azureTenantId` | Y | Input | The Azure tenant ID of the Event Grid resource | `"tenentID"` | +| `azureSubscriptionId` | Y | Input | The Azure subscription ID of the Event Grid resource | `"subscriptionId"` | +| `azureClientId` | Y | Input | The client ID that should be used by the binding to create or update the Event Grid Event Subscription and to authenticate incoming messages | `"clientId"` | +| `azureClientSecret` | Y | Input | The client id that should be used by the binding to create or update the Event Grid Event Subscription and to authenticate incoming messages | `"clientSecret"` | +| `subscriberEndpoint` | Y | Input | The HTTPS endpoint of the webhook Event Grid sends events (formatted as Cloud Events) to. If you're not re-writing URLs on ingress, it should be in the form of: `"https://[YOUR HOSTNAME]/"`
If testing on your local machine, you can use something like [ngrok](https://ngrok.com) to create a public endpoint. | `"https://[YOUR HOSTNAME]/"` | +| `handshakePort` | Y | Input | The container port that the input binding listens on when receiving events on the webhook | `"9000"` | +| `scope` | Y | Input | The identifier of the resource to which the event subscription needs to be created or updated. See the [scope section](#scope) for more details | `"/subscriptions/{subscriptionId}/"` | +| `eventSubscriptionName` | N | Input | The name of the event subscription. Event subscription names must be between 3 and 64 characters long and should use alphanumeric letters only | `"name"` | ### Scope -Scope is the identifier of the resource to which the event subscription needs to be created or updated. The scope can be a subscription, or a resource group, or a top level resource belonging to a resource provider namespace, or an Event Grid topic. For example: -- `'/subscriptions/{subscriptionId}/'` for a subscription -- `'/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}'` for a resource group -- `'/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}'` for a resource -- `'/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.EventGrid/topics/{topicName}'` for an Event Grid topic +Scope is the identifier of the resource to which the event subscription needs to be created or updated. The scope can be a subscription, a resource group, a top-level resource belonging to a resource provider namespace, or an Event Grid topic. For example: + +- `/subscriptions/{subscriptionId}/` for a subscription +- `/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}` for a resource group +- `/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}` for a resource +- `/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.EventGrid/topics/{topicName}` for an Event Grid topic + > Values in braces {} should be replaced with actual values. + ## Binding support This component supports both **input and output** binding interfaces. This component supports **output binding** with the following operations: -- `create` -## Additional information +- `create`: publishes a message on the Event Grid topic -Event Grid Binding creates an [event subscription](https://docs.microsoft.com/azure/event-grid/concepts#event-subscriptions) when Dapr initializes. Your Service Principal needs to have the RBAC permissions to enable this. +## Azure AD credentials + +The Azure Event Grid binding requires an Azure AD application and service principal for two reasons: + +- Creating an [event subscription](https://docs.microsoft.com/azure/event-grid/concepts#event-subscriptions) when Dapr is started (and updating it if the Dapr configuration changes) +- Authenticating messages delivered by Event Hubs to your application. + +Requirements: + +- The [Azure CLI](https://docs.microsoft.com/cli/azure/install-azure-cli) installed. +- [PowerShell 7](https://learn.microsoft.com/powershell/scripting/install/installing-powershell) installed. +- [Az module for PowerShell](https://learn.microsoft.com/powershell/azure/install-az-ps) for PowerShell installed: + `Install-Module Az -Scope CurrentUser -Repository PSGallery -Force` +- [Microsoft.Graph module for PowerShell](https://learn.microsoft.com/powershell/microsoftgraph/installation) for PowerShell installed: + `Install-Module Microsoft.Graph -Scope CurrentUser -Repository PSGallery -Force` + +For the first purpose, you will need to [create an Azure Service Principal](https://learn.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal). After creating it, take note of the Azure AD application's **clientID** (a UUID), and run the following script with the Azure CLI: ```bash +# Set the client ID of the app you created +CLIENT_ID="..." +# Scope of the resource, usually in the format: +# `/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.EventGrid/topics/{topicName}` +SCOPE="..." + # First ensure that Azure Resource Manager provider is registered for Event Grid -az provider register --namespace Microsoft.EventGrid -az provider show --namespace Microsoft.EventGrid --query "registrationState" +az provider register --namespace "Microsoft.EventGrid" +az provider show --namespace "Microsoft.EventGrid" --query "registrationState" # Give the SP needed permissions so that it can create event subscriptions to Event Grid -az role assignment create --assignee --role "EventGrid EventSubscription Contributor" --scopes +az role assignment create --assignee "$CLIENT_ID" --role "EventGrid EventSubscription Contributor" --scopes "$SCOPE" ``` -_Make sure to also to add quotes around the `[HandshakePort]` in your Event Grid binding component because Kubernetes expects string values from the config._ +For the second purpose, first download a script: + +```sh +curl -LO "https://raw.githubusercontent.com/dapr/components-contrib/master/.github/infrastructure/conformance/azure/setup-eventgrid-sp.ps1" +``` + +Then, **using PowerShell** (`pwsh`), run: + +```powershell +# Set the client ID of the app you created +$clientId = "..." + +# Authenticate with the Microsoft Graph +# You may need to add the -TenantId flag to the next command if needed +Connect-MgGraph -Scopes "Application.Read.All","Application.ReadWrite.All" +./setup-eventgrid-sp.ps1 $clientId +``` + +> Note: if your directory does not have a Service Principal for the application "Microsoft.EventGrid", you may need to run the command `Connect-MgGraph` and sign in as an admin for the Azure AD tenant (this is related to permissions on the Azure AD directory, and not the Azure subscription). Otherwise, please ask your tenant's admin to sign in and run this PowerShell command: `New-MgServicePrincipal -AppId "4962773b-9cdb-44cf-a8bf-237846a00ab7"` (the UUID is a constant) ### Testing locally - Install [ngrok](https://ngrok.com/download) -- Run locally using custom port `9000` for handshakes +- Run locally using a custom port, for example `9000`, for handshakes ```bash -# Using random port 9000 as an example +# Using port 9000 as an example ngrok http --host-header=localhost 9000 ``` -- Configure the ngrok's HTTPS endpoint and custom port to input binding metadata +- Configure the ngrok's HTTPS endpoint and the custom port to input binding metadata - Run Dapr ```bash @@ -115,19 +158,19 @@ dapr run --app-id dotnetwebapi --app-port 5000 --dapr-http-port 3500 dotnet run ### Testing on Kubernetes -Azure Event Grid requires a valid HTTPS endpoint for custom webhooks. Self signed certificates won't do. In order to enable traffic from public internet to your app's Dapr sidecar you need an ingress controller enabled with Dapr. There's a good article on this topic: [Kubernetes NGINX ingress controller with Dapr](https://carlos.mendible.com/2020/04/05/kubernetes-nginx-ingress-controller-with-dapr/). +Azure Event Grid requires a valid HTTPS endpoint for custom webhooks; self-signed certificates aren't accepted. In order to enable traffic from the public internet to your app's Dapr sidecar you need an ingress controller enabled with Dapr. There's a good article on this topic: [Kubernetes NGINX ingress controller with Dapr](https://carlos.mendible.com/2020/04/05/kubernetes-nginx-ingress-controller-with-dapr/). -To get started, first create `dapr-annotations.yaml` for Dapr annotations +To get started, first create a `dapr-annotations.yaml` file for Dapr annotations: ```yaml controller: - podAnnotations: - dapr.io/enabled: "true" - dapr.io/app-id: "nginx-ingress" - dapr.io/app-port: "80" + podAnnotations: + dapr.io/enabled: "true" + dapr.io/app-id: "nginx-ingress" + dapr.io/app-port: "80" ``` -Then install NGINX ingress controller to your Kubernetes cluster with Helm 3 using the annotations +Then install the NGINX ingress controller to your Kubernetes cluster with Helm 3 using the annotations: ```bash helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx @@ -137,12 +180,13 @@ helm install nginx-ingress ingress-nginx/ingress-nginx -f ./dapr-annotations.yam kubectl get svc -l component=controller -o jsonpath='Public IP is: {.items[0].status.loadBalancer.ingress[0].ip}{"\n"}' ``` -If deploying to Azure Kubernetes Service, you can follow [the official MS documentation for rest of the steps](https://docs.microsoft.com/azure/aks/ingress-tls) +If deploying to Azure Kubernetes Service, you can follow [the official Microsoft documentation for rest of the steps](https://docs.microsoft.com/azure/aks/ingress-tls): + - Add an A record to your DNS zone - Install cert-manager - Create a CA cluster issuer -Final step for enabling communication between Event Grid and Dapr is to define `http` and custom port to your app's service and an `ingress` in Kubernetes. This example uses .NET Core web api and Dapr default ports and custom port 9000 for handshakes. +Final step for enabling communication between Event Grid and Dapr is to define `http` and custom port to your app's service and an `ingress` in Kubernetes. This example uses a .NET Core web api and Dapr default ports and custom port 9000 for handshakes. ```yaml # dotnetwebapi.yaml @@ -217,7 +261,7 @@ spec: imagePullPolicy: Always ``` -Deploy binding and app (including ingress) to Kubernetes +Deploy the binding and app (including ingress) to Kubernetes ```bash # Deploy Dapr components @@ -226,7 +270,7 @@ kubectl apply -f eventgrid.yaml kubectl apply -f dotnetwebapi.yaml ``` -> **Note:** This manifest deploys everything to Kubernetes default namespace. +> **Note:** This manifest deploys everything to Kubernetes' default namespace. #### Troubleshooting possible issues with Nginx controller