Skip to content

Commit 665d5a8

Browse files
authored
refactor(lambda): migrate to aws-sdk v3 (aws#8041)
## Problem AWS SDK v2 is at EOL. All clients should migrate to V3 ## Solution Migrate Lambda client to AWS SDK V3 --- - Treat all work as PUBLIC. Private `feature/x` branches will not be squash-merged at release time. - Your code changes must meet the guidelines in [CONTRIBUTING.md](https://github.com/aws/aws-toolkit-vscode/blob/master/CONTRIBUTING.md#guidelines). - License: I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent d14e68c commit 665d5a8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+401
-328
lines changed

packages/core/src/awsService/appBuilder/explorer/nodes/deployedNode.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { getLogger } from '../../../../shared/logger/logger'
1313
import { DefaultLambdaClient } from '../../../../shared/clients/lambdaClient'
1414
import globals from '../../../../shared/extensionGlobals'
1515
import { defaultPartition } from '../../../../shared/regions/regionProvider'
16-
import { Lambda } from 'aws-sdk'
16+
import { FunctionConfiguration } from '@aws-sdk/client-lambda'
1717
import { RestApi } from '@aws-sdk/client-api-gateway'
1818
import { LambdaNode } from '../../../../lambda/explorer/lambdaNodes'
1919
import { LambdaFunctionNode } from '../../../../lambda/explorer/lambdaFunctionNode'
@@ -89,10 +89,10 @@ export async function generateDeployedNode(
8989
case SERVERLESS_FUNCTION_TYPE: {
9090
const defaultClient = new DefaultLambdaClient(regionCode)
9191
const lambdaNode = new LambdaNode(regionCode, defaultClient)
92-
let configuration: Lambda.FunctionConfiguration
92+
let configuration: FunctionConfiguration
9393
try {
9494
configuration = (await defaultClient.getFunction(deployedResource.PhysicalResourceId))
95-
.Configuration as Lambda.FunctionConfiguration
95+
.Configuration as FunctionConfiguration
9696
newDeployedResource = new LambdaFunctionNode(
9797
lambdaNode,
9898
regionCode,

packages/core/src/awsService/appBuilder/explorer/samProject.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { SamConfig, SamConfigErrorCode } from '../../../shared/sam/config'
99
import { getLogger } from '../../../shared/logger/logger'
1010
import { ToolkitError } from '../../../shared/errors'
1111
import { showViewLogsMessage } from '../../../shared/utilities/messages'
12+
import { Runtime } from '@aws-sdk/client-lambda'
1213

1314
export interface SamApp {
1415
location: SamAppLocation
@@ -24,7 +25,7 @@ export interface SamAppLocation {
2425
export interface ResourceTreeEntity {
2526
Id: string
2627
Type: string
27-
Runtime?: string
28+
Runtime?: Runtime
2829
CodeUri?: string
2930
Handler?: string
3031
Events?: ResourceTreeEntity[]

packages/core/src/awsService/appBuilder/lambda2sam/lambda2sam.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
import { downloadUnzip, getLambdaClient, getCFNClient, isPermissionError } from '../utils'
2727
import { openProjectInWorkspace } from '../walkthrough'
2828
import { ToolkitError } from '../../../shared/errors'
29-
import { ResourcesToImport, StackResource } from 'aws-sdk/clients/cloudformation'
29+
import { ResourceToImport, StackResource } from '@aws-sdk/client-cloudformation'
3030
import { SignatureV4 } from '@smithy/signature-v4'
3131
import { Sha256 } from '@aws-crypto/sha256-js'
3232
import { getIAMConnection } from '../../../auth/utils'
@@ -79,7 +79,7 @@ export async function lambdaToSam(lambdaNode: LambdaFunctionNode): Promise<void>
7979
progress.report({ increment: 30, message: 'Generating template...' })
8080
// 2.1 call api to get CFN
8181
let cfnTemplate: Template
82-
let resourcesToImport: ResourcesToImport
82+
let resourcesToImport: ResourceToImport[]
8383
try {
8484
;[cfnTemplate, resourcesToImport] = await callExternalApiForCfnTemplate(lambdaNode)
8585
} catch (error) {
@@ -282,7 +282,7 @@ export function ifSamTemplate(template: Template): boolean {
282282
*/
283283
export async function callExternalApiForCfnTemplate(
284284
lambdaNode: LambdaFunctionNode
285-
): Promise<[Template, ResourcesToImport]> {
285+
): Promise<[Template, ResourceToImport[]]> {
286286
const conn = await getIAMConnection()
287287
if (!conn || conn.type !== 'iam') {
288288
return [{}, []]
@@ -333,7 +333,7 @@ export async function callExternalApiForCfnTemplate(
333333

334334
let status: string | undefined = 'CREATE_IN_PROGRESS'
335335
let getGeneratedTemplateResponse
336-
let resourcesToImport: ResourcesToImport = []
336+
let resourcesToImport: ResourceToImport[] = []
337337
const cfn = await getCFNClient(lambdaNode.regionCode)
338338

339339
// Wait for template generation to complete
@@ -438,7 +438,7 @@ async function promptForProjectLocation(): Promise<vscode.Uri[] | undefined> {
438438
*/
439439
export async function deployCfnTemplate(
440440
template: Template,
441-
resourcesToImport: ResourcesToImport,
441+
resourcesToImport: ResourceToImport[],
442442
stackName: string,
443443
region: string
444444
): Promise<StackInfo> {
@@ -901,13 +901,13 @@ export async function getPhysicalIdfromCFNResourceName(
901901

902902
// Find resources that start with the given name (SAM transform often adds suffixes)
903903
const matchingResources = resources.StackResources.filter((resource: StackResource) =>
904-
resource.LogicalResourceId.startsWith(name)
904+
resource.LogicalResourceId?.startsWith(name)
905905
)
906906

907907
if (matchingResources.length === 0) {
908908
// Try a more flexible approach - check if the resource name is a substring
909909
const substringMatches = resources.StackResources.filter((resource: StackResource) =>
910-
resource.LogicalResourceId.includes(name)
910+
resource.LogicalResourceId?.includes(name)
911911
)
912912

913913
if (substringMatches.length === 0) {
@@ -926,7 +926,8 @@ export async function getPhysicalIdfromCFNResourceName(
926926
// If we have multiple matches, prefer exact prefix match
927927
// Sort by length to get the closest match (shortest additional suffix)
928928
matchingResources.sort(
929-
(a: StackResource, b: StackResource) => a.LogicalResourceId.length - b.LogicalResourceId.length
929+
(a: StackResource, b: StackResource) =>
930+
(a.LogicalResourceId?.length ?? 0) - (b.LogicalResourceId?.length ?? 0)
930931
)
931932

932933
const bestMatch = matchingResources[0]

packages/core/src/awsService/appBuilder/utils.ts

Lines changed: 89 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,51 @@ import { RuntimeFamily, getFamily } from '../../lambda/models/samLambdaRuntime'
2121
import { showMessage } from '../../shared/utilities/messages'
2222
import { DefaultLambdaClient } from '../../shared/clients/lambdaClient'
2323
import AdmZip from 'adm-zip'
24-
import { CloudFormation, Lambda } from 'aws-sdk'
24+
import {
25+
CloudFormationClient,
26+
CreateChangeSetCommand,
27+
CreateChangeSetInput,
28+
CreateChangeSetOutput,
29+
DescribeChangeSetCommand,
30+
DescribeChangeSetInput,
31+
DescribeChangeSetOutput,
32+
DescribeGeneratedTemplateCommand,
33+
DescribeGeneratedTemplateInput,
34+
DescribeGeneratedTemplateOutput,
35+
DescribeStackResourceCommand,
36+
DescribeStackResourceInput,
37+
DescribeStackResourceOutput,
38+
DescribeStackResourcesCommand,
39+
DescribeStackResourcesInput,
40+
DescribeStackResourcesOutput,
41+
DescribeStacksCommand,
42+
DescribeStacksInput,
43+
DescribeStacksOutput,
44+
ExecuteChangeSetCommand,
45+
ExecuteChangeSetInput,
46+
ExecuteChangeSetOutput,
47+
GetGeneratedTemplateCommand,
48+
GetGeneratedTemplateInput,
49+
GetGeneratedTemplateOutput,
50+
GetTemplateCommand,
51+
GetTemplateInput,
52+
GetTemplateOutput,
53+
waitUntilChangeSetCreateComplete,
54+
waitUntilStackImportComplete,
55+
waitUntilStackUpdateComplete,
56+
} from '@aws-sdk/client-cloudformation'
57+
import {
58+
FunctionConfiguration,
59+
FunctionUrlConfig,
60+
GetFunctionResponse,
61+
GetLayerVersionResponse,
62+
InvocationRequest,
63+
InvocationResponse,
64+
LayerVersionsListItem,
65+
Runtime,
66+
} from '@aws-sdk/client-lambda'
2567
import { isAwsError, UnknownError } from '../../shared/errors'
68+
import { WaiterConfiguration } from '@aws-sdk/types'
2669
const localize = nls.loadMessageBundle()
2770

2871
/**
@@ -230,7 +273,7 @@ export class EnhancedLambdaClient {
230273
}
231274
}
232275

233-
async invoke(name: string, payload?: Lambda.InvocationRequest['Payload']): Promise<Lambda.InvocationResponse> {
276+
async invoke(name: string, payload?: InvocationRequest['Payload']): Promise<InvocationResponse> {
234277
try {
235278
return await this.client.invoke(name, payload)
236279
} catch (error) {
@@ -246,7 +289,7 @@ export class EnhancedLambdaClient {
246289
}
247290
}
248291

249-
async *listFunctions(): AsyncIterableIterator<Lambda.FunctionConfiguration> {
292+
async *listFunctions(): AsyncIterableIterator<FunctionConfiguration> {
250293
try {
251294
yield* this.client.listFunctions()
252295
} catch (error) {
@@ -257,7 +300,7 @@ export class EnhancedLambdaClient {
257300
}
258301
}
259302

260-
async getFunction(name: string): Promise<Lambda.GetFunctionResponse> {
303+
async getFunction(name: string): Promise<GetFunctionResponse> {
261304
try {
262305
return await this.client.getFunction(name)
263306
} catch (error) {
@@ -273,7 +316,7 @@ export class EnhancedLambdaClient {
273316
}
274317
}
275318

276-
async getLayerVersion(name: string, version: number): Promise<Lambda.GetLayerVersionResponse> {
319+
async getLayerVersion(name: string, version: number): Promise<GetLayerVersionResponse> {
277320
try {
278321
return await this.client.getLayerVersion(name, version)
279322
} catch (error) {
@@ -289,7 +332,7 @@ export class EnhancedLambdaClient {
289332
}
290333
}
291334

292-
async *listLayerVersions(name: string): AsyncIterableIterator<Lambda.LayerVersionsListItem> {
335+
async *listLayerVersions(name: string): AsyncIterableIterator<LayerVersionsListItem> {
293336
try {
294337
yield* this.client.listLayerVersions(name)
295338
} catch (error) {
@@ -305,7 +348,7 @@ export class EnhancedLambdaClient {
305348
}
306349
}
307350

308-
async getFunctionUrlConfigs(name: string): Promise<Lambda.FunctionUrlConfigList> {
351+
async getFunctionUrlConfigs(name: string): Promise<FunctionUrlConfig[]> {
309352
try {
310353
return await this.client.getFunctionUrlConfigs(name)
311354
} catch (error) {
@@ -321,7 +364,7 @@ export class EnhancedLambdaClient {
321364
}
322365
}
323366

324-
async updateFunctionCode(name: string, zipFile: Uint8Array): Promise<Lambda.FunctionConfiguration> {
367+
async updateFunctionCode(name: string, zipFile: Uint8Array): Promise<FunctionConfiguration> {
325368
try {
326369
return await this.client.updateFunctionCode(name, zipFile)
327370
} catch (error) {
@@ -343,13 +386,13 @@ export class EnhancedLambdaClient {
343386
*/
344387
export class EnhancedCloudFormationClient {
345388
constructor(
346-
private readonly client: CloudFormation,
389+
private readonly client: CloudFormationClient,
347390
private readonly regionCode: string
348391
) {}
349392

350-
async describeStacks(params: CloudFormation.DescribeStacksInput): Promise<CloudFormation.DescribeStacksOutput> {
393+
async describeStacks(params: DescribeStacksInput): Promise<DescribeStacksOutput> {
351394
try {
352-
return await this.client.describeStacks(params).promise()
395+
return await this.client.send(new DescribeStacksCommand(params))
353396
} catch (error) {
354397
if (isPermissionError(error)) {
355398
const stackArn = params.StackName
@@ -361,9 +404,9 @@ export class EnhancedCloudFormationClient {
361404
}
362405
}
363406

364-
async getTemplate(params: CloudFormation.GetTemplateInput): Promise<CloudFormation.GetTemplateOutput> {
407+
async getTemplate(params: GetTemplateInput): Promise<GetTemplateOutput> {
365408
try {
366-
return await this.client.getTemplate(params).promise()
409+
return await this.client.send(new GetTemplateCommand(params))
367410
} catch (error) {
368411
if (isPermissionError(error)) {
369412
const stackArn = params.StackName
@@ -375,9 +418,9 @@ export class EnhancedCloudFormationClient {
375418
}
376419
}
377420

378-
async createChangeSet(params: CloudFormation.CreateChangeSetInput): Promise<CloudFormation.CreateChangeSetOutput> {
421+
async createChangeSet(params: CreateChangeSetInput): Promise<CreateChangeSetOutput> {
379422
try {
380-
return await this.client.createChangeSet(params).promise()
423+
return await this.client.send(new CreateChangeSetCommand(params))
381424
} catch (error) {
382425
if (isPermissionError(error)) {
383426
const stackArn = params.StackName
@@ -389,11 +432,9 @@ export class EnhancedCloudFormationClient {
389432
}
390433
}
391434

392-
async executeChangeSet(
393-
params: CloudFormation.ExecuteChangeSetInput
394-
): Promise<CloudFormation.ExecuteChangeSetOutput> {
435+
async executeChangeSet(params: ExecuteChangeSetInput): Promise<ExecuteChangeSetOutput> {
395436
try {
396-
return await this.client.executeChangeSet(params).promise()
437+
return await this.client.send(new ExecuteChangeSetCommand(params))
397438
} catch (error) {
398439
if (isPermissionError(error)) {
399440
const stackArn = params.StackName
@@ -405,11 +446,9 @@ export class EnhancedCloudFormationClient {
405446
}
406447
}
407448

408-
async describeChangeSet(
409-
params: CloudFormation.DescribeChangeSetInput
410-
): Promise<CloudFormation.DescribeChangeSetOutput> {
449+
async describeChangeSet(params: DescribeChangeSetInput): Promise<DescribeChangeSetOutput> {
411450
try {
412-
return await this.client.describeChangeSet(params).promise()
451+
return await this.client.send(new DescribeChangeSetCommand(params))
413452
} catch (error) {
414453
if (isPermissionError(error)) {
415454
const stackArn = params.StackName
@@ -421,11 +460,9 @@ export class EnhancedCloudFormationClient {
421460
}
422461
}
423462

424-
async describeStackResources(
425-
params: CloudFormation.DescribeStackResourcesInput
426-
): Promise<CloudFormation.DescribeStackResourcesOutput> {
463+
async describeStackResources(params: DescribeStackResourcesInput): Promise<DescribeStackResourcesOutput> {
427464
try {
428-
return await this.client.describeStackResources(params).promise()
465+
return await this.client.send(new DescribeStackResourcesCommand(params))
429466
} catch (error) {
430467
if (isPermissionError(error)) {
431468
const stackArn = params.StackName
@@ -437,11 +474,9 @@ export class EnhancedCloudFormationClient {
437474
}
438475
}
439476

440-
async describeStackResource(
441-
params: CloudFormation.DescribeStackResourceInput
442-
): Promise<CloudFormation.DescribeStackResourceOutput> {
477+
async describeStackResource(params: DescribeStackResourceInput): Promise<DescribeStackResourceOutput> {
443478
try {
444-
return await this.client.describeStackResource(params).promise()
479+
return await this.client.send(new DescribeStackResourceCommand(params))
445480
} catch (error) {
446481
if (isPermissionError(error)) {
447482
const stackArn = params.StackName
@@ -453,11 +488,9 @@ export class EnhancedCloudFormationClient {
453488
}
454489
}
455490

456-
async getGeneratedTemplate(
457-
params: CloudFormation.GetGeneratedTemplateInput
458-
): Promise<CloudFormation.GetGeneratedTemplateOutput> {
491+
async getGeneratedTemplate(params: GetGeneratedTemplateInput): Promise<GetGeneratedTemplateOutput> {
459492
try {
460-
return await this.client.getGeneratedTemplate(params).promise()
493+
return await this.client.send(new GetGeneratedTemplateCommand(params))
461494
} catch (error) {
462495
if (isPermissionError(error)) {
463496
throw createEnhancedPermissionError(error, 'cloudformation', 'getGeneratedTemplate')
@@ -466,11 +499,9 @@ export class EnhancedCloudFormationClient {
466499
}
467500
}
468501

469-
async describeGeneratedTemplate(
470-
params: CloudFormation.DescribeGeneratedTemplateInput
471-
): Promise<CloudFormation.DescribeGeneratedTemplateOutput> {
502+
async describeGeneratedTemplate(params: DescribeGeneratedTemplateInput): Promise<DescribeGeneratedTemplateOutput> {
472503
try {
473-
return await this.client.describeGeneratedTemplate(params).promise()
504+
return await this.client.send(new DescribeGeneratedTemplateCommand(params))
474505
} catch (error) {
475506
if (isPermissionError(error)) {
476507
throw createEnhancedPermissionError(error, 'cloudformation', 'describeGeneratedTemplate')
@@ -481,7 +512,20 @@ export class EnhancedCloudFormationClient {
481512

482513
async waitFor(state: string, params: any): Promise<any> {
483514
try {
484-
return await this.client.waitFor(state as any, params).promise()
515+
const waiterConfig = {
516+
client: this.client,
517+
maxWaitTime: 900,
518+
} satisfies WaiterConfiguration<CloudFormationClient>
519+
switch (state) {
520+
case 'changeSetCreateComplete':
521+
return await waitUntilChangeSetCreateComplete(waiterConfig, params)
522+
case 'stackImportComplete':
523+
return await waitUntilStackImportComplete(waiterConfig, params)
524+
case 'stackUpdateComplete':
525+
return await waitUntilStackUpdateComplete(waiterConfig, params)
526+
default:
527+
throw new Error(`Unsupported waiter state: ${state}`)
528+
}
485529
} catch (error) {
486530
if (isPermissionError(error)) {
487531
// For waitFor operations, we'll provide a generic permission error since the specific action varies
@@ -560,7 +604,7 @@ export async function getLambdaHandlerFile(
560604
folderUri: vscode.Uri,
561605
codeUri: string,
562606
handler: string,
563-
runtime: string
607+
runtime: Runtime
564608
): Promise<vscode.Uri | undefined> {
565609
const family = getFamily(runtime)
566610
if (!supportedRuntimeForHandler.has(family)) {
@@ -704,6 +748,9 @@ export function getLambdaClient(region: string): EnhancedLambdaClient {
704748
}
705749

706750
export async function getCFNClient(regionCode: string): Promise<EnhancedCloudFormationClient> {
707-
const originalClient = await globals.sdkClientBuilder.createAwsService(CloudFormation, {}, regionCode)
751+
const originalClient = globals.sdkClientBuilderV3.createAwsService({
752+
serviceClient: CloudFormationClient,
753+
region: regionCode,
754+
})
708755
return new EnhancedCloudFormationClient(originalClient, regionCode)
709756
}

0 commit comments

Comments
 (0)