From 5a2a405db375ee0d97c813ab5e17dad634bdcc4d Mon Sep 17 00:00:00 2001 From: Konosuke Kachi Date: Sun, 9 Oct 2022 14:37:39 +0900 Subject: [PATCH 1/8] refactor --- packages/@aws-cdk/aws-stepfunctions/lib/fields.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-stepfunctions/lib/fields.ts b/packages/@aws-cdk/aws-stepfunctions/lib/fields.ts index e78c026293798..b7fccd1979aed 100644 --- a/packages/@aws-cdk/aws-stepfunctions/lib/fields.ts +++ b/packages/@aws-cdk/aws-stepfunctions/lib/fields.ts @@ -298,14 +298,23 @@ export class FieldUtils { } function validateJsonPath(path: string) { + const intrinsicFunctionNames = [ + 'Format', + 'StringToJson', + 'JsonToString', + 'Array', + ]; + const intrinsicFunctionFullNames = intrinsicFunctionNames.map((fn) => `States.${fn}`); if (path !== '$' && !path.startsWith('$.') && path !== '$$' && !path.startsWith('$$.') && !path.startsWith('$[') - && ['Format', 'StringToJson', 'JsonToString', 'Array'].every(fn => !path.startsWith(`States.${fn}`)) + && intrinsicFunctionFullNames.every(fn => !path.startsWith(fn)) ) { - throw new Error(`JSON path values must be exactly '$', '$$', start with '$.', start with '$$.', start with '$[', or start with an intrinsic function: States.Format, States.StringToJson, States.JsonToString, or States.Array. Received: ${path}`); + const lastItem = intrinsicFunctionFullNames.pop(); + const intrinsicFunctionsStr = intrinsicFunctionFullNames.join(', ') + ', or ' + lastItem; + throw new Error(`JSON path values must be exactly '$', '$$', start with '$.', start with '$$.', start with '$[', or start with an intrinsic function: ${intrinsicFunctionsStr}. Received: ${path}`); } } From 09421acd1cb95e0f458253423000dd67b147853f Mon Sep 17 00:00:00 2001 From: Konosuke Kachi Date: Sun, 9 Oct 2022 18:08:56 +0900 Subject: [PATCH 2/8] Add missing intrinsic functions --- .../@aws-cdk/aws-stepfunctions/lib/fields.ts | 181 +++++++++++++++- .../lib/private/json-path.ts | 19 +- .../aws-stepfunctions/test/fields.test.ts | 196 +++++++++++++++++- 3 files changed, 385 insertions(+), 11 deletions(-) diff --git a/packages/@aws-cdk/aws-stepfunctions/lib/fields.ts b/packages/@aws-cdk/aws-stepfunctions/lib/fields.ts index b7fccd1979aed..6eb48199b8252 100644 --- a/packages/@aws-cdk/aws-stepfunctions/lib/fields.ts +++ b/packages/@aws-cdk/aws-stepfunctions/lib/fields.ts @@ -103,6 +103,161 @@ export class JsonPath { return new JsonPathToken(`States.Array(${values.map(renderInExpression).join(', ')})`).toString(); } + /** + * Make an intrinsic States.ArrayPartition expression + * + * Use this function to partition a large array. You can also use this intrinsic to slice the data and then send the payload in smaller chunks. + * + * @see https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-intrinsic-functions.html + */ + public static arrayPartition(array: any, chunkSize: number): string { + return new JsonPathToken(`States.ArrayPartition(${[array, chunkSize].map(renderInExpression).join(', ')})`).toString(); + } + + /** + * Make an intrinsic States.ArrayContains expression + * + * Use this function to determine if a specific value is present in an array. For example, you can use this function to detect if there was an error in a Map state iteration. + * + * @see https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-intrinsic-functions.html + */ + public static arrayContains(array: any, value: any): string { + return new JsonPathToken(`States.ArrayContains(${[array, value].map(renderInExpression).join(', ')})`).toString(); + } + + /** + * Make an intrinsic States.ArrayRange expression + * + * Use this function to create a new array containing a specific range of elements. The new array can contain up to 1000 elements. + * + * @see https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-intrinsic-functions.html + */ + public static arrayRange(start: number, end: number, step: number): string { + return new JsonPathToken(`States.ArrayRange(${[start, end, step].map(renderInExpression).join(', ')})`).toString(); + } + + /** + * Make an intrinsic States.ArrayGetItem expression + * + * Use this function to get a specified index's value in an array. + * + * @see https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-intrinsic-functions.html + */ + public static arrayGetItem(array: any, index: number): string { + return new JsonPathToken(`States.ArrayGetItem(${[array, index].map(renderInExpression).join(', ')})`).toString(); + } + + /** + * Make an intrinsic States.ArrayLength expression + * + * Use this function to get the length of an array. + * + * @see https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-intrinsic-functions.html + */ + public static arrayLength(array: any): string { + return new JsonPathToken(`States.ArrayLength(${renderInExpression(array)})`).toString(); + } + + /** + * Make an intrinsic States.ArrayUnique expression + * + * Use this function to get the length of an array. + * Use this function to remove duplicate values from an array and returns an array containing only unique elements. This function takes an array, which can be unsorted, as its sole argument. + * + * @see https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-intrinsic-functions.html + */ + public static arrayUnique(array: any): string { + return new JsonPathToken(`States.ArrayUnique(${renderInExpression(array)})`).toString(); + } + + /** + * Make an intrinsic States.Base64Encode expression + * + * Use this function to encode data based on MIME Base64 encoding scheme. You can use this function to pass data to other AWS services without using an AWS Lambda function. + * + * @see https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-intrinsic-functions.html + */ + public static base64Encode(input: string): string { + return new JsonPathToken(`States.Base64Encode(${renderInExpression(input)})`).toString(); + } + + /** + * Make an intrinsic States.Base64Decode expression + * + * Use this function to decode data based on MIME Base64 decoding scheme. You can use this function to pass data to other AWS services without using a Lambda function. + * + * @see https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-intrinsic-functions.html + */ + public static base64Decode(base64: string): string { + return new JsonPathToken(`States.Base64Decode(${renderInExpression(base64)})`).toString(); + } + + /** + * Make an intrinsic States.Hash expression + * + * Use this function to calculate the hash value of a given input. You can use this function to pass data to other AWS services without using a Lambda function. + * + * @see https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-intrinsic-functions.html + */ + public static hash(data: any, algorithm: string): string { + return new JsonPathToken(`States.Hash(${[data, algorithm].map(renderInExpression).join(', ')})`).toString(); + } + + /** + * Make an intrinsic States.JsonMerge expression + * + * Use this function to merge two JSON objects into a single object. + * + * @see https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-intrinsic-functions.html + */ + public static jsonMerge(value1: any, value2: any): string { + return new JsonPathToken(`States.JsonMerge(${[value1, value2].map(renderInExpression).join(', ')}, false)`).toString(); + } + + /** + * Make an intrinsic States.MathRandom expression + * + * Use this function to return a random number between the specified start and end number. For example, you can use this function to distribute a specific task between two or more resources. + * + * @see https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-intrinsic-functions.html + */ + public static mathRandom(start: number, end: number): string { + return new JsonPathToken(`States.MathRandom(${[start, end].map(renderInExpression).join(', ')})`).toString(); + } + + /** + * Make an intrinsic States.MathAdd expression + * + * Use this function to return the sum of two numbers. For example, you can use this function to increment values inside a loop without invoking a Lambda function. + * + * @see https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-intrinsic-functions.html + */ + public static mathAdd(num1: number, num2: number): string { + return new JsonPathToken(`States.MathAdd(${[num1, num2].map(renderInExpression).join(', ')})`).toString(); + } + + /** + * Make an intrinsic States.StringSplit expression + * + * Use this function to split a string into an array of values. This function takes two arguments.The first argument is a string and the second argument is the delimiting character that the function will use to divide the string. + * + * @see https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-intrinsic-functions.html + */ + public static stringSplit(inputString: string, splitter: string): string { + return new JsonPathToken(`States.StringSplit(${[inputString, splitter].map(renderInExpression).join(', ')})`).toString(); + } + + /** + * Make an intrinsic States.UUID expression + * + * Use this function to return a version 4 universally unique identifier (v4 UUID) generated using random numbers. For example, you can use this function to call other AWS services or resources that need a UUID parameter or insert items in a DynamoDB table. + * + * @see https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-intrinsic-functions.html + */ + public static uuid(): string { + return new JsonPathToken('States.UUID()').toString(); + } + /** * Make an intrinsic States.Format expression * @@ -299,10 +454,32 @@ export class FieldUtils { function validateJsonPath(path: string) { const intrinsicFunctionNames = [ - 'Format', + // Intrinsics for arrays + 'Array', + 'ArrayPartition', + 'ArrayContains', + 'ArrayRange', + 'ArrayGetItem', + 'ArrayLength', + 'ArrayUnique', + // Intrinsics for data encoding and decoding + 'Base64Encode', + 'Base64Decode', + // Intrinsic for hash calculation + 'Hash', + // Intrinsics for JSON data manipulation + 'JsonMerge', 'StringToJson', 'JsonToString', - 'Array', + // Intrinsics for Math operations + 'MathRandom', + 'MathAdd', + // Intrinsic for String operation + 'StringSplit', + // Intrinsic for unique identifier generation + 'UUID', + // Intrinsic for generic operation + 'Format', ]; const intrinsicFunctionFullNames = intrinsicFunctionNames.map((fn) => `States.${fn}`); if (path !== '$' diff --git a/packages/@aws-cdk/aws-stepfunctions/lib/private/json-path.ts b/packages/@aws-cdk/aws-stepfunctions/lib/private/json-path.ts index 7263da227261f..d6802227c4305 100644 --- a/packages/@aws-cdk/aws-stepfunctions/lib/private/json-path.ts +++ b/packages/@aws-cdk/aws-stepfunctions/lib/private/json-path.ts @@ -312,17 +312,22 @@ function pathFromToken(token: IResolvable | undefined) { } /** - * Render the string in a valid JSON Path expression. + * Render the string or number value in a valid JSON Path expression. * - * If the string is a Tokenized JSON path reference -- return the JSON path reference inside it. - * Otherwise, single-quote it. + * If the value is a Tokenized JSON path reference -- return the JSON path reference inside it. + * If the value is a number -- convert it to string. + * If the value is a string -- single-quote it. + * Otherwise, throw errors. * * Call this function whenever you're building compound JSONPath expressions, in * order to avoid having tokens-in-tokens-in-tokens which become very hard to parse. */ -export function renderInExpression(x: string) { - const path = jsonPathString(x); - return path ?? singleQuotestring(x); +export function renderInExpression(x: any) { + const path = jsonPathFromAny(x); + if (path) return path; + if (typeof x === 'number') return x.toString(10); + if (typeof x === 'string') return singleQuotestring(x); + throw new Error('Unxexpected value.'); } function singleQuotestring(x: string) { @@ -341,4 +346,4 @@ function singleQuotestring(x: string) { } ret.push("'"); return ret.join(''); -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-stepfunctions/test/fields.test.ts b/packages/@aws-cdk/aws-stepfunctions/test/fields.test.ts index eec3864f938e6..e36dfc19c4ecf 100644 --- a/packages/@aws-cdk/aws-stepfunctions/test/fields.test.ts +++ b/packages/@aws-cdk/aws-stepfunctions/test/fields.test.ts @@ -1,7 +1,7 @@ import { FieldUtils, JsonPath, TaskInput } from '../lib'; describe('Fields', () => { - const jsonPathValidationErrorMsg = /exactly '\$', '\$\$', start with '\$.', start with '\$\$.', start with '\$\[', or start with an intrinsic function: States.Format, States.StringToJson, States.JsonToString, or States.Array./; + const jsonPathValidationErrorMsg = /exactly '\$', '\$\$', start with '\$.', start with '\$\$.', start with '\$\[', or start with an intrinsic function: States.Array, States.ArrayPartition, States.ArrayContains, States.ArrayRange, States.ArrayGetItem, States.ArrayLength, States.ArrayUnique, States.Base64Encode, States.Base64Decode, States.Hash, States.JsonMerge, States.StringToJson, States.JsonToString, States.MathRandom, States.MathAdd, States.StringSplit, States.UUID, or States.Format./; test('deep replace correctly handles fields in arrays', () => { expect( @@ -74,6 +74,20 @@ describe('Fields', () => { expect(JsonPath.stringAt('States.StringToJson')).toBeDefined(); expect(JsonPath.stringAt('States.JsonToString')).toBeDefined(); expect(JsonPath.stringAt('States.Array')).toBeDefined(); + expect(JsonPath.stringAt('States.ArrayPartition')).toBeDefined(); + expect(JsonPath.stringAt('States.ArrayContains')).toBeDefined(); + expect(JsonPath.stringAt('States.ArrayRange')).toBeDefined(); + expect(JsonPath.stringAt('States.ArrayGetItem')).toBeDefined(); + expect(JsonPath.stringAt('States.ArrayLength')).toBeDefined(); + expect(JsonPath.stringAt('States.ArrayUnique')).toBeDefined(); + expect(JsonPath.stringAt('States.Base64Encode')).toBeDefined(); + expect(JsonPath.stringAt('States.Base64Decode')).toBeDefined(); + expect(JsonPath.stringAt('States.Hash')).toBeDefined(); + expect(JsonPath.stringAt('States.JsonMerge')).toBeDefined(); + expect(JsonPath.stringAt('States.MathRandom')).toBeDefined(); + expect(JsonPath.stringAt('States.MathAdd')).toBeDefined(); + expect(JsonPath.stringAt('States.StringSplit')).toBeDefined(); + expect(JsonPath.stringAt('States.UUID')).toBeDefined(); expect(() => JsonPath.stringAt('$hello')).toThrowError(jsonPathValidationErrorMsg); expect(() => JsonPath.stringAt('hello')).toThrowError(jsonPathValidationErrorMsg); @@ -222,6 +236,184 @@ describe('intrinsics constructors', () => { }); }); + test('arrayPartition', () => { + expect(FieldUtils.renderObject({ + Field: JsonPath.arrayPartition(JsonPath.listAt('$.inputArray'), 4), + })).toEqual({ + 'Field.$': 'States.ArrayPartition($.inputArray, 4)', + }); + + expect(FieldUtils.renderObject({ + Field: JsonPath.arrayPartition(JsonPath.listAt('$.inputArray'), JsonPath.numberAt('$.chunkSize')), + })).toEqual({ + 'Field.$': 'States.ArrayPartition($.inputArray, $.chunkSize)', + }); + }); + + test('arrayContains', () => { + expect(FieldUtils.renderObject({ + Field: JsonPath.arrayContains(JsonPath.listAt('$.inputArray'), 5), + })).toEqual({ + 'Field.$': 'States.ArrayContains($.inputArray, 5)', + }); + + expect(FieldUtils.renderObject({ + Field: JsonPath.arrayContains(JsonPath.listAt('$.inputArray'), 'a'), + })).toEqual({ + 'Field.$': "States.ArrayContains($.inputArray, 'a')", + }); + + expect(FieldUtils.renderObject({ + Field: JsonPath.arrayContains(JsonPath.listAt('$.inputArray'), JsonPath.numberAt('$.lookingFor')), + })).toEqual({ + 'Field.$': 'States.ArrayContains($.inputArray, $.lookingFor)', + }); + }); + + test('arrayRange', () => { + expect(FieldUtils.renderObject({ + Field: JsonPath.arrayRange(1, 9, 2), + })).toEqual({ + 'Field.$': 'States.ArrayRange(1, 9, 2)', + }); + + expect(FieldUtils.renderObject({ + Field: JsonPath.arrayRange(JsonPath.numberAt('$.start'), JsonPath.numberAt('$.end'), JsonPath.numberAt('$.step')), + })).toEqual({ + 'Field.$': 'States.ArrayRange($.start, $.end, $.step)', + }); + }); + + test('arrayGetItem', () => { + expect(FieldUtils.renderObject({ + Field: JsonPath.arrayGetItem(JsonPath.listAt('$.inputArray'), 5), + })).toEqual({ + 'Field.$': 'States.ArrayGetItem($.inputArray, 5)', + }); + + expect(FieldUtils.renderObject({ + Field: JsonPath.arrayGetItem(JsonPath.numberAt('$.inputArray'), JsonPath.numberAt('$.index')), + })).toEqual({ + 'Field.$': 'States.ArrayGetItem($.inputArray, $.index)', + }); + }); + + test('arrayLength', () => { + expect(FieldUtils.renderObject({ + Field: JsonPath.arrayLength(JsonPath.listAt('$.inputArray')), + })).toEqual({ + 'Field.$': 'States.ArrayLength($.inputArray)', + }); + }); + + test('arrayUnique', () => { + expect(FieldUtils.renderObject({ + Field: JsonPath.arrayUnique(JsonPath.listAt('$.inputArray')), + })).toEqual({ + 'Field.$': 'States.ArrayUnique($.inputArray)', + }); + }); + + test('base64Encode', () => { + expect(FieldUtils.renderObject({ + Field: JsonPath.base64Encode('Data to encode'), + })).toEqual({ + 'Field.$': "States.Base64Encode('Data to encode')", + }); + + expect(FieldUtils.renderObject({ + Field: JsonPath.base64Encode(JsonPath.stringAt('$.input')), + })).toEqual({ + 'Field.$': 'States.Base64Encode($.input)', + }); + }); + + test('base64Decode', () => { + expect(FieldUtils.renderObject({ + Field: JsonPath.base64Decode('RGF0YSB0byBlbmNvZGU='), + })).toEqual({ + 'Field.$': "States.Base64Decode('RGF0YSB0byBlbmNvZGU=')", + }); + + expect(FieldUtils.renderObject({ + Field: JsonPath.base64Decode(JsonPath.stringAt('$.base64')), + })).toEqual({ + 'Field.$': 'States.Base64Decode($.base64)', + }); + }); + + test('hash', () => { + expect(FieldUtils.renderObject({ + Field: JsonPath.hash('Input data', 'SHA-1'), + })).toEqual({ + 'Field.$': "States.Hash('Input data', 'SHA-1')", + }); + + expect(FieldUtils.renderObject({ + Field: JsonPath.hash(JsonPath.objectAt('$.Data'), JsonPath.stringAt('$.Algorithm')), + })).toEqual({ + 'Field.$': 'States.Hash($.Data, $.Algorithm)', + }); + }); + + test('jsonMerge', () => { + expect(FieldUtils.renderObject({ + Field: JsonPath.jsonMerge(JsonPath.objectAt('$.Obj1'), JsonPath.objectAt('$.Obj2')), + })).toEqual({ + 'Field.$': 'States.JsonMerge($.Obj1, $.Obj2, false)', + }); + }); + + test('mathRandom', () => { + expect(FieldUtils.renderObject({ + Field: JsonPath.mathRandom(1, 999), + })).toEqual({ + 'Field.$': 'States.MathRandom(1, 999)', + }); + + expect(FieldUtils.renderObject({ + Field: JsonPath.mathRandom(JsonPath.numberAt('$.start'), JsonPath.numberAt('$.end')), + })).toEqual({ + 'Field.$': 'States.MathRandom($.start, $.end)', + }); + }); + + test('mathAdd', () => { + expect(FieldUtils.renderObject({ + Field: JsonPath.mathAdd(1, 999), + })).toEqual({ + 'Field.$': 'States.MathAdd(1, 999)', + }); + + expect(FieldUtils.renderObject({ + Field: JsonPath.mathAdd(JsonPath.numberAt('$.value1'), JsonPath.numberAt('$.step')), + })).toEqual({ + 'Field.$': 'States.MathAdd($.value1, $.step)', + }); + }); + + test('stringSplit', () => { + expect(FieldUtils.renderObject({ + Field: JsonPath.stringSplit('1,2,3,4,5', ','), + })).toEqual({ + 'Field.$': "States.StringSplit('1,2,3,4,5', ',')", + }); + + expect(FieldUtils.renderObject({ + Field: JsonPath.stringSplit(JsonPath.stringAt('$.inputString'), JsonPath.stringAt('$.splitter')), + })).toEqual({ + 'Field.$': 'States.StringSplit($.inputString, $.splitter)', + }); + }); + + test('uuid', () => { + expect(FieldUtils.renderObject({ + Field: JsonPath.uuid(), + })).toEqual({ + 'Field.$': 'States.UUID()', + }); + }); + test('format', () => { expect(FieldUtils.renderObject({ Field: JsonPath.format('Hi my name is {}.', JsonPath.stringAt('$.Name')), @@ -260,4 +452,4 @@ test('find task token even if nested in intrinsic functions', () => { // Even if it's a hand-written literal and doesn't use our constructors expect(FieldUtils.containsTaskToken({ x: JsonPath.stringAt('States.Array($$.Task.Token)') })).toEqual(true); -}); \ No newline at end of file +}); From 1b16891d2b0d019fc1eaa02df7ffbd6842a8a4d1 Mon Sep 17 00:00:00 2001 From: Konosuke Kachi Date: Sun, 9 Oct 2022 20:40:51 +0900 Subject: [PATCH 3/8] Update readme --- packages/@aws-cdk/aws-stepfunctions/README.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-stepfunctions/README.md b/packages/@aws-cdk/aws-stepfunctions/README.md index 52386680d26ba..e4ae99f92f423 100644 --- a/packages/@aws-cdk/aws-stepfunctions/README.md +++ b/packages/@aws-cdk/aws-stepfunctions/README.md @@ -192,9 +192,23 @@ You can also call [intrinsic functions](https://docs.aws.amazon.com/step-functio | Method | Purpose | |--------|---------| | `JsonPath.array(JsonPath.stringAt('$.Field'), ...)` | make an array from other elements. | -| `JsonPath.format('The value is {}.', JsonPath.stringAt('$.Value'))` | insert elements into a format string. | +| `JsonPath.arrayPartition(JsonPath.listAt('$.inputArray'), 4)` | partition an array. | +| `JsonPath.arrayContains(JsonPath.listAt('$.inputArray'), 5)` | determine if a specific value is present in an array. | +| `JsonPath.arrayRange(1, 9, 2)` | create a new array containing a specific range of elements. | +| `JsonPath.arrayGetItem(JsonPath.listAt('$.inputArray'), 5)` | get a specified index's value in an array. | +| `JsonPath.arrayLength(JsonPath.listAt('$.inputArray'))` | get the length of an array. | +| `JsonPath.arrayUnique(JsonPath.listAt('$.inputArray'))` | remove duplicate values from an array. | +| `JsonPath.base64Encode(JsonPath.stringAt('$.input'))` | encode data based on MIME Base64 encoding scheme. | +| `JsonPath.base64Decode(JsonPath.stringAt('$.base64'))` | decode data based on MIME Base64 decoding scheme. | +| `JsonPath.hash(JsonPath.objectAt('$.Data'), JsonPath.stringAt('$.Algorithm'))` | calculate the hash value of a given input. | +| `JsonPath.jsonMerge(JsonPath.objectAt('$.Obj1'), JsonPath.objectAt('$.Obj2'))` | merge two JSON objects into a single object. | | `JsonPath.stringToJson(JsonPath.stringAt('$.ObjStr'))` | parse a JSON string to an object | | `JsonPath.jsonToString(JsonPath.objectAt('$.Obj'))` | stringify an object to a JSON string | +| `JsonPath.mathRandom(1, 999)` | return a random number. | +| `JsonPath.mathAdd(JsonPath.numberAt('$.value1'), JsonPath.numberAt('$.step'))` | return the sum of two numbers. | +| `JsonPath.stringSplit(JsonPath.stringAt('$.inputString'), JsonPath.stringAt('$.splitter'))` | split a string into an array of values. | +| `JsonPath.uuid()` | return a version 4 universally unique identifier (v4 UUID). | +| `JsonPath.format('The value is {}.', JsonPath.stringAt('$.Value'))` | insert elements into a format string. | ## Amazon States Language From ab29124d26cf8a21a1399b0193122c7b8419d00d Mon Sep 17 00:00:00 2001 From: Konosuke Kachi Date: Sun, 9 Oct 2022 19:19:59 +0900 Subject: [PATCH 4/8] Add integration test --- .../@aws-cdk/aws-stepfunctions/package.json | 1 + .../test/integ.intrinsics.ts | 56 ++++++ ...efaultTestDeployAssert1C1E1D7E.assets.json | 19 ++ ...aultTestDeployAssert1C1E1D7E.template.json | 36 ++++ ...stepfunctions-intrinsics-integ.assets.json | 19 ++ ...epfunctions-intrinsics-integ.template.json | 172 ++++++++++++++++++ .../test/intrinsics.integ.snapshot/cdk.out | 1 + .../test/intrinsics.integ.snapshot/integ.json | 12 ++ .../intrinsics.integ.snapshot/manifest.json | 123 +++++++++++++ .../test/intrinsics.integ.snapshot/tree.json | 156 ++++++++++++++++ 10 files changed, 595 insertions(+) create mode 100644 packages/@aws-cdk/aws-stepfunctions/test/integ.intrinsics.ts create mode 100644 packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.assets.json create mode 100644 packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.template.json create mode 100644 packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/aws-stepfunctions-intrinsics-integ.assets.json create mode 100644 packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/aws-stepfunctions-intrinsics-integ.template.json create mode 100644 packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/cdk.out create mode 100644 packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/integ.json create mode 100644 packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/manifest.json create mode 100644 packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/tree.json diff --git a/packages/@aws-cdk/aws-stepfunctions/package.json b/packages/@aws-cdk/aws-stepfunctions/package.json index f9cedd6d66502..386902dd64979 100644 --- a/packages/@aws-cdk/aws-stepfunctions/package.json +++ b/packages/@aws-cdk/aws-stepfunctions/package.json @@ -83,6 +83,7 @@ "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/integ-runner": "0.0.0", + "@aws-cdk/integ-tests": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.5.2" diff --git a/packages/@aws-cdk/aws-stepfunctions/test/integ.intrinsics.ts b/packages/@aws-cdk/aws-stepfunctions/test/integ.intrinsics.ts new file mode 100644 index 0000000000000..232328eb558de --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions/test/integ.intrinsics.ts @@ -0,0 +1,56 @@ +import * as cdk from '@aws-cdk/core'; +import * as integ from '@aws-cdk/integ-tests'; +import { JsonPath, Pass, StateMachine } from '../lib'; + +/* + * Stack verification steps: + * + * -- aws stepfunctions describe-state-machine --state-machine-arn has a status of `ACTIVE` + */ +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'aws-stepfunctions-intrinsics-integ'); + +const pass = new Pass(stack, 'pass', { + parameters: { + array1: JsonPath.array('asdf', JsonPath.stringAt('$.Id')), + arrayPartition1: JsonPath.arrayPartition(JsonPath.listAt('$.inputArray'), 4), + arrayPartition2: JsonPath.arrayPartition(JsonPath.listAt('$.inputArray'), JsonPath.numberAt('$.chunkSize')), + arrayContains1: JsonPath.arrayContains(JsonPath.listAt('$.inputArray'), 5), + arrayContains2: JsonPath.arrayContains(JsonPath.listAt('$.inputArray'), 'a'), + arrayContains3: JsonPath.arrayContains(JsonPath.listAt('$.inputArray'), JsonPath.numberAt('$.lookingFor')), + arrayRange1: JsonPath.arrayRange(1, 9, 2), + arrayRange2: JsonPath.arrayRange(JsonPath.numberAt('$.start'), JsonPath.numberAt('$.end'), JsonPath.numberAt('$.step')), + arrayGetItem1: JsonPath.arrayGetItem(JsonPath.listAt('$.inputArray'), 5), + arrayGetItem2: JsonPath.arrayGetItem(JsonPath.numberAt('$.inputArray'), JsonPath.numberAt('$.index')), + arrayLength1: JsonPath.arrayLength(JsonPath.listAt('$.inputArray')), + arrayUnique1: JsonPath.arrayUnique(JsonPath.listAt('$.inputArray')), + base64Encode1: JsonPath.base64Encode('Data to encode'), + base64Encode2: JsonPath.base64Encode(JsonPath.stringAt('$.input')), + base64Decode1: JsonPath.base64Decode('RGF0YSB0byBlbmNvZGU='), + base64Decode2: JsonPath.base64Decode(JsonPath.stringAt('$.base64')), + hash1: JsonPath.hash('Input data', 'SHA-1'), + hash2: JsonPath.hash(JsonPath.objectAt('$.Data'), JsonPath.stringAt('$.Algorithm')), + jsonMerge1: JsonPath.jsonMerge(JsonPath.objectAt('$.Obj1'), JsonPath.objectAt('$.Obj2')), + mathRandom1: JsonPath.mathRandom(1, 999), + mathRandom2: JsonPath.mathRandom(JsonPath.numberAt('$.start'), JsonPath.numberAt('$.end')), + mathAdd1: JsonPath.mathAdd(1, 999), + mathAdd2: JsonPath.mathAdd(JsonPath.numberAt('$.value1'), JsonPath.numberAt('$.step')), + stringSplit1: JsonPath.stringSplit('1,2,3,4,5', ','), + stringSplit2: JsonPath.stringSplit(JsonPath.stringAt('$.inputString'), JsonPath.stringAt('$.splitter')), + uuid: JsonPath.uuid(), + format1: JsonPath.format('Hi my name is {}.', JsonPath.stringAt('$.Name')), + format2: JsonPath.format(JsonPath.stringAt('$.Format'), JsonPath.stringAt('$.Name')), + stringToJson1: JsonPath.stringToJson(JsonPath.stringAt('$.Str')), + jsonToString1: JsonPath.jsonToString(JsonPath.objectAt('$.Obj')), + }, +}); + +new StateMachine(stack, 'StateMachine', { + definition: pass, +}); + +new integ.IntegTest(app, 'StateMachineIntrinsicsTest', { + testCases: [stack], +}); + +app.synth(); diff --git a/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.assets.json b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.assets.json new file mode 100644 index 0000000000000..7781e39eaa275 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.template.json b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/aws-stepfunctions-intrinsics-integ.assets.json b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/aws-stepfunctions-intrinsics-integ.assets.json new file mode 100644 index 0000000000000..f309a4b1ed461 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/aws-stepfunctions-intrinsics-integ.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "0969ff045f30d2fff3d0ee8d260f6d4ba27b98431560c1601d96fa47a574bd1b": { + "source": { + "path": "aws-stepfunctions-intrinsics-integ.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "0969ff045f30d2fff3d0ee8d260f6d4ba27b98431560c1601d96fa47a574bd1b.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/aws-stepfunctions-intrinsics-integ.template.json b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/aws-stepfunctions-intrinsics-integ.template.json new file mode 100644 index 0000000000000..c091a48351cfe --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/aws-stepfunctions-intrinsics-integ.template.json @@ -0,0 +1,172 @@ +{ + "Resources": { + "StateMachineRoleB840431D": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": { + "Fn::FindInMap": [ + "ServiceprincipalMap", + { + "Ref": "AWS::Region" + }, + "states" + ] + } + } + } + ], + "Version": "2012-10-17" + } + } + }, + "StateMachine2E01A3A5": { + "Type": "AWS::StepFunctions::StateMachine", + "Properties": { + "RoleArn": { + "Fn::GetAtt": [ + "StateMachineRoleB840431D", + "Arn" + ] + }, + "DefinitionString": "{\"StartAt\":\"pass\",\"States\":{\"pass\":{\"Type\":\"Pass\",\"Parameters\":{\"array1.$\":\"States.Array('asdf', $.Id)\",\"arrayPartition1.$\":\"States.ArrayPartition($.inputArray, 4)\",\"arrayPartition2.$\":\"States.ArrayPartition($.inputArray, $.chunkSize)\",\"arrayContains1.$\":\"States.ArrayContains($.inputArray, 5)\",\"arrayContains2.$\":\"States.ArrayContains($.inputArray, 'a')\",\"arrayContains3.$\":\"States.ArrayContains($.inputArray, $.lookingFor)\",\"arrayRange1.$\":\"States.ArrayRange(1, 9, 2)\",\"arrayRange2.$\":\"States.ArrayRange($.start, $.end, $.step)\",\"arrayGetItem1.$\":\"States.ArrayGetItem($.inputArray, 5)\",\"arrayGetItem2.$\":\"States.ArrayGetItem($.inputArray, $.index)\",\"arrayLength1.$\":\"States.ArrayLength($.inputArray)\",\"arrayUnique1.$\":\"States.ArrayUnique($.inputArray)\",\"base64Encode1.$\":\"States.Base64Encode('Data to encode')\",\"base64Encode2.$\":\"States.Base64Encode($.input)\",\"base64Decode1.$\":\"States.Base64Decode('RGF0YSB0byBlbmNvZGU=')\",\"base64Decode2.$\":\"States.Base64Decode($.base64)\",\"hash1.$\":\"States.Hash('Input data', 'SHA-1')\",\"hash2.$\":\"States.Hash($.Data, $.Algorithm)\",\"jsonMerge1.$\":\"States.JsonMerge($.Obj1, $.Obj2, false)\",\"mathRandom1.$\":\"States.MathRandom(1, 999)\",\"mathRandom2.$\":\"States.MathRandom($.start, $.end)\",\"mathAdd1.$\":\"States.MathAdd(1, 999)\",\"mathAdd2.$\":\"States.MathAdd($.value1, $.step)\",\"stringSplit1.$\":\"States.StringSplit('1,2,3,4,5', ',')\",\"stringSplit2.$\":\"States.StringSplit($.inputString, $.splitter)\",\"uuid.$\":\"States.UUID()\",\"format1.$\":\"States.Format('Hi my name is {}.', $.Name)\",\"format2.$\":\"States.Format($.Format, $.Name)\",\"stringToJson1.$\":\"States.StringToJson($.Str)\",\"jsonToString1.$\":\"States.JsonToString($.Obj)\"},\"End\":true}}}" + }, + "DependsOn": [ + "StateMachineRoleB840431D" + ] + } + }, + "Mappings": { + "ServiceprincipalMap": { + "af-south-1": { + "states": "states.af-south-1.amazonaws.com" + }, + "ap-east-1": { + "states": "states.ap-east-1.amazonaws.com" + }, + "ap-northeast-1": { + "states": "states.ap-northeast-1.amazonaws.com" + }, + "ap-northeast-2": { + "states": "states.ap-northeast-2.amazonaws.com" + }, + "ap-northeast-3": { + "states": "states.ap-northeast-3.amazonaws.com" + }, + "ap-south-1": { + "states": "states.ap-south-1.amazonaws.com" + }, + "ap-southeast-1": { + "states": "states.ap-southeast-1.amazonaws.com" + }, + "ap-southeast-2": { + "states": "states.ap-southeast-2.amazonaws.com" + }, + "ap-southeast-3": { + "states": "states.ap-southeast-3.amazonaws.com" + }, + "ca-central-1": { + "states": "states.ca-central-1.amazonaws.com" + }, + "cn-north-1": { + "states": "states.cn-north-1.amazonaws.com" + }, + "cn-northwest-1": { + "states": "states.cn-northwest-1.amazonaws.com" + }, + "eu-central-1": { + "states": "states.eu-central-1.amazonaws.com" + }, + "eu-north-1": { + "states": "states.eu-north-1.amazonaws.com" + }, + "eu-south-1": { + "states": "states.eu-south-1.amazonaws.com" + }, + "eu-south-2": { + "states": "states.eu-south-2.amazonaws.com" + }, + "eu-west-1": { + "states": "states.eu-west-1.amazonaws.com" + }, + "eu-west-2": { + "states": "states.eu-west-2.amazonaws.com" + }, + "eu-west-3": { + "states": "states.eu-west-3.amazonaws.com" + }, + "me-south-1": { + "states": "states.me-south-1.amazonaws.com" + }, + "sa-east-1": { + "states": "states.sa-east-1.amazonaws.com" + }, + "us-east-1": { + "states": "states.us-east-1.amazonaws.com" + }, + "us-east-2": { + "states": "states.us-east-2.amazonaws.com" + }, + "us-gov-east-1": { + "states": "states.us-gov-east-1.amazonaws.com" + }, + "us-gov-west-1": { + "states": "states.us-gov-west-1.amazonaws.com" + }, + "us-iso-east-1": { + "states": "states.amazonaws.com" + }, + "us-iso-west-1": { + "states": "states.amazonaws.com" + }, + "us-isob-east-1": { + "states": "states.amazonaws.com" + }, + "us-west-1": { + "states": "states.us-west-1.amazonaws.com" + }, + "us-west-2": { + "states": "states.us-west-2.amazonaws.com" + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/cdk.out new file mode 100644 index 0000000000000..8ecc185e9dbee --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/integ.json b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/integ.json new file mode 100644 index 0000000000000..96a6796634bf0 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "21.0.0", + "testCases": { + "StateMachineIntrinsicsTest/DefaultTest": { + "stacks": [ + "aws-stepfunctions-intrinsics-integ" + ], + "assertionStack": "StateMachineIntrinsicsTest/DefaultTest/DeployAssert", + "assertionStackName": "StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/manifest.json new file mode 100644 index 0000000000000..b76e7293a4ac1 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/manifest.json @@ -0,0 +1,123 @@ +{ + "version": "21.0.0", + "artifacts": { + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "aws-stepfunctions-intrinsics-integ.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-stepfunctions-intrinsics-integ.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-stepfunctions-intrinsics-integ": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-stepfunctions-intrinsics-integ.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/0969ff045f30d2fff3d0ee8d260f6d4ba27b98431560c1601d96fa47a574bd1b.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-stepfunctions-intrinsics-integ.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-stepfunctions-intrinsics-integ.assets" + ], + "metadata": { + "/aws-stepfunctions-intrinsics-integ/StateMachine/Role/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "StateMachineRoleB840431D" + } + ], + "/aws-stepfunctions-intrinsics-integ/StateMachine/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "StateMachine2E01A3A5" + } + ], + "/aws-stepfunctions-intrinsics-integ/Service-principalMap": [ + { + "type": "aws:cdk:logicalId", + "data": "ServiceprincipalMap" + } + ], + "/aws-stepfunctions-intrinsics-integ/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-stepfunctions-intrinsics-integ/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-stepfunctions-intrinsics-integ" + }, + "StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.assets" + ], + "metadata": { + "/StateMachineIntrinsicsTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/StateMachineIntrinsicsTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "StateMachineIntrinsicsTest/DefaultTest/DeployAssert" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/tree.json b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/tree.json new file mode 100644 index 0000000000000..f7b84b009cd20 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/tree.json @@ -0,0 +1,156 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.123" + } + }, + "aws-stepfunctions-intrinsics-integ": { + "id": "aws-stepfunctions-intrinsics-integ", + "path": "aws-stepfunctions-intrinsics-integ", + "children": { + "pass": { + "id": "pass", + "path": "aws-stepfunctions-intrinsics-integ/pass", + "constructInfo": { + "fqn": "@aws-cdk/aws-stepfunctions.Pass", + "version": "0.0.0" + } + }, + "StateMachine": { + "id": "StateMachine", + "path": "aws-stepfunctions-intrinsics-integ/StateMachine", + "children": { + "Role": { + "id": "Role", + "path": "aws-stepfunctions-intrinsics-integ/StateMachine/Role", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-stepfunctions-intrinsics-integ/StateMachine/Role/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": { + "Fn::FindInMap": [ + "ServiceprincipalMap", + { + "Ref": "AWS::Region" + }, + "states" + ] + } + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-stepfunctions-intrinsics-integ/StateMachine/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::StepFunctions::StateMachine", + "aws:cdk:cloudformation:props": { + "roleArn": { + "Fn::GetAtt": [ + "StateMachineRoleB840431D", + "Arn" + ] + }, + "definitionString": "{\"StartAt\":\"pass\",\"States\":{\"pass\":{\"Type\":\"Pass\",\"Parameters\":{\"array1.$\":\"States.Array('asdf', $.Id)\",\"arrayPartition1.$\":\"States.ArrayPartition($.inputArray, 4)\",\"arrayPartition2.$\":\"States.ArrayPartition($.inputArray, $.chunkSize)\",\"arrayContains1.$\":\"States.ArrayContains($.inputArray, 5)\",\"arrayContains2.$\":\"States.ArrayContains($.inputArray, 'a')\",\"arrayContains3.$\":\"States.ArrayContains($.inputArray, $.lookingFor)\",\"arrayRange1.$\":\"States.ArrayRange(1, 9, 2)\",\"arrayRange2.$\":\"States.ArrayRange($.start, $.end, $.step)\",\"arrayGetItem1.$\":\"States.ArrayGetItem($.inputArray, 5)\",\"arrayGetItem2.$\":\"States.ArrayGetItem($.inputArray, $.index)\",\"arrayLength1.$\":\"States.ArrayLength($.inputArray)\",\"arrayUnique1.$\":\"States.ArrayUnique($.inputArray)\",\"base64Encode1.$\":\"States.Base64Encode('Data to encode')\",\"base64Encode2.$\":\"States.Base64Encode($.input)\",\"base64Decode1.$\":\"States.Base64Decode('RGF0YSB0byBlbmNvZGU=')\",\"base64Decode2.$\":\"States.Base64Decode($.base64)\",\"hash1.$\":\"States.Hash('Input data', 'SHA-1')\",\"hash2.$\":\"States.Hash($.Data, $.Algorithm)\",\"jsonMerge1.$\":\"States.JsonMerge($.Obj1, $.Obj2, false)\",\"mathRandom1.$\":\"States.MathRandom(1, 999)\",\"mathRandom2.$\":\"States.MathRandom($.start, $.end)\",\"mathAdd1.$\":\"States.MathAdd(1, 999)\",\"mathAdd2.$\":\"States.MathAdd($.value1, $.step)\",\"stringSplit1.$\":\"States.StringSplit('1,2,3,4,5', ',')\",\"stringSplit2.$\":\"States.StringSplit($.inputString, $.splitter)\",\"uuid.$\":\"States.UUID()\",\"format1.$\":\"States.Format('Hi my name is {}.', $.Name)\",\"format2.$\":\"States.Format($.Format, $.Name)\",\"stringToJson1.$\":\"States.StringToJson($.Str)\",\"jsonToString1.$\":\"States.JsonToString($.Obj)\"},\"End\":true}}}" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-stepfunctions.CfnStateMachine", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-stepfunctions.StateMachine", + "version": "0.0.0" + } + }, + "Service-principalMap": { + "id": "Service-principalMap", + "path": "aws-stepfunctions-intrinsics-integ/Service-principalMap", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnMapping", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "StateMachineIntrinsicsTest": { + "id": "StateMachineIntrinsicsTest", + "path": "StateMachineIntrinsicsTest", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "StateMachineIntrinsicsTest/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "StateMachineIntrinsicsTest/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.123" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "StateMachineIntrinsicsTest/DefaultTest/DeployAssert", + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file From 926c938b6df88fea14409133abfd714bfc1f9fc0 Mon Sep 17 00:00:00 2001 From: Konosuke Kachi Date: Sat, 15 Oct 2022 11:00:00 +0900 Subject: [PATCH 5/8] Remove unnecessary comments --- packages/@aws-cdk/aws-stepfunctions/test/integ.intrinsics.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/@aws-cdk/aws-stepfunctions/test/integ.intrinsics.ts b/packages/@aws-cdk/aws-stepfunctions/test/integ.intrinsics.ts index 232328eb558de..88013ca84a617 100644 --- a/packages/@aws-cdk/aws-stepfunctions/test/integ.intrinsics.ts +++ b/packages/@aws-cdk/aws-stepfunctions/test/integ.intrinsics.ts @@ -2,11 +2,6 @@ import * as cdk from '@aws-cdk/core'; import * as integ from '@aws-cdk/integ-tests'; import { JsonPath, Pass, StateMachine } from '../lib'; -/* - * Stack verification steps: - * - * -- aws stepfunctions describe-state-machine --state-machine-arn has a status of `ACTIVE` - */ const app = new cdk.App(); const stack = new cdk.Stack(app, 'aws-stepfunctions-intrinsics-integ'); From d32fbf397ef27c2a8fda867a30c37366ef43a93d Mon Sep 17 00:00:00 2001 From: Konosuke Kachi Date: Wed, 19 Oct 2022 23:43:45 +0900 Subject: [PATCH 6/8] Add test for `renderInExpression` --- .../test/private/json-path.test.ts | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 packages/@aws-cdk/aws-stepfunctions/test/private/json-path.test.ts diff --git a/packages/@aws-cdk/aws-stepfunctions/test/private/json-path.test.ts b/packages/@aws-cdk/aws-stepfunctions/test/private/json-path.test.ts new file mode 100644 index 0000000000000..2e702fdc61c13 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions/test/private/json-path.test.ts @@ -0,0 +1,26 @@ +import { renderInExpression } from '../../lib/private/json-path'; +import { JsonPath } from '../../lib'; + +describe('RenderInExpression', () => { + test('simple number', () => { + expect(renderInExpression(1)).toBe('1'); + }); + test('simple string', () => { + expect(renderInExpression('a')).toBe("'a'"); + }); + test('jsonpath stringAt', () => { + expect(renderInExpression(JsonPath.stringAt('$.Field'))).toBe('$.Field'); + }); + test('jsonpath numberAt', () => { + expect(renderInExpression(JsonPath.numberAt('$.Field'))).toBe('$.Field'); + }); + test('jsonpath listAt', () => { + expect(renderInExpression(JsonPath.listAt('$.Field'))).toBe('$.Field'); + }); + test('jsonpath objectAt', () => { + expect(renderInExpression(JsonPath.objectAt('$.Field'))).toBe('$.Field'); + }); + test('raw array', () => { + expect(() => renderInExpression([1, 2])).toThrow(); + }) +}); From d2ff6e1c2053915433f8a1aa5aed3219b766474d Mon Sep 17 00:00:00 2001 From: Konosuke Kachi Date: Thu, 20 Oct 2022 01:10:01 +0900 Subject: [PATCH 7/8] Add an assertion for the integ test --- .../test/integ.intrinsics.ts | 11 +- ...efaultTestDeployAssert1C1E1D7E.assets.json | 17 +- ...aultTestDeployAssert1C1E1D7E.template.json | 96 +++ .../index.js | 767 ++++++++++++++++++ ...stepfunctions-intrinsics-integ.assets.json | 4 +- ...epfunctions-intrinsics-integ.template.json | 10 + .../intrinsics.integ.snapshot/manifest.json | 35 +- .../test/intrinsics.integ.snapshot/tree.json | 112 ++- 8 files changed, 1041 insertions(+), 11 deletions(-) create mode 100644 packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/asset.3074b79e05e7b98930b6449e01baa3e68b32ecff86328933c2542f7b7fe6fdac.bundle/index.js diff --git a/packages/@aws-cdk/aws-stepfunctions/test/integ.intrinsics.ts b/packages/@aws-cdk/aws-stepfunctions/test/integ.intrinsics.ts index 88013ca84a617..f07836da4c30e 100644 --- a/packages/@aws-cdk/aws-stepfunctions/test/integ.intrinsics.ts +++ b/packages/@aws-cdk/aws-stepfunctions/test/integ.intrinsics.ts @@ -1,5 +1,5 @@ import * as cdk from '@aws-cdk/core'; -import * as integ from '@aws-cdk/integ-tests'; +import { IntegTest, ExpectedResult } from '@aws-cdk/integ-tests'; import { JsonPath, Pass, StateMachine } from '../lib'; const app = new cdk.App(); @@ -40,12 +40,17 @@ const pass = new Pass(stack, 'pass', { }, }); -new StateMachine(stack, 'StateMachine', { +const stateMachine = new StateMachine(stack, 'StateMachine', { definition: pass, }); -new integ.IntegTest(app, 'StateMachineIntrinsicsTest', { +const integ = new IntegTest(app, 'StateMachineIntrinsicsTest', { testCases: [stack], }); +integ.assertions.awsApiCall('StepFunctions', 'describeStateMachine', { + stateMachineArn: stateMachine.stateMachineArn, +}).expect(ExpectedResult.objectLike({ + status: 'ACTIVE', +})); app.synth(); diff --git a/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.assets.json b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.assets.json index 7781e39eaa275..b732375a777a4 100644 --- a/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.assets.json +++ b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.assets.json @@ -1,7 +1,20 @@ { "version": "21.0.0", "files": { - "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "3074b79e05e7b98930b6449e01baa3e68b32ecff86328933c2542f7b7fe6fdac": { + "source": { + "path": "asset.3074b79e05e7b98930b6449e01baa3e68b32ecff86328933c2542f7b7fe6fdac.bundle", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "3074b79e05e7b98930b6449e01baa3e68b32ecff86328933c2542f7b7fe6fdac.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "9efe81f855fa5f7925cf5a69c0ef1ff9563e05b71711a017100aa3d0e6921ab0": { "source": { "path": "StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.template.json", "packaging": "file" @@ -9,7 +22,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "objectKey": "9efe81f855fa5f7925cf5a69c0ef1ff9563e05b71711a017100aa3d0e6921ab0.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.template.json b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.template.json index ad9d0fb73d1dd..52f6684a436e2 100644 --- a/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.template.json +++ b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.template.json @@ -1,4 +1,100 @@ { + "Resources": { + "AwsApiCallStepFunctionsdescribeStateMachine": { + "Type": "Custom::DeployAssert@SdkCallStepFunctionsdescribeStateMachin", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "service": "StepFunctions", + "api": "describeStateMachine", + "expected": "{\"$ObjectLike\":{\"status\":\"ACTIVE\"}}", + "parameters": { + "stateMachineArn": { + "Fn::ImportValue": "aws-stepfunctions-intrinsics-integ:ExportsOutputRefStateMachine2E01A3A5BA46F753" + } + }, + "flattenResponse": "false", + "salt": "1666195539323" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ], + "Policies": [ + { + "PolicyName": "Inline", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "states:DescribeStateMachine" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ] + } + } + ] + } + }, + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Runtime": "nodejs14.x", + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "3074b79e05e7b98930b6449e01baa3e68b32ecff86328933c2542f7b7fe6fdac.zip" + }, + "Timeout": 120, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + } + }, + "Outputs": { + "AssertionResultsAwsApiCallStepFunctionsdescribeStateMachine": { + "Value": { + "Fn::GetAtt": [ + "AwsApiCallStepFunctionsdescribeStateMachine", + "assertion" + ] + } + } + }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/asset.3074b79e05e7b98930b6449e01baa3e68b32ecff86328933c2542f7b7fe6fdac.bundle/index.js b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/asset.3074b79e05e7b98930b6449e01baa3e68b32ecff86328933c2542f7b7fe6fdac.bundle/index.js new file mode 100644 index 0000000000000..6bee1ced2a9b7 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/asset.3074b79e05e7b98930b6449e01baa3e68b32ecff86328933c2542f7b7fe6fdac.bundle/index.js @@ -0,0 +1,767 @@ +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// lib/assertions/providers/lambda-handler/index.ts +var lambda_handler_exports = {}; +__export(lambda_handler_exports, { + handler: () => handler, + isComplete: () => isComplete, + onTimeout: () => onTimeout +}); +module.exports = __toCommonJS(lambda_handler_exports); + +// ../assertions/lib/matcher.ts +var Matcher = class { + static isMatcher(x) { + return x && x instanceof Matcher; + } +}; +var MatchResult = class { + constructor(target) { + this.failures = []; + this.captures = /* @__PURE__ */ new Map(); + this.finalized = false; + this.target = target; + } + push(matcher, path, message) { + return this.recordFailure({ matcher, path, message }); + } + recordFailure(failure) { + this.failures.push(failure); + return this; + } + hasFailed() { + return this.failures.length !== 0; + } + get failCount() { + return this.failures.length; + } + compose(id, inner) { + const innerF = inner.failures; + this.failures.push(...innerF.map((f) => { + return { path: [id, ...f.path], message: f.message, matcher: f.matcher }; + })); + inner.captures.forEach((vals, capture) => { + vals.forEach((value) => this.recordCapture({ capture, value })); + }); + return this; + } + finished() { + if (this.finalized) { + return this; + } + if (this.failCount === 0) { + this.captures.forEach((vals, cap) => cap._captured.push(...vals)); + } + this.finalized = true; + return this; + } + toHumanStrings() { + return this.failures.map((r) => { + const loc = r.path.length === 0 ? "" : ` at ${r.path.join("")}`; + return "" + r.message + loc + ` (using ${r.matcher.name} matcher)`; + }); + } + recordCapture(options) { + let values = this.captures.get(options.capture); + if (values === void 0) { + values = []; + } + values.push(options.value); + this.captures.set(options.capture, values); + } +}; + +// ../assertions/lib/private/matchers/absent.ts +var AbsentMatch = class extends Matcher { + constructor(name) { + super(); + this.name = name; + } + test(actual) { + const result = new MatchResult(actual); + if (actual !== void 0) { + result.recordFailure({ + matcher: this, + path: [], + message: `Received ${actual}, but key should be absent` + }); + } + return result; + } +}; + +// ../assertions/lib/private/type.ts +function getType(obj) { + return Array.isArray(obj) ? "array" : typeof obj; +} + +// ../assertions/lib/match.ts +var Match = class { + static absent() { + return new AbsentMatch("absent"); + } + static arrayWith(pattern) { + return new ArrayMatch("arrayWith", pattern); + } + static arrayEquals(pattern) { + return new ArrayMatch("arrayEquals", pattern, { subsequence: false }); + } + static exact(pattern) { + return new LiteralMatch("exact", pattern, { partialObjects: false }); + } + static objectLike(pattern) { + return new ObjectMatch("objectLike", pattern); + } + static objectEquals(pattern) { + return new ObjectMatch("objectEquals", pattern, { partial: false }); + } + static not(pattern) { + return new NotMatch("not", pattern); + } + static serializedJson(pattern) { + return new SerializedJson("serializedJson", pattern); + } + static anyValue() { + return new AnyMatch("anyValue"); + } + static stringLikeRegexp(pattern) { + return new StringLikeRegexpMatch("stringLikeRegexp", pattern); + } +}; +var LiteralMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.partialObjects = options.partialObjects ?? false; + if (Matcher.isMatcher(this.pattern)) { + throw new Error("LiteralMatch cannot directly contain another matcher. Remove the top-level matcher or nest it more deeply."); + } + } + test(actual) { + if (Array.isArray(this.pattern)) { + return new ArrayMatch(this.name, this.pattern, { subsequence: false, partialObjects: this.partialObjects }).test(actual); + } + if (typeof this.pattern === "object") { + return new ObjectMatch(this.name, this.pattern, { partial: this.partialObjects }).test(actual); + } + const result = new MatchResult(actual); + if (typeof this.pattern !== typeof actual) { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected type ${typeof this.pattern} but received ${getType(actual)}` + }); + return result; + } + if (actual !== this.pattern) { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected ${this.pattern} but received ${actual}` + }); + } + return result; + } +}; +var ArrayMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.subsequence = options.subsequence ?? true; + this.partialObjects = options.partialObjects ?? false; + } + test(actual) { + if (!Array.isArray(actual)) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected type array but received ${getType(actual)}` + }); + } + if (!this.subsequence && this.pattern.length !== actual.length) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected array of length ${this.pattern.length} but received ${actual.length}` + }); + } + let patternIdx = 0; + let actualIdx = 0; + const result = new MatchResult(actual); + while (patternIdx < this.pattern.length && actualIdx < actual.length) { + const patternElement = this.pattern[patternIdx]; + const matcher = Matcher.isMatcher(patternElement) ? patternElement : new LiteralMatch(this.name, patternElement, { partialObjects: this.partialObjects }); + const matcherName = matcher.name; + if (this.subsequence && (matcherName == "absent" || matcherName == "anyValue")) { + throw new Error(`The Matcher ${matcherName}() cannot be nested within arrayWith()`); + } + const innerResult = matcher.test(actual[actualIdx]); + if (!this.subsequence || !innerResult.hasFailed()) { + result.compose(`[${actualIdx}]`, innerResult); + patternIdx++; + actualIdx++; + } else { + actualIdx++; + } + } + for (; patternIdx < this.pattern.length; patternIdx++) { + const pattern = this.pattern[patternIdx]; + const element = Matcher.isMatcher(pattern) || typeof pattern === "object" ? " " : ` [${pattern}] `; + result.recordFailure({ + matcher: this, + path: [], + message: `Missing element${element}at pattern index ${patternIdx}` + }); + } + return result; + } +}; +var ObjectMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.partial = options.partial ?? true; + } + test(actual) { + if (typeof actual !== "object" || Array.isArray(actual)) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected type object but received ${getType(actual)}` + }); + } + const result = new MatchResult(actual); + if (!this.partial) { + for (const a of Object.keys(actual)) { + if (!(a in this.pattern)) { + result.recordFailure({ + matcher: this, + path: [`/${a}`], + message: "Unexpected key" + }); + } + } + } + for (const [patternKey, patternVal] of Object.entries(this.pattern)) { + if (!(patternKey in actual) && !(patternVal instanceof AbsentMatch)) { + result.recordFailure({ + matcher: this, + path: [`/${patternKey}`], + message: `Missing key '${patternKey}' among {${Object.keys(actual).join(",")}}` + }); + continue; + } + const matcher = Matcher.isMatcher(patternVal) ? patternVal : new LiteralMatch(this.name, patternVal, { partialObjects: this.partial }); + const inner = matcher.test(actual[patternKey]); + result.compose(`/${patternKey}`, inner); + } + return result; + } +}; +var SerializedJson = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const result = new MatchResult(actual); + if (getType(actual) !== "string") { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected JSON as a string but found ${getType(actual)}` + }); + return result; + } + let parsed; + try { + parsed = JSON.parse(actual); + } catch (err) { + if (err instanceof SyntaxError) { + result.recordFailure({ + matcher: this, + path: [], + message: `Invalid JSON string: ${actual}` + }); + return result; + } else { + throw err; + } + } + const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern); + const innerResult = matcher.test(parsed); + result.compose(`(${this.name})`, innerResult); + return result; + } +}; +var NotMatch = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern); + const innerResult = matcher.test(actual); + const result = new MatchResult(actual); + if (innerResult.failCount === 0) { + result.recordFailure({ + matcher: this, + path: [], + message: `Found unexpected match: ${JSON.stringify(actual, void 0, 2)}` + }); + } + return result; + } +}; +var AnyMatch = class extends Matcher { + constructor(name) { + super(); + this.name = name; + } + test(actual) { + const result = new MatchResult(actual); + if (actual == null) { + result.recordFailure({ + matcher: this, + path: [], + message: "Expected a value but found none" + }); + } + return result; + } +}; +var StringLikeRegexpMatch = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const result = new MatchResult(actual); + const regex = new RegExp(this.pattern, "gm"); + if (typeof actual !== "string") { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected a string, but got '${typeof actual}'` + }); + } + if (!regex.test(actual)) { + result.recordFailure({ + matcher: this, + path: [], + message: `String '${actual}' did not match pattern '${this.pattern}'` + }); + } + return result; + } +}; + +// lib/assertions/providers/lambda-handler/base.ts +var https = __toESM(require("https")); +var url = __toESM(require("url")); +var AWS = __toESM(require("aws-sdk")); +var CustomResourceHandler = class { + constructor(event, context) { + this.event = event; + this.context = context; + this.timedOut = false; + this.timeout = setTimeout(async () => { + await this.respond({ + status: "FAILED", + reason: "Lambda Function Timeout", + data: this.context.logStreamName + }); + this.timedOut = true; + }, context.getRemainingTimeInMillis() - 1200); + this.event = event; + this.physicalResourceId = extractPhysicalResourceId(event); + } + async handle() { + try { + if ("stateMachineArn" in this.event.ResourceProperties) { + const req = { + stateMachineArn: this.event.ResourceProperties.stateMachineArn, + name: this.event.RequestId, + input: JSON.stringify(this.event) + }; + await this.startExecution(req); + return; + } else { + const response = await this.processEvent(this.event.ResourceProperties); + return response; + } + } catch (e) { + console.log(e); + throw e; + } finally { + clearTimeout(this.timeout); + } + } + async handleIsComplete() { + try { + const result = await this.processEvent(this.event.ResourceProperties); + return result; + } catch (e) { + console.log(e); + return; + } finally { + clearTimeout(this.timeout); + } + } + async startExecution(req) { + try { + const sfn = new AWS.StepFunctions(); + await sfn.startExecution(req).promise(); + } finally { + clearTimeout(this.timeout); + } + } + respond(response) { + if (this.timedOut) { + return; + } + const cfResponse = { + Status: response.status, + Reason: response.reason, + PhysicalResourceId: this.physicalResourceId, + StackId: this.event.StackId, + RequestId: this.event.RequestId, + LogicalResourceId: this.event.LogicalResourceId, + NoEcho: false, + Data: response.data + }; + const responseBody = JSON.stringify(cfResponse); + console.log("Responding to CloudFormation", responseBody); + const parsedUrl = url.parse(this.event.ResponseURL); + const requestOptions = { + hostname: parsedUrl.hostname, + path: parsedUrl.path, + method: "PUT", + headers: { "content-type": "", "content-length": responseBody.length } + }; + return new Promise((resolve, reject) => { + try { + const request2 = https.request(requestOptions, resolve); + request2.on("error", reject); + request2.write(responseBody); + request2.end(); + } catch (e) { + reject(e); + } finally { + clearTimeout(this.timeout); + } + }); + } +}; +function extractPhysicalResourceId(event) { + switch (event.RequestType) { + case "Create": + return event.LogicalResourceId; + case "Update": + case "Delete": + return event.PhysicalResourceId; + } +} + +// lib/assertions/providers/lambda-handler/assertion.ts +var AssertionHandler = class extends CustomResourceHandler { + async processEvent(request2) { + let actual = decodeCall(request2.actual); + const expected = decodeCall(request2.expected); + let result; + const matcher = new MatchCreator(expected).getMatcher(); + console.log(`Testing equality between ${JSON.stringify(request2.actual)} and ${JSON.stringify(request2.expected)}`); + const matchResult = matcher.test(actual); + matchResult.finished(); + if (matchResult.hasFailed()) { + result = { + failed: true, + assertion: JSON.stringify({ + status: "fail", + message: [ + ...matchResult.toHumanStrings(), + JSON.stringify(matchResult.target, void 0, 2) + ].join("\n") + }) + }; + if (request2.failDeployment) { + throw new Error(result.assertion); + } + } else { + result = { + assertion: JSON.stringify({ + status: "success" + }) + }; + } + return result; + } +}; +var MatchCreator = class { + constructor(obj) { + this.parsedObj = { + matcher: obj + }; + } + getMatcher() { + try { + const final = JSON.parse(JSON.stringify(this.parsedObj), function(_k, v) { + const nested = Object.keys(v)[0]; + switch (nested) { + case "$ArrayWith": + return Match.arrayWith(v[nested]); + case "$ObjectLike": + return Match.objectLike(v[nested]); + case "$StringLike": + return Match.stringLikeRegexp(v[nested]); + default: + return v; + } + }); + if (Matcher.isMatcher(final.matcher)) { + return final.matcher; + } + return Match.exact(final.matcher); + } catch { + return Match.exact(this.parsedObj.matcher); + } + } +}; +function decodeCall(call) { + if (!call) { + return void 0; + } + try { + const parsed = JSON.parse(call); + return parsed; + } catch (e) { + return call; + } +} + +// lib/assertions/providers/lambda-handler/utils.ts +function decode(object) { + return JSON.parse(JSON.stringify(object), (_k, v) => { + switch (v) { + case "TRUE:BOOLEAN": + return true; + case "FALSE:BOOLEAN": + return false; + default: + return v; + } + }); +} + +// lib/assertions/providers/lambda-handler/sdk.ts +function flatten(object) { + return Object.assign( + {}, + ...function _flatten(child, path = []) { + return [].concat(...Object.keys(child).map((key) => { + let childKey = Buffer.isBuffer(child[key]) ? child[key].toString("utf8") : child[key]; + if (typeof childKey === "string") { + childKey = isJsonString(childKey); + } + return typeof childKey === "object" && childKey !== null ? _flatten(childKey, path.concat([key])) : { [path.concat([key]).join(".")]: childKey }; + })); + }(object) + ); +} +var AwsApiCallHandler = class extends CustomResourceHandler { + async processEvent(request2) { + const AWS2 = require("aws-sdk"); + console.log(`AWS SDK VERSION: ${AWS2.VERSION}`); + if (!Object.prototype.hasOwnProperty.call(AWS2, request2.service)) { + throw Error(`Service ${request2.service} does not exist in AWS SDK version ${AWS2.VERSION}.`); + } + const service = new AWS2[request2.service](); + const response = await service[request2.api](request2.parameters && decode(request2.parameters)).promise(); + console.log(`SDK response received ${JSON.stringify(response)}`); + delete response.ResponseMetadata; + const respond = { + apiCallResponse: response + }; + const flatData = { + ...flatten(respond) + }; + const resp = request2.flattenResponse === "true" ? flatData : respond; + console.log(`Returning result ${JSON.stringify(resp)}`); + return resp; + } +}; +function isJsonString(value) { + try { + return JSON.parse(value); + } catch { + return value; + } +} + +// lib/assertions/providers/lambda-handler/types.ts +var ASSERT_RESOURCE_TYPE = "Custom::DeployAssert@AssertEquals"; +var SDK_RESOURCE_TYPE_PREFIX = "Custom::DeployAssert@SdkCall"; + +// lib/assertions/providers/lambda-handler/index.ts +async function handler(event, context) { + console.log(`Event: ${JSON.stringify({ ...event, ResponseURL: "..." })}`); + const provider = createResourceHandler(event, context); + try { + if (event.RequestType === "Delete") { + await provider.respond({ + status: "SUCCESS", + reason: "OK" + }); + return; + } + const result = await provider.handle(); + if ("stateMachineArn" in event.ResourceProperties) { + console.info('Found "stateMachineArn", waiter statemachine started'); + return; + } else if ("expected" in event.ResourceProperties) { + console.info('Found "expected", testing assertions'); + const actualPath = event.ResourceProperties.actualPath; + const actual = actualPath ? result[`apiCallResponse.${actualPath}`] : result.apiCallResponse; + const assertion = new AssertionHandler({ + ...event, + ResourceProperties: { + ServiceToken: event.ServiceToken, + actual, + expected: event.ResourceProperties.expected + } + }, context); + try { + const assertionResult = await assertion.handle(); + await provider.respond({ + status: "SUCCESS", + reason: "OK", + data: { + ...assertionResult, + ...result + } + }); + return; + } catch (e) { + await provider.respond({ + status: "FAILED", + reason: e.message ?? "Internal Error" + }); + return; + } + } + await provider.respond({ + status: "SUCCESS", + reason: "OK", + data: result + }); + } catch (e) { + await provider.respond({ + status: "FAILED", + reason: e.message ?? "Internal Error" + }); + return; + } + return; +} +async function onTimeout(timeoutEvent) { + const isCompleteRequest = JSON.parse(JSON.parse(timeoutEvent.Cause).errorMessage); + const provider = createResourceHandler(isCompleteRequest, standardContext); + await provider.respond({ + status: "FAILED", + reason: "Operation timed out: " + JSON.stringify(isCompleteRequest) + }); +} +async function isComplete(event, context) { + console.log(`Event: ${JSON.stringify({ ...event, ResponseURL: "..." })}`); + const provider = createResourceHandler(event, context); + try { + const result = await provider.handleIsComplete(); + const actualPath = event.ResourceProperties.actualPath; + if (result) { + const actual = actualPath ? result[`apiCallResponse.${actualPath}`] : result.apiCallResponse; + if ("expected" in event.ResourceProperties) { + const assertion = new AssertionHandler({ + ...event, + ResourceProperties: { + ServiceToken: event.ServiceToken, + actual, + expected: event.ResourceProperties.expected + } + }, context); + const assertionResult = await assertion.handleIsComplete(); + if (!(assertionResult == null ? void 0 : assertionResult.failed)) { + await provider.respond({ + status: "SUCCESS", + reason: "OK", + data: { + ...assertionResult, + ...result + } + }); + return; + } else { + console.log(`Assertion Failed: ${JSON.stringify(assertionResult)}`); + throw new Error(JSON.stringify(event)); + } + } + await provider.respond({ + status: "SUCCESS", + reason: "OK", + data: result + }); + } else { + console.log("No result"); + throw new Error(JSON.stringify(event)); + } + return; + } catch (e) { + console.log(e); + throw new Error(JSON.stringify(event)); + } +} +function createResourceHandler(event, context) { + if (event.ResourceType.startsWith(SDK_RESOURCE_TYPE_PREFIX)) { + return new AwsApiCallHandler(event, context); + } else if (event.ResourceType.startsWith(ASSERT_RESOURCE_TYPE)) { + return new AssertionHandler(event, context); + } else { + throw new Error(`Unsupported resource type "${event.ResourceType}`); + } +} +var standardContext = { + getRemainingTimeInMillis: () => 9e4 +}; +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + handler, + isComplete, + onTimeout +}); diff --git a/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/aws-stepfunctions-intrinsics-integ.assets.json b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/aws-stepfunctions-intrinsics-integ.assets.json index f309a4b1ed461..d2e1e83193b8a 100644 --- a/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/aws-stepfunctions-intrinsics-integ.assets.json +++ b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/aws-stepfunctions-intrinsics-integ.assets.json @@ -1,7 +1,7 @@ { "version": "21.0.0", "files": { - "0969ff045f30d2fff3d0ee8d260f6d4ba27b98431560c1601d96fa47a574bd1b": { + "3e297f2466514c81633efd55d6b611657afa510cc934191cdd1ee23cdad3c30c": { "source": { "path": "aws-stepfunctions-intrinsics-integ.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "0969ff045f30d2fff3d0ee8d260f6d4ba27b98431560c1601d96fa47a574bd1b.json", + "objectKey": "3e297f2466514c81633efd55d6b611657afa510cc934191cdd1ee23cdad3c30c.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/aws-stepfunctions-intrinsics-integ.template.json b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/aws-stepfunctions-intrinsics-integ.template.json index c091a48351cfe..4b26dc59ad824 100644 --- a/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/aws-stepfunctions-intrinsics-integ.template.json +++ b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/aws-stepfunctions-intrinsics-integ.template.json @@ -135,6 +135,16 @@ } } }, + "Outputs": { + "ExportsOutputRefStateMachine2E01A3A5BA46F753": { + "Value": { + "Ref": "StateMachine2E01A3A5" + }, + "Export": { + "Name": "aws-stepfunctions-intrinsics-integ:ExportsOutputRefStateMachine2E01A3A5BA46F753" + } + } + }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/manifest.json index b76e7293a4ac1..610687b57db93 100644 --- a/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/manifest.json @@ -23,7 +23,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/0969ff045f30d2fff3d0ee8d260f6d4ba27b98431560c1601d96fa47a574bd1b.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/3e297f2466514c81633efd55d6b611657afa510cc934191cdd1ee23cdad3c30c.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -57,6 +57,12 @@ "data": "ServiceprincipalMap" } ], + "/aws-stepfunctions-intrinsics-integ/Exports/Output{\"Ref\":\"StateMachine2E01A3A5\"}": [ + { + "type": "aws:cdk:logicalId", + "data": "ExportsOutputRefStateMachine2E01A3A5BA46F753" + } + ], "/aws-stepfunctions-intrinsics-integ/BootstrapVersion": [ { "type": "aws:cdk:logicalId", @@ -88,7 +94,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/9efe81f855fa5f7925cf5a69c0ef1ff9563e05b71711a017100aa3d0e6921ab0.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -101,9 +107,34 @@ } }, "dependencies": [ + "aws-stepfunctions-intrinsics-integ", "StateMachineIntrinsicsTestDefaultTestDeployAssert1C1E1D7E.assets" ], "metadata": { + "/StateMachineIntrinsicsTest/DefaultTest/DeployAssert/AwsApiCallStepFunctionsdescribeStateMachine/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "AwsApiCallStepFunctionsdescribeStateMachine" + } + ], + "/StateMachineIntrinsicsTest/DefaultTest/DeployAssert/AwsApiCallStepFunctionsdescribeStateMachine/AssertionResults": [ + { + "type": "aws:cdk:logicalId", + "data": "AssertionResultsAwsApiCallStepFunctionsdescribeStateMachine" + } + ], + "/StateMachineIntrinsicsTest/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Role": [ + { + "type": "aws:cdk:logicalId", + "data": "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73" + } + ], + "/StateMachineIntrinsicsTest/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Handler": [ + { + "type": "aws:cdk:logicalId", + "data": "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F" + } + ], "/StateMachineIntrinsicsTest/DefaultTest/DeployAssert/BootstrapVersion": [ { "type": "aws:cdk:logicalId", diff --git a/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/tree.json b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/tree.json index f7b84b009cd20..34c717c5aa1c2 100644 --- a/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-stepfunctions/test/intrinsics.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.123" + "version": "10.1.129" } }, "aws-stepfunctions-intrinsics-integ": { @@ -104,6 +104,24 @@ "fqn": "@aws-cdk/core.CfnMapping", "version": "0.0.0" } + }, + "Exports": { + "id": "Exports", + "path": "aws-stepfunctions-intrinsics-integ/Exports", + "children": { + "Output{\"Ref\":\"StateMachine2E01A3A5\"}": { + "id": "Output{\"Ref\":\"StateMachine2E01A3A5\"}", + "path": "aws-stepfunctions-intrinsics-integ/Exports/Output{\"Ref\":\"StateMachine2E01A3A5\"}", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.129" + } } }, "constructInfo": { @@ -124,12 +142,102 @@ "path": "StateMachineIntrinsicsTest/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.123" + "version": "10.1.129" } }, "DeployAssert": { "id": "DeployAssert", "path": "StateMachineIntrinsicsTest/DefaultTest/DeployAssert", + "children": { + "AwsApiCallStepFunctionsdescribeStateMachine": { + "id": "AwsApiCallStepFunctionsdescribeStateMachine", + "path": "StateMachineIntrinsicsTest/DefaultTest/DeployAssert/AwsApiCallStepFunctionsdescribeStateMachine", + "children": { + "SdkProvider": { + "id": "SdkProvider", + "path": "StateMachineIntrinsicsTest/DefaultTest/DeployAssert/AwsApiCallStepFunctionsdescribeStateMachine/SdkProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "StateMachineIntrinsicsTest/DefaultTest/DeployAssert/AwsApiCallStepFunctionsdescribeStateMachine/SdkProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.129" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.AssertionsProvider", + "version": "0.0.0" + } + }, + "Default": { + "id": "Default", + "path": "StateMachineIntrinsicsTest/DefaultTest/DeployAssert/AwsApiCallStepFunctionsdescribeStateMachine/Default", + "children": { + "Default": { + "id": "Default", + "path": "StateMachineIntrinsicsTest/DefaultTest/DeployAssert/AwsApiCallStepFunctionsdescribeStateMachine/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "AssertionResults": { + "id": "AssertionResults", + "path": "StateMachineIntrinsicsTest/DefaultTest/DeployAssert/AwsApiCallStepFunctionsdescribeStateMachine/AssertionResults", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.AwsApiCall", + "version": "0.0.0" + } + }, + "SingletonFunction1488541a7b23466481b69b4408076b81": { + "id": "SingletonFunction1488541a7b23466481b69b4408076b81", + "path": "StateMachineIntrinsicsTest/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81", + "children": { + "Staging": { + "id": "Staging", + "path": "StateMachineIntrinsicsTest/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Staging", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "Role": { + "id": "Role", + "path": "StateMachineIntrinsicsTest/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Role", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "Handler": { + "id": "Handler", + "path": "StateMachineIntrinsicsTest/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Handler", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.129" + } + } + }, "constructInfo": { "fqn": "@aws-cdk/core.Stack", "version": "0.0.0" From 452e2516f547f464ac4298b6fd7be9ab7cf534f3 Mon Sep 17 00:00:00 2001 From: Konosuke Kachi Date: Thu, 20 Oct 2022 18:02:24 +0900 Subject: [PATCH 8/8] Fix lint errors --- .../@aws-cdk/aws-stepfunctions/test/private/json-path.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-stepfunctions/test/private/json-path.test.ts b/packages/@aws-cdk/aws-stepfunctions/test/private/json-path.test.ts index 2e702fdc61c13..20a7b3a2bcec6 100644 --- a/packages/@aws-cdk/aws-stepfunctions/test/private/json-path.test.ts +++ b/packages/@aws-cdk/aws-stepfunctions/test/private/json-path.test.ts @@ -1,5 +1,5 @@ -import { renderInExpression } from '../../lib/private/json-path'; import { JsonPath } from '../../lib'; +import { renderInExpression } from '../../lib/private/json-path'; describe('RenderInExpression', () => { test('simple number', () => { @@ -22,5 +22,5 @@ describe('RenderInExpression', () => { }); test('raw array', () => { expect(() => renderInExpression([1, 2])).toThrow(); - }) + }); });