Skip to content

Commit d56c8b9

Browse files
fix: Optimization
1 parent 9e593ce commit d56c8b9

File tree

1 file changed

+122
-87
lines changed

1 file changed

+122
-87
lines changed

src/infraDeploy.ts

Lines changed: 122 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)