From 3d3f2df41f98a0f63216f9f2c32d9eda27dbfb89 Mon Sep 17 00:00:00 2001 From: Yiming Luo Date: Wed, 18 Sep 2024 14:09:56 -0400 Subject: [PATCH] Update documentation for xfn->Lambda context injection --- .../stepfunctions/__tests__/helpers.test.ts | 18 ++++++------- src/commands/stepfunctions/helpers.ts | 25 +++++++++++++++---- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/commands/stepfunctions/__tests__/helpers.test.ts b/src/commands/stepfunctions/__tests__/helpers.test.ts index 2342cf9b4..69e74f5da 100644 --- a/src/commands/stepfunctions/__tests__/helpers.test.ts +++ b/src/commands/stepfunctions/__tests__/helpers.test.ts @@ -31,7 +31,7 @@ const createMockContext = (): BaseContext => { describe('stepfunctions command helpers tests', () => { const context = createMockContext() describe('injectContextForLambdaFunctions test', () => { - test('already has JsonMerge added to payload field', () => { + test('Case 4.2: already has JsonMerge added to payload field', () => { const step: StepType = { Type: 'Task', Resource: 'arn:aws:states:::lambda:invoke', @@ -44,7 +44,7 @@ describe('stepfunctions command helpers tests', () => { expect(injectContextForLambdaFunctions(step, context, 'Lambda Invoke')).toBeFalsy() }) - test('no payload field', () => { + test('Case 1: no Payload or Payload.$', () => { const step: StepType = { Type: 'Task', Resource: 'arn:aws:states:::lambda:invoke', @@ -57,7 +57,7 @@ describe('stepfunctions command helpers tests', () => { expect(step.Parameters?.['Payload.$']).toEqual(`$$['Execution', 'State', 'StateMachine']`) }) - test('payload is not a JSON object', () => { + test('Case 3: Payload is not a JSON object', () => { const step: StepType = { Type: 'Task', Resource: 'arn:aws:states:::lambda:invoke', @@ -70,7 +70,7 @@ describe('stepfunctions command helpers tests', () => { expect(injectContextForLambdaFunctions(step, context, 'Lambda Invoke')).toBeFalsy() }) - test('already injected Execution and State into Payload', () => { + test('Case 2.1: already injected Execution, State and StateMachine into Payload', () => { const step: StepType = { Type: 'Task', Resource: 'arn:aws:states:::lambda:invoke', @@ -87,7 +87,7 @@ describe('stepfunctions command helpers tests', () => { expect(injectContextForLambdaFunctions(step, context, 'Lambda Invoke')).toBeFalsy() }) - test('custom State field in Payload', () => { + test('Case 2.2: custom State field in Payload', () => { const step: StepType = { Type: 'Task', Resource: 'arn:aws:states:::lambda:invoke', @@ -102,7 +102,7 @@ describe('stepfunctions command helpers tests', () => { expect(injectContextForLambdaFunctions(step, context, 'Lambda Invoke')).toBeFalsy() }) - test('no Execution, State, or StateMachine field in Payload', () => { + test('Case 2.3: no Execution, State, or StateMachine field in Payload', () => { const step: StepType = { Type: 'Task', Resource: 'arn:aws:states:::lambda:invoke', @@ -119,7 +119,7 @@ describe('stepfunctions command helpers tests', () => { expect(payload['StateMachine.$']).toEqual('$$.StateMachine') }) - test('default payload field of $', () => { + test('Case 4.1: default payload field of $', () => { const step: StepType = { Type: 'Task', Resource: 'arn:aws:states:::lambda:invoke', @@ -133,7 +133,7 @@ describe('stepfunctions command helpers tests', () => { expect(step.Parameters?.['Payload.$']).toEqual('States.JsonMerge($$, $, false)') }) - test('custom payload field not using JsonPath expression', () => { + test('Case 4.3: custom payload field not using JsonPath expression', () => { const step: StepType = { Type: 'Task', Resource: 'arn:aws:states:::lambda:invoke', @@ -146,7 +146,7 @@ describe('stepfunctions command helpers tests', () => { expect(injectContextForLambdaFunctions(step, context, 'Lambda Invoke')).toBeFalsy() }) - test('custom payload field using JsonPath expression', () => { + test('Case 4.3: custom payload field using JsonPath expression', () => { const step: StepType = { Type: 'Task', Resource: 'arn:aws:states:::lambda:invoke', diff --git a/src/commands/stepfunctions/helpers.ts b/src/commands/stepfunctions/helpers.ts index 28ea10be0..f52c2b956 100644 --- a/src/commands/stepfunctions/helpers.ts +++ b/src/commands/stepfunctions/helpers.ts @@ -214,6 +214,17 @@ export type ParametersType = { } } +// Truth table +// Case | Input | Expected +// -----|----------------------------------------------------------|--------- +// 1 | No "Payload" or "Payload.$" | true +// 2.1 | "Payload" is object, already injected | false +// 2.2 | "Payload" object has Execution, State or StateMachine | false +// 2.3 | "Payload" object has no Execution, State or StateMachine | true +// 3 | "Payload" is not object | false +// 4.1 | "Payload.$": "$" (default payload) | true +// 4.2 | "Payload.$": "States.JsonMerge($$, $, false)" | false +// 4.3 | Custom "Payload.$" | false export const injectContextForLambdaFunctions = (step: StepType, context: BaseContext, stepName: string): boolean => { if (step.Resource?.startsWith('arn:aws:lambda')) { context.stdout.write( @@ -239,7 +250,7 @@ check out https://docs.datadoghq.com/serverless/step_functions/troubleshooting/\ return false } - // payload field not set + // Case 1: payload field not set if (!step.Parameters.hasOwnProperty('Payload.$') && !step.Parameters.hasOwnProperty('Payload')) { step.Parameters[`Payload.$`] = `$$['Execution', 'State', 'StateMachine']` @@ -248,7 +259,7 @@ check out https://docs.datadoghq.com/serverless/step_functions/troubleshooting/\ if (step.Parameters.hasOwnProperty('Payload')) { if (typeof step.Parameters['Payload'] !== 'object') { - // payload is not a JSON object + // Case 3: payload is not a JSON object context.stdout .write(`[Warn] Step ${stepName}'s Payload field is not a JSON object. Step Functions Context Object \ injection skipped. Your Step Functions trace will not be merged with downstream Lambda traces. To manually \ @@ -256,12 +267,14 @@ merge these traces, check out https://docs.datadoghq.com/serverless/step_functio return false } else { + // Case 2: payload is not a JSON object const payload = step.Parameters.Payload if ( payload['Execution.$'] === '$$.Execution' && payload['State.$'] === '$$.State' && payload['StateMachine.$'] === '$$.StateMachine' ) { + // Case 2.1: already injected into "Payload" context.stdout.write(`Step ${stepName}: Context injection is already set up. Skipping context injection.\n`) return false @@ -273,6 +286,7 @@ merge these traces, check out https://docs.datadoghq.com/serverless/step_functio payload.hasOwnProperty('StateMachine.$') || payload.hasOwnProperty('StateMachine') ) { + // Case 2.2: "Payload" object has Execution, State or StateMachine context.stdout .write(`[Warn] Step ${stepName} may be using custom Execution, State or StateMachine field. Step Functions Context Object \ injection skipped. Your Step Functions trace will not be merged with downstream Lambda traces. To manually \ @@ -280,6 +294,7 @@ merge these traces, check out https://docs.datadoghq.com/serverless/step_functio return false } else { + // Case 2.3: "Payload" object has no Execution, State or StateMachine payload['Execution.$'] = '$$.Execution' payload['State.$'] = '$$.State' payload['StateMachine.$'] = '$$.StateMachine' @@ -289,21 +304,21 @@ merge these traces, check out https://docs.datadoghq.com/serverless/step_functio } } - // default payload + // Case 4.1: default payload if (step.Parameters['Payload.$'] === '$') { step.Parameters[`Payload.$`] = 'States.JsonMerge($$, $, false)' return true } - // context injection is already set up + // Case 4.2: context injection is already set up using "Payload.$" if (step.Parameters['Payload.$'] === 'States.JsonMerge($$, $, false)') { context.stdout.write(` Step ${stepName}: Context injection is already set up. Skipping context injection.\n`) return false } - // custom payload + // Case 4.3: custom "Payload.$" context.stdout .write(`[Warn] Step ${stepName} has a custom Payload field. Step Functions Context Object injection skipped. \ Your Step Functions trace will not be merged with downstream Lambda traces. To manually merge these traces, \