@@ -303,15 +303,13 @@ async function deleteLayerVersion(
303
303
}
304
304
305
305
/**
306
- * Check if policy needs to be removed from the Lambda role
306
+ * Get the role name from a Lambda function
307
307
* @param functionName
308
- * @returns
308
+ * @returns role name
309
309
*/
310
- async function analyzeRemovePolicyFromLambdaRole ( functionName : string ) {
310
+ async function getRoleNameFromFunction ( functionName : string ) : Promise < string > {
311
311
try {
312
- Logger . verbose (
313
- `[Function ${ functionName } ] Analyzing policy removal from Lambda role` ,
314
- ) ;
312
+ Logger . verbose ( `[Function ${ functionName } ] Getting role from function` ) ;
315
313
316
314
const getFunctionResponse = await getLambdaClient ( ) . send (
317
315
new GetFunctionCommand ( {
@@ -325,6 +323,7 @@ async function analyzeRemovePolicyFromLambdaRole(functionName: string) {
325
323
) ;
326
324
}
327
325
326
+ // Extract the role name from the role ARN
328
327
const roleName = roleArn . split ( '/' ) . pop ( ) ;
329
328
330
329
if ( ! roleName ) {
@@ -334,23 +333,40 @@ async function analyzeRemovePolicyFromLambdaRole(functionName: string) {
334
333
}
335
334
336
335
Logger . verbose ( `[Function ${ functionName } ] Found role: ${ roleName } ` ) ;
336
+ return roleName ;
337
+ } catch ( error : any ) {
338
+ throw new Error ( `Failed to get role name from function ${ functionName } .` , {
339
+ cause : error ,
340
+ } ) ;
341
+ }
342
+ }
343
+
344
+ /**
345
+ * Check if policy needs to be removed from the Lambda role
346
+ * @param roleName
347
+ * @returns
348
+ */
349
+ async function analyzeRoleRemove ( roleName : string ) {
350
+ try {
351
+ Logger . verbose (
352
+ `[Role ${ roleName } ] Analyzing policy removal from Lambda role` ,
353
+ ) ;
337
354
338
355
const existingPolicy = await createPolicyDocument ( roleName ) ;
339
356
340
357
const needToRemovePolicy = ! ! existingPolicy ;
341
358
Logger . verbose (
342
- `[Function ${ functionName } ] Policy ${ needToRemovePolicy ? 'needs to be removed' : 'not found to remove' } from role ${ roleName } ` ,
359
+ `[Role ${ roleName } ] Policy ${ needToRemovePolicy ? 'needs to be removed' : 'not found to remove' } from role ${ roleName } ` ,
343
360
) ;
344
361
345
362
return {
346
363
needToRemovePolicy,
347
364
roleName,
348
365
} ;
349
366
} catch ( error : any ) {
350
- throw new Error (
351
- `Failed to analyze removal policy from Lambda ${ functionName } .` ,
352
- { cause : error } ,
353
- ) ;
367
+ throw new Error ( `Failed to analyze removal policy from role ${ roleName } .` , {
368
+ cause : error ,
369
+ } ) ;
354
370
}
355
371
}
356
372
@@ -502,24 +518,54 @@ async function getInfraChangesForAdding(): Promise<InfraAddingChanges> {
502
518
} ) ,
503
519
) ;
504
520
505
- const rolesToAddPromise = Promise . all (
521
+ const lambdasToRemovePromise = Promise . all (
522
+ configLambdasRemove . map ( async ( func ) => {
523
+ return analyzeLambdaRemove ( func . functionName ) ;
524
+ } ) ,
525
+ ) ;
526
+
527
+ // Get all role names for lambdas to update, ensure uniqueness, then analyze
528
+ const roleNamesToAddSet = new Set < string > ( ) ;
529
+ const roleNamesToAddPromise = Promise . all (
506
530
configLambdasUpdate . map ( async ( func ) => {
507
- const roleUpdate = await analyzeLambdaRoleAdd ( func . functionName ) ;
508
- return roleUpdate . addPolicy ? roleUpdate . roleName : undefined ;
531
+ const roleName = await getRoleNameFromFunction ( func . functionName ) ;
532
+ roleNamesToAddSet . add ( roleName ) ;
509
533
} ) ,
510
534
) ;
511
535
512
- const lambdasToRemovePromise = Promise . all (
536
+ // Get all role names for lambdas to remove, ensure uniqueness, then analyze
537
+ const roleNamesToRemoveSet = new Set < string > ( ) ;
538
+ const roleNamesToRemovePromise = Promise . all (
513
539
configLambdasRemove . map ( async ( func ) => {
514
- return analyzeRemoveLambda ( func . functionName ) ;
540
+ const roleName = await getRoleNameFromFunction ( func . functionName ) ;
541
+ roleNamesToRemoveSet . add ( roleName ) ;
515
542
} ) ,
516
543
) ;
517
544
545
+ // Analyze roles to add
546
+ await roleNamesToAddPromise ;
547
+
548
+ const roleNamesToAdd = Array . from ( roleNamesToAddSet ) ;
549
+ const rolesToAddPromise = Promise . all (
550
+ roleNamesToAdd . map ( async ( roleName ) => {
551
+ const roleUpdate = await analyzeRoleAdd ( roleName ) ;
552
+ return roleUpdate . addPolicy ? roleUpdate . roleName : undefined ;
553
+ } ) ,
554
+ ) ;
555
+
556
+ // Analyze roles to remove
557
+ await roleNamesToRemovePromise ;
558
+
559
+ let roleNamesToRemove = Array . from ( roleNamesToRemoveSet ) ;
560
+
561
+ // make sure that roles removed are not in the list to add
562
+ roleNamesToRemove = roleNamesToRemove . filter (
563
+ ( role ) => ! roleNamesToAdd . includes ( role ) ,
564
+ ) ;
565
+
518
566
const rolesToRemovePromise = Promise . all (
519
- configLambdasRemove . map ( async ( func ) => {
520
- const roleRemoval = await analyzeRemovePolicyFromLambdaRole (
521
- func . functionName ,
522
- ) ;
567
+ roleNamesToRemove . map ( async ( roleName ) => {
568
+ const roleRemoval = await analyzeRoleRemove ( roleName ) ;
523
569
return roleRemoval . needToRemovePolicy ? roleRemoval . roleName : undefined ;
524
570
} ) ,
525
571
) ;
@@ -540,12 +586,7 @@ async function getInfraChangesForAdding(): Promise<InfraAddingChanges> {
540
586
) as InfraLambdaUpdate [ ] ;
541
587
542
588
const rolesToRemove = await rolesToRemovePromise ;
543
- let rolesToRemoveFiltered = rolesToRemove . filter ( ( r ) => r ) as string [ ] ;
544
-
545
- // Filter out roles that are being added to avoid conflicts
546
- rolesToRemoveFiltered = rolesToRemoveFiltered . filter (
547
- ( r ) => ! rolesToAdd . includes ( r ) ,
548
- ) ;
589
+ const rolesToRemoveFiltered = rolesToRemove . filter ( ( r ) => r ) as string [ ] ;
549
590
550
591
return {
551
592
deployLayer : ! existingLayer ,
@@ -562,7 +603,7 @@ async function getInfraChangesForAdding(): Promise<InfraAddingChanges> {
562
603
* @param func - Lambda function properties
563
604
* @returns Lambda update configuration or undefined if no update needed
564
605
*/
565
- async function analyzeRemoveLambda ( functionName : string ) {
606
+ async function analyzeLambdaRemove ( functionName : string ) {
566
607
try {
567
608
const {
568
609
environmentVariables,
@@ -601,8 +642,8 @@ async function analyzeRemoveLambda(functionName: string) {
601
642
}
602
643
603
644
Logger . verbose (
604
- `[Function ${ functionName } ] ${ needToRemoveEnvironmentVariables ? 'Removing environment variables' : 'No environment variables to remove' } . Existing environment variables: ` ,
605
- JSON . stringify ( ddlEnvironmentVariables , null , 2 ) ,
645
+ `[Function ${ functionName } ] ${ needToRemoveEnvironmentVariables ? 'Environment variables needed to be removed ' : 'No environment variables to remove' } . Existing environment variables: ` +
646
+ JSON . stringify ( environmentVariables , null , 2 ) ,
606
647
) ;
607
648
608
649
const needToRemove = needToRemoveLayer || needToRemoveEnvironmentVariables ;
@@ -661,15 +702,24 @@ async function getInfraChangesForRemoving(): Promise<InfraRemovalChanges> {
661
702
662
703
const lambdasToRemovePromise = Promise . all (
663
704
allLambdas . map ( async ( func ) => {
664
- return analyzeRemoveLambda ( func . functionName ) ;
705
+ return analyzeLambdaRemove ( func . functionName ) ;
665
706
} ) ,
666
707
) ;
667
708
668
- const rolesToRemovePromise = Promise . all (
709
+ // Get all role names for lambdas to remove, ensure uniqueness, then analyze
710
+ const roleNamesToRemoveSet = new Set < string > ( ) ;
711
+ await Promise . all (
669
712
allLambdas . map ( async ( func ) => {
670
- const roleRemoval = await analyzeRemovePolicyFromLambdaRole (
671
- func . functionName ,
672
- ) ;
713
+ const roleName = await getRoleNameFromFunction ( func . functionName ) ;
714
+ roleNamesToRemoveSet . add ( roleName ) ;
715
+ } ) ,
716
+ ) ;
717
+
718
+ const roleNamesToRemove = Array . from ( roleNamesToRemoveSet ) ;
719
+
720
+ const rolesToRemovePromise = Promise . all (
721
+ roleNamesToRemove . map ( async ( roleName ) => {
722
+ const roleRemoval = await analyzeRoleRemove ( roleName ) ;
673
723
return roleRemoval . needToRemovePolicy ? roleRemoval . roleName : undefined ;
674
724
} ) ,
675
725
) ;
@@ -849,11 +899,11 @@ async function analyzeLambdaAdd(
849
899
timeout : Math . max ( initialTimeout , 300 ) ,
850
900
} ;
851
901
} else {
852
- let needToUpdate : boolean = false ;
902
+ let needToUpdateLayer : boolean = false ;
853
903
854
904
// check if layer is already attached
855
905
if ( ! ddlLayerArns ?. find ( ( arn ) => arn === existingLayerVersionArn ) ) {
856
- needToUpdate = true ;
906
+ needToUpdateLayer = true ;
857
907
Logger . verbose (
858
908
`[Function ${ functionName } ] Layer not attached to the function` ,
859
909
) ;
@@ -865,10 +915,10 @@ async function analyzeLambdaAdd(
865
915
866
916
// check if layers with the wrong version are attached
867
917
if (
868
- ! needToUpdate &&
918
+ ! needToUpdateLayer &&
869
919
ddlLayerArns . find ( ( arn ) => arn !== existingLayerVersionArn )
870
920
) {
871
- needToUpdate = true ;
921
+ needToUpdateLayer = true ;
872
922
Logger . verbose (
873
923
`[Function ${ functionName } ] Layer with the wrong version attached to the function` ,
874
924
) ;
@@ -893,18 +943,21 @@ async function analyzeLambdaAdd(
893
943
initialExecWrapper,
894
944
} ) ;
895
945
946
+ let needToUpdateEnvironmentVariables = false ;
947
+
896
948
// check if environment variables are already set for each property
897
949
for ( const [ key , value ] of Object . entries ( ddlEnvironmentVariables ) ) {
898
950
if ( ! environmentVariables || environmentVariables [ key ] !== value ) {
899
- needToUpdate = true ;
900
- Logger . verbose (
901
- `[Function ${ functionName } ] Need to update environment variables` ,
902
- ) ;
951
+ needToUpdateEnvironmentVariables = true ;
903
952
break ;
904
953
}
905
954
}
955
+ Logger . verbose (
956
+ `[Function ${ functionName } ] ${ needToUpdateEnvironmentVariables ? 'Need to update environment variables' : 'No need to update environment variables' } . Existing environment variables: ` +
957
+ JSON . stringify ( environmentVariables , null , 2 ) ,
958
+ ) ;
906
959
907
- return needToUpdate
960
+ return needToUpdateLayer || needToUpdateEnvironmentVariables
908
961
? {
909
962
functionName,
910
963
layers : [ existingLayerVersionArn , ...otherLayerArns ] ,
@@ -940,59 +993,41 @@ async function addPolicyToRole(roleName: string) {
940
993
941
994
/**
942
995
* Prepare the Lambda role for the update
943
- * @param functionName
996
+ * @param roleName
944
997
* @returns
945
998
*/
946
- async function analyzeLambdaRoleAdd ( functionName : string ) {
947
- Logger . verbose (
948
- `[Function ${ functionName } ] Analyzing role for policy attachment` ,
949
- ) ;
950
-
951
- const getFunctionResponse = await getLambdaClient ( ) . send (
952
- new GetFunctionCommand ( {
953
- FunctionName : functionName ,
954
- } ) ,
955
- ) ;
956
- const roleArn = getFunctionResponse . Configuration ?. Role ;
957
- if ( ! roleArn ) {
958
- throw new Error (
959
- `[Function ${ functionName } ] Failed to retrieve the role ARN.` ,
960
- ) ;
961
- }
962
-
963
- // Extract the role name from the role ARN
964
- const roleName = roleArn . split ( '/' ) . pop ( ) ;
965
-
966
- if ( ! roleName ) {
967
- throw new Error (
968
- `[Function ${ functionName } ] Failed to extract role name from role ARN: ${ roleArn } .` ,
969
- ) ;
970
- }
971
-
972
- Logger . verbose ( `[Function ${ functionName } ] Found role: ${ roleName } ` ) ;
999
+ async function analyzeRoleAdd ( roleName : string ) {
1000
+ try {
1001
+ Logger . verbose ( `[Role ${ roleName } ] Analyzing role for policy attachment` ) ;
973
1002
974
- const existingPolicy = await createPolicyDocument ( roleName ) ;
1003
+ const existingPolicy = await createPolicyDocument ( roleName ) ;
975
1004
976
- let addPolicy : boolean = true ;
1005
+ let addPolicy : boolean = true ;
977
1006
978
- // compare existing policy with the new one
979
- if ( existingPolicy ) {
980
- if ( JSON . stringify ( existingPolicy ) === JSON . stringify ( policyDocument ) ) {
981
- Logger . verbose (
982
- `[Function ${ functionName } ] Policy already attached to the role ${ roleName } ` ,
983
- ) ;
984
- addPolicy = false ;
1007
+ // compare existing policy with the new one
1008
+ if ( existingPolicy ) {
1009
+ if ( JSON . stringify ( existingPolicy ) === JSON . stringify ( policyDocument ) ) {
1010
+ Logger . verbose (
1011
+ `[Role ${ roleName } ] Policy already attached to the role` ,
1012
+ ) ;
1013
+ addPolicy = false ;
1014
+ } else {
1015
+ Logger . verbose (
1016
+ `[Role ${ roleName } ] Different policy found on role, will update` ,
1017
+ ) ;
1018
+ }
985
1019
} else {
986
- Logger . verbose (
987
- `[Function ${ functionName } ] Different policy found on role ${ roleName } , will update` ,
988
- ) ;
1020
+ Logger . verbose ( `[Role ${ roleName } ] No policy found on role, will attach` ) ;
989
1021
}
990
- } else {
991
- Logger . verbose (
992
- `[Function ${ functionName } ] No policy found on role ${ roleName } , will attach` ,
1022
+ return { addPolicy, roleName } ;
1023
+ } catch ( error : any ) {
1024
+ throw new Error (
1025
+ `Failed to analyze role ${ roleName } for policy attachment.` ,
1026
+ {
1027
+ cause : error ,
1028
+ } ,
993
1029
) ;
994
1030
}
995
- return { addPolicy, roleName } ;
996
1031
}
997
1032
998
1033
/**
0 commit comments