Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(events): archive events #12060

Merged
merged 9 commits into from
Feb 25, 2021
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