-
Notifications
You must be signed in to change notification settings - Fork 8
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: Extracts forwarder stack #47
base: main
Are you sure you want to change the base?
Conversation
Hey @pistazie - thanks for your PR. Sure enough, there's not currently a good way to do this, as the forwarder stack is inside the If I understand the requirements from Datadog's side, we need to install all of the DD stacks into one region. Let's call this the "home region". That means that the home region will get:
Then, each additional region needs just the forwarder stack. Current ApproachIf that's correct, with your recommended approach, I think a user would do something like this: #!/usr/bin/env node
import { App, Stack, StackProps } from 'aws-cdk-lib';
import { Secret } from 'aws-cdk-lib/aws-secretsmanager';
import { DatadogIntegration, DatadogForwarder } from 'cdk-datadog-integration';
const app = new App();
class MonitoringStack extends Stack {
private homeRegion = 'us-east-1';
constructor(scope: App, props: Required<Pick<StackProps, 'env'>>) {
super(scope, 'MonitoringStack', props);
const { region } = props.env;
const externalId = 'foobar';
if (region === this.homeRegion) {
new DatadogIntegration(this, 'Datadog', {
apiKey: new Secret(this, 'DatadogSecret', {}),
externalId,
})
} else {
// It might make sense be nice if this extended a `Construct` instead of `cdk.CfnStack`, like DatadogIntegration.
new DatadogForwarder(this, 'DatadogForwarder', {
apiKey: new Secret(this, 'DatadogSecret', {}),
externalId,
})
}
}
}
new MonitoringStack(app, { env: { account: '1', region: 'us-east-1' }}); // Creates 3 stacks
new MonitoringStack(app, { env: { account: '1', region: 'us-west-2' }}); // Creates forwarder
new MonitoringStack(app, { env: { account: '1', region: 'us-east-2' }}); // Creates forwarder I think this would work, but it exposes the implementation details to the user. Additionally, would we need to add the Alternative IdeaInstead of making the user implement this We could add a new optional parameter to the interface DatadogIntegrationConfig {
// all existing properties...
readonly multiRegionConfig?: {
/**
* The region the stack is currently being deployed to.
* Since DatadogIntegration is a region-agnostic construct, we'd have to have the user tell us
*/
currentStackRegion: string;
/** The region that gets all three stacks. */
homeRegion: string;
};
} Then the constructor(
scope: Construct,
id: string,
props: DatadogIntegrationConfig,
) {
super(scope, id);
if (props.multiRegionConfig) {
const { currentStackRegion, homeRegion } = props.multiRegionConfig;
if (homeRegion === currentStackRegion) {
// set up everything
} else {
// set up forwarder only
}
}
} Then the user's #!/usr/bin/env node
import { App, Stack, StackProps } from 'aws-cdk-lib';
import { Secret } from 'aws-cdk-lib/aws-secretsmanager';
import { DatadogIntegration } from 'cdk-datadog-integration';
const app = new App();
class MonitoringStack extends Stack {
constructor(scope: App, props: Required<Pick<StackProps, 'env'>>) {
super(scope, 'MonitoringStack', props);
const externalId = 'foobar';
new DatadogIntegration(this, 'Datadog', {
apiKey: new Secret(this, 'DatadogSecret', {}),
externalId,
multiRegionConfig: {
homeRegion: 'us-east-1',
currentRegion: props.env.region,
},
})
}
}
new MonitoringStack(app, { env: { account: '1', region: 'us-east-1' }}); // Creates 3 stacks
new MonitoringStack(app, { env: { account: '1', region: 'us-west-2' }}); // Creates forwarder
new MonitoringStack(app, { env: { account: '1', region: 'us-east-2' }}); // Creates forwarder As a future improvement, we could even do something fancy like replicate the secret from the home region for the user. Thoughts?What do you think? Thanks again for taking the time to contribute back to this project. |
Hi, Interesting stuff. I like the multi-home region configuration. I have two reservations:
How about the following Idea: // bin/cdk.ts
const app = new cdk.App()
datadogMonitoringStacks(app, {
homeRegion : 'us-east-1',
additionalRegions: ['us-west-1', 'eu-central-1']
})
// adds one stack of two nested stacks in us-east-1 (macro, integration)
// adds one forwarder stack in us-east-1
// adds one forwarder stack per `additionalRegion` This way, there aren't superfluous nested stacks, the library is usable for forwarder only, and each region has explicitly a forwarder stack. wdyt? |
Sure, I can definitely understand your concern there. My counter-argument is that, as a user, I don't really care about what goes into the Datadog setup working. Sure, under the hood it's deploying some different components, but I just know "Datadog works in the regions I care about". That said, in either case, I think we should allow importing and creating each individual
In the example of the monitoring stack, we actually need a wrapping stack to do the Secrets Manager secret import/creation. I've also seen a lot of folks that have other monitoring setup they need to do in each region (like CloudWatch billing alarms). In general, I'm not tied to requiring folks to create a top-level monitoring stack. I was mostly using it as an example to think through how people would interact with the library with this change.
// bin/cdk.ts
const app = new cdk.App()
datadogMonitoringStacks(app, {
homeRegion : 'us-east-1',
additionalRegions: ['us-west-1', 'eu-central-1']
})
// adds one stack of two nested stacks in us-east-1 (macro, integration)
// adds one forwarder stack in us-east-1
// adds one forwarder stack per `additionalRegion` Again, the main issue here is regarding the API key secret. You'd need to have the definition (or import) of the key associated with a different stack and passed in as a cross-stack reference. Also, I'm not a huge fan of the "function that creates How to proceedAgain, thank you for your time and willingness to discuss this with me 😄 I think we should proceed with extracting the As mentioned before, I don't think we need to provide the Then, we can circle back on the larger What do you think? |
Just to throw in my two cents, I would like the ability to skip the forwarder stack, we've configured everything to go through Kinesis and don't need it. |
In order to configure multiple regions, one has to configure the Forwarder stack in each region. This is currently not supported as:
This PR is a POC of separating concerns and adding an opt-out option for the forwarder.
If this approach is acceptable, I'm happy to add the rest of the stack parameters, test cases, and documentation.
wdyt?