§ Documentation
Load Balancer
Emulated load balancers, target groups, listeners, rules, and health checks — driven with the real ELBv2 and cloud LB SDKs
aws ELBazr LBgcp LB
Emulates a managed load balancer — the ELB-style front door that spreads traffic across a pool of backends. You create a load balancer, register targets in a target group, and attach a listener that routes a port to that group; listener rules and per-LB attributes tune how the traffic is steered.
Reach for it when your code provisions load balancers, registers or deregisters targets, or reacts to target health — so you can exercise those paths without a live LB. Because the SDK-compat server speaks the real wire protocol, your production provisioning code runs unchanged against it. Under the hood a load balancer, its target groups, and its listeners are plain named records wired together by ARN.
| Provider | Service | SDK-compat | Driver |
|---|---|---|---|
| AWS | ELBv2 | ✓ Live | aws.ELB |
| Azure | LB | ✓ Live | azure.LB |
| GCP | LB | ✓ Live | gcp.LB |
Drive it with the real SDK#
Run cloudemu as a server and point your existing production code at it — the same client, with only the endpoint redirected. Start it with cloudemu serve (or docker run --rm -p 4566:4566 ghcr.io/stackshy/cloudemu), which serves the AWS API on http://localhost:4566:
cloudemu serve # AWS API on http://localhost:4566Then point the stock ELBv2 client at that endpoint and create an ALB and a target group exactly as the real client would:
import (
"github.com/aws/aws-sdk-go-v2/aws"
elb "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2"
elbtypes "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2/types"
)
client := elb.NewFromConfig(cfg, func(o *elb.Options) {
o.BaseEndpoint = aws.String("http://localhost:4566")
})
lb, _ := client.CreateLoadBalancer(ctx, &elb.CreateLoadBalancerInput{
Name: aws.String("my-alb"),
Type: elbtypes.LoadBalancerTypeEnumApplication,
Scheme: elbtypes.LoadBalancerSchemeEnumInternetFacing,
Subnets: []string{"subnet-a", "subnet-b"},
})
tg, _ := client.CreateTargetGroup(ctx, &elb.CreateTargetGroupInput{
Name: aws.String("web-targets"), Port: aws.Int32(8080), Protocol: elbtypes.ProtocolEnumHttp,
})The same pattern works with armnetwork.LoadBalancersClient (Azure) and the GCP forwarding-rule / backend-service REST clients — only the endpoint changes. See the SDK-Compat Server page.
In-process (Go unit tests)#
For Go unit tests written inside cloudemu-aware code, stand the same wire server up in-process with httptest.NewServer and point the client at ts.URL. The Drivers you pass name exactly the drivers this service needs:
import (
"github.com/stackshy/cloudemu/v2"
awsserver "github.com/stackshy/cloudemu/v2/server/aws"
)
cloud := cloudemu.NewAWS()
ts := httptest.NewServer(awsserver.New(awsserver.Drivers{ELB: cloud.ELB}))
defer ts.Close()
// point the same elb client at ts.URL instead of the running endpointCall the driver directly#
When you don't need to drive a real SDK — for example in cloudemu-only setup code — skip the HTTP hop and call the driver. The load balancer is the entry point; create it, then wire a target group and a listener by ARN:
import lbdriver "github.com/stackshy/cloudemu/v2/services/loadbalancer/driver"
lb, _ := aws.ELB.CreateLoadBalancer(ctx, lbdriver.LBConfig{
Name: "web-lb", Type: "application", Scheme: "internet-facing",
})
tg, _ := aws.ELB.CreateTargetGroup(ctx, lbdriver.TargetGroupConfig{
Name: "web-targets", Port: 8080, Protocol: "HTTP",
})
aws.ELB.RegisterTargets(ctx, tg.ARN, []lbdriver.Target{
{ID: "i-00000001", Port: 8080}, {ID: "i-00000002", Port: 8080},
})
aws.ELB.CreateListener(ctx, lbdriver.ListenerConfig{
LBARN: lb.ARN, Port: 443, Protocol: "HTTPS", TargetGroupARN: tg.ARN,
})RegisterTargets takes []lbdriver.Target (an ID plus optional port), and listeners reference the load balancer and target group by their ARN.
Rules, attributes, and target health#
A listener can carry rules that steer requests to different target groups by path or host, and each load balancer has an attribute set you can read and modify. Target health is settable directly so you can assert how your code reacts to a backend going unhealthy:
// Path-based routing rule on a listener.
aws.ELB.CreateRule(ctx, lbdriver.RuleConfig{
ListenerARN: listener.ARN, Priority: 10,
Conditions: []lbdriver.RuleCondition{{Field: "path-pattern", Values: []string{"/api/*"}}},
Actions: []lbdriver.RuleAction{{Type: "forward", TargetGroupARN: tg.ARN}},
})
rules, _ := aws.ELB.DescribeRules(ctx, listener.ARN)
// Attributes: the typed fields plus an open Extra map for anything AWS adds.
aws.ELB.PutLBAttributes(ctx, lb.ARN, lbdriver.LBAttributes{
IdleTimeout: 120, DeletionProtection: true,
Extra: map[string]string{"load_balancing.cross_zone.enabled": "true"},
})
attrs, _ := aws.ELB.GetLBAttributes(ctx, lb.ARN)
// Drive a target unhealthy, then read health back.
aws.ELB.SetTargetHealth(ctx, tg.ARN, "i-00000001", "unhealthy")
health, _ := aws.ELB.DescribeTargetHealth(ctx, tg.ARN)
aws.ELB.DeregisterTargets(ctx, tg.ARN, []lbdriver.Target{{ID: "i-00000002", Port: 8080}})Behavior & fidelity#
| Behavior | What happens |
|---|---|
| Target groups carry health-check configuration | Health status drives which targets are eligible, and SetTargetHealth lets a test flip that state deterministically. |
| Objects are wired by ARN | Listeners and rules reference a load balancer and target group by ARN; a target group can back more than one listener. |
| Attributes keep unknown keys | LBAttributes.Extra holds attributes outside the typed set, so a caller reading back its own write gets the right answer even for keys the struct never learned. |
SDK-compat — Live#
Real elasticloadbalancingv2, armnetwork.LoadBalancers, and GCP LB clients drive the emulator end-to-end:
| Provider | Coverage |
|---|---|
| AWS ELBv2 | Load balancers, target groups, listeners, rules, and target health |
| Azure LB | Load balancers via ARM |
| GCP LB | Forwarding rules and backend services via REST |
See SDK-Compat for the full per-operation list.