Skip to content

Commit

Permalink
feat(events): archive events (#12060)
Browse files Browse the repository at this point in the history
Add the possibility to archive events from an Event Bus. It's also possible to archive specific events by passing an event patterns. See the [following blogpost](https://aws.amazon.com/blogs/aws/new-archive-and-replay-events-with-amazon-eventbridge/) for more information about event archiving and replay.

Archiving should be possible from an imported EventBus.

closes #11531

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
DaWyz authored Feb 25, 2021
1 parent 146a97f commit 465cd9c
Show file tree
Hide file tree
Showing 6 changed files with 338 additions and 16 deletions.
23 changes: 23 additions & 0 deletions packages/@aws-cdk/aws-events/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,26 @@ In this situation, the CDK will wire the 2 accounts together:

For more information, see the
[AWS documentation on cross-account events](https://docs.aws.amazon.com/eventbridge/latest/userguide/eventbridge-cross-account-event-delivery.html).

## Archiving

It is possible to archive all or some events sent to an event bus. It is then possible to [replay these events](https://aws.amazon.com/blogs/aws/new-archive-and-replay-events-with-amazon-eventbridge/).

```ts
import * as cdk from '@aws-cdk/core';

const stack = new stack();

const bus = new EventBus(stack, 'bus', {
eventBusName: 'MyCustomEventBus'
});

bus.archive('MyArchive', {
archiveName: 'MyCustomEventBusArchive',
description: 'MyCustomerEventBus Archive',
eventPattern: {
account: [stack.account],
},
retention: cdk.Duration.days(365),
});
```
77 changes: 77 additions & 0 deletions packages/@aws-cdk/aws-events/lib/archive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { Duration, Resource } from '@aws-cdk/core';
import { Construct } from 'constructs';
import { IEventBus } from './event-bus';
import { EventPattern } from './event-pattern';
import { CfnArchive } from './events.generated';

/**
* The event archive base properties
*/
export interface BaseArchiveProps {
/**
* The name of the archive.
*
* @default - Automatically generated
*/
readonly archiveName?: string;
/**
* A description for the archive.
*
* @default - none
*/
readonly description?: string;
/**
* An event pattern to use to filter events sent to the archive.
*/
readonly eventPattern: EventPattern;
/**
* The number of days to retain events for. Default value is 0. If set to 0, events are retained indefinitely.
* @default - Infinite
*/
readonly retention?: Duration;
}


/**
* The event archive properties
*/
export interface ArchiveProps extends BaseArchiveProps {
/**
* The event source associated with the archive.
*/
readonly sourceEventBus: IEventBus;
}

/**
* Define an EventBridge Archive
*
* @resource AWS::Events::Archive
*/
export class Archive extends Resource {
/**
* The archive name.
* @attribute
*/
public readonly archiveName: string;

/**
* The ARN of the archive created.
* @attribute
*/
public readonly archiveArn: string;

constructor(scope: Construct, id: string, props: ArchiveProps) {
super(scope, id, { physicalName: props.archiveName });

let archive = new CfnArchive(this, 'Archive', {
sourceArn: props.sourceEventBus.eventBusArn,
description: props.description,
eventPattern: props.eventPattern,
retentionDays: props.retention?.toDays({ integral: true }) || 0,
archiveName: this.physicalName,
});

this.archiveArn = archive.attrArn;
this.archiveName = archive.attrArchiveName;
}
}
81 changes: 65 additions & 16 deletions packages/@aws-cdk/aws-events/lib/event-bus.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as iam from '@aws-cdk/aws-iam';
import { IResource, Lazy, Names, Resource, Stack, Token } from '@aws-cdk/core';
import { Construct } from 'constructs';
import { Archive, BaseArchiveProps } from './archive';
import { CfnEventBus } from './events.generated';

/**
Expand Down Expand Up @@ -37,6 +38,15 @@ export interface IEventBus extends IResource {
* @link https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-events-eventbus.html#cfn-events-eventbus-eventsourcename
*/
readonly eventSourceName?: string;

/**
* Create an EventBridge archive to send events to.
* When you create an archive, incoming events might not immediately start being sent to the archive.
* Allow a short period of time for changes to take effect.
*
* @param props Properties of the archive
*/
archive(id: string, props: BaseArchiveProps): Archive;
}

/**
Expand Down Expand Up @@ -96,12 +106,45 @@ export interface EventBusAttributes {
readonly eventSourceName?: string;
}

abstract class EventBusBase extends Resource implements IEventBus {
/**
* The physical ID of this event bus resource
*/
public abstract readonly eventBusName: string;

/**
* The ARN of the event bus, such as:
* arn:aws:events:us-east-2:123456789012:event-bus/aws.partner/PartnerName/acct1/repo1.
*/
public abstract readonly eventBusArn: string;

/**
* The policy for the event bus in JSON form.
*/
public abstract readonly eventBusPolicy: string;

/**
* The name of the partner event source
*/
public abstract readonly eventSourceName?: string;

public archive(id: string, props: BaseArchiveProps): Archive {
return new Archive(this, id, {
sourceEventBus: this,
description: props.description || `Event Archive for ${this.eventBusName} Event Bus`,
eventPattern: props.eventPattern,
retention: props.retention,
archiveName: props.archiveName,
});
}
}

/**
* Define an EventBridge EventBus
*
* @resource AWS::Events::EventBus
*/
export class EventBus extends Resource implements IEventBus {
export class EventBus extends EventBusBase {

/**
* Import an existing event bus resource
Expand All @@ -112,13 +155,11 @@ export class EventBus extends Resource implements IEventBus {
public static fromEventBusArn(scope: Construct, id: string, eventBusArn: string): IEventBus {
const parts = Stack.of(scope).parseArn(eventBusArn);

class Import extends Resource implements IEventBus {
public readonly eventBusArn = eventBusArn;
public readonly eventBusName = parts.resourceName || '';
public readonly eventBusPolicy = '';
}

return new Import(scope, id);
return new ImportedEventBus(scope, id, {
eventBusArn: eventBusArn,
eventBusName: parts.resourceName || '',
eventBusPolicy: '',
});
}

/**
Expand All @@ -128,14 +169,7 @@ export class EventBus extends Resource implements IEventBus {
* @param attrs Imported event bus properties
*/
public static fromEventBusAttributes(scope: Construct, id: string, attrs: EventBusAttributes): IEventBus {
class Import extends Resource implements IEventBus {
public readonly eventBusArn = attrs.eventBusArn;
public readonly eventBusName = attrs.eventBusName;
public readonly eventBusPolicy = attrs.eventBusPolicy;
public readonly eventSourceName = attrs.eventSourceName;
}

return new Import(scope, id);
return new ImportedEventBus(scope, id, attrs);
}

/**
Expand Down Expand Up @@ -241,3 +275,18 @@ export class EventBus extends Resource implements IEventBus {
this.eventSourceName = eventBus.eventSourceName;
}
}

class ImportedEventBus extends EventBusBase {
public readonly eventBusArn: string;
public readonly eventBusName: string;
public readonly eventBusPolicy: string;
public readonly eventSourceName?: string;
constructor(scope: Construct, id: string, attrs: EventBusAttributes) {
super(scope, id);

this.eventBusArn = attrs.eventBusArn;
this.eventBusName = attrs.eventBusName;
this.eventBusPolicy = attrs.eventBusPolicy;
this.eventSourceName = attrs.eventSourceName;
}
}
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-events/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export * from './event-bus';
export * from './event-pattern';
export * from './schedule';
export * from './on-event-options';
export * from './archive';

// AWS::Events CloudFormation Resources:
export * from './events.generated';
45 changes: 45 additions & 0 deletions packages/@aws-cdk/aws-events/test/test.archive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { expect, haveResource } from '@aws-cdk/assert';
import { Duration, Stack } from '@aws-cdk/core';
import { Test } from 'nodeunit';
import { EventBus } from '../lib';
import { Archive } from '../lib/archive';

export = {
'creates an archive for an EventBus'(test: Test) {
// GIVEN
const stack = new Stack();

// WHEN
let eventBus = new EventBus(stack, 'Bus');

new Archive(stack, 'Archive', {
sourceEventBus: eventBus,
eventPattern: {
account: [stack.account],
},
retention: Duration.days(10),
});

// THEN
expect(stack).to(haveResource('AWS::Events::EventBus', {
Name: 'Bus',
}));

expect(stack).to(haveResource('AWS::Events::Archive', {
EventPattern: {
account: [{
Ref: 'AWS::AccountId',
}],
},
RetentionDays: 10,
SourceArn: {
'Fn::GetAtt': [
'BusEA82B648',
'Arn',
],
},
}));

test.done();
},
}
Loading

0 comments on commit 465cd9c

Please sign in to comment.