diff --git a/.github/workflows/validate-examples.yml b/.github/workflows/validate-examples.yml index afd4b688..0f796372 100644 --- a/.github/workflows/validate-examples.yml +++ b/.github/workflows/validate-examples.yml @@ -144,7 +144,7 @@ jobs: fail-fast: false matrix: examples: - ["actors", "client", "configuration", "invoke/grpc", "invoke/grpc-proxying", "pubsub"] + ["actors", "client", "configuration", "invoke/grpc", "invoke/grpc-proxying", "pubsub", "secrets-bulk"] steps: - name: Check out code uses: actions/checkout@v4 diff --git a/Cargo.toml b/Cargo.toml index 4f4a4893..6d72c756 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ readme = "README.md" keywords = ["microservices", "dapr"] [dependencies] -dapr-macros = {version="0.14.0", path = "macros" } +dapr-macros = { version = "0.14.0", path = "macros" } futures = "0.3" tonic = "0.11.0" prost = "0.12.3" @@ -33,25 +33,25 @@ axum-test = "14.3.0" once_cell = "1.18.0" tokio = { version = "1", features = ["full"] } uuid = { version = "1.4.0", features = ["v4"] } -dapr = {path="./"} +dapr = { path = "./" } tokio-test = "0.4.2" tokio-stream = { version = "0.1" } [[example]] -name = "client" -path = "examples/client/client.rs" +name = "actor-client" +path = "examples/actors/client.rs" [[example]] -name = "configuration" -path = "examples/configuration/main.rs" +name = "actor-server" +path = "examples/actors/server.rs" [[example]] -name = "publisher" -path = "examples/pubsub/publisher.rs" +name = "configuration" +path = "examples/configuration/main.rs" [[example]] -name = "subscriber" -path = "examples/pubsub/subscriber.rs" +name = "client" +path = "examples/client/client.rs" [[example]] name = "invoke-grpc-client" @@ -70,9 +70,13 @@ name = "invoke-grpc-proxying-server" path = "examples/invoke/grpc-proxying/server.rs" [[example]] -name = "actor-client" -path = "examples/actors/client.rs" +name = "publisher" +path = "examples/pubsub/publisher.rs" [[example]] -name = "actor-server" -path = "examples/actors/server.rs" +name = "subscriber" +path = "examples/pubsub/subscriber.rs" + +[[example]] +name = "secrets-bulk" +path = "examples/secrets-bulk/app.rs" diff --git a/examples/secrets-bulk/README.md b/examples/secrets-bulk/README.md new file mode 100644 index 00000000..ca070f6a --- /dev/null +++ b/examples/secrets-bulk/README.md @@ -0,0 +1,39 @@ +Before you run the example make sure local redis state store is running by executing: +``` +docker ps +``` + +1. To run the example we need to first build the examples using the following command: + +``` +cargo build --examples +``` + +2. Run the example with dapr using the following command: + + + +```bash +dapr run --app-id=rustapp --dapr-grpc-port 3500 --resources-path ./resources/ cargo run -- --example secrets-bulk +``` + + + +If everything went well you should see the following output along with dapr logs: +``` +== APP == Found secret1 with value: TestSecret1 +== APP == Found secret2 with value: TestSecret2 +== APP == Found secret3 with value: TestSecret3 +``` +_Note: The order of the secrets returned is not ordered_ diff --git a/examples/secrets-bulk/app.rs b/examples/secrets-bulk/app.rs new file mode 100644 index 00000000..ddaea872 --- /dev/null +++ b/examples/secrets-bulk/app.rs @@ -0,0 +1,23 @@ +#[tokio::main] +async fn main() -> Result<(), Box> { + // Get the Dapr port and create a connection + let port: u16 = std::env::var("DAPR_GRPC_PORT")?.parse()?; + let addr = format!("https://127.0.0.1:{}", port); + + // Create the client + let mut client = dapr::Client::::connect(addr).await?; + + let secret_store = "localsecretstore"; + + let secrets_response = client.get_bulk_secret(secret_store, None).await?; + + for (secret_name, secret_content) in &secrets_response.data { + println!( + "Found {} with value: {}", + secret_name, + &secret_content.secrets.get(secret_name).unwrap() + ); + } + + Ok(()) +} diff --git a/examples/secrets-bulk/resources/local-secret-store.yaml b/examples/secrets-bulk/resources/local-secret-store.yaml new file mode 100644 index 00000000..7284827a --- /dev/null +++ b/examples/secrets-bulk/resources/local-secret-store.yaml @@ -0,0 +1,13 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: localsecretstore + namespace: default +spec: + type: secretstores.local.file + version: v1 + metadata: + - name: secretsFile + value: secrets.json + - name: nestedSeparator + value: ":" diff --git a/examples/secrets-bulk/secrets.json b/examples/secrets-bulk/secrets.json new file mode 100644 index 00000000..12123dad --- /dev/null +++ b/examples/secrets-bulk/secrets.json @@ -0,0 +1,5 @@ +{ + "secret1": "TestSecret1", + "secret2": "TestSecret2", + "secret3": "TestSecret3" +} diff --git a/src/client.rs b/src/client.rs index 8b4d675f..6c9e3ec4 100644 --- a/src/client.rs +++ b/src/client.rs @@ -128,6 +128,27 @@ impl Client { .await } + /// Get all secrets for a given store + /// + /// # Arguments + /// + /// * `store_name` - The name of the secret store. + pub async fn get_bulk_secret( + &mut self, + store_name: S, + metadata: Option>, + ) -> Result + where + S: Into, + { + self.0 + .get_bulk_secret(GetBulkSecretRequest { + store_name: store_name.into(), + metadata: metadata.unwrap_or_default(), + }) + .await + } + /// Get the state for a specific key. /// /// # Arguments @@ -373,6 +394,10 @@ pub trait DaprInterface: Sized { request: InvokeBindingRequest, ) -> Result; async fn get_secret(&mut self, request: GetSecretRequest) -> Result; + async fn get_bulk_secret( + &mut self, + request: GetBulkSecretRequest, + ) -> Result; async fn get_state(&mut self, request: GetStateRequest) -> Result; async fn save_state(&mut self, request: SaveStateRequest) -> Result<(), Error>; async fn delete_state(&mut self, request: DeleteStateRequest) -> Result<(), Error>; @@ -434,6 +459,16 @@ impl DaprInterface for dapr_v1::dapr_client::DaprClient { Ok(self.get_secret(Request::new(request)).await?.into_inner()) } + async fn get_bulk_secret( + &mut self, + request: GetBulkSecretRequest, + ) -> Result { + Ok(self + .get_bulk_secret(Request::new(request)) + .await? + .into_inner()) + } + async fn get_state(&mut self, request: GetStateRequest) -> Result { Ok(self.get_state(Request::new(request)).await?.into_inner()) } @@ -538,6 +573,12 @@ pub type GetSecretRequest = dapr_v1::GetSecretRequest; /// A response from getting secret pub type GetSecretResponse = dapr_v1::GetSecretResponse; +/// A request for getting bulk secrets +pub type GetBulkSecretRequest = dapr_v1::GetBulkSecretRequest; + +/// A response for getting bulk secrets +pub type GetBulkSecretResponse = dapr_v1::GetBulkSecretResponse; + /// A response from getting metadata pub type GetMetadataResponse = dapr_v1::GetMetadataResponse;