internal TheStateMachineStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) { // Step Function Starts Here // The first thing we need to do is see if they are asking for pineapple on a pizza _pineappleCheckHandler = new Lambda.Function(this, "pineappleCheckHandler", new Lambda.FunctionProps { Runtime = Lambda.Runtime.NODEJS_12_X, Code = Lambda.Code.FromAsset("lambda_fns"), Handler = "orderPizza.handler" }); /* * Step functions are built up of steps, we need to define our first step * This step was refactored due to Deprecated function */ _orderPizzaTask = new StepFunctionTasks.LambdaInvoke(this, "Order Pizza Job", new StepFunctionTasks.LambdaInvokeProps { LambdaFunction = _pineappleCheckHandler, InputPath = "$.flavour", ResultPath = "$.pineappleAnalysis", PayloadResponseOnly = true }); // Pizza Order failure step defined _jobFailed = new StepFunction.Fail(this, "Sorry, We Dont add Pineapple", new StepFunction.FailProps { Cause = "They asked for Pineapple", Error = "Failed To Make Pizza" }); // If they didnt ask for pineapple let's cook the pizza _cookPizza = new StepFunction.Pass(this, "Lets make your pizza"); // If they ask for a pizza with pineapple, fail. Otherwise cook the pizza _chainDefinition = StepFunction.Chain .Start(_orderPizzaTask) .Next(new StepFunction.Choice(this, "With Pineapple?") // Logical choice added to flow .When(StepFunction.Condition.BooleanEquals("$.pineappleAnalysis.containsPineapple", true), _jobFailed) .Otherwise(_cookPizza)); // Building the state machine _stateMachine = new StepFunction.StateMachine(this, "StateMachine", new StepFunction.StateMachineProps { Definition = _chainDefinition, Timeout = Duration.Minutes(5), TracingEnabled = true, StateMachineType = StepFunction.StateMachineType.EXPRESS }); /** * HTTP API Definition **/ // We need to give our HTTP API permission to invoke our step function _httpApiRole = new IAM.Role(this, "HttpAPIRole", new IAM.RoleProps { AssumedBy = new IAM.ServicePrincipal("apigateway.amazonaws.com"), InlinePolicies = new Dictionary <string, IAM.PolicyDocument> { { "AllowSFNExec", new IAM.PolicyDocument(new IAM.PolicyDocumentProps { Statements = new IAM.PolicyStatement[] { new IAM.PolicyStatement(new IAM.PolicyStatementProps { Actions = new string[] { "states:StartSyncExecution" }, Effect = IAM.Effect.ALLOW, Resources = new string[] { _stateMachine.StateMachineArn } }) } }) } } }); _api = new APIGateway.HttpApi(this, "TheStateMachineAPI", new APIGateway.HttpApiProps { CreateDefaultStage = true }); _integration = new APIGateway.CfnIntegration(this, "Integration", new APIGateway.CfnIntegrationProps { ApiId = _api.HttpApiId, IntegrationType = "AWS_PROXY", ConnectionType = "INTERNET", IntegrationSubtype = "StepFunctions-StartSyncExecution", CredentialsArn = _httpApiRole.RoleArn, RequestParameters = new Dictionary <string, string> { { "Input", "$request.body" }, { "StateMachineArn", _stateMachine.StateMachineArn } }, PayloadFormatVersion = "1.0", TimeoutInMillis = 10000 }); new APIGateway.CfnRoute(this, "DefaultRoute", new APIGateway.CfnRouteProps { ApiId = _api.HttpApiId, RouteKey = APIGateway.HttpRouteKey.DEFAULT.Key, Target = "integrations/" + _integration.Ref }); new Amazon.CDK.CfnOutput(this, "HTTP API Url", new Amazon.CDK.CfnOutputProps { Value = _api.Url }); }
internal TheStateMachineStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) { // Step Function Starts Here // The first thing we need to do is see if they are asking for pineapple on a pizza _pineppaleCheckHandler = new Lambda.Function(this, "pineappleCheckLambdaHandler", new Lambda.FunctionProps { Runtime = Lambda.Runtime.NODEJS_12_X, Code = Lambda.Code.FromAsset("lambda_fns"), Handler = "orderPizza.handler" }); /* * Step functions are built up of steps, we need to define our first step * This step was refactored due to Deprecated function */ _orderPizzaTask = new StepFuncionTasks.LambdaInvoke(this, "Order Pizza Job", new StepFuncionTasks.LambdaInvokeProps { LambdaFunction = _pineppaleCheckHandler, InputPath = "$.flavour", ResultPath = "$.pineappleAnalysis", PayloadResponseOnly = true }); // Pizza Order failure step defined _jobFailed = new StepFunction.Fail(this, "Sorry, We Dont add Pineapple", new StepFunction.FailProps { Cause = "Failed To Make Pizza", Error = "They asked for Pineapple" }); // If they didnt ask for pineapple let's cook the pizza _cookPizza = new StepFunction.Pass(this, "Lets make your pizza"); // If they ask for a pizza with pineapple, fail. Otherwise cook the pizza _chainDefinition = StepFunction.Chain .Start(_orderPizzaTask) .Next(new StepFunction.Choice(this, "With Pineapple?") // Logical choice added to flow .When(StepFunction.Condition.BooleanEquals("$.pineappleAnalysis.containsPineapple", true), _jobFailed) .Otherwise(_cookPizza)); // Building the state machine _stateMachine = new StepFunction.StateMachine(this, "StateMachine", new StepFunction.StateMachineProps { Definition = _chainDefinition, Timeout = Duration.Minutes(5) }); /** * Dead Letter Queue Setup * SQS creation * https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html */ _deadeLetterQueue = new SQS.Queue(this, "stateMachineLambdaDLQ", new SQS.QueueProps { VisibilityTimeout = Duration.Seconds(300) }); // defines an AWS Lambda resource to connect to our API Gateway _stateMachineHandler = new Lambda.Function(this, "stateMachineLambdaHandler", new Lambda.FunctionProps { Runtime = Lambda.Runtime.NODEJS_12_X, Code = Lambda.Code.FromAsset("lambda_fns"), Handler = "stateMachineLambda.handler", DeadLetterQueue = _deadeLetterQueue, Environment = new Dictionary <string, string> { { "statemachine_arn", _stateMachine.StateMachineArn } } }); // Grants to state machine execution _stateMachine.GrantStartExecution(_stateMachineHandler); /* * Simple API Gateway proxy integration */ // defines an API Gateway REST API resource backed by our "sqs_publish_lambda" function. new APIGateway.LambdaRestApi(this, "Endpoint", new APIGateway.LambdaRestApiProps { Handler = _stateMachineHandler }); }