Skip to content

Commit

Permalink
feat: update all cache behavior that has Fingerprint pro association
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergey Shelomentsev committed Feb 12, 2024
1 parent 6e36986 commit 3f12e31
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 34 deletions.
3 changes: 2 additions & 1 deletion mgmt-lambda/DefaultSettings.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export const defaults = {
AWS_REGION: 'us-east-1',
LAMBDA_DISTRIBUTION_BUCKET: 'fingerprint-pro-cloudfront-integration-lambda-function',
LAMBDA_DISTRIBUTION_BUCKET_KEY: 'release/lambda_latest.zip',
LAMBDA_DISTRIBUTION_BUCKET_KEY: 'releaseV2/lambda_latest.zip',
LAMBDA_HANDLER_NAME: 'fingerprintjs-pro-cloudfront-lambda-function.handler',
FP_CDN_URL: 'fpcdn.io',
}
1 change: 1 addition & 0 deletions mgmt-lambda/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export async function handler(
try {
return await handleUpdate(lambdaClient, cloudFrontClient, deploymentSettings)
} catch (e: any) {
console.error(e)
return handleError(e)
}
}
Expand Down
92 changes: 70 additions & 22 deletions mgmt-lambda/handlers/updateHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export async function handleUpdate(
settings: DeploymentSettings,
): Promise<APIGatewayProxyResult> {
console.info(`Going to upgrade Fingerprint Pro function association at CloudFront distribution.`)
console.info(`Settings: ${settings}`)
console.info(`Settings: ${JSON.stringify(settings)}`)

const isLambdaFunctionExist = await checkIfLambdaFunctionWithNameExists(lambdaClient, settings.LambdaFunctionName)
if (!isLambdaFunctionExist) {
Expand Down Expand Up @@ -71,20 +71,67 @@ async function updateCloudFrontConfig(
throw new ApiException(ErrorCode.CloudFrontDistributionNotFound)
}

const cacheBehaviors = cfConfig.DistributionConfig.CacheBehaviors
const fpCbs = cacheBehaviors?.Items?.filter((it) => it.TargetOriginId === 'fpcdn.io')
if (!fpCbs || fpCbs?.length === 0) {
const distributionConfig = cfConfig.DistributionConfig

let fpCacheBehaviorsFound = 0
let fpCacheBehaviorsUpdated = 0
const pathPatterns = []

if (distributionConfig.DefaultCacheBehavior?.TargetOriginId === defaults.FP_CDN_URL) {
fpCacheBehaviorsFound++
const lambdas = distributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations?.Items?.filter(
(it) => it && it.EventType === 'origin-request' && it.LambdaFunctionARN?.includes(`${lambdaFunctionName}:`),

Check warning on line 83 in mgmt-lambda/handlers/updateHandler.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

Check warning on line 83 in mgmt-lambda/handlers/updateHandler.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch

Check warning on line 83 in mgmt-lambda/handlers/updateHandler.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch

Check warning on line 83 in mgmt-lambda/handlers/updateHandler.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch

Check warning on line 83 in mgmt-lambda/handlers/updateHandler.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🕹️ Function is not covered

Warning! Not covered function
)
if (lambdas?.length === 1) {
lambdas[0].LambdaFunctionARN = latestFunctionArn

Check warning on line 86 in mgmt-lambda/handlers/updateHandler.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
fpCacheBehaviorsUpdated++

Check warning on line 87 in mgmt-lambda/handlers/updateHandler.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
pathPatterns.push('/*')

Check warning on line 88 in mgmt-lambda/handlers/updateHandler.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
console.info('Updated Fingerprint Pro Lambda@Edge function association in the default cache behavior')

Check warning on line 89 in mgmt-lambda/handlers/updateHandler.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
} else {
console.info(
'The default cache behavior has targeted to FP CDN, but has no Fingerprint Pro Lambda@Edge association',
)
}

Check warning on line 94 in mgmt-lambda/handlers/updateHandler.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch
}

const fpCbs = distributionConfig.CacheBehaviors?.Items?.filter((it) => it.TargetOriginId === defaults.FP_CDN_URL)
if (fpCbs && fpCbs?.length > 0) {
fpCacheBehaviorsFound += fpCbs.length
fpCbs.forEach((cacheBehavior) => {
const lambdas = cacheBehavior.LambdaFunctionAssociations?.Items?.filter(
(it) => it && it.EventType === 'origin-request' && it.LambdaFunctionARN?.includes(`${lambdaFunctionName}:`),
)
if (lambdas?.length === 1) {
lambdas[0].LambdaFunctionARN = latestFunctionArn
fpCacheBehaviorsUpdated++
if (cacheBehavior.PathPattern) {
let pathPattern = cacheBehavior.PathPattern
if (!cacheBehavior.PathPattern.startsWith('/')) {
pathPattern = '/' + pathPattern
}
pathPatterns.push(pathPattern)
} else {
console.error(`Path pattern is not defined for cache behavior ${JSON.stringify(cacheBehavior)}`)
}
} else {
console.info(
`Cache behavior ${JSON.stringify(
cacheBehavior,
)} has targeted to FP CDN, but has no Fingerprint Pro Lambda@Edge association`,
)
}
})
}

if (fpCacheBehaviorsFound === 0) {
throw new ApiException(ErrorCode.CacheBehaviorNotFound)
}
const cacheBehavior = fpCbs[0]
const lambdas = cacheBehavior.LambdaFunctionAssociations?.Items?.filter(
(it) => it && it.EventType === 'origin-request' && it.LambdaFunctionARN?.includes(`${lambdaFunctionName}:`),
)
if (!lambdas || lambdas?.length === 0) {
if (fpCacheBehaviorsUpdated === 0) {
throw new ApiException(ErrorCode.LambdaFunctionAssociationNotFound)
}
const lambda = lambdas[0]
lambda.LambdaFunctionARN = latestFunctionArn
if (pathPatterns.length === 0) {
throw new ApiException(ErrorCode.CacheBehaviorPatternNotDefined)
}

const updateParams: UpdateDistributionCommandInput = {
DistributionConfig: cfConfig.DistributionConfig,
Expand All @@ -97,21 +144,20 @@ async function updateCloudFrontConfig(
console.info(`CloudFront update has finished, ${JSON.stringify(updateCFResult)}`)

console.info('Going to invalidate routes for upgraded cache behavior')
if (!cacheBehavior.PathPattern) {
throw new ApiException(ErrorCode.CacheBehaviorPatternNotDefined)
}

let pathPattern = cacheBehavior.PathPattern
if (!pathPattern.startsWith('/')) {
pathPattern = '/' + pathPattern
}
invalidateFingerprintIntegrationCache(cloudFrontClient, cloudFrontDistributionId, pathPatterns)
}

async function invalidateFingerprintIntegrationCache(
cloudFrontClient: CloudFrontClient,
distributionId: string,
pathPatterns: string[],
) {
const invalidationParams: CreateInvalidationCommandInput = {
DistributionId: cloudFrontDistributionId,
DistributionId: distributionId,
InvalidationBatch: {
Paths: {
Quantity: 1,
Items: [pathPattern],
Items: pathPatterns,
},
CallerReference: 'fingerprint-pro-management-lambda-function',
},
Expand All @@ -133,9 +179,11 @@ async function updateLambdaFunctionCode(lambdaClient: LambdaClient, functionName
FunctionName: functionName,
Publish: true,
})
console.info('Sending update command to Lambda runtime')
console.info(`Sending update command to Lambda runtime with data ${JSON.stringify(command)}`)
const result = await lambdaClient.send(command)

console.info(`Got update command result: ${JSON.stringify(result)}`)

if (!result) {
throw new ApiException(ErrorCode.LambdaFunctionARNNotFound)
}
Expand Down
10 changes: 5 additions & 5 deletions mgmt-lambda/test/app.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ describe('Update endpoint', () => {
lambdaMock
.on(UpdateFunctionCodeCommand, {
S3Bucket: 'fingerprint-pro-cloudfront-integration-lambda-function',
S3Key: 'release/lambda_latest.zip',
S3Key: 'releaseV2/lambda_latest.zip',
FunctionName: 'arn:aws:lambda:us-east-1:1234567890:function:fingerprint-pro-lambda-function',
Publish: true,
})
Expand Down Expand Up @@ -363,7 +363,7 @@ describe('Update endpoint', () => {
lambdaMock
.on(UpdateFunctionCodeCommand, {
S3Bucket: 'fingerprint-pro-cloudfront-integration-lambda-function',
S3Key: 'release/lambda_latest.zip',
S3Key: 'releaseV2/lambda_latest.zip',
FunctionName: 'incorrect',
Publish: true,
})
Expand Down Expand Up @@ -444,7 +444,7 @@ describe('Update endpoint', () => {
lambdaMock
.on(UpdateFunctionCodeCommand, {
S3Bucket: 'fingerprint-pro-cloudfront-integration-lambda-function',
S3Key: 'release/lambda_latest.zip',
S3Key: 'releaseV2/lambda_latest.zip',
FunctionName: 'arn:aws:lambda:us-east-1:1234567890:function:fingerprint-pro-lambda-function',
Publish: true,
})
Expand Down Expand Up @@ -486,7 +486,7 @@ describe('Update endpoint', () => {
lambdaMock
.on(UpdateFunctionCodeCommand, {
S3Bucket: 'fingerprint-pro-cloudfront-integration-lambda-function',
S3Key: 'release/lambda_latest.zip',
S3Key: 'releaseV2/lambda_latest.zip',
FunctionName: 'arn:aws:lambda:us-east-1:1234567890:function:fingerprint-pro-lambda-function',
Publish: true,
})
Expand Down Expand Up @@ -554,7 +554,7 @@ describe('Update endpoint', () => {
lambdaMock
.on(UpdateFunctionCodeCommand, {
S3Bucket: 'fingerprint-pro-cloudfront-integration-lambda-function',
S3Key: 'release/lambda_latest.zip',
S3Key: 'releaseV2/lambda_latest.zip',
FunctionName: 'arn:aws:lambda:us-east-1:1234567890:function:fingerprint-pro-lambda-function',
Publish: true,
})
Expand Down
12 changes: 6 additions & 6 deletions mgmt-lambda/test/handlers/handleUpdate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ describe('Handle mgmt-update', () => {
lambdaMock
.on(UpdateFunctionCodeCommand, {
S3Bucket: 'fingerprint-pro-cloudfront-integration-lambda-function',
S3Key: 'release/lambda_latest.zip',
S3Key: 'releaseV2/lambda_latest.zip',
FunctionName: 'fingerprint-pro-lambda-function',
Publish: true,
})
Expand Down Expand Up @@ -224,7 +224,7 @@ describe('Handle mgmt-update', () => {
lambdaMock
.on(UpdateFunctionCodeCommand, {
S3Bucket: 'fingerprint-pro-cloudfront-integration-lambda-function',
S3Key: 'release/lambda_latest.zip',
S3Key: 'releaseV2/lambda_latest.zip',
FunctionName: 'fingerprint-pro-lambda-function',
Publish: true,
})
Expand Down Expand Up @@ -303,7 +303,7 @@ describe('Handle mgmt-update', () => {
lambdaMock
.on(UpdateFunctionCodeCommand, {
S3Bucket: 'fingerprint-pro-cloudfront-integration-lambda-function',
S3Key: 'release/lambda_latest.zip',
S3Key: 'releaseV2/lambda_latest.zip',
FunctionName: 'fingerprint-pro-lambda-function',
Publish: true,
})
Expand Down Expand Up @@ -400,7 +400,7 @@ describe('Handle mgmt-update', () => {
lambdaMock
.on(UpdateFunctionCodeCommand, {
S3Bucket: 'fingerprint-pro-cloudfront-integration-lambda-function',
S3Key: 'release/lambda_latest.zip',
S3Key: 'releaseV2/lambda_latest.zip',
FunctionName: 'fingerprint-pro-lambda-function',
Publish: true,
})
Expand Down Expand Up @@ -433,7 +433,7 @@ describe('Handle mgmt-update', () => {
lambdaMock
.on(UpdateFunctionCodeCommand, {
S3Bucket: 'fingerprint-pro-cloudfront-integration-lambda-function',
S3Key: 'release/lambda_latest.zip',
S3Key: 'releaseV2/lambda_latest.zip',
FunctionName: 'fingerprint-pro-lambda-function',
Publish: true,
})
Expand Down Expand Up @@ -496,7 +496,7 @@ describe('Handle mgmt-update', () => {
lambdaMock
.on(UpdateFunctionCodeCommand, {
S3Bucket: 'fingerprint-pro-cloudfront-integration-lambda-function',
S3Key: 'release/lambda_latest.zip',
S3Key: 'releaseV2/lambda_latest.zip',
FunctionName: 'fingerprint-pro-lambda-function',
Publish: true,
})
Expand Down

0 comments on commit 3f12e31

Please sign in to comment.