Giter Club home page Giter Club logo

asl-validator's People

Contributors

aslafy-z avatar christophebougere avatar crazyglue avatar egnwd avatar fernly-park avatar fossabot avatar hervenivon avatar hhprogram avatar massfords avatar monken avatar noxharmonium avatar oshikiri avatar pwtyler avatar ramgrandhi avatar spcape avatar taschmidt avatar theburningmonk avatar tvhees avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

asl-validator's Issues

Parallel state should allow Catch property

Given a Parallel state

{
  "States": {
    "A": {
      "Type": "Parallel",
      "Branches": [
        {
          "StartAt": "B",
          "States": {
            "B": {
              "Type": "Fail"
            }
          }
        },
        {
          "StartAt": "C",
          "States": {
            "C": {
              "Type": "Pass",
              "End": true
            }
          }
        }
      ],
      "Catch": {
        "ErrorEquals": [
          "States.ALL"
        ],
        "Next": "D"
      }
    },
    "D": {
      "Type": "Fail"
    }
  }
}

It should allow the Catch property: http://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-parallel-state.html?shortFooter=true

However it fails.

Version 1.0.2

Parallel States forced to be followed by choice state

For some reason State Machines with a Parallel State only validate if they are immediately followed by a choice state, even though other states are valid.
Ex: This returns invalid, when it isn't.

{
	"StartAt": "Parallel State",
	"States":{
		"Parallel State":{
			"Type":"Parallel",
			"Branches":[
				{
					"StartAt":"DummyState",
					"States":{
						"DummyState": {
							"Type": "Pass",
							"End": "True"	
						}
					}
				},
				{
					"StartAt":"DummyState2",
					"States":{
						"DummyState2": {
							"Type": "Pass",
							"End": "True"
						}
					}
				}
			],
			"Next":"Finished"
		},
		"Finished": {
			"Type": "Pass",
			"End": true
		}
	}
}

Validator not linting, always shows help

Describe the bug
When trying to use the validator, it prints the help.
I'm passing the the --json-path just as always but it prints the help

To Reproduce
just try to use it:

$ asl-validator --json-path states_good_1.json
Usage: asl-validator [options]

Amazon States Language validator

Options:
  -v, --version                       output the version number
  --json-definition <jsonDefinition>  JSON definition
  --json-path <jsonPath>              JSON path
  --silent                            silent mode
  -h, --help                          display help for command
any jsonm or file

Expected behavior
The linter/validator should run

Version: [e.g. 1.9.4, can be found by running asl-validator --version]
1.9.7

Additional context
Add any other context about the problem here.

Validation error in Parameters for Task type Pass

Describe the bug
For State Type Pass it throws validation errror

 keyword: 'type',
    dataPath: ".States['EmptyState'].Parameters[0]",
    schemaPath: 'pass.json#/properties/Parameters/items/type',
    params: { type: 'object' },
    message: 'should be object'

To Reproduce
Please provide a complete state machine definition:

{
  "StartAt": "EmptyState",
  "States": {
    "EmptyState": {
       "Type": "Pass",
      "Parameters": ["abc"],
      "ResultPath": "$.emptyState",
      "End": true
    }
  }
}

Expected behavior

Parameters can accept ARRAY, NUMBER, BOOLEAN, OBJECT, STRING

Version: [e.g. 1.9.4, can be found by running asl-validator --version]
2.2.1
Additional context
Add any other context about the problem here.

ResultPath: null breaks validator

It is valid syntax to set the ResultPath to null (and is useful sometimes when you don't need the result and don't want it taking up space in your state object). But it breaks the parser. It throws the following error:

