{"id":17340355,"url":"https://github.com/mariotoffia/gogreengrass","last_synced_at":"2026-05-03T04:39:57.372Z","repository":{"id":111006495,"uuid":"311879143","full_name":"mariotoffia/gogreengrass","owner":"mariotoffia","description":"Deploy go lambdas onto AWS green grass devices and use the GGC APIs. ","archived":false,"fork":false,"pushed_at":"2021-10-11T08:44:17.000Z","size":2432,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-01T13:29:37.879Z","etag":null,"topics":["aws","aws-lambda","go","golang","greengrass","lambdas"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mariotoffia.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-11-11T06:10:16.000Z","updated_at":"2021-10-11T08:44:20.000Z","dependencies_parsed_at":null,"dependency_job_id":"a39e9ab6-ad8c-4d3a-a18f-1b9f0ac27dc3","html_url":"https://github.com/mariotoffia/gogreengrass","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mariotoffia%2Fgogreengrass","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mariotoffia%2Fgogreengrass/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mariotoffia%2Fgogreengrass/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mariotoffia%2Fgogreengrass/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mariotoffia","download_url":"https://codeload.github.com/mariotoffia/gogreengrass/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245812947,"owners_count":20676723,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","aws-lambda","go","golang","greengrass","lambdas"],"created_at":"2024-10-15T15:44:43.832Z","updated_at":"2026-05-03T04:39:57.331Z","avatar_url":"https://github.com/mariotoffia.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![GoDoc](https://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](https://pkg.go.dev/mod/github.com/mariotoffia/gogreengrass)\n[![GitHub Actions](https://img.shields.io/github/workflow/status/mariotoffia/gogreengrass/Go?style=flat-square)](https://github.com/mariotoffia/gogreengrass/actions?query=workflow%3AGo)\n\n# Overview of gogreengrass \n\n:bulb: **Deploy your cloud go lambda onto greengrass core devices without alteration**\n\nThis 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.\n\nIt also enables a go programmer to create much more efficient greengrass specific lambdas using the simplified lambda model if that is required.\n\n**NOTE: This is still very much in development!**\n\n## Example\n\nPrimary 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.\n\nIt is possible to use e.g. _CDK_ to deploy the lambda.\n\nFor example, create this simple lambda that you want to execute in same thread as the `main` function.\n\n```golang\n\n//go:generate gogreengrass --sdkc\n\nfunc main() {\n\ttype MyEvent struct {\n\t\tData  int    `json:\"data\"`\n\t\tHello string `json:\"hello\"`\n\t}\n\n\ttype MyResponse struct {\n\t\tAge   int    `json:\"age\"`\n\t\tTopic string `json:\"topic\"`\n\t}\n\n\tsdkc.Start(func(c context.Context, data MyEvent) (MyResponse, error) {\n\n\t\tlc, _ := lambdacontext.FromContext(c)\n\n\t\tfmt.Printf(\n\t\t\t\"context: %v, topic: %s, data: '%v'\\n\",\n\t\t\tlc, lc.ClientContext.Custom[\"subject\"], data,\n\t\t)\n\n\t\tresp := MyResponse{Age: 19, Topic: \"feed/myfunc\"}\n\n\t\tsdkc.NewQueue().PublishObject(\n\t\t\t\"feed/testlambda\", sdkc.QueueFullPolicyOptionAllOrError, \u0026resp,\n\t\t)\n\n\t\treturn resp, nil\n\t})\n}\n```\n\nMake 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. \n\nThe following _CDK_ definition can be used to deploy the above lambda (_see sample: internal/test/sdkc/lambda_).\n\n```typescript\nimport * as cdk from '@aws-cdk/core';\nimport * as lambda from '@aws-cdk/aws-lambda';\nimport path = require(\"path\");\n\nconst GREENGRASS_EXECUTABLE = new lambda.Runtime('arn:aws:greengrass:::runtime/function/executable')\n\nexport class TestLambda extends cdk.Stack {\n\n  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {\n    super(scope, id, props);\n\n    const testlambda = new lambda.Function(this, 'testlambda', {\n      runtime: GREENGRASS_EXECUTABLE,\n      functionName: 'testlambda',\n      handler: 'testlambda',\n      code: lambda.Code.fromAsset(path.join(__dirname, '../../_out/testlambda')),\n      timeout: cdk.Duration.seconds(30),\n      currentVersionOptions: {\n        removalPolicy: cdk.RemovalPolicy.RETAIN,\n      }\n    });\n\n    testlambda.currentVersion.addAlias('live')\n  }\n}\n```\n_Note that the lambda runtime is in this case arn:aws:greengrass:::runtime/function/executable_.\n\nWhen doing `npm run deploy` it will show up in the IoT Core Greengrass console lambda for the greengrass group.\n\n## Command Line Tool\nInstall 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.\n\n```gogreengrass -h``` emits the following:\n\n```bash\ngogreengrass v0.0.6\nUsage: gogreengrass [--out PATH] [--sdkc]\n\nOptions:\n  --out PATH, -o PATH    The out path to write the shared AWS C runtime library mock. Default is /tmp/gogreengrass\n  --sdkc, -l             Installs the c runtime shared library in /tmp/gogreengrass (or if -o, some other path)\n  --help, -h             display this help and exit\n  --version              display version and exit\n  ```\n\n## C Runtime\n\nThis 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.\n\n### Lambda\n\nThe go version of the lambda runtime is layered. The \"slim\" or simple layer and the standard AWS lambda layer. Depending on the\nuse-case and performance on the device you may choose one over the other. \n\n\n#### Standard Lambda\n\nThe standard AWS lambda layer is behaving exactly the same as a standard cloud lambda, hence portable. \n\nWhen 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.\n\n```go\n\tsdkc.Start(func(c context.Context, data MyEvent) (MyResponse, error) {\n\t\t// process the data here\n\t})\n```\n\nIf you want to continue on main thread and fire up a dispatcher on a separate thread, you may use `StartWithOpts` to control this behavior. \n\n```go\n\tsdkc.StartWithOpts(\n\t\tfunc(c context.Context, data MyEvent) (MyResponse, error) { // \u003c1\u003e\n\t\t// process the data here\n\t\t}, \n\t\tRuntimeOptionSeparateThread, // \u003c2\u003e\n\t\ttrue  // \u003c3\u003e\n\t)\n```\n\u003c1\u003e This function is executed on a single background thread. Hence, the invocations is serialized on that thread. The main thread continues.\n\u003c2\u003e The specifies the separate thread behavior.\n\u003c3\u003e If set to `true`, it will always fetch the payload. If `false` it is up to the lambda to fetch the data (_see below_).\n\nSince 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`.\n\n```go\n// registered lambda\nfunc(c context.Context) error {\n\tr := NewRequestReader()\n\tb := make([]byte, 256)\n\tfor {\n\t\tn, err := \tr.Read(b)\n\t\tif n \u003e 0 {\n\t\t\t// process the b[:n]\n\t\t}\n\n\t\tif err == io.EOF {\n\t\t\tbreak\n\t\t}\n\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n}\n```\n\nIf you only want to read it all directly, e.g. want to do custom `Unmarshal` or other.\n\n```go\nif buf, err := ioutil.ReadAll(NewRequestReader()); err == nil {\n   // the complete request payload is in buf\n}\n```\n\nIn 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.\n\n#### Slim Lambda\n\nThe 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.\n\n```go\n\tsdkc.GGStart(func(lc *sdkc.LambdaContextSlim) { // \u003c1\u003e\n\n\t\tsdk.Log(sdkc.LogLevelInfo, \"%s, %s\\n\", lc.ClientContext, lc.FunctionARN) // \u003c2\u003e\n\t\tsdk.Log(sdkc.LogLevelInfo, \"Payload: %s\\n\", string(lc.Payload)) // \u003c3\u003e\n       // \u003c4\u003e\n\t})\n```\n\u003c1\u003e The one and only function type to register.\n\u003c2\u003e ClientContext is a string that you may unmarshal yourself.\n\u003c3\u003e The payload is a `[]byte` (in this case it will be populated since `GGStart` do set _payload_ to `true`)\n\u003c4\u003e If you want to return data, you have to write either error output or return payload yourself.\n\nAs with standard lambda, one may register using `GGStartWithOpts` to change if background thread or read / write data yourself.\n\nTo 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.\n\n### Install C Runtime SDK Mock Library \n\nYou 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. \n\n```bash\ngogreengrass -sdkc\n```\n\nThis 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.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmariotoffia%2Fgogreengrass","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmariotoffia%2Fgogreengrass","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmariotoffia%2Fgogreengrass/lists"}