Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/mariotoffia/gogreengrass
Deploy go lambdas onto AWS green grass devices and use the GGC APIs.
https://github.com/mariotoffia/gogreengrass
aws aws-lambda go golang greengrass lambdas
Last synced: 21 days ago
JSON representation
Deploy go lambdas onto AWS green grass devices and use the GGC APIs.
- Host: GitHub
- URL: https://github.com/mariotoffia/gogreengrass
- Owner: mariotoffia
- License: apache-2.0
- Created: 2020-11-11T06:10:16.000Z (about 4 years ago)
- Default Branch: main
- Last Pushed: 2021-10-11T08:44:17.000Z (about 3 years ago)
- Last Synced: 2024-10-16T15:44:48.356Z (2 months ago)
- Topics: aws, aws-lambda, go, golang, greengrass, lambdas
- Language: Go
- Homepage:
- Size: 2.32 MB
- Stars: 1
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[![GoDoc](https://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](https://pkg.go.dev/mod/github.com/mariotoffia/gogreengrass)
[![GitHub Actions](https://img.shields.io/github/workflow/status/mariotoffia/gogreengrass/Go?style=flat-square)](https://github.com/mariotoffia/gogreengrass/actions?query=workflow%3AGo)# Overview of gogreengrass
:bulb: **Deploy your cloud go lambda onto greengrass core devices without alteration**
This library is a enabler to deploy standard aws go lambdas onto greengrass device lambdas. It also exposes the greengrass local API functions (greengrass SDK) to e.g. communicate with MQTT, local device shadow / secrets manager etc.
It also enables a go programmer to create much more efficient greengrass specific lambdas using the simplified lambda model if that is required.
**NOTE: This is still very much in development!**
## Example
Primary mode is to use GGC C Runtime and deploy golang lambdas as **greengrass lambda executable**. In this mode the go lambda is dynamically linked to the GGC C runtime and is much more optimal.
It is possible to use e.g. _CDK_ to deploy the lambda.
For example, create this simple lambda that you want to execute in same thread as the `main` function.
```golang
//go:generate gogreengrass --sdkc
func main() {
type MyEvent struct {
Data int `json:"data"`
Hello string `json:"hello"`
}type MyResponse struct {
Age int `json:"age"`
Topic string `json:"topic"`
}sdkc.Start(func(c context.Context, data MyEvent) (MyResponse, error) {
lc, _ := lambdacontext.FromContext(c)
fmt.Printf(
"context: %v, topic: %s, data: '%v'\n",
lc, lc.ClientContext.Custom["subject"], data,
)resp := MyResponse{Age: 19, Topic: "feed/myfunc"}
sdkc.NewQueue().PublishObject(
"feed/testlambda", sdkc.QueueFullPolicyOptionAllOrError, &resp,
)return resp, nil
})
}
```Make sure to have the shared library shim installed by `gogreengrass -sdkc` - _see Command Line Tool_. Since this file is decorated with generator pattern, `go generate` will create the library shim. Just do a standard _go_ build `go build -o testlambda main.go` and include it into your deployment.
The following _CDK_ definition can be used to deploy the above lambda (_see sample: internal/test/sdkc/lambda_).
```typescript
import * as cdk from '@aws-cdk/core';
import * as lambda from '@aws-cdk/aws-lambda';
import path = require("path");const GREENGRASS_EXECUTABLE = new lambda.Runtime('arn:aws:greengrass:::runtime/function/executable')
export class TestLambda extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);const testlambda = new lambda.Function(this, 'testlambda', {
runtime: GREENGRASS_EXECUTABLE,
functionName: 'testlambda',
handler: 'testlambda',
code: lambda.Code.fromAsset(path.join(__dirname, '../../_out/testlambda')),
timeout: cdk.Duration.seconds(30),
currentVersionOptions: {
removalPolicy: cdk.RemovalPolicy.RETAIN,
}
});testlambda.currentVersion.addAlias('live')
}
}
```
_Note that the lambda runtime is in this case arn:aws:greengrass:::runtime/function/executable_.When doing `npm run deploy` it will show up in the IoT Core Greengrass console lambda for the greengrass group.
## Command Line Tool
Install the command line tool by `go get -u github.com/mariotoffia/gogreengrass`. This tool may be used in order to install the mock shared library if using C runtime.```gogreengrass -h``` emits the following:
```bash
gogreengrass v0.0.6
Usage: gogreengrass [--out PATH] [--sdkc]Options:
--out PATH, -o PATH The out path to write the shared AWS C runtime library mock. Default is /tmp/gogreengrass
--sdkc, -l Installs the c runtime shared library in /tmp/gogreengrass (or if -o, some other path)
--help, -h display this help and exit
--version display version and exit
```## C Runtime
This is the preferred method to create your go lambdas. Use the _sdkc_ package to interact with the lambda runtime and greengrass specific APIs such as local device shadow / secrets manager or publish data on _MQTT_ etc.
### Lambda
The go version of the lambda runtime is layered. The "slim" or simple layer and the standard AWS lambda layer. Depending on the
use-case and performance on the device you may choose one over the other.#### Standard Lambda
The standard AWS lambda layer is behaving exactly the same as a standard cloud lambda, hence portable.
When using the convenience function `Start` it starts the lambda dispatcher on the main thread and the lambda gets invoked on the main thread. This is more or less the standard cloud version of it.
```go
sdkc.Start(func(c context.Context, data MyEvent) (MyResponse, error) {
// process the data here
})
```If you want to continue on main thread and fire up a dispatcher on a separate thread, you may use `StartWithOpts` to control this behavior.
```go
sdkc.StartWithOpts(
func(c context.Context, data MyEvent) (MyResponse, error) { // <1>
// process the data here
},
RuntimeOptionSeparateThread, // <2>
true // <3>
)
```
<1> This function is executed on a single background thread. Hence, the invocations is serialized on that thread. The main thread continues.
<2> The specifies the separate thread behavior.
<3> If set to `true`, it will always fetch the payload. If `false` it is up to the lambda to fetch the data (_see below_).Since the lambda function do take `MyEvent` the payload must be set to `true` in order to `Unmarshal` into that object. If lambda wants no payload or want to handle this itself, specify `false`.
```go
// registered lambda
func(c context.Context) error {
r := NewRequestReader()
b := make([]byte, 256)
for {
n, err := r.Read(b)
if n > 0 {
// process the b[:n]
}if err == io.EOF {
break
}if err != nil {
return err
}
}
}
```If you only want to read it all directly, e.g. want to do custom `Unmarshal` or other.
```go
if buf, err := ioutil.ReadAll(NewRequestReader()); err == nil {
// the complete request payload is in buf
}
```In short, you may use standard portable go lambdas or very specialized on the "standard" track. You may even do more lightweight lambdas using the more low level lambda.
#### Slim Lambda
The slim lambda is a non reflective and no `Unmarshal` path and hence is more optimized. You have two options to register the lambda (as with regular lambda). The `GGStart` and `GGStartWithOpts`, it works exactly the same on registration part, except that the lambda function is fixed. You have to do all reading, writing and others yourself.
```go
sdkc.GGStart(func(lc *sdkc.LambdaContextSlim) { // <1>sdk.Log(sdkc.LogLevelInfo, "%s, %s\n", lc.ClientContext, lc.FunctionARN) // <2>
sdk.Log(sdkc.LogLevelInfo, "Payload: %s\n", string(lc.Payload)) // <3>
// <4>
})
```
<1> The one and only function type to register.
<2> ClientContext is a string that you may unmarshal yourself.
<3> The payload is a `[]byte` (in this case it will be populated since `GGStart` do set _payload_ to `true`)
<4> If you want to return data, you have to write either error output or return payload yourself.As with standard lambda, one may register using `GGStartWithOpts` to change if background thread or read / write data yourself.
To write a response, do create a `NewResponseWriter` and do a `Write(buff)`. If any errors is returned, use the `NewErrorResponseWriter` and do a `Write(buff)`. Both of them implements the `io.Writer` interface.
### Install C Runtime SDK Mock Library
You need to have the mock version of the shared library. Either follow the instructions in the [greengrass core C SDK](https://github.com/aws/aws-greengrass-core-sdk-c) or use the `gogreengrass` ability to store _libaws-greengrass-core-sdk-c.so_ in your _/tmp/gogreengrass_ folder.
```bash
gogreengrass -sdkc
```This writes the shared library (shim) that makes your go lambdas build and run. When deployed onto the greengrass core device, the real shared library is already present (**this library shall never be part of the package**) - see the [greengrass core C SDK](https://github.com/aws/aws-greengrass-core-sdk-c) for more information.