Skip to content
This repository has been archived by the owner on Oct 25, 2022. It is now read-only.

Commit

Permalink
Merge pull request #20 from montaro/cloud-events-example
Browse files Browse the repository at this point in the history
Cloud Events Example
  • Loading branch information
bszwarc committed Aug 5, 2019
2 parents ce488d1 + 94fdf35 commit b22e12d
Show file tree
Hide file tree
Showing 4 changed files with 257 additions and 0 deletions.
103 changes: 103 additions & 0 deletions cloud-events-e2e-scenario/README.md
@@ -0,0 +1,103 @@
# Receive Cloud Events from an external solution

This is an example scenario which demonstrates how Kyma can receive Cloud Events from an external solution. To make things easier, this scenario uses a **local Kyma installation**.

This scenario uses a mocked external solution. You can mock the sending of Events using an HTTP client.
You can also use other mocked or real solutions.
The runtime flow involves following steps:

1. The external solution sends an `order.created` Event.
2. The Event is accepted by Kyma.
3. The Event triggers the deployed lambda.
4. The lambda prints out CE context attributes.

## Prerequisites

### Install Kyma locally

Use these [instructions](https://github.com/kyma-project/kyma/blob/master/docs/kyma/04-02-local-installation.md) to install and configure Kyma locally.

### Create a Namespace

Create a Namespace called `workshop`. You can choose a different name, but remember to use it in the commands.

### Create Application

1. In the Kyma Console, go to **Integration** > **Application** > **Create Application**.
2. Enter the Application name: sample-external-solution.

## Installation

### Establish secure connection

Use the [connector service](https://github.com/kyma-project/kyma/blob/master/docs/application-connector/02-02-connector-service.md) to establish a secure connection between the mocked external solution and your application.

Follow these steps connect an external solution to Kyma:
1. Clone [this repository](https://github.com/janmedrek/one-click-integration-script).

2. In the Kyma Console, navigate to **Integration** > **Applications** > **sample-external-solution**.
3. Click **Connect Application**.
4. Copy the token.

5. Use the one-click-generation [helper script](https://github.com/janmedrek/one-click-integration-script) to generate the certificate:

```bash
./one-click-integration.sh -u <paste URL here>
```

This script generates a `generated.pem` file. It contains the signed certificate and key that you will use for subsequent communications.

> **NOTE** The token expires quickly, so use it right away or generate a new one.
### Mock an external solution

Use any HTTP client, such as curl or postman, to send a request from the mocked external solution to Kyma.

### Register Events

1. Register Events via the metadata API using [`register-events.json`](./register-events.json):

```bash
# Using httpie
http POST https://gateway.kyma.local/sample-external-solution/v1/metadata/services --cert=generated.pem --verify=no < register-events.json
# Using curl
curl -X POST -H "Content-Type: application/json" -d @./register-events.json https://gateway.kyma.local/sample-external-solution/v1/metadata/services --cert generated.pem -k
```

To verify the Event flow, navigate to **Integration** > **Applications** > **sample-external-solution**. You can see the registered Events.

### Bind Application

1. Navigate to **Integration** > **Applications** > **sample-external-solution**
2. Create a binding with the `workshop` Namespace.

### Add Events and APIs to the Namespace

1. Select the `workshop` Namespace and go to **Service Management** > **Catalog**.
2. Click **Services** to see the registered Events.
3. Click on the Event entry to reveal details.
4. Click **Add once** button to add Events to your Namespace.
5. Go to **Service Instances** > **Services** tab to see if the Events are available.

### Create lambda

1. Create the lambda definition in lambda ui using [lambda.js](./lambda.js) in the workshop namespace

2. Click **Select Function trigger** button to select an Event trigger, then choose
**order.created**.

## Runtime

### Publish the Event

Use the certificate generated by the `./one-click-integration.sh` script to send a Cloud Event to the gateway using any HTTP client, such as curl, httpie, or postman. You can also use CloudEvents SDK. For details, see [this example](./example.go)

## Verification

To check if the lambda function was triggered properly, inspect the Pod logs in the `workshop` Namespace:

```bash
kubectl -n work logs lambdaname-xxx-xxxx -c lambdaname -f
```

You can also find traces under `https://jaeger.kyma.local/`.
67 changes: 67 additions & 0 deletions cloud-events-e2e-scenario/example.go
@@ -0,0 +1,67 @@
package main

import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
"log"
"net/http"
"time"

cloudevents "github.com/cloudevents/sdk-go"
"github.com/google/uuid"
)

func main() {
event := cloudevents.NewEvent()
event.Context = cloudevents.EventContextV03{}.AsV03()
event.SetID(uuid.New().String())
event.SetType("order.created")
event.SetSource("external-application")
event.SetTime(time.Now())
event.SetExtension("eventtypeversion", "v1")
event.SetDataContentType("application/json")
event.SetData(23)

// Add path to client certificate and key
cert, err := tls.LoadX509KeyPair("generated.crt", "generated.key")
if err != nil {
log.Fatalln("Unable to load cert", err)
}
clientCACert, err := ioutil.ReadFile("generated.crt")
if err != nil {
log.Fatal("Unable to open cert", err)
}

clientCertPool := x509.NewCertPool()
clientCertPool.AppendCertsFromPEM(clientCACert)

tlsConfig := &tls.Config{
Certificates: []tls.Certificate{cert},
RootCAs: clientCertPool,
InsecureSkipVerify: true,
}

tlsConfig.BuildNameToCertificate()

client := &http.Client{
Transport: &http.Transport{TLSClientConfig: tlsConfig},
}
target := "https://gateway.kyma.local/sample-external-solution/v2/events"
t, err := cloudevents.NewHTTPTransport(
cloudevents.WithTarget(target),
cloudevents.WithStructuredEncoding())

t.Client = client
c, err := cloudevents.NewClient(t)
if err != nil {
panic("unable to create cloudevent client: " + err.Error())
}
_, err = c.Send(context.Background(), event)
if err != nil {
panic("failed to send cloudevent: " + err.Error())
}
fmt.Printf("Successfully sent a new event to: %s", target)
}
15 changes: 15 additions & 0 deletions cloud-events-e2e-scenario/lambda.js
@@ -0,0 +1,15 @@
module.exports = {
main: function (event, context) {
console.log(event);
console.log("Cloud Events Attributes");
console.log("ce-specversion: " + event.extensions.request.headers['ce-specversion']);
console.log("ce-type: " + event.extensions.request.headers['ce-type']);
console.log("ce-source: " + event.extensions.request.headers['ce-source']);
console.log("ce-id: " + event.extensions.request.headers['ce-id']);
console.log("ce-time: " + event.extensions.request.headers['ce-time']);
console.log("ce-eventtypeversion: " + event.extensions.request.headers['ce-eventtypeversion']);
console.log("ce-knativehistory: " + event.extensions.request.headers['ce-knativehistory']);
console.log("content-type: " + event.extensions.request.headers['content-type']);
return event.data;
}
}
72 changes: 72 additions & 0 deletions cloud-events-e2e-scenario/register-events.json
@@ -0,0 +1,72 @@
{
"name": "es-all-events",
"provider": "Amazing Web Shop using Kyma",
"description": "Sample service for e-2-e flow",
"events": {
"spec": {
"asyncapi": "1.0.0",
"info": {
"title": "ES Events",
"version": "1.0.0",
"description": "Description of all the EC events\n"
},
"baseTopic": "stage.com.external.solution",
"topics": {
"order.created.v1": {
"subscribe": {
"summary": "Event containing information about the order added.",
"payload": {
"type": "object",
"properties": {
"orderCode": {
"title": "OrderCode",
"description": "Resource identifier",
"type": "string"
}
},
"example": {
"orderCode": "4caad296-e0c5-491e-98ac-0ed118f9474e"
}
}
}
},
"payment.received.v1": {
"subscribe": {
"summary": "Event containing information about the payment received.",
"payload": {
"type": "object",
"properties": {
"orderCode": {
"title": "paymentReceivedCode",
"description": "Resource identifier",
"type": "string"
}
},
"example": {
"orderCode": "b5870936-16d4-45e1-b9c6-4a3cd4417187"
}
}
}
},
"address.updated.v1": {
"subscribe": {
"summary": "Event containing information about the updated addrees",
"payload": {
"type": "object",
"properties": {
"orderCode": {
"title": "addressUpdatedCode",
"description": "Resource identifier",
"type": "string"
}
},
"example": {
"orderCode": "c3ec6858-de3d-4e0a-9d14-779ed023c7ee"
}
}
}
}
}
}
}
}

0 comments on commit b22e12d

Please sign in to comment.