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

feature: make custom resource provider framework region aware #29957

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -23,8 +23,8 @@ import {
CORE_INTERNAL_STACK,
CORE_INTERNAL_CR_PROVIDER,
PATH_MODULE,
REGION_INFO,
} from './modules';
import { toLambdaRuntime } from './utils/framework-utils';

/**
* Initialization properties for a class constructor.
Expand Down Expand Up @@ -86,7 +86,7 @@ export abstract class HandlerFrameworkClass extends ClassType {
*/
public static buildFunction(scope: HandlerFrameworkModule, props: HandlerFrameworkClassProps): HandlerFrameworkClass {
return new (class Function extends HandlerFrameworkClass {
protected readonly externalModules = [PATH_MODULE, CONSTRUCTS_MODULE, LAMBDA_MODULE];
protected readonly externalModules = [PATH_MODULE, CONSTRUCTS_MODULE, LAMBDA_MODULE, REGION_INFO, CORE_MODULE];

public constructor() {
super(scope, {
Expand All @@ -97,11 +97,13 @@ export abstract class HandlerFrameworkClass extends ClassType {

this.importExternalModulesInto(scope);

this.buildCustomResourceRuntimeDeterminer();

const superProps = new ObjectLiteral([
new Splat(expr.ident('props')),
['code', expr.directCode(`lambda.Code.fromAsset(path.join(__dirname, '${props.codeDirectory}'))`)],
['handler', expr.lit(props.handler)],
['runtime', expr.directCode(toLambdaRuntime(props.runtime))],
['runtime', expr.directCode(`${this.name}.builtInCustomResourceNodeRuntime(scope)`)],
]);
this.buildConstructor({
constructorPropsType: LAMBDA_MODULE.FunctionOptions,
Expand All @@ -118,7 +120,7 @@ export abstract class HandlerFrameworkClass extends ClassType {
*/
public static buildSingletonFunction(scope: HandlerFrameworkModule, props: HandlerFrameworkClassProps): HandlerFrameworkClass {
return new (class SingletonFunction extends HandlerFrameworkClass {
protected readonly externalModules = [PATH_MODULE, CONSTRUCTS_MODULE, LAMBDA_MODULE];
protected readonly externalModules = [PATH_MODULE, CONSTRUCTS_MODULE, LAMBDA_MODULE, REGION_INFO, CORE_MODULE];

public constructor() {
super(scope, {
Expand All @@ -129,6 +131,8 @@ export abstract class HandlerFrameworkClass extends ClassType {

this.importExternalModulesInto(scope);

this.buildCustomResourceRuntimeDeterminer();

const uuid: PropertySpec = {
name: 'uuid',
type: Type.STRING,
Expand Down Expand Up @@ -163,7 +167,7 @@ export abstract class HandlerFrameworkClass extends ClassType {
new Splat(expr.ident('props')),
['code', expr.directCode(`lambda.Code.fromAsset(path.join(__dirname, '${props.codeDirectory}'))`)],
['handler', expr.lit(props.handler)],
['runtime', expr.directCode(toLambdaRuntime(props.runtime))],
['runtime', expr.directCode(`${this.name}.builtInCustomResourceNodeRuntime(scope)`)],
]);
this.buildConstructor({
constructorPropsType: _interface.type,
Expand Down Expand Up @@ -318,6 +322,10 @@ export abstract class HandlerFrameworkClass extends ClassType {
LAMBDA_MODULE.import(scope, 'lambda');
return;
}
case REGION_INFO.fqn: {
REGION_INFO.importSelective(scope, ['FactName']);
return;
}
}
}

Expand Down Expand Up @@ -353,4 +361,21 @@ export abstract class HandlerFrameworkClass extends ClassType {
const superInitializerArgs: Expression[] = [scope, id, props.superProps];
init.addBody(new SuperInitializer(...superInitializerArgs));
}

private buildCustomResourceRuntimeDeterminer() {
const builtInCustomResourceNodeRuntime = this.addMethod({
name: 'builtInCustomResourceNodeRuntime',
visibility: MemberVisibility.Private,
static: true,
returnType: LAMBDA_MODULE.Function,
});
builtInCustomResourceNodeRuntime.addParameter({
name: 'scope',
type: CONSTRUCTS_MODULE.Construct,
});
builtInCustomResourceNodeRuntime.addBody(
stmt.constVar(expr.ident('runtimeName'), expr.directCode('Stack.of(scope).regionalFact(FactName.DEFAULT_CR_NODE_VERSION, "nodejs18.x")')),
stmt.ret(expr.directCode('runtimeName ? new lambda.Runtime(runtimeName, lambda.RuntimeFamily.NODEJS, { supportsInlineCode: true }) : lambda.Runtime.NODEJS_18_X')),
);
}
}
Expand Up @@ -52,9 +52,18 @@ class LambdaModule extends ExternalModule {
}
}

class RegionInfo extends ExternalModule {
public readonly FactName = Type.fromName(this, 'FactName');

public constructor() {
super('../../../region-info');
}
}

export const PATH_MODULE = new PathModule();
export const CONSTRUCTS_MODULE = new ConstructsModule();
export const CORE_MODULE = new CoreModule();
export const CORE_INTERNAL_STACK = new CoreInternalStack();
export const CORE_INTERNAL_CR_PROVIDER = new CoreInternalCustomResourceProvider();
export const LAMBDA_MODULE = new LambdaModule();
export const REGION_INFO = new RegionInfo();
8 changes: 8 additions & 0 deletions packages/aws-cdk-lib/region-info/build-tools/fact-tables.ts
Expand Up @@ -90,6 +90,14 @@ export const PARTITION_MAP: { [region: string]: Region } = {
'us-isob-': { partition: Partition.UsIsoB, domainSuffix: 'sc2s.sgov.gov' },
};

export const CR_DEFAULT_RUNTIME_MAP: Record<Partition, string> = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs be the value that feeds into Runtime.NODEJS_LATEST. There is no way to do NODEJS_LATEST correctly with a hardcoded constant.

[Partition.Default]: 'nodejs18.x',
[Partition.Cn]: 'nodejs18.x',
[Partition.UsGov]: 'nodejs18.x',
[Partition.UsIso]: 'nodejs18.x',
[Partition.UsIsoB]: 'nodejs18.x',
};

// https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html#access-logging-bucket-permissions
// https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html#attach-bucket-policy
// Any not listed regions use the service principal "logdelivery.elasticloadbalancing.amazonaws.com"
Expand Down
Expand Up @@ -13,6 +13,7 @@ import {
PARAMS_AND_SECRETS_LAMBDA_LAYER_ARNS,
APPCONFIG_LAMBDA_LAYER_ARNS,
PARTITION_SAML_SIGN_ON_URL,
CR_DEFAULT_RUNTIME_MAP,
} from './fact-tables';
import { AWS_CDK_METADATA } from './metadata';
import {
Expand Down Expand Up @@ -85,6 +86,8 @@ export async function main(): Promise<void> {

registerFact(region, 'APPMESH_ECR_ACCOUNT', APPMESH_ECR_ACCOUNTS[region]);

registerFact(region, 'DEFAULT_CR_NODE_VERSION', CR_DEFAULT_RUNTIME_MAP[partition]);

registerFact(region, 'SAML_SIGN_ON_URL', PARTITION_SAML_SIGN_ON_URL[partition]);

const firehoseCidrBlock = FIREHOSE_CIDR_BLOCKS[region];
Expand Down
5 changes: 5 additions & 0 deletions packages/aws-cdk-lib/region-info/lib/fact.ts
Expand Up @@ -195,6 +195,11 @@ export class FactName {
*/
public static readonly SAML_SIGN_ON_URL = 'samlSignOnUrl';

/**
* The default NodeJS version used for custom resource function runtimes
*/
public static readonly DEFAULT_CR_NODE_VERSION = 'defaultCrNodeVersion';

/**
* The ARN of CloudWatch Lambda Insights for a version (e.g. 1.0.98.0)
*/
Expand Down