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(kinesisfirehose): add HTTP Endpoint and Datadog destination #33657

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
Prev Previous commit
Next Next commit
feat: adding tests, bucket
  • Loading branch information
Benjamin Pottier authored and benjaminpottier committed Mar 5, 2025
commit e65de4a6900c3cb73accdabc6627d698d45dd793
13 changes: 10 additions & 3 deletions packages/aws-cdk-lib/aws-kinesisfirehose/lib/datadog.ts
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@ import * as iam from '../../aws-iam';
import { ISecret } from '../../aws-secretsmanager';
import { Duration, Size } from '../../core';
import { createBackupConfig, createBufferingHints, createEncryptionConfig, createLoggingOptions, createProcessingConfig } from './private/helpers';
import { Bucket } from '../../aws-s3';

export enum DatadogLogsEndpointUrl {
DATADOG_LOGS_US1 = 'https://aws-kinesis-http-intake.logs.datadoghq.com/v1/input',
@@ -85,7 +86,10 @@ export class Datadog implements IDestination {
streamId: 'DatadogDestination',
}) ?? {};

const { backupConfig, dependables: backupDependables } = createBackupConfig(scope, role, this.props.s3Backup) ?? {};
const bucket = new Bucket(scope, 'S3 Configuration', {});
bucket.grantReadWrite(role);

const { dependables: backupDependables } = createBackupConfig(scope, role, this.props.s3Backup) ?? {};

this.props.apiKey.grantRead(role);

@@ -94,7 +98,10 @@ export class Datadog implements IDestination {
cloudWatchLoggingOptions: loggingOptions,
processingConfiguration: createProcessingConfig(scope, role, this.props.processor),
roleArn: role.roleArn,
s3BackupConfiguration: backupConfig,
s3Configuration: {
bucketArn: bucket.bucketArn,
roleArn: role.roleArn,
},
s3BackupMode: this.getS3BackupMode(),
endpointConfiguration: {
url: this.props.url,
@@ -103,7 +110,7 @@ export class Datadog implements IDestination {
contentEncoding: 'GZIP',
},
retryOptions: {
DurationInSeconds: this.props.retryDuration?.toSeconds() ?? 60,
durationInSeconds: this.props.retryDuration?.toSeconds() ?? 60,
},
bufferingHints: {
sizeInMBs: this.props.bufferHints?.size?.toMebibytes() ?? 4,
1 change: 1 addition & 0 deletions packages/aws-cdk-lib/aws-kinesisfirehose/lib/index.ts
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ export * from './processor';
export * from './common';
export * from './s3-bucket';
export * from './logging-config';
export * from './datadog';

// AWS::KinesisFirehose CloudFormation Resources:
export * from './kinesisfirehose.generated';
66 changes: 66 additions & 0 deletions packages/aws-cdk-lib/aws-kinesisfirehose/test/datadog.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,82 @@
import * as cdk from '../..';
import { Match, Template } from '../../assertions';
import * as iam from '../../aws-iam';
import * as secretsmanager from '../../aws-secretsmanager';
import * as firehose from '../lib';

describe('Datadog destination', () => {
let stack: cdk.Stack;
let destinationRole: iam.IRole;
let secret: secretsmanager.Secret;

beforeEach(() => {
stack = new cdk.Stack();
secret = new secretsmanager.Secret(stack, 'ApiSecret', {});
destinationRole = new iam.Role(stack, 'Destination Role', {
assumedBy: new iam.ServicePrincipal('firehose.amazonaws.com'),
});
});

it('provides defaults when only required configuration is provided', () => {
new firehose.DeliveryStream(stack, 'DeliveryStream', {
destination: new firehose.Datadog({
apiKey: secret,
url: firehose.DatadogLogsEndpointUrl.DATADOG_LOGS_US1,
role: destinationRole,
}),
});
Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', {
HttpEndpointDestinationConfiguration: {
RoleARN: stack.resolve(destinationRole.roleArn),
CloudWatchLoggingOptions: {
Enabled: true,
},
BufferingHints: {
IntervalInSeconds: 60,
SizeInMBs: 4,
},
RequestConfiguration: {
ContentEncoding: 'GZIP',
},
RetryOptions: {
DurationInSeconds: 60,
},
},
});
Template.fromStack(stack).resourceCountIs('AWS::Logs::LogGroup', 1);
Template.fromStack(stack).resourceCountIs('AWS::Logs::LogStream', 1);
});

it('creates a role when none is provided', () => {
new firehose.DeliveryStream(stack, 'DeliveryStream', {
destination: new firehose.Datadog({
apiKey: secret,
url: firehose.DatadogLogsEndpointUrl.DATADOG_LOGS_US1,
}),
});

Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', {
HttpEndpointDestinationConfiguration: {
RoleARN: {
'Fn::GetAtt': [
'DeliveryStreamDatadogDestinationRoleBBA16F35',
'Arn',
],
},
},
});
Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', {
AssumeRolePolicyDocument: {
Statement: [
{
Effect: 'Allow',
Principal: {
Service: 'firehose.amazonaws.com',
},
Action: 'sts:AssumeRole',
},
],
},
});
});
});