feat(api): add EventBridge Pipes to the cloud explorer
CI / checks (pull_request) Successful in 27m2s

Create pipes from SQS, Kinesis, DynamoDB streams or MSK to Lambda, SQS, SNS,
EventBridge buses or Step Functions, with an optional filter, enrichment and
input template; start and stop them, see the flow with links to each resource,
and send a test message to an SQS source. Sources and targets the runtime's
poller cannot deliver between are refused on create.
This commit is contained in:
Zakaria
2026-10-25 12:49:15 -04:00
parent 6e0bb98844
commit 12b50f4868
14 changed files with 773 additions and 0 deletions
+151
View File
@@ -0,0 +1,151 @@
import type {CloudProvider, FieldSchema, ServiceSchema, TableColumnSchema} from './types'
/** CreatePipe's name rule. */
export const PIPE_NAME_PATTERN = '^[\\.\\-_A-Za-z0-9]{1,64}$'
export const PIPE_STARTING_POSITIONS = ['TRIM_HORIZON', 'LATEST'] as const
/**
* The sources and targets the runtime's pipe poller actually moves events
* between, keyed by the ARN's service field. Anything else is refused on create
* rather than accepted into a pipe that would never deliver.
*/
export const PIPE_SOURCE_SERVICES = {sqs: 'SQS queue', kinesis: 'Kinesis stream', dynamodb: 'DynamoDB stream', kafka: 'MSK topic'} as const
export const PIPE_TARGET_SERVICES = {lambda: 'Lambda function', sqs: 'SQS queue', sns: 'SNS topic', events: 'EventBridge event bus', states: 'Step Functions state machine'} as const
export const PIPE_ENRICHMENT_SERVICES = {lambda: 'Lambda function', states: 'Step Functions state machine'} as const
const ARN = '^arn:aws[a-z-]*:[a-z0-9-]+:[a-z0-9-]*:\\d{12}:.+$'
const pipeColumns: TableColumnSchema[] = [
{name: 'name', label: 'Name'},
{name: 'status', label: 'State', format: 'badge'},
{name: 'source', label: 'Source', path: 'metadata.sourceName'},
{name: 'target', label: 'Target', path: 'metadata.targetName'},
{name: 'createdAt', label: 'Created', format: 'datetime'},
]
const pipeFilters: FieldSchema[] = [{name: 'search', label: 'Search', type: 'text', required: false}]
export function awsPipesSchema(): ServiceSchema {
return {
cloud: 'aws',
service: 'pipes',
displayName: 'EventBridge Pipes',
fields: [
{
name: 'name',
label: 'Name',
type: 'text',
required: true,
validation: {pattern: PIPE_NAME_PATTERN, message: 'Use up to 64 letters, numbers, dots, dashes and underscores'},
},
{name: 'description', label: 'Description', type: 'text', required: false, validation: {maxLength: 512}},
{
name: 'source',
label: 'Source ARN',
type: 'text',
required: true,
span: true,
description: 'Where events come from: an SQS queue, a Kinesis stream, a DynamoDB stream or an MSK cluster.',
validation: {pattern: ARN, message: 'Use the ARN of a queue or stream'},
},
{
name: 'startingPosition',
label: 'Starting position',
type: 'select',
required: false,
defaultValue: 'LATEST',
description: 'For streams and MSK: read new records only, or everything still in the stream.',
options: [
{label: 'New records only (LATEST)', value: 'LATEST'},
{label: 'Oldest record (TRIM_HORIZON)', value: 'TRIM_HORIZON'},
],
},
{
name: 'topicName',
label: 'MSK topic',
type: 'text',
required: false,
description: 'Required when the source is an MSK cluster.',
},
{
name: 'batchSize',
label: 'Batch size',
type: 'text',
required: false,
description: 'Records sent to the target at once. 1 to 10,000; leave empty for the default of 10.',
validation: {pattern: '^[1-9][0-9]{0,4}$', message: 'Use a whole number from 1 to 10000'},
},
{
name: 'filterPattern',
label: 'Filter pattern',
type: 'textarea',
required: false,
span: true,
description: 'Optional EventBridge event pattern; only matching records go on. For SQS, match the parsed message under body, for example {"body": {"kind": ["order"]}}.',
},
{
name: 'enrichment',
label: 'Enrichment ARN',
type: 'text',
required: false,
span: true,
description: 'Optional Lambda function or Step Functions state machine that transforms each batch before the target gets it.',
validation: {pattern: ARN, message: 'Use the ARN of a Lambda function or state machine'},
},
{
name: 'target',
label: 'Target ARN',
type: 'text',
required: true,
span: true,
description: 'Where events go: a Lambda function, SQS queue, SNS topic, EventBridge event bus or Step Functions state machine.',
validation: {pattern: ARN, message: 'Use the ARN of the target'},
},
{
name: 'inputTemplate',
label: 'Target input template',
type: 'textarea',
required: false,
span: true,
description: 'Optional. Reshape what the target receives, with <$.path> placeholders, for example {"id": <$.messageId>}.',
},
{
name: 'roleArn',
label: 'Execution role ARN',
type: 'text',
required: true,
span: true,
description: 'The IAM role the pipe uses to read the source and call the target, as AWS requires. Create one in IAM first.',
validation: {pattern: '^arn:aws[a-z-]*:iam::\\d{12}:role/.+$', message: 'Use an IAM role ARN such as arn:aws:iam::000000000000:role/pipe-role'},
},
{
name: 'desiredState',
label: 'State after creating',
type: 'select',
required: false,
defaultValue: 'RUNNING',
options: [
{label: 'Running', value: 'RUNNING'},
{label: 'Stopped', value: 'STOPPED'},
],
},
],
actions: ['list', 'create', 'delete', 'inspect'],
capabilities: {
resourceActions: [
{name: 'list', label: 'List pipes', enabled: true, status: 'available', runtimeRequired: true},
{name: 'create', label: 'Create pipe', enabled: true, status: 'available', runtimeRequired: true},
{name: 'delete', label: 'Delete pipe', enabled: true, status: 'available', runtimeRequired: true},
{name: 'inspect', label: 'Inspect pipe', enabled: true, status: 'available', runtimeRequired: true},
{name: 'start', label: 'Start pipe', enabled: true, status: 'available', runtimeRequired: true},
{name: 'stop', label: 'Stop pipe', enabled: true, status: 'available', runtimeRequired: true},
],
},
filters: pipeFilters,
columns: pipeColumns,
}
}
export function pipesSchemaFor(cloud: CloudProvider): ServiceSchema | null {
return cloud === 'aws' ? awsPipesSchema() : null
}