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

fix(integ-tests-alpha): incorrect sdk client resolution #26271

Merged
merged 5 commits into from
Jul 11, 2023
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { CustomResourceHandler } from './base';
import { AwsApiCallRequest, AwsApiCallResult } from './types';
import { decode } from './utils';
import { getV3ClientPackageName, findV3ClientConstructor } from 'aws-cdk-lib/custom-resources';

/**
* Flattens a nested object
Expand Down Expand Up @@ -29,22 +30,62 @@ export function flatten(object: object): { [key: string]: any } {
);
}

function getServiceClient(service: string): any {
const clientPackageName = `@aws-sdk/client-${service.toLowerCase()}`;
interface V3SdkPkg {
service: string;
packageName: string;
pkg: object;
}

function getServicePackage(service: string): V3SdkPkg {
const packageName = getV3ClientPackageName(service);
try {
/* eslint-disable-next-line @typescript-eslint/no-require-imports */
const pkg = require(packageName);

return {
service,
pkg,
packageName,
};
} catch (e) {
throw Error(`Service ${service} client package with name '${packageName}' does not exist.`);
}
}

function getServiceClient(sdkCall: V3SdkPkg): any {
try {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const pkg = require(clientPackageName);
return new pkg[service]({});
const ServiceClient = findV3ClientConstructor(sdkCall.pkg);
return new ServiceClient({});
} catch (e) {
// Just import a known client module
throw Error(`Service ${service} client package with name '${clientPackageName}' does not exist.`);
throw Error(`No client constructor found within package: ${sdkCall.packageName}`);
}
}

function getSdkCommand(sdkCall: V3SdkPkg, api: string): any {
const commandName = api.endsWith('Command') ? api : `${api}Command`;
const command = Object.entries(sdkCall.pkg).find(
([name]) => name.toLowerCase() === commandName.toLowerCase(),
)?.[1] as { new (input: any): any };

if (!command) {
throw new Error(`Unable to find command named: ${commandName} for api: ${api} in service package`);
}
return command;
}

export class AwsApiCallHandler extends CustomResourceHandler<AwsApiCallRequest, AwsApiCallResult | { [key: string]: string }> {
protected async processEvent(request: AwsApiCallRequest): Promise<AwsApiCallResult | { [key: string]: string } | undefined> {
const client = getServiceClient(request.service);
const response = await client[request.api](request.parameters && decode(request.parameters));
const sdkPkg = getServicePackage(request.service);
const client = getServiceClient(sdkPkg);

const Command = getSdkCommand(sdkPkg, request.api);
const response = await client.send(
new Command(
(request.parameters &&
decode(request.parameters)) ?? {},
),
);
// const response = await client[request.api](request.parameters && decode(request.parameters));

console.log(`SDK response received ${JSON.stringify(response)}`);
delete response.ResponseMetadata;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -605,3 +605,5 @@ function awsSdkToIamAction(service: string, action: string): string {
const iamAction = action.charAt(0).toUpperCase() + action.slice(1);
return `${iamService}:${iamAction}`;
}

export * from './runtime/utils';
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { execSync } from 'child_process';
// fails in the CDK app executed with ts-node
/* eslint-disable-next-line import/no-extraneous-dependencies,import/no-unresolved */
import * as AWSLambda from 'aws-lambda';
import { findV3ClientConstructor } from './v2-to-v3/find-client-constructor';
import { getV3ClientPackageName } from './v2-to-v3/get-v3-client-package-name';
import { AwsSdkCall } from '../../aws-custom-resource';
import { decodeCall, decodeSpecialValues, filterKeys, flatten, respond, startsWithOneOf } from '../shared';
Expand Down Expand Up @@ -106,17 +107,7 @@ export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent
}

awsSdk = await awsSdk;
const [_clientName, ServiceClient] = Object.entries(awsSdk).find(
([name]) => {
// Services expose a base __Client class that we don't want ever
return name.endsWith('Client') && name !== '__Client';
},
) as [string, {
new (config: any): {
send: (command: any) => Promise<any>
config: any
}
}];
const ServiceClient = findV3ClientConstructor(awsSdk);

const client = new ServiceClient({
apiVersion: call.apiVersion,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export function findV3ClientConstructor(pkg: Object) {
const [_clientName, ServiceClient] = Object.entries(pkg).find(
([name]) => {
// Services expose a base __Client class that we don't want ever
return name.endsWith('Client') && name !== '__Client';
},
) as [string, {
new (config: any): {
send: (command: any) => Promise<any>
config: any
}
}];
return ServiceClient;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ export { PHYSICAL_RESOURCE_ID_REFERENCE } from './shared';
const env = process.env.AWS_EXECUTION_ENV;
// eslint-disable-next-line @typescript-eslint/no-require-imports
const runtime = env && env >= 'AWS_Lambda_nodejs18.x' ? require('./aws-sdk-v3-handler') : require('./aws-sdk-v2-handler');
export const handler = runtime.handler;
export const handler = runtime.handler;
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { getV3ClientPackageName } from './aws-sdk-v3-handler/v2-to-v3/get-v3-client-package-name';
export { findV3ClientConstructor } from './aws-sdk-v3-handler/v2-to-v3/find-client-constructor';