Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of Dapr Building Block: Bindings #7960

Open
1 task done
SoTrx opened this issue Sep 23, 2024 · 4 comments · May be fixed by #7970
Open
1 task done

Implementation of Dapr Building Block: Bindings #7960

SoTrx opened this issue Sep 23, 2024 · 4 comments · May be fixed by #7970
Labels
feature This issue describes a feature request in Radius triaged This issue has been reviewed and triaged

Comments

@SoTrx
Copy link
Contributor

SoTrx commented Sep 23, 2024

Overview of feature request

The Dapr bindings building block allows interaction with external systems by reacting to external system events through input bindings (e.g., messages received from SaaS software events) or by triggering an external system's response with output bindings (e.g., SMTP, SMS, etc.).
From a component standpoint, the only difference between input and output bindings is the direction metadata.

This enhancement will improve compatibility between Radius and Dapr. The building block is straightforward and won’t require any major changes to the daprrp aside from the new type.

Acceptance criteria

  • A new Applications.Dapr/bindings resource can be created.
  • Appropriate documentation will be provided.
  • No new local development recipe is needed, as bindings interacts with external systems.

Additional context

https://docs.dapr.io/developing-applications/building-blocks/bindings/bindings-overview/

Would you like to support us?

  • Yes, I would like to support you

AB#13234

@SoTrx SoTrx added the feature This issue describes a feature request in Radius label Sep 23, 2024
@radius-triage-bot
Copy link

👋 @SoTrx Thanks for filing this feature request.

A project maintainer will review this feature request and get back to you soon.

We also welcome community contributions! If you would like to pick this item up sooner and submit a pull request, please visit our contribution guidelines and assign this to yourself by commenting "/assign" on this issue.

For more information on our triage process please visit our triage overview

@lakshmimsft lakshmimsft added the triaged This issue has been reviewed and triaged label Sep 23, 2024
@radius-triage-bot
Copy link

👍 We've reviewed this issue and have agreed to add it to our backlog. Please subscribe to this issue for notifications, we'll provide updates when we pick it up.

We also welcome community contributions! If you would like to pick this item up sooner and submit a pull request, please visit our contribution guidelines and assign this to yourself by commenting "/assign" on this issue.

For more information on our triage process please visit our triage overview

@Reshrahim
Copy link
Contributor

@SoTrx - Just FYI, we have been working on expanding the built in Radius types with the User defined types solution. This will simplify a lot of writing Go code to make new resource type work in Radius. You can find more context about it in these docs

  1. PM feature spec - Add features spec for Resource extensibility  design-notes#58
  2. Technical design -https://github.com/radius-project/design-notes/blob/main/architecture/2024-07-user-defined-types.md

That said, UDT's feature is still in design and no ETA at the moment. If you have plans to contribute to this now, please go ahead with the current way of adding new types to Radius.

@SoTrx
Copy link
Contributor Author

SoTrx commented Oct 5, 2024

Changes for users

This update introduces the Dapr Bindings Building Block.
Bindings are a way for applications to interact with external systems. There are two kinds of bindings:

  • Output bindings trigger external systems to react, and are often used for notifications.
  • Input bindings make applications react to external systems, such as CRON jobs or messages received in an external queue.
resource myapp 'Applications.Core/containers@2023-10-01-preview' = {
  name: '${baseName}-ctnr'
  properties: {
    connections: {
      mail: {
        source: mailing.id
      }
      cron: {
        source: cron.id
      }
    }
  ...
  }
}

// Output binding to an SMTP server. 
// https://docs.dapr.io/reference/components-reference/supported-bindings/smtp/
resource mailing 'Applications.Dapr/bindings@2023-10-01-preview' = {
  name: '${baseName}-mail'
  properties: {
    application: app.id
    environment: environment
    resourceProvisioning: 'manual'
    type: 'bindings.smtp'
    metadata: {...}
  }
}

// Input binding : a CRON scheduler
// https://docs.dapr.io/reference/components-reference/supported-bindings/cron/
resource cron 'Applications.Dapr/bindings@2023-10-01-preview' = {
  name: '${baseName}-cron'
  properties: {
    application: app.id
    environment: environment
    resourceProvisioning: 'manual'
    type: 'bindings.cron'
    metadata: {...}
  }
}

Using a connection with a binding injects the corresponding Dapr component name into the app container environment variable as CONNECTION_$(connection_name)_COMPONENTNAME. This allows the application to access the binding as shown below:

import (
	"encoding/json"
	"log"
	"net/http"
	"github.com/gorilla/mux"
)

func sendMail(w http.ResponseWriter, r *http.Request) {
        ctx := context.Background()
        client, _:= dapr.NewClient()
        // Sending an email with the output binding
        in := &dapr.InvokeBindingRequest{
            Name:      CONNECTION_MAIL_COMPONENTNAME,
            Operation: "create",
            Data: []byte("This is the body of the message"),
            Metadata: map[string]string{"emailTo": "example@example.net", "subject": "Not fishy"},
        }
        
        out, _:= client.InvokeBinding(ctx, in)
        w.WriteHeader(http.StatusOK)     
}

func main() {
	r := mux.NewRouter()
       // Each time a request is received with the input binding
	r.HandleFunc(CONNECTION_CRON_COMPONENTNAME, sendMail).Methods("POST", "OPTIONS")
	http.ListenAndServe(":6002", r)
}

Changes in Radius

This change adds the resource type Applications.Dapr/Bindings to the Dapr resource provider. This addition has no side effects on other resources in the provider.

Frontend

model DaprBindingResource
  is TrackedResourceRequired<DaprBindingProperties, "DaprBindings"> {
  @doc("Binding name")
  @key("bindingName")
  @path
  @segment("bindings")
  name: ResourceNameString;
}

@doc("Dapr binding portable resource properties")
model DaprBindingProperties {
  ...EnvironmentScopedResource;
  ...DaprResourceProperties;

  @doc("A collection of references to resources associated with the binding")
  resources?: ResourceReference[];

  ...RecipeBaseProperties;
}

Inner representation

type DaprBinding struct {
	v1.BaseResource

	// (Properties common to other components)
	Properties DaprBindingProperties `json:"properties"`

	// ResourceMetadata represents internal DataModel properties common to all portable resource types.
	datamodel.PortableResourceMetadata
}

Example emitted component

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: binding
  [labels]
spec:
  type: bindings.redis
  metadata:
  - name: redisHost
    value: localhost:6379
  - name: redisPassword
    value: <PASSWORD>

Let me know If I need to add anything to this description

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature This issue describes a feature request in Radius triaged This issue has been reviewed and triaged
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants