@@ -303,15 +303,13 @@ async function deleteLayerVersion(
303303}
304304
305305/**
306- * Check if policy needs to be removed from the Lambda role
306+ * Get the role name from a Lambda function
307307 * @param functionName
308- * @returns
308+ * @returns role name
309309 */
310- async function analyzeRemovePolicyFromLambdaRole ( functionName : string ) {
310+ async function getRoleNameFromFunction ( functionName : string ) : Promise < string > {
311311 try {
312- Logger . verbose (
313- `[Function ${ functionName } ] Analyzing policy removal from Lambda role` ,
314- ) ;
312+ Logger . verbose ( `[Function ${ functionName } ] Getting role from function` ) ;
315313
316314 const getFunctionResponse = await getLambdaClient ( ) . send (
317315 new GetFunctionCommand ( {
@@ -325,6 +323,7 @@ async function analyzeRemovePolicyFromLambdaRole(functionName: string) {
325323 ) ;
326324 }
327325
326+ // Extract the role name from the role ARN
328327 const roleName = roleArn . split ( '/' ) . pop ( ) ;
329328
330329 if ( ! roleName ) {
@@ -334,23 +333,40 @@ async function analyzeRemovePolicyFromLambdaRole(functionName: string) {
334333 }
335334
336335 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+ ) ;
337354
338355 const existingPolicy = await createPolicyDocument ( roleName ) ;
339356
340357 const needToRemovePolicy = ! ! existingPolicy ;
341358 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 } ` ,
343360 ) ;
344361
345362 return {
346363 needToRemovePolicy,
347364 roleName,
348365 } ;
349366 } 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+ } ) ;
354370 }
355371}
356372
@@ -502,24 +518,54 @@ async function getInfraChangesForAdding(): Promise<InfraAddingChanges> {
502518 } ) ,
503519 ) ;
504520
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 (
506530 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 ) ;
509533 } ) ,
510534 ) ;
511535
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 (
513539 configLambdasRemove . map ( async ( func ) => {
514- return analyzeRemoveLambda ( func . functionName ) ;
540+ const roleName = await getRoleNameFromFunction ( func . functionName ) ;
541+ roleNamesToRemoveSet . add ( roleName ) ;
515542 } ) ,
516543 ) ;
517544
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+
518566 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 ) ;
523569 return roleRemoval . needToRemovePolicy ? roleRemoval . roleName : undefined ;
524570 } ) ,
525571 ) ;
@@ -540,12 +586,7 @@ async function getInfraChangesForAdding(): Promise<InfraAddingChanges> {
540586 ) as InfraLambdaUpdate [ ] ;
541587
542588 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 [ ] ;
549590
550591 return {
551592 deployLayer : ! existingLayer ,
@@ -562,7 +603,7 @@ async function getInfraChangesForAdding(): Promise<InfraAddingChanges> {
562603 * @param func - Lambda function properties
563604 * @returns Lambda update configuration or undefined if no update needed
564605 */
565- async function analyzeRemoveLambda ( functionName : string ) {
606+ async function analyzeLambdaRemove ( functionName : string ) {
566607 try {
567608 const {
568609 environmentVariables,
@@ -601,8 +642,8 @@ async function analyzeRemoveLambda(functionName: string) {
601642 }
602643
603644 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 ) ,
606647 ) ;
607648
608649 const needToRemove = needToRemoveLayer || needToRemoveEnvironmentVariables ;
@@ -661,15 +702,24 @@ async function getInfraChangesForRemoving(): Promise<InfraRemovalChanges> {
661702
662703 const lambdasToRemovePromise = Promise . all (
663704 allLambdas . map ( async ( func ) => {
664- return analyzeRemoveLambda ( func . functionName ) ;
705+ return analyzeLambdaRemove ( func . functionName ) ;
665706 } ) ,
666707 ) ;
667708
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 (
669712 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 ) ;
673723 return roleRemoval . needToRemovePolicy ? roleRemoval . roleName : undefined ;
674724 } ) ,
675725 ) ;
@@ -849,11 +899,11 @@ async function analyzeLambdaAdd(
849899 timeout : Math . max ( initialTimeout , 300 ) ,
850900 } ;
851901 } else {
852- let needToUpdate : boolean = false ;
902+ let needToUpdateLayer : boolean = false ;
853903
854904 // check if layer is already attached
855905 if ( ! ddlLayerArns ?. find ( ( arn ) => arn === existingLayerVersionArn ) ) {
856- needToUpdate = true ;
906+ needToUpdateLayer = true ;
857907 Logger . verbose (
858908 `[Function ${ functionName } ] Layer not attached to the function` ,
859909 ) ;
@@ -865,10 +915,10 @@ async function analyzeLambdaAdd(
865915
866916 // check if layers with the wrong version are attached
867917 if (
868- ! needToUpdate &&
918+ ! needToUpdateLayer &&
869919 ddlLayerArns . find ( ( arn ) => arn !== existingLayerVersionArn )
870920 ) {
871- needToUpdate = true ;
921+ needToUpdateLayer = true ;
872922 Logger . verbose (
873923 `[Function ${ functionName } ] Layer with the wrong version attached to the function` ,
874924 ) ;
@@ -893,18 +943,21 @@ async function analyzeLambdaAdd(
893943 initialExecWrapper,
894944 } ) ;
895945
946+ let needToUpdateEnvironmentVariables = false ;
947+
896948 // check if environment variables are already set for each property
897949 for ( const [ key , value ] of Object . entries ( ddlEnvironmentVariables ) ) {
898950 if ( ! environmentVariables || environmentVariables [ key ] !== value ) {
899- needToUpdate = true ;
900- Logger . verbose (
901- `[Function ${ functionName } ] Need to update environment variables` ,
902- ) ;
951+ needToUpdateEnvironmentVariables = true ;
903952 break ;
904953 }
905954 }
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+ ) ;
906959
907- return needToUpdate
960+ return needToUpdateLayer || needToUpdateEnvironmentVariables
908961 ? {
909962 functionName,
910963 layers : [ existingLayerVersionArn , ...otherLayerArns ] ,
@@ -940,59 +993,41 @@ async function addPolicyToRole(roleName: string) {
940993
941994/**
942995 * Prepare the Lambda role for the update
943- * @param functionName
996+ * @param roleName
944997 * @returns
945998 */
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` ) ;
9731002
974- const existingPolicy = await createPolicyDocument ( roleName ) ;
1003+ const existingPolicy = await createPolicyDocument ( roleName ) ;
9751004
976- let addPolicy : boolean = true ;
1005+ let addPolicy : boolean = true ;
9771006
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+ }
9851019 } 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` ) ;
9891021 }
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+ } ,
9931029 ) ;
9941030 }
995- return { addPolicy, roleName } ;
9961031}
9971032
9981033/**
0 commit comments