Skip to content

Commit 55a4fa0

Browse files
authored
Merge pull request #32539 from abrennan89/godocs
[srvls][SRVOCF-278] Adding golang functions docs
2 parents 89d4a78 + b8f2fb3 commit 55a4fa0

12 files changed

+245
-11
lines changed

_topic_map.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2944,15 +2944,17 @@ Topics:
29442944
- Name: Using a Kafka source
29452945
File: serverless-kafka-source
29462946
# Functions - uncomment at tech preview
2947-
# - Name: OpenShift Serverless Functions
2948-
# Dir: functions
2947+
#- Name: Functions
2948+
# Dir: functions
29492949
# Topics:
29502950
# - Name: About OpenShift Serverless Functions
29512951
# File: serverless-functions-about
29522952
# - Name: Getting started
29532953
# File: serverless-functions-getting-started
29542954
# - Name: Setting up OpenShift Serverless Functions
29552955
# File: serverless-functions-setup
2956+
# - Name: Developing Golang functions
2957+
# File: serverless-developing-go-functions
29562958
# - Name: Developing Python functions
29572959
# File: serverless-developing-python-functions
29582960
# Networking

modules/serverless-create-func-kn.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ envVars: {}
3434
----
3535
$ kn func create <path> -r <registry> -l <runtime> -t <trigger> -i <image> -n <namespace>
3636
----
37-
+
38-
If the image is unspecified, you are prompted for a registry name. The image name is derived from this registry and the function name.
37+
** Supported runtimes include `node`, `go`, `python`, and `quarkus`.
38+
** If the image is unspecified, you are prompted for a registry name. The image name is derived from this registry and the function name.
3939
+
4040
.Example command
4141
[source,terminal]
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Module included in the following assemblies
2+
//
3+
// * /serverless/functions/serverless-developing-go-functions.adoc
4+
5+
[id="serverless-go-function-return-values_{context}"]
6+
= Golang function return values
7+
8+
HTTP triggered functions can set the response directly by using the Golang link:https://golang.org/pkg/net/http/#ResponseWriter[http.ResponseWriter].
9+
10+
.Example HTTP response
11+
[source,go]
12+
----
13+
func Handle(ctx context.Context, res http.ResponseWriter, req *http.Request) {
14+
// Set response
15+
res.Header().Add("Content-Type", "text/plain")
16+
res.Header().Add("Content-Length", "3")
17+
res.WriteHeader(200)
18+
_, err := fmt.Fprintf(res, "OK\n")
19+
if err != nil {
20+
fmt.Fprintf(os.Stderr, "error or response write: %v", err)
21+
}
22+
}
23+
----
24+
25+
Functions triggered by a CloudEvent might return nothing, `error`, or `CloudEvent` in order to push events into the Knative Eventing system. In this case, you must set a unique `ID`, proper `Source`, and a `Type` for the CloudEvent. The data can be populated from a defined structure, or from a `map`.
26+
27+
.Example CloudEvent response
28+
[source,go]
29+
----
30+
func Handle(ctx context.Context, event cloudevents.Event) (resp *cloudevents.Event, err error) {
31+
// ...
32+
response := cloudevents.NewEvent()
33+
response.SetID("example-uuid-32943bac6fea")
34+
response.SetSource("purchase/getter")
35+
response.SetType("purchase")
36+
// Set the data from Purchase type
37+
response.SetData(cloudevents.ApplicationJSON, Purchase{
38+
CustomerId: custId,
39+
ProductId: prodId,
40+
})
41+
// OR set the data directly from map
42+
response.SetData(cloudevents.ApplicationJSON, map[string]string{"customerId": custId, "productId": prodId})
43+
// Validate the response
44+
resp = &response
45+
if err = resp.Validate(); err != nil {
46+
fmt.Printf("invalid event created. %v", err)
47+
}
48+
return
49+
}
50+
----

