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: rds.DatabaseInstance.fromLookup #32358

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 53 additions & 1 deletion packages/aws-cdk-lib/aws-rds/lib/instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import * as kms from '../../aws-kms';
import * as logs from '../../aws-logs';
import * as s3 from '../../aws-s3';
import * as secretsmanager from '../../aws-secretsmanager';
import { ArnComponents, ArnFormat, Duration, FeatureFlags, IResource, Lazy, RemovalPolicy, Resource, Stack, Token, Tokenization } from '../../core';
import * as cxschema from '../../cloud-assembly-schema';
import { ArnComponents, ArnFormat, ContextProvider, Duration, FeatureFlags, IResource, Lazy, RemovalPolicy, Resource, Stack, Token, Tokenization } from '../../core';
import * as cxapi from '../../cx-api';

/**
Expand Down Expand Up @@ -132,6 +133,47 @@ export interface DatabaseInstanceAttributes {
* A new or imported database instance.
*/
export abstract class DatabaseInstanceBase extends Resource implements IDatabaseInstance {
/**
* Lookup an existing DatabaseInstance using instanceIdentifier.
*/
public static fromLookup(scope: Construct, id: string, options: DatabaseInstanceLookupOptions): IDatabaseInstance {
interface DatabaseInstanceContextResponse {
instanceIdentifier: string;
instanceArn: string;
dbInstanceEndpointAddress: string;
dbInstanceEndpointPort: number;
instanceResourceId?: string;
dbSecurityGroupIds: string[];
}

const response: DatabaseInstanceContextResponse = ContextProvider.getValue(scope, {
provider: cxschema.ContextProvider.RDS_DATABASE_INSTANCE_PROVIDER,
props: {
instanceIdentifier: options.instanceIdentifier,
} as cxschema.DatabaseInstanceContextQuery,
dummyValue: {},
}).value;

// Get ISecurityGroup from securityGroupId
const securityGroups: ec2.ISecurityGroup[] = [];
for (const securityGroupId of response.dbSecurityGroupIds) {
const securityGroup = ec2.SecurityGroup.fromSecurityGroupId(
scope,
`LSG-${securityGroupId}`,
securityGroupId,
);
securityGroups.push(securityGroup);
}

return this.fromDatabaseInstanceAttributes(scope, id, {
instanceEndpointAddress: response.dbInstanceEndpointAddress,
port: response.dbInstanceEndpointPort,
instanceIdentifier: response.instanceIdentifier,
securityGroups: securityGroups,
instanceResourceId: response.instanceResourceId,
});
}

/**
* Import an existing database instance.
*/
Expand Down Expand Up @@ -1159,6 +1201,16 @@ export interface DatabaseInstanceProps extends DatabaseInstanceSourceProps {
readonly storageEncryptionKey?: kms.IKey;
}

/**
* Properties for looking up an existing DatabaseInstance.
*/
export interface DatabaseInstanceLookupOptions {
/**
* The instance identifier of the DatabaseInstance
*/
readonly instanceIdentifier: string;
}

/**
* A database instance
*
Expand Down
92 changes: 92 additions & 0 deletions packages/aws-cdk-lib/aws-rds/test/instance.from-lookup.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { Construct } from 'constructs';
import * as cxschema from '../../cloud-assembly-schema';
import { ContextProvider, GetContextValueOptions, GetContextValueResult, Lazy, Stack } from '../../core';
import * as rds from '../lib';

describe('DatabaseInstanceBase from lookup', () => {
test('return correct instance info', () => {
const previous = mockDbInstanceContextProviderWith({
instanceIdentifier: 'instance-1',
instanceArn: 'arn:aws:rds:us-east-1:123456789012:db:instance-1',
dbInstanceEndpointAddress: 'instance-1.testserver.us-east-1.rds.amazonaws.com',
dbInstanceEndpointPort: 5432,
instanceResourceId: 'db-ABCDEFGHI',
dbSecurityGroupIds: [],
}, options => {
expect(options.instanceIdentifier).toEqual('instance-1');
});

const stack = new Stack(undefined, undefined, { env: { region: 'us-east-1', account: '123456789012' } });
const instance = rds.DatabaseInstance.fromLookup(stack, 'Key', {
instanceIdentifier: 'instance-1',
});

expect(instance.instanceIdentifier).toEqual('instance-1');
expect(instance.dbInstanceEndpointAddress).toEqual('instance-1.testserver.us-east-1.rds.amazonaws.com');
expect(instance.dbInstanceEndpointPort).toEqual('5432');
expect(instance.instanceResourceId).toEqual('db-ABCDEFGHI');

restoreContextProvider(previous);
});

test('return correct instance with DBSG', () => {
const previous = mockDbInstanceContextProviderWith({
instanceIdentifier: 'instance-1',
instanceArn: 'arn:aws:rds:us-east-1:123456789012:db:instance-1',
dbInstanceEndpointAddress: 'instance-1.testserver.us-east-1.rds.amazonaws.com',
dbInstanceEndpointPort: 5432,
instanceResourceId: 'db-ABCDEFGHI',
dbSecurityGroupIds: ['dbsg-1', 'dbsg-2'],
}, options => {
expect(options.instanceIdentifier).toEqual('instance-1');
});

const stack = new Stack(undefined, undefined, { env: { region: 'us-east-1', account: '123456789012' } });
const instance = rds.DatabaseInstance.fromLookup(stack, 'Key', {
instanceIdentifier: 'instance-1',
});

expect(instance.instanceIdentifier).toEqual('instance-1');
expect(instance.dbInstanceEndpointAddress).toEqual('instance-1.testserver.us-east-1.rds.amazonaws.com');
expect(instance.dbInstanceEndpointPort).toEqual('5432');
expect(instance.instanceResourceId).toEqual('db-ABCDEFGHI');
expect(instance.connections.securityGroups.length).toEqual(2);

restoreContextProvider(previous);
});
});

interface MockDatabaseInstanceContextResponse {
instanceIdentifier: string;
instanceArn: string;
dbInstanceEndpointAddress: string;
dbInstanceEndpointPort: number;
instanceResourceId?: string;
dbSecurityGroupIds: string[];
}

function mockDbInstanceContextProviderWith(
response: MockDatabaseInstanceContextResponse,
paramValidator?: (options: cxschema.DatabaseInstanceContextQuery) => void) {

const previous = ContextProvider.getValue;
ContextProvider.getValue = (_scope: Construct, options: GetContextValueOptions) => {
// do some basic sanity checks
expect(options.provider).toEqual(cxschema.ContextProvider.RDS_DATABASE_INSTANCE_PROVIDER);

if (paramValidator) {
paramValidator(options.props as any);
}

return {
value: {
...response,
} as MockDatabaseInstanceContextResponse,
};
};
return previous;
}

function restoreContextProvider(previous: (scope: Construct, options: GetContextValueOptions) => GetContextValueResult): void {
ContextProvider.getValue = previous;
}
21 changes: 20 additions & 1 deletion packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ Flags come in three types:
| [@aws-cdk/core:cfnIncludeRejectComplexResourceUpdateCreatePolicyIntrinsics](#aws-cdkcorecfnincluderejectcomplexresourceupdatecreatepolicyintrinsics) | When enabled, CFN templates added with `cfn-include` will error if the template contains Resource Update or Create policies with CFN Intrinsics that include non-primitive values. | 2.161.0 | (fix) |
| [@aws-cdk/aws-stepfunctions-tasks:fixRunEcsTaskPolicy](#aws-cdkaws-stepfunctions-tasksfixrunecstaskpolicy) | When enabled, the resource of IAM Run Ecs policy generated by SFN EcsRunTask will reference the definition, instead of constructing ARN. | 2.163.0 | (fix) |
| [@aws-cdk/aws-dynamodb:resourcePolicyPerReplica](#aws-cdkaws-dynamodbresourcepolicyperreplica) | When enabled will allow you to specify a resource policy per replica, and not copy the source table policy to all replicas | 2.164.0 | (fix) |
| [@aws-cdk/core:aspectStabilization](#aws-cdkcoreaspectstabilization) | When enabled, a stabilization loop will be run when invoking Aspects during synthesis. | V2NEXT | (config) |

<!-- END table -->

Expand Down Expand Up @@ -195,6 +196,7 @@ are migrating a v1 CDK project to v2, explicitly set any of these flags which do
| [@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2\_2021](#aws-cdkaws-cloudfrontdefaultsecuritypolicytlsv12_2021) | Enable this feature flag to have cloudfront distributions use the security policy TLSv1.2_2021 by default. | (fix) | 1.117.0 | `false` | `true` |
| [@aws-cdk/pipelines:reduceAssetRoleTrustScope](#aws-cdkpipelinesreduceassetroletrustscope) | Remove the root account principal from PipelineAssetsFileRole trust policy | (default) | | `false` | `true` |
| [@aws-cdk/aws-stepfunctions-tasks:useNewS3UriParametersForBedrockInvokeModelTask](#aws-cdkaws-stepfunctions-tasksusenews3uriparametersforbedrockinvokemodeltask) | When enabled, use new props for S3 URI field in task definition of state machine for bedrock invoke model. | (fix) | | `false` | `true` |
| [@aws-cdk/core:aspectStabilization](#aws-cdkcoreaspectstabilization) | When enabled, a stabilization loop will be run when invoking Aspects during synthesis. | (config) | | `false` | `true` |

<!-- END diff -->

Expand All @@ -211,7 +213,8 @@ Here is an example of a `cdk.json` file that restores v1 behavior for these flag
"@aws-cdk/aws-lambda:recognizeVersionProps": false,
"@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": false,
"@aws-cdk/pipelines:reduceAssetRoleTrustScope": false,
"@aws-cdk/aws-stepfunctions-tasks:useNewS3UriParametersForBedrockInvokeModelTask": false
"@aws-cdk/aws-stepfunctions-tasks:useNewS3UriParametersForBedrockInvokeModelTask": false,
"@aws-cdk/core:aspectStabilization": false
}
}
```
Expand Down Expand Up @@ -1529,4 +1532,20 @@ This is a feature flag as the old behavior was technically incorrect but users m
| 2.164.0 | `false` | `true` |


### @aws-cdk/core:aspectStabilization

*When enabled, a stabilization loop will be run when invoking Aspects during synthesis.* (config)

Currently, when Aspects are invoked in one single pass of the construct tree.
This means that the Aspects that create other Aspects are not run and Aspects that create new nodes of the tree sometimes do not inherit their parent Aspects.

When this feature flag is enabled, a stabilization loop is run to recurse the construct tree multiple times when invoking Aspects.


| Since | Default | Recommended |
| ----- | ----- | ----- |
| (not in v1) | | |
| V2NEXT | `true` | `true` |


<!-- END details -->
Loading
Loading