-
Notifications
You must be signed in to change notification settings - Fork 68
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #326 from codegold79/kn-go-echo
- Loading branch information
Showing
7 changed files
with
344 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
# kn-go-echo | ||
|
||
Simple Go function running in Knative to echo [CloudEvents](https://github.com/cloudevents/sdk-go). | ||
In addition, [ko](https://github.com/google/ko) is used to create the artifacts. | ||
|
||
Valid events will be printed out JSON-encoded, separated by their CloudEvent | ||
`attributes` and `data` for better readability. This example service also | ||
returns the received event, enabling it to be used as part of a pipeline of | ||
events. | ||
|
||
## Step 1: Build with `ko` | ||
|
||
`ko` was created to help Knative developers build images and binaries without | ||
the need for Dockerfiles nor Makefiles. See more information in [this Knative | ||
blog](https://knative.dev/blog/2018/12/18/ko-fast-kubernetes-microservice-development-in-go/). | ||
|
||
Follow setup instructions at https://github.com/google/ko. | ||
|
||
After installing ko, set the destination for images with an environment variable. | ||
|
||
``` bash | ||
KO_DOCKER_REPO=my-dockerhub-user | ||
``` | ||
|
||
Run the following command from the `kn-go-echo` directory. It will build and | ||
push the image to your local Docker daemon. To have `ko` publish and use a | ||
container image registry, remove the `--local` flag. | ||
|
||
```bash | ||
ko publish --local . | ||
``` | ||
|
||
## Step 2: Test | ||
|
||
To run the container using a locally stored image, use | ||
|
||
```bash | ||
docker run -p 8080:8080 $(ko publish --local .) | ||
``` | ||
|
||
In a separate window, send a POST request. You can send fake cloud event for | ||
testing purposes. | ||
|
||
```bash | ||
$ curl -X POST -i -d@testdata/cloudevent.json \ | ||
--header 'Content-Type: application/cloudevents+json' \ | ||
localhost:8080 | ||
HTTP/1.1 100 Continue | ||
|
||
HTTP/1.1 200 OK | ||
Ce-Id: 08179137-b8e0-4973-b05f-8f212bf5003b | ||
Ce-Source: https://10.0.0.1:443/sdk | ||
Ce-Specversion: 1.0 | ||
Ce-Subject: VmPoweredOffEvent | ||
Ce-Time: 2020-02-11T21:29:54.9052539Z | ||
Ce-Type: com.vmware.event.router/event | ||
Content-Length: 1042 | ||
Content-Type: application/json | ||
Date: Fri, 07 May 2021 21:29:27 GMT | ||
|
||
{ "Key": 9902, "ChainId": 9895, "CreatedTime": "2020-02-11T21:28:23.677595Z", "UserName": "VSPHERE.LOCAL\\Administrator", "Datacenter": { "Name": "testDC", "Datacenter": { "Type": "Datacenter", "Value": "datacenter-2" } }, "ComputeResource": { "Name": "cls", "ComputeResource": { "Type": "ClusterComputeResource", "Value": "domain-c7" } }, "Host": { "Name": "10.185.22.74", "Host": { "Type": "HostSystem", "Value": "host-21" } }, "Vm": { "Name": "test-01", "Vm": { "Type": "VirtualMachine", "Value": "vm-56" } }, "Ds": null, "Net": null, "Dvs": null, "FullFormattedMessage": "test-01 on 10.0.0.1 in testDC is powered off", "ChangeTag": "", "Template": false } | ||
``` | ||
|
||
The following lines should appear in the docker container: | ||
|
||
``` | ||
2021/05/06 21:09:03 listening on :8080 | ||
***cloud event*** | ||
Context Attributes, | ||
specversion: 1.0 | ||
type: com.vmware.event.router/event | ||
source: https://10.0.0.1:443/sdk | ||
subject: VmPoweredOffEvent | ||
id: 08179137-b8e0-4973-b05f-8f212bf5003b | ||
time: 2020-02-11T21:29:54.9052539Z | ||
datacontenttype: application/json | ||
Data, | ||
{ | ||
"Key": 9902, | ||
"ChainId": 9895, | ||
"CreatedTime": "2020-02-11T21:28:23.677595Z", | ||
"UserName": "VSPHERE.LOCAL\\Administrator", | ||
"Datacenter": { | ||
"Name": "testDC", | ||
"Datacenter": { | ||
"Type": "Datacenter", | ||
"Value": "datacenter-2" | ||
} | ||
}, | ||
"ComputeResource": { | ||
"Name": "cls", | ||
"ComputeResource": { | ||
"Type": "ClusterComputeResource", | ||
"Value": "domain-c7" | ||
} | ||
}, | ||
"Host": { | ||
"Name": "10.185.22.74", | ||
"Host": { | ||
"Type": "HostSystem", | ||
"Value": "host-21" | ||
} | ||
}, | ||
"Vm": { | ||
"Name": "test-01", | ||
"Vm": { | ||
"Type": "VirtualMachine", | ||
"Value": "vm-56" | ||
} | ||
}, | ||
"Ds": null, | ||
"Net": null, | ||
"Dvs": null, | ||
"FullFormattedMessage": "test-01 on 10.0.0.1 in testDC is powered off", | ||
"ChangeTag": "", | ||
"Template": false | ||
} | ||
``` | ||
|
||
## Step 3: Deploy | ||
|
||
**Note:** The following steps assume a working Knative environment using the | ||
`default` Rabbit broker. The Knative `service` and `trigger` will be installed in the | ||
`vmware-functions` Kubernetes namespace, assuming that the broker is also available there. | ||
|
||
Edit the function.yaml file with the name of the container image from Step 1 if you made any changes. If not, the default VMware container image will suffice and then deploy the function to VMware Event Broker Appliance (VEBA): | ||
|
||
```bash | ||
# Deploy function | ||
kubectl -n vmware-functions apply -f function.yaml | ||
``` | ||
|
||
For testing purposes, the function.yaml contains the following annotations, which will ensure the Knative Service Pod will always run exactly one instance for debugging purposes. Functions deployed through through the VMware Event Broker Appliance UI defaults to scale to 0, which means the pods will only run when it is triggered by an vCenter Event. | ||
|
||
```yaml | ||
annotations: | ||
autoscaling.knative.dev/maxScale: "1" | ||
autoscaling.knative.dev/minScale: "1" | ||
``` | ||
## Step 4: Undeploy | ||
```bash | ||
# Undeploy function | ||
kubectl -n vmware-functions delete -f function.yaml | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
apiVersion: serving.knative.dev/v1 | ||
kind: Service | ||
metadata: | ||
name: kn-go-echo | ||
labels: | ||
app: veba-ui | ||
spec: | ||
template: | ||
metadata: | ||
annotations: | ||
autoscaling.knative.dev/maxScale: "1" | ||
autoscaling.knative.dev/minScale: "1" | ||
spec: | ||
containers: | ||
- image: projects.registry.vmware.com/veba/kn-go-echo:1.0 | ||
--- | ||
apiVersion: eventing.knative.dev/v1 | ||
kind: Trigger | ||
metadata: | ||
name: kn-go-echo-trigger | ||
labels: | ||
app: veba-ui | ||
spec: | ||
broker: default | ||
subscriber: | ||
ref: | ||
apiVersion: serving.knative.dev/v1 | ||
kind: Service | ||
name: kn-go-echo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module github.com/vmware-samples/vcenter-event-broker-appliance/examples/go/kn-echo | ||
|
||
go 1.15 | ||
|
||
require github.com/cloudevents/sdk-go/v2 v2.4.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
github.com/cloudevents/sdk-go/v2 v2.4.1 h1:rZJoz9QVLbWQmnvLPDFEmv17Czu+CfSPwMO6lhJ72xQ= | ||
github.com/cloudevents/sdk-go/v2 v2.4.1/go.mod h1:MZiMwmAh5tGj+fPFvtHv9hKurKqXtdB9haJYMJ/7GJY= | ||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= | ||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= | ||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= | ||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= | ||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | ||
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= | ||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= | ||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= | ||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= | ||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= | ||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= | ||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= | ||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= | ||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= | ||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= | ||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= | ||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= | ||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= | ||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | ||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= | ||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= | ||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= | ||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= | ||
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= | ||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= | ||
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= | ||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= | ||
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= | ||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= | ||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= | ||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= | ||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"log" | ||
"strings" | ||
|
||
cloudevents "github.com/cloudevents/sdk-go/v2" | ||
) | ||
|
||
// echoSuffix indicates the event is an echo. | ||
const echoSuffix = ".echo" | ||
|
||
func main() { | ||
ctx := context.Background() | ||
|
||
client, err := cloudevents.NewClientHTTP() | ||
if err != nil { | ||
log.Fatalf("creating HTTP client, %v", err) | ||
} | ||
|
||
log.Println("listening on :8080") | ||
if err := client.StartReceiver(ctx, receive); err != nil { | ||
log.Fatalf("start receiver: %s", err.Error()) | ||
} | ||
} | ||
|
||
func receive(ctx context.Context, event cloudevents.Event) *cloudevents.Event { | ||
fmt.Printf("***cloud event***\n%s", event) | ||
|
||
// Don't return the event if it is an echo. Prevent an infinite event echo loop. | ||
if isEcho(event.Type()) { | ||
return nil | ||
} | ||
|
||
event.SetType(event.Type() + echoSuffix) | ||
return &event | ||
} | ||
|
||
func isEcho(s string) bool { | ||
trimmed := strings.TrimSuffix(s, echoSuffix) | ||
return trimmed != s | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package main | ||
|
||
import ( | ||
"testing" | ||
) | ||
|
||
func TestIsEcho(t *testing.T) { | ||
tests := []struct { | ||
input string | ||
want bool | ||
}{ | ||
{"blah blah blah.echo", true}, | ||
{"blah blah blah", false}, | ||
{"echo echo .echo blah blah blah", false}, | ||
{"echo echo .echo blah blah blah.echo", true}, | ||
} | ||
|
||
for _, tt := range tests { | ||
if got := isEcho(tt.input); got != tt.want { | ||
t.Errorf("got isEcho(%q) %t, want %t", tt.input, got, tt.want) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
{ | ||
"id": "08179137-b8e0-4973-b05f-8f212bf5003b", | ||
"source": "https://10.0.0.1:443/sdk", | ||
"specversion": "1.0", | ||
"type": "com.vmware.event.router/event", | ||
"subject": "VmPoweredOffEvent", | ||
"time": "2020-02-11T21:29:54.9052539Z", | ||
"data": { | ||
"Key": 9902, | ||
"ChainId": 9895, | ||
"CreatedTime": "2020-02-11T21:28:23.677595Z", | ||
"UserName": "VSPHERE.LOCAL\\Administrator", | ||
"Datacenter": { | ||
"Name": "testDC", | ||
"Datacenter": { | ||
"Type": "Datacenter", | ||
"Value": "datacenter-2" | ||
} | ||
}, | ||
"ComputeResource": { | ||
"Name": "cls", | ||
"ComputeResource": { | ||
"Type": "ClusterComputeResource", | ||
"Value": "domain-c7" | ||
} | ||
}, | ||
"Host": { | ||
"Name": "10.185.22.74", | ||
"Host": { | ||
"Type": "HostSystem", | ||
"Value": "host-21" | ||
} | ||
}, | ||
"Vm": { | ||
"Name": "test-01", | ||
"Vm": { | ||
"Type": "VirtualMachine", | ||
"Value": "vm-56" | ||
} | ||
}, | ||
"Ds": null, | ||
"Net": null, | ||
"Dvs": null, | ||
"FullFormattedMessage": "test-01 on 10.0.0.1 in testDC is powered off", | ||
"ChangeTag": "", | ||
"Template": false | ||
}, | ||
"datacontenttype": "application/json" | ||
} |