modules/serverless-go-template.adoc

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Module included in the following assemblies
2+
//
3+
// * /serverless/functions/serverless-developing-go-functions.adoc
4+
5+
[id="serverless-go-template_{context}"]
6+
= Golang function template structure
7+
8+
When you create a Golang function using the `kn` CLI, the project directory looks like a typical Go project, with the exception of an additional `func.yaml` configuration file.
9+
10+
Golang functions have few restrictions. The only requirements are that your project must be defined in a `function` module, and must export the function `Handle()`.
11+
12+
Both `http` and `event` trigger functions have the same template structure:
13+
14+
.Template structure
15+
[source,terminal]
16+
----
17+
fn
18+
├── README.md
19+
├── func.yaml <1>
20+
├── go.mod <2>
21+
├── go.sum
22+
├── handle.go
23+
└── handle_test.go
24+
----
25+
<1> The `func.yaml` configuration file is used to determine the image name and registry.
26+
<2> You can add any required dependencies to the `go.mod` file, which can include additional local Golang files. When the project is built for deployment, these dependencies are included in the resulting runtime container image.
27+
+
28+
.Example of adding dependencies
29+
[source,terminal]
30+
----
31+
$ go get gopkg.in/[email protected]
32+
----
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Module included in the following assemblies
2+
//
3+
// * /serverless/functions/serverless-developing-go-functions.adoc
4+
5+
[id="serverless-invoking-go-functions-cloudevent_{context}"]
6+
= Functions triggered by a CloudEvent
7+
8+
When an incoming CloudEvent is received, the event is invoked by the link:https://cloudevents.github.io/sdk-go/[CloudEvents Golang SDK] and the `Event` type as a parameter.
9+
10+
You can leverage the Golang link:https://golang.org/pkg/context/[Context] as an optional parameter in the function contract, as shown in the list of supported function signatures:
11+
12+
.Supported function signatures
13+
[source,go]
14+
----
15+
Handle()
16+
Handle() error
17+
Handle(context.Context)
18+
Handle(context.Context) error
19+
Handle(cloudevents.Event)
20+
Handle(cloudevents.Event) error
21+
Handle(context.Context, cloudevents.Event)
22+
Handle(context.Context, cloudevents.Event) error
23+
Handle(cloudevents.Event) *cloudevents.Event
24+
Handle(cloudevents.Event) (*cloudevents.Event, error)
25+
Handle(context.Context, cloudevents.Event) *cloudevents.Event
26+
Handle(context.Context, cloudevents.Event) (*cloudevents.Event, error)
27+
----
28+
29+
[id="serverless-invoking-go-functions-cloudevent-example_{context}"]
30+
== CloudEvent trigger example
31+
32+
A CloudEvent is received which contains a JSON string in the data property:
33+
34+
[source,json]
35+
----
36+
{
37+
"customerId": "0123456",
38+
"productId": "6543210"
39+
}
40+
----
41+
42+
To access this data, a structure must be defined which maps properties in the CloudEvent data, and retrieves the data from the incoming event. The following example uses the `Purchase` structure:
43+
44+
[source,go]
45+
----
46+
type Purchase struct {
47+
CustomerId string `json:"customerId"`
48+
ProductId string `json:"productId"`
49+
}
50+
func Handle(ctx context.Context, event cloudevents.Event) (err error) {
51+
52+
purchase := &Purchase{}
53+
if err = event.DataAs(purchase); err != nil {
54+
fmt.Fprintf(os.Stderr, "failed to parse incoming CloudEvent %s\n", err)
55+
return
56+
}
57+
// ...
58+
}
59+
----
60+
61+
Alternatively, a Golang `encoding/json` package could be used to access the CloudEvent directly as JSON in the form of a bytes array:
62+
63+
[source,go]
64+
----
65+
func Handle(ctx context.Context, event cloudevents.Event) {
66+
bytes, err := json.Marshal(event)
67+
// ...
68+
}
69+
----
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Module included in the following assemblies
2+
//
3+
// * /serverless/functions/serverless-developing-go-functions.adoc
4+
5+
[id="serverless-invoking-go-functions-http_{context}"]
6+
= Functions triggered by an HTTP request
7+
8+
When an incoming HTTP request is received, your function is invoked with a standard Golang link:https://golang.org/pkg/context/[Context] as the first parameter, followed by two more parameters:
9+
10+
* link:https://golang.org/pkg/net/http/#ResponseWriter[`http.ResponseWriter`]
11+
* link:https://golang.org/pkg/net/http/#Request[`http.Request`]
12+
13+
You can use standard Golang techniques to access the request, and set a proper HTTP response of your function.
14+
15+
.Example HTTP response
16+
[source,go]
17+
----
18+
func Handle(ctx context.Context, res http.ResponseWriter, req *http.Request) {
19+
// Read body
20+
body, err := ioutil.ReadAll(req.Body)
21+
defer req.Body.Close()
22+
if err != nil {
23+
http.Error(res, err.Error(), 500)
24+
return
25+
}
26+
// Process body and function logic
27+
// ...
28+
}
29+
----

