feat(api): add EventBridge Pipes to the cloud explorer
CI / checks (pull_request) Successful in 27m2s
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:
@@ -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
|
||||
}
|
||||
@@ -281,6 +281,13 @@ export const SERVICE_CATALOG = {
|
||||
group: 'Provisioning',
|
||||
order: 20,
|
||||
},
|
||||
pipes: {
|
||||
displayName: 'Pipes',
|
||||
displayNameByCloud: {aws: 'EventBridge Pipes'},
|
||||
iconKey: 'pipes',
|
||||
group: 'Integration',
|
||||
order: 25,
|
||||
},
|
||||
scheduler: {
|
||||
displayName: 'Cloud Scheduler',
|
||||
displayNameByCloud: {gcp: 'Cloud Scheduler'},
|
||||
|
||||
Reference in New Issue
Block a user