Serverless
In-memory functions-as-a-service modelled on Lambda, Azure Functions, and Cloud Functions, driven with the real cloud SDKs
aws Lambdaazr Functionsgcp Cloud Functions
Emulates functions-as-a-service — the Lambda/Azure Functions/Cloud Functions control plane where you create a function and invoke it with a payload. Instead of deploying a zip, you register a plain Go function as the handler; an Invoke then runs it in-process and returns its response bytes. That keeps the create/invoke path fast and deterministic while still exercising your production wiring.
Reach for it in tests when your code creates a function, invokes it synchronously, and reads the response — for example verifying an orchestration that fans out to Lambdas, or a caller that depends on a function's output shape — without deploying to a real cloud. You get the function's response back exactly as the SDK would deliver it.
| Provider | Service | SDK-compat | Driver |
|---|---|---|---|
| AWS | Lambda (REST + JSON) | ✓ Live | aws.Lambda |
| Azure | Functions (Function Apps + /api/{name} invoke) | ✓ Live | azure.Functions |
| GCP | Cloud Functions v1 (Create LRO + :call) | ✓ Live | gcp.CloudFunctions |
Drive it with the real SDK#
The recommended path is to point the real SDK at the SDK-compat server. Because there's no real runtime, you register a Go handler so Invoke has something to execute — then the stock Lambda client creates and calls the function unchanged:
import (
"github.com/aws/aws-sdk-go-v2/service/lambda"
lambdatypes "github.com/aws/aws-sdk-go-v2/service/lambda/types"
awsserver "github.com/stackshy/cloudemu/v2/server/aws"
)
cloud := cloudemu.NewAWS()
ts := httptest.NewServer(awsserver.New(awsserver.Drivers{Lambda: cloud.Lambda}))
client := lambda.NewFromConfig(cfg, func(o *lambda.Options) {
o.BaseEndpoint = aws.String(ts.URL)
})
client.CreateFunction(ctx, &lambda.CreateFunctionInput{
FunctionName: aws.String("my-handler"),
Runtime: lambdatypes.RuntimeGo1x,
Role: aws.String("arn:aws:iam::000000000000:role/test"),
Handler: aws.String("main"),
Code: &lambdatypes.FunctionCode{ZipFile: []byte("z")},
})
// Register a Go handler so Invoke has something to run.
cloud.Lambda.RegisterHandler("my-handler", func(ctx context.Context, payload []byte) ([]byte, error) {
return []byte(`{"status":"ok"}`), nil
})
resp, _ := client.Invoke(ctx, &lambda.InvokeInput{
FunctionName: aws.String("my-handler"),
Payload: []byte(`{"key":"value"}`),
})
fmt.Println(string(resp.Payload)) // {"status":"ok"}Same shape with armappservice (Azure) and google.golang.org/api/cloudfunctions/v1 (GCP) — see SDK-Compat Server.
Call the driver directly#
For in-process setup you can skip the HTTP hop. The flow is the same three steps — create, register a handler, invoke — with the driver's own input structs:
import sdriver "github.com/stackshy/cloudemu/v2/services/serverless/driver"
aws.Lambda.CreateFunction(ctx, sdriver.FunctionConfig{
Name: "my-handler", Runtime: "go1.x", Handler: "main",
})
aws.Lambda.RegisterHandler("my-handler", func(_ context.Context, p []byte) ([]byte, error) {
return []byte(`{"ok":true}`), nil
})
out, _ := aws.Lambda.Invoke(ctx, sdriver.InvokeInput{
FunctionName: "my-handler", Payload: []byte(`{}`),
})Invoke returns an InvokeOutput carrying the status code, response payload, and any handler error string.
Behavior & fidelity#
- Invoke runs your registered handler. A function created but never given a handler via
RegisterHandlerhas nothing to execute; register one keyed by function name before invoking. The handler's returned bytes come straight back as the invocation payload. - Handler errors surface as invocation errors. An error returned from the handler is reported on the invocation result rather than as a transport failure — matching how the real services distinguish a function error from a call failure.
- GCP create/delete are long-running. Cloud Functions Create and Delete return an LRO you poll via
Operations.Get, mirroring the real v1 API;:callis the synchronous invoke. - Portable-API-only extras. The driver also exposes surface not yet on the SDK-compat layer — published versions, weighted aliases, layers, reserved/provisioned concurrency, and event source mappings. Reach for these through the Portable Go API when a test needs them.
- SDK-compat status — Live. Lambda (CreateFunction, GetFunction, ListFunctions, DeleteFunction, sync Invoke), Azure Functions (
Microsoft.Web/sitesCRUD +/api/{name}invoke), and GCP Cloud Functions (Create/Delete LROs, Get, List,:call) all work through the real SDKs. See SDK-Compat for the full surface.