{ AssertionError [ERR_ASSERTION]: we need a path null
    at JSONPath.parse (/Users/marissa/Desktop/Local_Sites/stagingpilot-serverless/deployBySfn/node_modules/jsonpath/lib/index.js:16:10)
    at jp.query.map (/Users/marissa/Desktop/Local_Sites/stagingpilot-serverless/deployBySfn/node_modules/asl-validator/src/validator.js:33:12)
    at Array.map (<anonymous>)
    at validator (/Users/marissa/Desktop/Local_Sites/stagingpilot-serverless/deployBySfn/node_modules/asl-validator/src/validator.js:31:6)
    at module.exports (/Users/marissa/Desktop/Local_Sites/stagingpilot-serverless/deployBySfn/src/validateASL.js:29:30)
    at AwsInvokeLocal.invokeLocalNodeJs (/usr/local/lib/node_modules/serverless/lib/plugins/aws/invokeLocal/index.js:331:12)
    at AwsInvokeLocal.invokeLocal (/usr/local/lib/node_modules/serverless/lib/plugins/aws/invokeLocal/index.js:125:19)
    at AwsInvokeLocal.tryCatcher (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/promise.js:512:31)
    at Promise._settlePromise (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromise0 (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/promise.js:614:10)
    at Promise._settlePromises (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/promise.js:693:18)
    at Async._drainQueue (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/async.js:133:16)
    at Async._drainQueues (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/async.js:143:10)
    at Immediate.Async.drainQueues (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/async.js:17:14)
    at runCallback (timers.js:789:20)
    at tryOnImmediate (timers.js:751:5)
    at processImmediate [as _immediateCallback] (timers.js:722:5)
    generatedMessage: false,
    name: 'AssertionError [ERR_ASSERTION]',
    code: 'ERR_ASSERTION',
    actual: false,
    expected: true,
    operator: '==' }

But it also then causes normal tasks to return errors claiming Resource is an additional property or that it isn't a string when it is.

{ keyword: 'additionalProperties',
    dataPath: '.States[\'Log Status: Beginning Updates\']',
    schemaPath: 'http://asl-validator.cloud/succeed#/additionalProperties',
    params: { additionalProperty: 'Resource' },
    message: 'should NOT have additional properties' }

null is no longer a valid ResultPath

Describe the bug
"ResultPath": null is used for discarding the output of a state. Since upgrading to 3.0.2, schema validation is now failing with:

[
  {
    'Error code': 'SCHEMA_VALIDATION_FAILED',
    Message: '/States/Hello/ResultPath is invalid. must be string',
    schemaError: {
      instancePath: '/States/Hello/ResultPath',
      schemaPath: 'paths.json#/definitions/asl_ref_path/type'
    }
  }
]

To Reproduce

{
    "StartAt": "Hello",
    "States": {
        "Hello": {
            "Type": "Task",
            "Resource": "arn:aws:lambda:us-east-1:123456789012:function:foo",
            "Parameters": {
                "foo.$": "$.foo"
            },
            "ResultPath": null,
            "Next": "Goodbye"
        },
        "Goodbye": {
            "Type": "Succeed"
        }
    }
}

Expected behavior

null is accepted as a valid ResultPath.

Version:
3.0.2

Definition of "Branches" is incorrect

In the parallel.json schema, Branches is defined as:

{
    "Branches": {
      "type": "array",
      "items": {
        "types": {
          "$ref": "http://asl-validator.cloud/state-machine#"
        }
      }
    }
}

This seems to be invalid and results in allowing anything to be included in a branch.

The correct definition is:

{
    "Branches": {
      "type": "array",
      "items": {
          "$ref": "http://asl-validator.cloud/state-machine#"
      }
    }
}

Error in asl inspection in test case

Describe the bug
A clear and concise description of what the bug is.
Error in asl inspection in test case
{
'Error code': 'SCHEMA_VALIDATION_FAILED',
Message: '/States/X is invalid. must match exactly one schema in oneOf',
schemaError: { instancePath: '/States/X', schemaPath: '#/oneOf' }
}
To Reproduce
Please provide a complete state machine definition:

{
  "Comment": "https://states-language.net/spec.html#parameters",
  "StartAt": "X",
  "States": {
    "X": {
      "Type": "Task",
      "Resource": "arn:aws:swf:us-east-1:123456789012:task:X",
      "Parameters": {
        "flagged": true,
        "parts": {
          "first.$": "$.vals[0]",
          "last3.$": "$.vals[3:]"
        }
      },
      "End": true
    }
  }
}

Expected behavior
A clear and concise description of what you expected to happen.

Version:
3.0.8
Additional context
Add any other context about the problem here.

Add YAML support

Is your feature request related to a problem? Please describe.
ASL written in YAML is supported natively by various AWS tools (https://docs.aws.amazon.com/step-functions/latest/dg/development-options.html#development-options-format) and makes ASL significantly easier to read, write and annotate - YAML supports inline comments, multiline strings, amongst other features.

Describe the solution you'd like
The ASL validator tool to be able to validate .yaml/.yml files natively, ideally automatically loading the file based upon its type (e.g. asl-validator statemachine/foo.asl.yml).

Describe alternatives you've considered
I'm currently converting my YAML into JSON dynamically and passing it through at the shell level, like so:

asl-validator --json-definition "$(yq @json statemachine/stock-buyer.asl.yml)"

This works, but isn't easily typed out and relies on having a separate application to perform the conversion.

Additional context
N/A

asl-validator not working on the browser

Describe the bug
I am getting the following error when I try to run the validation on my React application

TypeError: _uniq is not a function
    at unique (jsonpath.js:4851:1)
    at Handlers.subscript-descendant-union (jsonpath.js:4711:1)
    at jsonpath.js:5001:1
    at Array.forEach (<anonymous>)
    at jsonpath.js:4998:1
    at Array.forEach (<anonymous>)
    at JSONPath.nodes (jsonpath.js:4992:1)
    at JSONPath.query (jsonpath.js:4958:1)
    at module.exports (json-path-errors.js:3:1)
    at validator (validator.js:40:1)

To Reproduce
The error comes up with any state machine

aslValidator({});

Version: 2.0.0

invalid transition out of a Parallel or Map container not caught by validator

Describe the bug
The Parallel and Map states do not allow states to link into or out from the state machine nested within a branch or iterator.

Here's the relevant part of the spec for Parallel:

A state in a Parallel State branch "States" field MUST NOT have a "Next" field that targets a field outside of that "States" field. A state MUST NOT have a "Next" field which matches a state name inside a Parallel State branch’s "States" field unless it is also inside the same "States" field.

Put another way, states in a branch’s "States" field can transition only to each other, and no state outside of that "States" field can transition into it.

To Reproduce
PR with test cases is inbound. Here's the parallel test:

{
  "Comment": "An example of the Amazon States Language using a parallel state to execute two branches at the same time.",
  "StartAt": "Parallel",
  "States": {
    "Parallel": {
      "Type": "Parallel",
      "Next": "Final State",
      "Branches": [
        {
          "StartAt": "Wait 20s",
          "States": {
            "Wait 20s": {
              "Type": "Wait",
              "Seconds": 20,
              "End": true
            }
          }
        },
        {
          "StartAt": "Pass",
          "States": {
            "Pass": {
              "Type": "Pass",
              "Next": "ChoiceState"
            },
            "ChoiceState": {
              "Type": "Choice",
              "Choices": [
                {
                  "Variable": "$.foo",
                  "NumericEquals": 1,
                  "Next": "Wait 10s"
                },
                {
                  "Variable": "$.foo",
                  "NumericEquals": 2,
                  "Next": "Final State" <---- this is an error
                }
              ],
              "Default": "Wait 10s"
            },
            "Wait 10s": {
              "Type": "Wait",
              "Seconds": 10,
              "End": true
            }
          }
        }
      ]
    },
    "Final State": {
      "Type": "Pass",
      "End": true
    }
  }
}

Expected behavior
Error is reported when a branch/iterator tries to link to a state outside of its container

Version:
2.0.0

Additional context
Add any other context about the problem here.

Error in schema validation for ToleratedFailureCount

Describe the bug
A clear and concise description of what the bug is.
Error when try to deploy from serverless yaml as JSON path with "ToleratedFailureCountPath" or any of these with validate mode ON.
**

ToleratedFailureCountPath/ToleratedFailureCount
ToleratedFailurePercentagePath/ToleratedFailurePercentageCount

**
Error:
✕ State machine "myMachine" definition is invalid:
SCHEMA_VALIDATION_FAILED: /States/X is invalid. must match exactly one schema in oneOf
To Reproduce
Please provide a complete state machine definition:

    maMachine:
      name: 'maMachine'
      definition:
        Comment: 'step f demo distributed mode'
        StartAt: X
        States:
          X:
            Type: Map
            MaxConcurrency: 100
            ToleratedFailureCountPath: "$.Count"
            ItemsPath: "$"
            ItemReader:
              ReaderConfig:
                InputType: JSON
              Resource: 'arn:aws:states:::s3:getObject'
              Parameters:
                Bucket: 'BUCKET_NAME'
                Key: 'key'
            ItemProcessor:
              ProcessorConfig:
                Mode: DISTRIBUTED
                ExecutionType: EXPRESS
              StartAt: ProcessArrayElement
              States:
                ProcessArrayElement:
                  Type: Task
                  Resource:
                    Fn::GetAtt: [lambdafunc, Arn]
                  End: true
            Label: Map
            End: true

Expected behavior
State machine "myMachine" definition is valid

Version:
node 16.17.0
serverless 3.25.1
SDK 4.3.2
serverless-step-functions: "^3.12.0"

Map ItemProcessor schema fails to validate unless ProcessorConfig is present

Describe the bug
Map's ItemProcessor schema fails to validate unless ProcessorConfig is present, despite this field being optional (spec references below); when not present inline mode is used. The issue is caused by the requirement that the schema match oneOf the subschemas at https://github.com/ChristopheBougere/asl-validator/blob/main/src/schemas/map.json#L75.

To Reproduce

{
  "StartAt": "Do Things",
  "States": {
    "Do Things": {
      "Type": "Map",
      "ItemProcessor": {
        "StartAt": "Run",
        "States": {
          "Run": {
            "Type": "Pass",
            "Result": {
              "ok": true
            },
            "End": true
          }
        }
      },
      "End": true
    }
  }
}

Expected behavior
The schema to successfully validate.

Version: 3.6.1

Additional context
Ref: https://states-language.net/#map-item-processor

The "ItemProcessor" field MAY contain a field named "ProcessorConfig", whose value MUST be a JSON object whose value is defined by the interpreter. The interpreter will execute the ItemProcessor according to the ProcessorConfig.

Ref: https://docs.aws.amazon.com/step-functions/latest/dg/concepts-asl-use-map-state-inline.html#map-state-inline-additional-fields

ProcessorConfig – An optional JSON object that specifies the processing mode for the Map state. This object contains the Mode sub-field. This field defaults to INLINE, which uses the Map state in Inline mode.

OutputPath "$.[0]" causes an error during validation

Hello,

When setting the OutputPath of a step function to "$.[0]" the following error occurs although this is a valid output of a step function.

✕ State machine definition is invalid: [ Error: Parse error on line 1:
  $.[0]
  --^
  Expecting 'STAR', 'IDENTIFIER', 'SCRIPT_EXPRESSION', 'INTEGER', 'END', got '['
      at Parser.parseError (/home/mojo/node_modules/jsonpath/generated/parser.js:166:15)
      at Parser.parser.yy.parseError (/home/mojo/node_modules/jsonpath/lib/parser.js:13:17)
      at Parser.parse (/home/mojo/node_modules/jsonpath/generated/parser.js:224:22)
      at JSONPath.parse (/home/mojo/node_modules/jsonpath/lib/index.js:17:22)
      at jp.query.filter.map (/home/mojo/node_modules/asl-validator/src/lib/json-path-errors.js:7:10)
      at Array.map (<anonymous>)
      at module.exports.definition (/home/mojo/node_modules/asl-validator/src/lib/json-path-errors.js:5:4)
      at validator (/home/mojo/node_modules/asl-validator/src/validator.js:33:26)
      at Object.<anonymous> (/home/mojo/node_modules/asl-validator/bin/asl-validator.js:55:18)
      at Module._compile (internal/modules/cjs/loader.js:778:30) ]

My minimal step function to reproduce this error is:

{
	"StartAt": "SampleTask",
	"States": {
		"SampleTask": {
			"Type": "Task",
			"OutputPath": "$.[0]",
			"Resource": {
				"Fn::GetAtt": [
					"account-input",
					"Arn"
				]
			},
			"End": true
		}
	}
}

What i don't understand is, that it seems like the schema is just checking if it is string or null. So i don't get why a string with a bracket causes this issue.

Thank you!

Why this template is invalid?

Hi, first time using this script.

This is the sample from aws console:

{
  "Comment": "An example of the Amazon States Language for scheduling a task.",
  "StartAt": "Wait for Timestamp",
  "States": {
    "Wait for Timestamp": {
      "Type": "Wait",
      "SecondsPath": "$.timer_seconds",
      "Next": "Send SNS Message"
    },
    "Send SNS Message": {
      "Type": "Task",
      "Resource": "arn:0000000000:lambda:::function:SendToSNS",
      "Retry": [
        {
          "ErrorEquals": [
            "States.ALL"
          ],
          "IntervalSeconds": 1,
          "MaxAttempts": 3,
          "BackoffRate": 2
        }
      ],
      "End": true
    }
  }
}

This is the error:

asl-validator --json-path example.json
✕ State machine definition is invalid: [ { keyword: 'additionalProperties',
    dataPath: ".States['Send SNS Message']",
    schemaPath: '#/additionalProperties',
    params: { additionalProperty: 'Resource' },
    message: 'should NOT have additional properties' },
  { keyword: 'additionalProperties',
    dataPath: ".States['Send SNS Message']",
    schemaPath: 'http://asl-validator.cloud/fail#/additionalProperties',
    params: { additionalProperty: 'Resource' },
    message: 'should NOT have additional properties' },
  { keyword: 'additionalProperties',
    dataPath: ".States['Send SNS Message']",
    schemaPath: '#/additionalProperties',
    params: { additionalProperty: 'Resource' },
    message: 'should NOT have additional properties' },
  { keyword: 'additionalProperties',
    dataPath: ".States['Send SNS Message']",
    schemaPath: 'http://asl-validator.cloud/pass#/additionalProperties',
    params: { additionalProperty: 'Resource' },
    message: 'should NOT have additional properties' },
  { keyword: 'additionalProperties',
    dataPath: ".States['Send SNS Message']",
    schemaPath: 'http://asl-validator.cloud/succeed#/additionalProperties',
    params: { additionalProperty: 'Resource' },
    message: 'should NOT have additional properties' },
  { keyword: 'pattern',
    dataPath: ".States['Send SNS Message'].Resource",
    schemaPath:
     'http://asl-validator.cloud/task#/properties/Resource/pattern',
    params:
     { pattern: '^arn:aws:([a-z]|-)+:([a-z]|[0-9]|-)*:[0-9]*:([a-z]|-)+:.+$' },
    message:
     'should match pattern "^arn:aws:([a-z]|-)+:([a-z]|[0-9]|-)*:[0-9]*:([a-z]|-)+:.+$"' },
  { keyword: 'additionalProperties',
    dataPath: ".States['Send SNS Message']",
    schemaPath: 'http://asl-validator.cloud/wait#/additionalProperties',
    params: { additionalProperty: 'Resource' },
    message: 'should NOT have additional properties' },
  { keyword: 'oneOf',
    dataPath: ".States['Send SNS Message']",
    schemaPath: '#/oneOf',
    params: { passingSchemas: null },
    message: 'should match exactly one schema in oneOf' } ]


nested maps generate an error due to bad path expression in validator

Describe the bug
I'm getting this error with an ASL with a nested map.

Parse error on line 1:
    $.['Next','Default']

It's due to the newly merged state-transitions.js code.

To Reproduce
Please provide a complete state machine definition:

{
  "StartAt": "Map",
  "States": {
    "Map": {
      "Type": "Map",
      "Next": "Final State",
      "Iterator": {
        "StartAt": "Map2",
        "States": {
          "Map2": {
            "Type": "Map",
            "End": true,
            "Iterator": {
              "StartAt": "Wait 20s",
              "States": {
                "Wait 20s": {
                  "Type": "Wait",
                  "Seconds": 20,
                  "End": true
                }
              }
            }
          }
        }
      }
    },
    "Final State": {
      "Type": "Succeed"
    }
  }
}

Expected behavior
no error

Version: 2.1.0

Additional context
I was missing a test case for a nested map so it wasn't hitting this path in the code. The migration to jsonpath-plus will fix this but it could also be fixed with the existing jsonpath library.

Incorrect transition target error for Choice state

For a Choice state, Default target is optional [1]. Yet asl-validator fails when Default is not present.

For example, this

Choose X:
  Type: Choice
  Choices:
    - Variable: "$.foo"
      BooleanEquals: true
      Next: True State
    - Variable: "$.foo"
      BooleanEquals: false
      Next: False State

will fail with

[
  {
    'Error code': 'MISSING_TRANSITION_TARGET',
    Message: "Missing 'StartAt'|'Next'|'Default' target: Choose X"
  }
]

I believe this condition needs to be fixed

// check if all 'Next', 'StartAt' and 'Default' states exist
const inexistant = reachableStates.filter((state) => machineStates.indexOf(state) === -1)
.map((state) => ({
'Error code': 'MISSING_TRANSITION_TARGET',
Message: `Missing 'StartAt'|'Next'|'Default' target: ${state}`,
}));

[1] https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-choice-state.html

Add check for Wait state timestamp and seconds fields

Describe the bug
The Wait state property Seconds cannot be used with SecondsPath. The same is true for Timestamp and TimestampPath

To Reproduce
I'll add a test case to demonstrate

Expected behavior
Validator should report an error on a Wait state with conflicting properties

Version:
3.x

Additional context
Follow on work from #119

Validator accepting states with invalid state names exceeding the 80 character limit.

Describe the bug
State names have an 80-character limit enforced by AWS, but not caught by asl-validator.

On deploy, AWS throws:

An error occurred (InvalidDefinition) when calling the CreateStateMachine operation: Invalid State Machine Definition: 'INVALID_STATE_NAME: Invalid State name: State 'This is an exceptionally long state name that I know will fail when I try to deploy to AWS' exceeds the 80-character limit allowed by the service at /States/This is an exceptionally long state name that I know will fail when I try to deploy to AWS'

To Reproduce
Please provide a complete state machine definition:

{
	"Comment": "Passing asl-validator but fails to deploy.",
	"StartAt": "Hello",
	"States": {
		"Hello": {
			"Type": "Pass",
			"Next": "This is an exceptionally long state name that I know will fail when I try to deploy to AWS"
		},
		"This is an exceptionally long state name that I know will fail when I try to deploy to AWS": {
			"Type": "Pass",
			"End": true
		}
	}
}

Expected behavior
asl-validator would catch the invalid state name and raise an error.

Version:
1.9.5

Pass state fails validation when InputPath is used to access the Context Object

Hello, In August 2020, AWS released numerous updates for Step Functions, most of which you support. They added support for accessing the Context Object outside of just Parameters. See https://docs.aws.amazon.com/step-functions/latest/dg/input-output-contextobject.html

When using a Pass State with an InputPath to referencing the $$.Execution.Id the validator returns an error even though this properly deployed and works without issue. I also started an issue at serverless-step-functions, but it seems the correct place for this is here. I have tested this InputPath in other states and it seems the same issue exists across the board.

definition:
  Comment: "Testing getting Context Object from InputPath in Pass State"
  StartAt: pass-execution-details
  States:
    pass-execution-details:
      Type: Pass
      ResultPath: $.AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID
      InputPath: $$.Execution.Id
      End: True

This fails with:

✕ State machine "test-pass-inputpath" definition is invalid:
  undefined: undefined
  No errors

The code from serverless-step-functions

        if (stateMachineObj.definition) {
          if (this.serverless.service.stepFunctions.validate) {
            const { isValid, errorsText } = aslValidator(stateMachineObj.definition);
            if (isValid) {
              this.serverless.cli.consoleLog(`✓ State machine "${stateMachineName}" definition is valid`);
            } else {
              const errorMessage = [
                `✕ State machine "${stateMachineName}" definition is invalid:`,
                errorsText(),
              ].join('\n');
              throw new this.serverless.classes.Error(errorMessage);
            }
          }

replace JSON path expression in mustNotHaveDuplicateFieldNamesAfterEvaluation with a traversal

Describe the bug
The JSON path expression used to identify the objects in the payload to check for duplicate fields throws an error when it encounters an array. This looks to be an issue in the jsonpath-plus library.

To Reproduce
Use the input for #104 (part of the repo now in valid-parameters-issue104.json and remove the try/catch added in mustNotHaveDuplicateFieldNamesAfterEvaluation

Expected behavior
Shouldn't throw a runtime exception from the jsonpath-plus library. Should instead correctly report the payload template as valid or invalid.

Version:
3.0.x

Additional context
I think the fix is to replace the jsonpath-plus specific expression $..[Parameters,ResultSelector]..*[?(@property.match(/^.+\.\$$/))][0]^^ with a simple graph traversal. There's too much dark magic in the expression evaluation even without this array handling issue.

Duplicate state name is not caught during validation

Describe the bug
State names must be unique within the scope of the whole state machine.

To Reproduce
PR is inbound w/ a test

{
  "Comment": "Exhibits duplicate state error. State names MUST be unique within the scope of the whole state machine.",
  "StartAt": "Map",
  "States": {
    "Map": {
      "Type": "Map",
      "Next": "Final State",
      "InputPath": "$.input",
      "ItemsPath": "$.items",
      "MaxConcurrency": 0,
      "Iterator": {
        "StartAt": "Final State",
        "States": {
          "Final State": {
            "Type": "Wait",
            "Seconds": 20,
            "End": true
          }
        }
      },
      "ResultPath": "$.result"
    },
    "Final State": {
      "Type": "Pass",
      "End": true
    }
  }
}

Expected behavior
Report an error

Version:
2.0.0

Additional context

Uncaught Error in Catch/retry

Sorry to keep posting things. I found another error which isn't caught. The following code returns as valid, but actually Error Equals should be ErrorEquals. It's missed in both catch and retry blocks.

{
  "StartAt": "Testing",
  "States": {
    "Testing": {
      "Type": "Task",
	  "Resource": "arn:aws:lambda:us-west-2:111126812102:function:some-dev-function",
	  "Catch": [
		{
			"Error Equals": [
				"Some Error"
			],
			"Next": "Success"
		}
	  ],
      "Next": "Success"
    },
    "Success": {
      "Type": "Pass",
      "End": true
    }
  }
}

loc.indexOf is not a function (jsonpath-plus regression)

Describe the bug
2.2.0 with jsonpath-plus introduced a regression where an OutputPath like $[(@.length-1)].bar throws an error.

Same state machine definition passes validation in <2.2.0 and works in Step Functions.

To Reproduce

{
  "StartAt": "map",
  "States": {
    "map": {
      "Type": "Map",
      "End": true,
      "InputPath": "$",
      "ItemsPath": "$.foo",
      "Parameters": {
        "bar.$": "$"
      },
      "Iterator": {
        "StartAt": "pass",
        "States": {
          "pass": {
            "Type": "Pass",
            "End": true
          }
        }
      },
      "ResultPath": "$",
      "OutputPath": "$[(@.length-1)].bar"
    }
  }
}

Expected behavior
This is a valid state machine, it should not error out with loc.indexOf is not a function.

Version: 2.2.0

False positive error with nested parallelism

Describe the bug
Certain cases of nested parallelism cause false positive validation errors from this library.
I've tracked it down to the JSONPath in nextAndDefaultTargets, $.[Next,Default] for "container" states, not working as I think it's intended to.

To Reproduce
I've added a test case in the associated PR.

Expected behavior
No validation error for the attached test case, which AWS happily accepts.

Version:
2.2.1

Validator does not catch invalid field value in Parameters object

Version: 1.7.0
The following state definition should fail validation:

{
  "Comment": "This SFN Should Fail Validation but does not",
  "StartAt": "Hello, World",
  "States": {
    "Hello, World": {
      "Type": "Task",
      "Parameters": {
        "foo": "bar",
        "lorem.$": "ipsum",
        "dolor.$": "$.sit.amet"
      },
      "Resource": "arn:aws:states:us-east-1:12345:activity:hello-world",
      "End": true
    }
  }
}

"lorem.$": "ipsum", is invalid, the value must be a valid JSONPath. Currently it passes validation, but fails on a deploy to AWS.

bump asl-path-validator dependency to support new AWS intrinsic functions

Describe the bug
AWS just released 14 new intrinsic functions.

To Reproduce
Use any of the new functions and you'll get an error.

Expected behavior
New intrinsic functions should be accepted

Version:
3.0.x

Additional context
I've released 0.11 of asl-path-validator which supports the new functions.

Parameter with list returns validation error

Hello Again! When using parameter with a list in yaml, the validator returns an error stating the Parameter must be an object. The SFN deploys correctly without validation and produces the expected output. Using the serverless-step-function plugin with validation leads to the following error:

✕ State machine "passParameterList" definition is invalid:
  
  data.States['pass-execution-details'] should NOT have additional properties
  data.States['pass-execution-details'] should NOT have additional properties
  data.States['pass-execution-details'].Type should match pattern "^Parallel$"
  data.States['pass-execution-details'].Parameters should be object
  data.States['pass-execution-details'] should NOT have additional properties
  data.States['pass-execution-details'].Type should match pattern "^Task$"
  data.States['pass-execution-details'] should NOT have additional properties
  data.States['pass-execution-details'].Type should match pattern "^Map$"
  data.States['pass-execution-details'] should match exactly one schema in oneOf

To Reproduce

service: test-parameter-with-list

provider:
  name: aws

plugins:
  - serverless-step-functions

stepFunctions:
  validate: true
  stateMachines:
    passParameterList: 
      name: mdw-source-system-director-${opt:stage}
      definition:
        StartAt: pass-execution-details
        States: 
          pass-execution-details:
            Type: Pass
            Parameters:
              - execution_id.$: $$.Execution.Id
                timestamp.$: $$.Execution.StartTime
            ResultPath: $.execution_details

I got the same error when testing with a Task step

Expected behavior
The following would be the output from this step.

"execution_details": [
    {
      "execution_id": "arn:aws:states:us-east-1......",
      "timestamp": "2021-02-11T04:27:15.193Z"
    }
  ]

Version: [e.g. 1.9.4, can be found by running asl-validator --version]

detect duplicate field names in payload templates resulting from substitution

Is your feature request related to a problem? Please describe.
Need a new rule to detect duplicate field names in a payload template following the rename that occurs after evaluation.

Describe the solution you'd like
Add a new validator that detects names that will collide.

invalid:

"Parameters" : {
    "static": "foo",
   "static.$": "$.path.to.value"  
}

The above is valid JSON at the time of deploy but will be invalid after evaluation since static.$ is renamed to static which collides with the existing field.

Validator accepting state machine definition with no terminal state

Input-

{
    "Comment": "A simple minimal example of the States language",
    "StartAt": "Hello World",
    "States": {
        "Hello World": {
            "Type": "Task",
            "Resource": "arn:aws:lambda:us-east-1:123456789012:function:HelloWorld",
            "Next": "Hello World2"
        },
        "Hello World2": {
            "Type": "Task",
            "Resource": "arn:aws:lambda:us-east-1:123456789012:function:HelloWorld",
            "Next": "Hello World3"
        },
        "Hello World3": {
            "Type": "Task",
            "Resource": "arn:aws:lambda:us-east-1:123456789012:function:HelloWorld",
            "Next": "Hello World"
        }
    }
}

Output-
✓ State machine definition is valid

Relax task ARN validation to allow Lambda aliases

It is valid to use an alias when referencing Lambdas from step function tasks but the validator seems to reject them.

An example ARN that is rejected by asl-validator is:

arn:aws:lambda:us-west-2:123456789012:function:MyFunction:$LATEST

On this page:

https://docs.aws.amazon.com/step-functions/latest/dg/connect-lambda.html

It mentions that:

You can invoke a specific Lambda function version or alias by specifying those options in the Amazon Resource Name in the Resource field. See the following in the Lambda documentation.

See also: https://docs.aws.amazon.com/lambda/latest/dg/aliases-intro.html

I believe fixing this would be as simple as changing this Regex

^arn:aws:([a-z]|-)+:([a-z]|[0-9]|-)*:[0-9]*:([a-z]|-)+:[a-zA-Z0-9-_.]+$

https://github.com/airware/asl-validator/blob/master/src/schemas/task.json#L28

to

^arn:aws:([a-z]|-)+:([a-z]|[0-9]|-)*:[0-9]*:([a-z]|-)+:[a-zA-Z0-9-_.]+(:(\$LATEST|[a-zA-Z0-9-_]+))?$

See the FunctionName regex on https://docs.aws.amazon.com/lambda/latest/dg/API_CreateAlias.html

Let me know if that works and I'll make the change.

Thanks!

Error in schema validation for ItemBatcher

Describe the bug
Error when validating DISTRIBUTED mode Map step with ItemBatcher option specified.

Error:
✕ State machine "batchedMachine" definition is invalid:
SCHEMA_VALIDATION_FAILED: /States/Batched/ItemBatcher is invalid. must match exactly one schema in oneOf

To Reproduce
Please provide a complete state machine definition:

    batchedMachine:
      name: 'batchedMachine'
      definition:
        Comment: 'batched distributed map step function'
        StartAt: Batched
        States:
          Batched:
            Type: Map
            MaxConcurrency: 1
            ItemsPath: $.items
            ResultPath: $.batched
            End: true
            ItemBatcher:
              MaxItemsPerBatch: 2
              BatchInput:
                batchInput: inputValue
            ItemProcessor:
              ProcessorConfig:
                Mode: DISTRIBUTED
                ExecutionType: EXPRESS
              StartAt: Test-Batched
              States:
                Test-Batched:
                  Type: Pass
                  End: true

Expected behavior
State machine definition should pass validation

Version:
node 16.11.1
serverless: 3.28.1
SDK: 4.3.2
serverless-step-functions: ^3.13.0

Validation error for Parameters

Describe the bug
New error based on changes made in 101 / 102
Validation error

 {
    'Error code': 'SCHEMA_VALIDATION_FAILED',
    Message: '/States/Publish to Slack/Parameters/slackMessage/blocks is invalid. must match exactly one schema in oneOf',
    schemaError: {
      instancePath: '/States/Publish to Slack/Parameters/slackMessage/blocks',
      schemaPath: '#/patternProperties/%5E.%2B((%5B%5E.%5D%5B%5E%24%5D)%7C(%5B%5E.%5D%5B%24%5D))%24/oneOf'
    }
  }

To Reproduce
Please provide a complete state machine definition:

{
  "StartAt": "Publish to Slack",
  "States": {
      "Publish to Slack": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:::function:publish-to-slack-lambda",
      "Parameters": {
        "slackMessage": {
          "channel.$": "$.slackErrorChannel",
          "text": "$.slackMessage.title",
          "blocks": [
            {
              "type": "section",
              "text": {
                "type": "mrkdwn",
                "text.$": "$.slackMessage.errorMessage"
              }
            },
            {
              "type": "section",
              "text": {
                "type": "mrkdwn",
                "text.$": "$.slackMessage.orderId"
              }
            },
            {
              "type": "section",
              "text": {
                "type": "mrkdwn",
                "text.$": "$.slackMessage.orderItemId"
              }
            },
            {
              "type": "section",
              "text": {
                "type": "mrkdwn",
                "text.$": "$.slackMessage.stack"
              }
            },
            {
              "type": "section",
              "text": {
                "type": "mrkdwn",
                "text.$": "$.slackMessage.link"
              }
            }
          ]
        }
      },
      "Next": "Failure"
    },
    "Failure": {
      "Type": "Fail"
    },
    "Success": {
      "Type": "Succeed"
    }
  }
}

Expected behavior
No validation error

Version:
3.0.2
Additional context
Add any other context about the problem here.

validator rejects path expression containing a hyphen

Describe the bug
I'm getting a lexical error parsing an ASL that contains a hyphen in an expression like this: $.test-input.delay-seconds

To Reproduce
See the AWS example here: https://github.com/aws-samples/aws-stepfunctions-examples/blob/main/sam/app-decompose-for-parallelism/statemachine/runner-simplewait.asl.json

Expected behavior
should accept this pattern

Version:
2.0.0

Additional context
The ASL cites a specific Java library for its definition of the path expressions. The JS library uses its own BNF grammar for its parser and this grammar doesn't include a hyphen.

Here's the lib linked to from the spec: https://github.com/json-path/JsonPath (it supports hyphens)

Maybe switch to https://github.com/JSONPath-Plus/JSONPath?

Add Parameters property to Pass state schema

Per the Pass state docs I think a line needs to be added for Parameters in the pass state schema file . I think the entry should be the same as the schema found in the task state schema.

I'm currently using this plugin that relies on this validator and I am getting an error when defining my AWS step function state machine with a Pass state that contains a Parameters property.

The error I get when trying to deploy a state machine:

 ✕ State machine "elasticsearch-cycle" definition is invalid:
[{"keyword":"additionalProperties","dataPath":".States['PopIPFromList']","schemaPath":
"#/additionalProperties","params":{"additionalProperty":"Parameters"},"message":"should NOT have additional properties"}, 
{"keyword":"additionalProperties","dataPath":".States['PopIPFromList']","schemaPath":
"http://asl-validator.cloud/fail#/additionalProperties","params":{"additionalProperty":"Parameters"},"message":"should NOT have additional properties"}, 
{"keyword":"additionalProperties","dataPath":".States['PopIPFromList']","schemaPath":
"#/additionalProperties","params":{"additionalProperty":"Parameters"},"message":"should NOT have additional properties"}, 
{"keyword":"additionalProperties","dataPath":".States['PopIPFromList']","schemaPath":
"http://asl-validator.cloud/pass#/additionalProperties","params": 
{"additionalProperty":"Parameters"},"message":"should NOT have additional properties"},{"keyword":"additionalProperties","dataPath":".States['PopIPFromList']","schemaPath":
"http://asl-validator.cloud/succeed#/additionalProperties","params": 
{"additionalProperty":"Parameters"},"message":"should NOT have additional properties"},{"keyword":"pattern","dataPath":".States['PopIPFromList'].Type","schemaPath":
"http://asl-validator.cloud/task#/properties/Type/pattern","params": 
{"pattern":"^Task$"},"message":"should match pattern \"^Task$\""},{"keyword":"additionalProperties","dataPath":".States['PopIPFromList']","schemaPath":
"http://asl-validator.cloud/wait#/additionalProperties","params": 
{"additionalProperty":"Parameters"},"message":"should NOT have additional properties"},{"keyword":"oneOf","dataPath":".States['PopIPFromList']","schemaPath":
"#/oneOf","params":{"passingSchemas":null},"message":"should match exactly one schema in oneOf"}]

A snippet of my state machine:

          PopIPFromList:
            Type: Pass
            Parameters: 
              inputList.$: $.inputList[1:]
            End: true

However, this should work as this translates to the proper JSON that we see in this example (search for their Pop Element from List state)

Please let me know if I'm missing something or if not - how I might help push up this minor patch.

add configuration to the validation to enable or disable named validations

Is your feature request related to a problem? Please describe.

There isn't a way to enforce a strict mode where the process definition is valid according to the ASL definition and doesn't contain any extension elements like a cloud flare deployment function call.

It would also be nice to disable one or more validations. The primary example of this is disabling the path expression checks. There's value in knowing the basic flow of the step function is valid without having to implement every expression. It's also possible that the expressions could be checked elsewhere in the build by another tool and the check in this lib is therefore redundant.

Describe the solution you'd like

Provide a config to enable/disable some of the checkers.

Add support for new Distributed Map in Step Functions Definition

Is your feature request related to a problem? Please describe.
Wide known serverless-step-functions module depends on asl in this place. As @brycenrogers mentioned here

Note: this does not currently work with validate: true as asl-validator does not yet support this behavior.

I've recently faced a limitation in step function, found out it can be fixed with new functionality however syntax validator (asl-validator) does not support it(

We kindly ask to extend the asl-validator with support of new DISTRIBUTED Map options
Screenshot 2023-01-05 at 01 40 48

Describe the solution you'd like
I guess this file should be updated with new properties that Map supports.
Then I will initiate the serverless-step-functions module to update asl-validate -> now we can deploy step functions with fresh AWS functionality altogether)

Describe alternatives you've considered
Don't think we can avoid updating the asl-validator with new AWS functionality

Additional context
https://docs.aws.amazon.com/step-functions/latest/dg/concepts-inline-vs-distributed-map.html

Support validating multiple files at once

Is your feature request related to a problem? Please describe.
This is somewhat of a bug and somewhat of a feature request - at present, asl-validator needs to be invoked once per file to be checked and doesn't support checking multiple files simultaneously, such as:

asl-validator --json-path statemachine/*.asl.json
asl-validator --json-path statemachine/foo.asl.json statemachine/bar.asl.json ...

The bug aspect of this is that when invoked with multiple filenames the validator will only check the first one specified and silently ignore the rest. In the example above, if foo.asl.json is valid but bar.asl.json isn't, then a success message will be printed as only the first file gets checked.

Having the ability to check multiple files at once makes processing faster as only one instance of the validator is needed to test any number of files; this becomes increasingly more of an issue with more state machine definitions. From a user's perspective, it simplifies use of the tool by allowing globbing, as above, where multiple ASLs can to be checked without needing to name files individually and re-run the validator separately for each. Adding multiple file support would also make this tool compatible with https://pre-commit.com/, for use as a pre-commit Git hook.

Describe the solution you'd like
Support for multiple files to be validated in one run, such that the command examples given above are possible.

In addition, console output doesn't currently indicate which ASL definition file has succeeded or failed, so that would need to be added for clarity, such as:

✓ State machine definition is valid (statemachine/foo.asl.json)
✕ State machine definition is invalid (statemachine/bar.asl.json):
 MISSING_TRANSITION_TARGET: State Process Data is not reachable
MISSING_TRANSITION_TARGET: Missing 'StartAt'|'Next'|'Default' target: Process Data

Describe alternatives you've considered
I'm currently wrapping asl-validator in shell loops and Makefiles so as invoking it one at a time for each file, echoing out the filename being checked so I know which fails and when, and taking care not to call the app with multiple paths to avoid the bug.

Additional context
Add any other context or screenshots about the feature request here.

Cannot Understand Invalid Template Results

I have been unable to determine where the issue with my state definition is. I am able to successfully create the machine in AWS however the validator keeps giving a unspecified error.

➜  asl-validator --json-path ../stepfunctiondef_COMPLETE.json
✕ State machine definition is invalid:
 undefined: undefined
undefined: undefined
undefined: undefined
undefined: undefined
undefined: undefined
No errors

Json input account details made up

{
  "Comment": "A step function for  Decision Engine flow",
  "StartAt": "Pass Component Name",
  "States": {
    "Pass Component Name": {
      "Type": "Pass",
      "Result": "emr-handler-steps-dev-east",
      "ResultPath": "$.message.componentName",
      "Next": "Create EMR"
    },
    "Create EMR": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:emr-handler-lambda-dev-east",
      "ResultPath": "$.jobFlowId",
      "Next": "Pass Job Flow ID",
      "Parameters": {
        "action": "create-emr",
        "emrConfig.$": "$.emrConfig"
      },
      "Retry": [
        {
          "ErrorEquals": [
            "States.ALL"
          ],
          "IntervalSeconds": 300,
          "MaxAttempts": 4,
          "BackoffRate": 1
        }
      ],
      "Catch": [
        {
          "ErrorEquals": [
            "States.ALL"
          ],
          "ResultPath": "$.message.message.error-info",
          "Next": "EMR Failure"
        }
      ]
    },
    "Pass Job Flow ID": {
      "Type": "Pass",
      "InputPath": "$.jobFlowId",
      "ResultPath": "$.message.message.jobFlowId",
      "Next": "Wait 4 Minutes"
    },
    "Wait 4 Minutes": {
      "Type": "Wait",
      "Seconds": 240,
      "Next": "Get Cluster Status"
    },
    "Get Cluster Status": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:emr-handler-lambda-dev-east",
      "Parameters": {
        "action": "is-emr-ready",
        "jobFlowId.$": "$.jobFlowId.jobFlowId"
      },
      "ResultPath": "$.isClusterReady",
      "Next": "Is EMR Ready",
      "Retry": [
        {
          "ErrorEquals": [
            "Lambda.ServiceException",
            "Lambda.SdkClientException",
            "Lambda.EC2ThrottledException",
            "Lambda.EC2UnexpectedException",
            "Lambda.TooManyRequestsException",
            "Lambda.Unknown",
            "ClientError"
          ],
          "IntervalSeconds": 15,
          "MaxAttempts": 6,
          "BackoffRate": 2
        },
        {
          "ErrorEquals": [
            "EMRNotReadyException"
          ],
          "IntervalSeconds": 300,
          "BackoffRate": 1,
          "MaxAttempts": 12
        }
      ],
      "Catch": [
        {
          "ErrorEquals": [
            "EMRNotReadyException",
            "EMRFailedException",
            "ClientError"
          ],
          "ResultPath": "$.message.message.error-info",
          "Next": "EMR Failure"
        }
      ]
    },
    "Is EMR Ready": {
      "Type": "Choice",
      "Choices": [
        {
          "Variable": "$.isClusterReady.emr-status",
          "StringEquals": "READY",
          "Next": "Submit Steps"
        },
        {
          "Variable": "$.isClusterReady.emr-status",
          "StringEquals": "FAILED",
          "Next": "EMR Failure"
        }
      ]
    },
    "Submit Steps": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:emr-handler-lambda-dev-east",
      "Next": "Pass Step IDs",
      "Parameters": {
        "action": "submit-steps",
        "jobFlowId.$": "$.jobFlowId.jobFlowId",
        "steps.$": "$.steps"
      },
      "ResultPath": "$.stepIds",
      "Retry": [
        {
          "ErrorEquals": [
            "Lambda.ServiceException",
            "Lambda.SdkClientException",
            "Lambda.EC2ThrottledException",
            "Lambda.EC2UnexpectedException",
            "Lambda.Unknown",
            "ClientError"
          ],
          "IntervalSeconds": 15,
          "MaxAttempts": 6,
          "BackoffRate": 2
        }
      ],
      "Catch": [
        {
          "ErrorEquals": [
            "States.ALL"
          ],
          "ResultPath": "$.message.message.error-info",
          "Next": "EMR Failure"
        }
      ]
    },
    "Pass Step IDs": {
      "Type": "Pass",
      "InputPath": "$.stepIds",
      "ResultPath": "$.message.message.stepIds",
      "Next": "Step Status Check"
    },
    "Step Status Check": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:emr-handler-lambda-dev-east",
      "Parameters": {
        "action": "are-steps-done",
        "jobFlowId.$": "$.jobFlowId.jobFlowId",
        "stepIds.$": "$.stepIds.stepIds"
      },
      "Retry": [
        {
          "ErrorEquals": [
            "StepsIncompleteException"
          ],
          "IntervalSeconds": 300,
          "BackoffRate": 1,
          "MaxAttempts": 12
        },
        {
          "ErrorEquals": [
            "Lambda.ServiceException",
            "Lambda.SdkClientException",
            "Lambda.EC2ThrottledException",
            "Lambda.EC2UnexpectedException",
            "Lambda.TooManyRequestsException",
            "Lambda.Unknown",
            "ClientError"
          ],
          "IntervalSeconds": 15,
          "MaxAttempts": 6,
          "BackoffRate": 2
        }
      ],
      "Catch": [
        {
          "ErrorEquals": [
            "StepsIncompleteException",
            "StepsFailedException",
            "ClientError"
          ],
          "ResultPath": "$.message.message.error-info",
          "Next": "EMR Failure"
        }
      ],
      "ResultPath": "$.areStepsDone",
      "Next": "Are Steps Done"
    },
    "Are Steps Done": {
      "Type": "Choice",
      "Choices": [
        {
          "Variable": "$.areStepsDone.are-steps-done",
          "StringEquals": "YES",
          "Next": "EMR Success"
        },
        {
          "Variable": "$.areStepsDone.are-steps-done",
          "StringEquals": "FAILED",
          "Next": "EMR Failure"
        }
      ]
    },
    "EMR Failure": {
      "Type": "Pass",
      "Result": "failure",
      "ResultPath": "$.state",
      "Next": "Notify Failure"
    },
    "Destroy EMR": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:emr-handler-lambda-dev-east",
      "Parameters": {
        "action": "terminate-emr",
        "jobFlowId.$": "$.jobFlowId.jobFlowId"
      },
      "ResultPath": "$.destroy-status",
      "Next": "Check failure",
      "Retry": [
        {
          "ErrorEquals": [
            "States.ALL"
          ],
          "IntervalSeconds": 60,
          "MaxAttempts": 5,
          "BackoffRate": 1
        }
      ]
    },
    "EMR Success": {
      "Type": "Pass",
      "Result": "success",
      "ResultPath": "$.state",
      "Next": "Notify Success"
    },
    "Check failure": {
      "Type": "Choice",
      "Choices": [
        {
          "Variable": "$.destroy-status.emr-status",
          "StringEquals": "TERMINATED",
          "Next": "Pipeline successful"
        }
      ],
      "Default": "Pipeline failed"
    },
    "Pipeline failed": {
      "Type": "Fail",
      "Cause": "Pipeline failure",
      "Error": "FailedException"
    },
    "Pipeline successful": {
      "Type": "Succeed"
    },
    "Notify Success": {
      "Type": "Task",
     "Resource": "arn:aws:states:::sns:publish",
     "Parameters": {
       "TopicArn": "arn:aws:sns:us-east-1:123456789012:emr-handler-result-dev-east",
       "Subject": " dev-east reconciliation success. ✅",
       "Message.$": "$.message",
       "MessageAttributes": {
         "severity": {
           "DataType": "String",
           "StringValue": "INFO"
         }
       },
       "MessageStructure": "String"
     },
      "ResultPath": "$.snsresult",
      "Next": "Destroy EMR"
     },
    "Notify Failure": {
      "Type": "Task",
     "Resource": "arn:aws:states:::sns:publish",
     "Parameters": {
       "TopicArn": "arn:aws:sns:us-east-1:123456789012:emr-handler-result-dev-east",
       "Subject": " dev-east reconciliation failure. ❌",
       "Message.$": "$.message",
       "MessageAttributes": {
         "severity": {
           "DataType": "String",
           "StringValue": "ERROR"
         }
       },
       "MessageStructure": "String"
     },
      "ResultPath": "$.snsresult",
      "Next": "Destroy EMR"
     }
  }
}

CloudFormation Lambda function ARN with substitution support

Currently the validator do not support lambda function arn that contains CloudFormation substitution.

if lambda arn in json code look like arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${LambdaName}
the result is:

✕ State machine definition is invalid:

data.States['Test'] should NOT have additional properties
data.States['Test'] should NOT have additional properties
data.States['Test'] should NOT have additional properties
data.States['Test'] should NOT have additional properties
data.States['Test'] should NOT have additional properties
data.States['Test'].Resource should match pattern "^arn:aws:([a-z]|-)+:([a-z]|[0-9]|-):[0-9]:([a-z]|-)+:[a-zA-Z0-9-.]+(:($LATEST|[a-zA-Z0-9-]+))?$"

Support for CloudFormation arn format allow to create json file with ASL code that is later injected into an auto generated CloudFormation file using a development language, and run ASL validation test into a CI/C pipeline prior the injection into CloudFormation template.

May I suggest replacing existing regex in src/schemas/task.json with:

^(arn:aws:([a-z]|-)+:(${[a-zA-z:-]+}|([a-z]|[0-9]|-)):(${[a-zA-z:-]+}|[0-9]{12}):([a-z]|-)+:(${)?[a-zA-Z0-9-.]+(})?(:($LATEST|[a-zA-Z0-9-]+))?$)|(\${.\})

this will allow support for lambda arn with formats:

arn:aws:lambda:us-east-1:999999999999:function:Lambda-test
arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${LambdaName}
arn:aws:lambda:us-east-1:999999999999:function:Lambda-test:$LATEST

and will make the test successful even when Lambda arn includes CloudFormation substitutions.

Unreachable State Not Caught

If a state us unreachable it should be considered invalid ASL, but right now still validates.
Ex: ( "Finished Choice" is unreachable but this returns valid)

{
	"StartAt": "Start State",
	"States":{
		"Start State": {
			"Type": "Pass",
			"Next": "Finished"
		},
		"Finished Choice":{
			"Type":"Choice",
			"Choices": [
				{
					"Variable": "$.x",
					"BooleanEquals": false,
					"Next": "Finished"
				}
			],
			"Default": "Finished"
		},
		"Finished": {
			"Type": "Pass",
			"End": true
		}
	}
}

Add support for SAM/CloudFormation DefinitionSubstitutions

When using SAM DefinitionSubstitutions to provide Task Resource values, the validation fails because the token string doesn't match the ARN regex.

I realize this is hard to handle because the content of the replacement strings isn't known until deploy time. Maybe this could be handled by a parameter that effectively means "DefinitionSubstitution tokens (/\$\{.+\}/) are always considered valid." It does leave a bit of a validation hole, but it at least means that users of SAM/CFN can validate the rest of the ASL structure.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.