modules/serverless-python-function-return-values.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
[id="serverless-python-function-return-values_{context}"]
66
= Python function return values
77

8-
Functions can return any value supported by https://flask.palletsprojects.com/en/1.1.x/quickstart/#about-responses[Flask] because the invocation framework proxies these values directly to the Flask server.
8+
Functions can return any value supported by link:https://flask.palletsprojects.com/en/1.1.x/quickstart/#about-responses[Flask] because the invocation framework proxies these values directly to the Flask server.
99

1010
.Example
1111
[source,python]
@@ -34,4 +34,4 @@ def main(context):
3434
return data
3535
----
3636

37-
This example sends a CloudEvent as the response value, with a type of `"my.type"` and a source of `"/my/function"`. The CloudEvent [`data` property](https://github.com/cloudevents/spec/blob/v1.0.1/spec.md#event-data) is set to the returned `data` variable. The `event_source` and `event_type` decorator attributes are both optional.
37+
This example sends a CloudEvent as the response value, with a type of `"my.type"` and a source of `"/my/function"`. The CloudEvent link:https://github.com/cloudevents/spec/blob/v1.0.1/spec.md#event-data[`data` property] is set to the returned `data` variable. The `event_source` and `event_type` decorator attributes are both optional.

modules/serverless-python-template.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
[id="serverless-python-template_{context}"]
66
= Python function template structure
77

8-
When you create a Python function by using the `kn func` CLI, the project directory looks similar to a typical Python project.
8+
When you create a Python function by using the `kn` CLI, the project directory looks similar to a typical Python project.
99

1010
Python functions have very few restrictions. The only requirements are that your project contains a `func.py` file that contains a `main()` function, and a `func.yaml` configuration file.
1111

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Module included in the following assemblies
2+
//
3+
// * /serverless/functions/serverless-developing-go-functions.adoc
4+
5+
[id="serverless-testing-go-functions_{context}"]
6+
= Testing Golang functions
7+
8+
Golang functions can be tested locally on your computer. In the default project that is created when you create a function using `kn func create`, there is a `handle_test.go` file which contains some basic tests. These tests can be extended as needed.
9+
10+
.Procedure
11+
12+
* Run the tests:
13+
+
14+
[source,terminal]
15+
----
16+
$ go test
17+
----
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
include::modules/serverless-document-attributes.adoc[]
2+
[id="serverless-developing-go-functions"]
3+
= Developing Golang functions
4+
:context: serverless-developing-go-functions
5+
include::modules/common-attributes.adoc[]
6+
7+
toc::[]
8+
9+
:FeatureName: {FunctionsProductName}
10+
include::modules/technology-preview.adoc[leveloffset=+2]
11+
12+
After you have xref:../../serverless/functions/serverless-functions-getting-started.adoc#serverless-create-func-kn_serverless-functions-getting-started[created a Golang function project], you can modify the template files provided to add business logic to your function.
13+
14+
[id="prerequisites_serverless-developing-go-functions"]
15+
== Prerequisites
16+
17+
* Before you can develop functions, you must complete the steps in xref:../../serverless/functions/serverless-functions-setup.adoc#serverless-functions-setup[Setting up {FunctionsProductName}].
18+
19+
include::modules/serverless-go-template.adoc[leveloffset=+1]
20+
21+
[id="serverless-developing-go-functions-about-invoking_{context}"]
22+
== About invoking Golang functions
23+
24+
Golang functions are invoked by using different methods, depending on whether they are triggered by a HTTP request or a CloudEvent.
25+
26+
include::modules/serverless-invoking-go-functions-http.adoc[leveloffset=+2]
27+
include::modules/serverless-invoking-go-functions-cloudevent.adoc[leveloffset=+2]
28+
29+
include::modules/serverless-go-function-return-values.adoc[leveloffset=+1]
30+
include::modules/serverless-testing-go-functions.adoc[leveloffset=+1]
31+
32+
[id="next-steps_serverless-developing-go-functions"]
33+
== Next steps
34+
35+
* xref:../../serverless/functions/serverless-functions-getting-started.adoc#serverless-build-func-kn_serverless-functions-getting-started[Build] and xref:../../serverless/functions/serverless-functions-getting-started.adoc#serverless-deploy-func-kn_serverless-functions-getting-started[deploy] a function.

0 commit comments

Comments
 (0)