Documentation
¶
Overview ¶
Package eventtarget resolves and delivers event payloads to AWS target ARNs.
It is the shared "fan a payload out to whatever the ARN names" seam used by EventBridge rule targets (issue #467) and, by design, by any other service that has to deliver to an arbitrary AWS target — EventBridge Pipes (#470) is the next intended consumer, which is why the classification and the dispatcher live here rather than inside internal/services/eventbridge.
Delivery goes through the emulator's own root router rather than through per-service Go interfaces. That keeps one code path per sink (the same one an SDK client would take), so a target delivery observes exactly the validation, region routing and errors a real call would — in particular a missing function/queue/stream produces the service's own error instead of a silent no-op, which is what makes "dropped" and "dead-lettered" outcomes reportable at all.
Nothing here blocks or does I/O at construction time: NewDispatcher only stores handles.
Index ¶
- Constants
- Variables
- func DisplayName(k Kind) string
- func FunctionName(arn string) string
- func ResourceName(arn string) string
- func SelectPath(doc any, path string) (any, bool)
- type Dispatcher
- type InputTransformer
- type Kind
- type MessageAttribute
- type PathTemplate
- type Request
- type UnsupportedKindError
Constants ¶
const ( // InvocationEvent is an asynchronous invoke. It is the zero value, and the // invocation type EventBridge rule targets use. InvocationEvent = "" // InvocationRequestResponse waits for the function's result, so a handled // function error becomes a delivery failure. EventBridge Pipes uses it. InvocationRequestResponse = "RequestResponse" )
Lambda invocation types, as the Invoke API spells them.
Variables ¶
var ErrMalformedARN = errors.New("target ARN is malformed")
ErrMalformedARN is returned by Classify for a value that is not an ARN at all. AWS performs this shape check synchronously when a target is added.
Functions ¶
func DisplayName ¶
DisplayName returns the human label for a kind ("Step Functions" for KindStepFunctions), or "Unknown" for a kind this package does not deliver to.
func FunctionName ¶
FunctionName returns the Lambda function name an ARN names, dropping any version or alias qualifier. A bare name is returned unchanged, matching the FunctionName forms the Lambda API accepts.
func ResourceName ¶
ResourceName returns the trailing resource name of an ARN: the part after the last ":" or "/", whichever comes later. It covers every shape the supported sinks use — sqs:...:queue-name, lambda:...:function:name, kinesis:...:stream/name, firehose:...:deliverystream/name.
func SelectPath ¶
SelectPath evaluates the JSONPath subset EventBridge accepts against a decoded JSON document and returns the selected node.
Supported: the root "$", dotted member access ("$.detail.orderId" — member names may contain dashes, as "detail-type" does), and zero-based array indexing ("$.resources[0]"). Filters, wildcards, recursive descent and slices are not supported; a path using them selects nothing, which callers surface rather than silently treating as an empty value.
Types ¶
type Dispatcher ¶
type Dispatcher struct {
// contains filtered or unexported fields
}
Dispatcher delivers payloads to target ARNs through a root http.Handler.
The zero value is not usable; construct one with NewDispatcher. A Dispatcher is safe for concurrent use — it holds no mutable state.
func NewDispatcher ¶
func NewDispatcher(router http.Handler, defaultRegion string) *Dispatcher
NewDispatcher returns a Dispatcher that delivers through router. router is the emulator's root handler; defaultRegion is used when neither the request context nor the target ARN names one.
func (*Dispatcher) Deliver ¶
func (d *Dispatcher) Deliver(ctx context.Context, req Request) error
Deliver dispatches req to the sink its ARN names.
It returns an error when the sink rejects the delivery (a missing function, queue or stream produces the service's own AWS error), when the target kind is not deliverable, or when the dispatcher has no router. Callers decide what a failure means — retry, dead-letter, or drop.
func (*Dispatcher) DeliverResponse ¶
DeliverResponse is Deliver for a caller that needs what the sink answered, not only whether it accepted the delivery.
Only a Lambda target invoked with InvocationRequestResponse has an answer to return: EventBridge Pipes reads it to honour a partial-batch failure report, which is a decision about the source records and so cannot be made inside the sink. Every other kind returns a nil payload and behaves exactly as Deliver.
func (*Dispatcher) InvokeJSONTarget ¶
InvokeJSONTarget performs an AWS JSON 1.1 X-Amz-Target call against the root router. It is the low-level escape hatch for target types whose request body the caller owns — EventBridge's scheduled ECS RunTask target builds its body from the rule's EcsParameters and dispatches it through here.
type InputTransformer ¶
type InputTransformer struct {
// InputPathsMap maps a placeholder name to the JSONPath selecting its
// value from the event.
InputPathsMap map[string]string
// InputTemplate is the template text. Placeholders are written <name>.
InputTemplate string
}
InputTransformer renders a target's InputTemplate from named JSONPath selections, matching EventBridge's InputTransformer target field.
func (InputTransformer) Render ¶
Render substitutes every placeholder in the template and returns the result.
A string selection is substituted without quotes — templates supply their own, as AWS's do (`{"id":"<order>"}`) — and any other value is substituted as JSON. reserved supplies EventBridge's `aws.events.*` variables; callers that have no rule context pass nil.
A placeholder whose path selects nothing renders as an empty string, the same as AWS's behaviour for an absent node in a quoted position. The rendered template is returned verbatim: AWS does not require it to be JSON, and a target that wants a JSON body is responsible for writing one.
type Kind ¶
type Kind string
Kind is the AWS service segment of a target ARN, restricted to the target types this package can actually deliver to.
type MessageAttribute ¶
type MessageAttribute struct {
// DataType is AWS's attribute data type — "String" or "Number".
DataType string
// StringValue is the attribute value.
StringValue string
}
MessageAttribute is one SQS or SNS message attribute. Both services model the same shape — a data type naming how the value should be read, and the value itself — and both spell the string form of it identically, so one type serves the two sinks.
Only the string form is carried. AWS's Binary and *.custom data types exist, but no caller here produces one: an emulator sender that needs to say "this is a number" says so with DataType "Number" and a decimal StringValue, exactly as the SDKs do.
type PathTemplate ¶
type PathTemplate string
PathTemplate is an EventBridge Pipes `InputTemplate`.
Pipes writes JSON paths inline — `<$.body.orderId>` — rather than naming them through an InputPathsMap the way rule targets do, and adds a set of `aws.pipes.*` reserved variables. The path syntax is the same subset SelectPath implements, which is why this sits beside InputTransformer.
A template may be free text, a bare path, or JSON with paths embedded in it; Pipes applies it to each record of a batch individually, not to the array.
func (PathTemplate) Render ¶
Render substitutes every placeholder in the template against one record.
A placeholder beginning `$.` (or exactly `$`) selects from doc; anything else is looked up in reserved, which supplies the `aws.pipes.*` variables. A string value is substituted as a quoted JSON string unless the template already supplied the quotes, so `<$.id>` and `"<$.id>"` both render valid JSON — AWS accepts either. Objects, arrays and numbers substitute as JSON without quotes. A path that selects nothing substitutes an empty string, matching AWS's "that variable isn't created" behaviour.
The result is returned verbatim: AWS does not require a rendered template to be JSON, and a target that needs JSON is responsible for a template that produces it.
type Request ¶
type Request struct {
// ARN of the target. Required.
ARN string
// Kind the ARN resolved to. Callers that already classified the ARN pass
// it here; a zero Kind is resolved by Deliver.
Kind Kind
// Payload is the fully transformed body to deliver. Sinks that carry
// binary records (Kinesis, Firehose) receive these bytes verbatim.
Payload []byte
// PartitionKey is the Kinesis record partition key. Required by Kinesis;
// ignored by every other kind.
PartitionKey string
// ExecutionName names the Step Functions execution. Optional — Step
// Functions generates one when empty.
ExecutionName string
// MessageGroupID sets the SQS FIFO message group. Optional.
MessageGroupID string
// MessageDeduplicationID sets the SQS FIFO deduplication ID. Optional.
MessageDeduplicationID string
// Subject sets the SNS message subject. Optional.
Subject string
// MessageAttributes are the message attributes to send alongside the
// payload. Honoured by the SQS and SNS sinks — the two kinds AWS models
// message attributes on — and ignored by every other kind. Optional.
MessageAttributes map[string]MessageAttribute
// InvocationType selects how a Lambda target is invoked:
// InvocationRequestResponse waits for the result and turns a function error
// into a delivery failure, and the zero value invokes asynchronously.
// Ignored by every other kind.
InvocationType string
// Source, DetailType and Resources populate the PutEvents entry an
// EventBridge event-bus target receives. Ignored by every other kind.
Source string
DetailType string
Resources []string
}
Request is one delivery: a payload bound for a single target ARN.
type UnsupportedKindError ¶
type UnsupportedKindError struct {
// Service is the ARN's service segment, e.g. "logs".
Service string
}
UnsupportedKindError reports a well-formed ARN naming a service this emulator cannot deliver to. Callers must surface it rather than accepting the target and dropping it at delivery time — see docs/plans/full-emulation-priority.md §2.1.
func (*UnsupportedKindError) Error ¶
func (e *UnsupportedKindError) Error() string