mirror of https://github.com/knative/docs.git
Add sample for cloudevents-nodejs (#2446)
* Add sample for cloudevents-nodejs Signed-off-by: Carlos Santana <csantana@us.ibm.com> * Add license headers Signed-off-by: Carlos Santana <csantana@us.ibm.com> * better to return 202 Accepted Signed-off-by: Carlos Santana <csantana@us.ibm.com>
This commit is contained in:
parent
2cc9a5afe9
commit
7c8c382e88
|
@ -7,9 +7,9 @@ Serving resources and how they can be applied across common use cases.
|
|||
| Name | Description | Languages |
|
||||
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
|
||||
| Hello World | A quick introduction that highlights how to deploy an app using Knative Serving. | [C#](./hello-world/helloworld-csharp/README.md), [Go](./hello-world/helloworld-go/README.md), [Java (Spark)](./hello-world/helloworld-java-spark/README.md), [Java (Spring)](./hello-world/helloworld-java-spring/README.md), [Kotlin](./hello-world/helloworld-kotlin/README.md), [Node.js](./hello-world/helloworld-nodejs/README.md), [PHP](./hello-world/helloworld-php/README.md), [Python](./hello-world/helloworld-python/README.md), [Ruby](./hello-world/helloworld-ruby/README.md), [Scala](./hello-world/helloworld-scala/README.md), [Shell](./hello-world/helloworld-shell/README.md) |
|
||||
| Cloud Events | A quick introduction that highlights how to send and receive Cloud Events. | [C#](./cloudevents/cloudevents-dotnet/README.md), [Go](./cloudevents/cloudevents-go/README.md) |
|
||||
| Cloud Events | A quick introduction that highlights how to send and receive Cloud Events. | [C#](./cloudevents/cloudevents-dotnet/README.md), [Go](./cloudevents/cloudevents-go/README.md), [Node.js](./cloudevents/cloudevents-nodejs/README.md) |
|
||||
| Advanced Deployment | Simple blue/green-like application deployment pattern illustrating the process of updating a live application without dropping any traffic. | [YAML](./blue-green-deployment.md) |
|
||||
| Autoscale | A demonstration of the autoscaling capabilities of Knative. | [Go](./autoscale-go/README.md) | | | |
|
||||
| Autoscale | A demonstration of the autoscaling capabilities of Knative. | [Go](./autoscale-go/README.md) |
|
||||
| Github Webhook | A simple webhook handler that demonstrates interacting with Github. | [Go](./gitwebhook-go/README.md) |
|
||||
| gRPC | A simple gRPC server. | [Go](./grpc-ping-go/README.md) |
|
||||
| Knative Routing | An example of mapping multiple Knative services to different paths under a single domain name using the Istio VirtualService concept. | [Go](./knative-routing-go/README.md) |
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Dockerfile
|
||||
README.md
|
||||
node_modules/
|
||||
npm-debug.log
|
|
@ -0,0 +1,2 @@
|
|||
node_modules/
|
||||
npm-debug.log*
|
|
@ -0,0 +1,38 @@
|
|||
# Copyright 2020 The Knative Authors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
FROM registry.access.redhat.com/ubi8/nodejs-12
|
||||
|
||||
# Copy application dependency manifests to the container image.
|
||||
# A wildcard is used to ensure both package.json AND package-lock.json are copied.
|
||||
# Copying this separately prevents re-running npm install on every code change.
|
||||
COPY package*.json ./
|
||||
|
||||
# Use ci is faster and more reliable following package-lock.json
|
||||
RUN npm ci --only=production
|
||||
|
||||
# Doc port listening port
|
||||
ENV PORT 8080
|
||||
|
||||
EXPOSE $PORT
|
||||
|
||||
ARG ENV=production
|
||||
|
||||
ENV NODE_ENV $ENV
|
||||
|
||||
# Run the web service on container startup.
|
||||
CMD npm run $NODE_ENV
|
||||
|
||||
# Copy local code to the container image.
|
||||
COPY . ./
|
|
@ -0,0 +1,100 @@
|
|||
A simple web app written in Node.js that can receive and send Cloud Events that you
|
||||
can use for testing. It supports running in two modes:
|
||||
|
||||
1. The default mode has the app reply to your input events with the output
|
||||
event, which is simplest for demonstrating things working in isolation, but
|
||||
is also the model for working for the Knative Eventing `Broker` concept.
|
||||
|
||||
2. `K_SINK` mode has the app send events to the destination encoded in
|
||||
`$K_SINK`, which is useful to demonstrate how folks can synthesize events to
|
||||
send to a Service or Broker when not initiated by a Broker invocation (e.g.
|
||||
implementing an event source)
|
||||
|
||||
The application will use `$K_SINK`-mode whenever the environment variable is
|
||||
specified.
|
||||
|
||||
Follow the steps below to create the sample code and then deploy the app to your
|
||||
cluster. You can also download a working copy of the sample, by running the
|
||||
following commands:
|
||||
|
||||
```shell
|
||||
git clone -b "{{< branch >}}" https://github.com/knative/docs knative-docs
|
||||
cd knative-docs/docs/serving/samples/cloudevents/cloudevents-nodejs
|
||||
```
|
||||
|
||||
## Before you begin
|
||||
|
||||
- A Kubernetes cluster with Knative installed and DNS configured. Follow the
|
||||
[installation instructions](../../../../install/README.md) if you need to
|
||||
create one.
|
||||
- [Docker](https://www.docker.com) installed and running on your local machine,
|
||||
and a Docker Hub account configured (we'll use it for a container registry).
|
||||
|
||||
## The sample code.
|
||||
|
||||
1. If you look in `index.js`, you will see two key functions for the
|
||||
different modes of operation:
|
||||
|
||||
```js
|
||||
const receiveAndSend = (cloudEvent, res) => {
|
||||
// This is called whenever an event is received if $K_SINK is set, and sends a new event
|
||||
// to the url in $K_SINK.
|
||||
}
|
||||
|
||||
const receiveAndReply = (cloudEvent, res) => {
|
||||
// This is called whenever an event is received if $K_SINK is NOT set, and it replies with
|
||||
// the new event instead.
|
||||
}
|
||||
```
|
||||
|
||||
1. If you look in `Dockerfile`, you will see how the dependencies are installed using npm.
|
||||
You can build and push this to your registry of choice via:
|
||||
|
||||
```shell
|
||||
docker build -t <image> .
|
||||
docker push <image>
|
||||
```
|
||||
|
||||
1. If you look in `service.yaml`, take the `<image>` name above and insert it
|
||||
into the `image:`.
|
||||
|
||||
```shell
|
||||
kubectl apply -f service.yaml
|
||||
```
|
||||
|
||||
## Testing the sample
|
||||
|
||||
Get the URL for your Service with:
|
||||
|
||||
```shell
|
||||
$ kubectl get ksvc
|
||||
NAME URL LATESTCREATED LATESTREADY READY REASON
|
||||
cloudevents-nodejs http://cloudevents-nodejs.default.1.2.3.4.xip.io cloudevents-nodejs-ss5pj cloudevents-nodejs-ss5pj True
|
||||
```
|
||||
|
||||
Then send a cloud event to it with:
|
||||
|
||||
```shell
|
||||
$ curl -X POST \
|
||||
-H "content-type: application/json" \
|
||||
-H "ce-specversion: 1.0" \
|
||||
-H "ce-source: curl-command" \
|
||||
-H "ce-type: curl.demo" \
|
||||
-H "ce-id: 123-abc" \
|
||||
-d '{"name":"Dave"}' \
|
||||
http://cloudevents-nodejs.default.1.2.3.4.xip.io
|
||||
```
|
||||
|
||||
You will get back:
|
||||
|
||||
```shell
|
||||
{"message":"Hello, Dave"}
|
||||
```
|
||||
|
||||
## Removing the sample app deployment
|
||||
|
||||
To remove the sample app from your cluster, delete the service record:
|
||||
|
||||
```shell
|
||||
kubectl delete --filename service.yaml
|
||||
```
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
Copyright 2020 The Knative Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
const express = require('express')
|
||||
const { CloudEvent, HTTPEmitter, HTTPReceiver } = require('cloudevents-sdk')
|
||||
const PORT = process.env.PORT || 8080
|
||||
const target = process.env.K_SINK
|
||||
const app = express()
|
||||
const receiver = new HTTPReceiver()
|
||||
|
||||
const main = () => {
|
||||
app.listen(PORT, function () {
|
||||
console.log(`Cookie monster is hungry for some cloudevents on port ${PORT}!`)
|
||||
const modeMessage = target ? `send cloudevents to K_SINK: ${target}` : 'reply back with cloudevents'
|
||||
console.log(`Cookie monster is going to ${modeMessage}`)
|
||||
})
|
||||
}
|
||||
|
||||
// handle shared the logic for producing the Response event from the Request.
|
||||
const handle = (data) => {
|
||||
return { message: `Hello, ${data.name ? data.name : 'nameless'}` }
|
||||
}
|
||||
|
||||
// receiveAndSend responds with ack, and send a new event forward
|
||||
const receiveAndSend = (cloudEvent, res) => {
|
||||
const data = handle(cloudEvent.getData())
|
||||
const newCloudEvent = new CloudEvent()
|
||||
.type('dev.knative.docs.sample')
|
||||
.source('https://github.com/knative/docs/docs/serving/samples/cloudevents/cloudevents-nodejs')
|
||||
.time(new Date())
|
||||
.data(data)
|
||||
|
||||
// With only an endpoint URL, this creates a v1 emitter
|
||||
const emitter = new HTTPEmitter({
|
||||
url: target
|
||||
})
|
||||
// Reply back to dispatcher/client as soon as possible
|
||||
res.status(202).end()
|
||||
// Send the new Event to the K_SINK
|
||||
emitter.send(newCloudEvent)
|
||||
.then((res) => {
|
||||
console.log(`Sent event: ${JSON.stringify(newCloudEvent.format(), null, 2)}`)
|
||||
console.log(`K_SINK responded: ${JSON.stringify({ status: res.status, headers: res.headers, data: res.data }, null, 2)}`)
|
||||
})
|
||||
.catch(console.error)
|
||||
}
|
||||
|
||||
// receiveAndReply responds with new event
|
||||
const receiveAndReply = (cloudEvent, res) => {
|
||||
const data = handle(cloudEvent.getData())
|
||||
const newCloudEvent = new CloudEvent()
|
||||
.type('dev.knative.docs.sample')
|
||||
.source('https://github.com/knative/docs/docs/serving/samples/cloudevents/cloudevents-nodejs')
|
||||
.time(new Date())
|
||||
|
||||
console.log(`Reply event: ${JSON.stringify(newCloudEvent.format(), null, 2)}`)
|
||||
res.set(getHeaders(newCloudEvent))
|
||||
res.status(200).send(data)
|
||||
}
|
||||
|
||||
const getHeaders = (cloudEvent) => {
|
||||
/* TODO: SDK should provide a better way to get the headers from a cloudEvent, using fake url for now ¯\_(ツ)_/¯ */
|
||||
const emitter = new HTTPEmitter({
|
||||
url: 'http://example.com'
|
||||
})
|
||||
return emitter.headers(cloudEvent)
|
||||
}
|
||||
|
||||
app.use((req, res, next) => {
|
||||
let data = ''
|
||||
req.setEncoding('utf8')
|
||||
req.on('data', function (chunk) {
|
||||
data += chunk
|
||||
})
|
||||
req.on('end', function () {
|
||||
req.body = data
|
||||
next()
|
||||
})
|
||||
})
|
||||
|
||||
app.post('/', function (req, res) {
|
||||
try {
|
||||
const event = receiver.accept(req.headers, req.body)
|
||||
console.log(`Accepted event: ${JSON.stringify(event.format(), null, 2)}`)
|
||||
target ? receiveAndSend(event, res) : receiveAndReply(event, res)
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
res.status(415)
|
||||
.header('Content-Type', 'application/json')
|
||||
.send(JSON.stringify(err))
|
||||
}
|
||||
})
|
||||
|
||||
main()
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
title: "Cloud Events - Node.js"
|
||||
linkTitle: "Node.js"
|
||||
weight: 1
|
||||
type: "docs"
|
||||
---
|
||||
|
||||
{{% readfile file="README.md" %}}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"name": "knative-serving-cloudevents",
|
||||
"version": "1.0.0",
|
||||
"description": "Simple CloudEvents sample in Node.js",
|
||||
"repository": "https://github.com/knative/docs",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "node index.js",
|
||||
"production": "npm start",
|
||||
"dev": "nodemon index.js",
|
||||
"lint": "standard --fix"
|
||||
},
|
||||
"author": "",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"cloudevents-sdk": "cloudevents/sdk-javascript#57991e1",
|
||||
"express": "^4.17.1",
|
||||
"nodemon": "^2.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"standard": "^14.3.4"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
# Copyright 2020 The Knative Authors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
apiVersion: serving.knative.dev/v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: cloudevents-nodejs
|
||||
namespace: default
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- image: <registry/repository/image:tag>
|
||||
# Uncomment this to send events somewhere.
|
||||
# env:
|
||||
# - name: K_SINK
|
||||
# value: http://default-broker.default.svc.cluster.local
|
Loading…
Reference in New Issue