Usar o AWS CDK para criar um fluxo de trabalho expresso no Step Functions
Neste tutorial, você vai saber como criar uma API REST do API Gateway com a máquina de estado expressa síncrona como integração de backend, usando o framework de infraestrutura como código (IAC) do AWS Cloud Development Kit (AWS CDK).
Você usará o constructo StepFunctionsRestApi para conectar a máquina de estado ao API Gateway. A estrutura StepFunctionsRestApi vai configurar um mapeamento padrão de entrada/saída e a API REST do API Gateway, com as permissões necessárias e um método HTTP “ANY”.
Como o AWS CDK é um framework de infraestrutura como código (IAC), você vai definir a infraestrutura da AWS usando uma linguagem de programação. Você vai definir uma aplicação em uma das linguagens aceitas do CDK, sintetizar o código em um modelo do CloudFormation e implantar a infraestrutura na conta da AWS.
Você vai usar o CloudFormation para definir uma API REST do API Gateway, que é integrada à máquina de estado síncrona expressa como backend e usar o Console de gerenciamento da AWS para iniciar a execução.
Antes de iniciar este tutorial, configure o ambiente de desenvolvimento do AWS CDK conforme descrito em Getting Started With the AWS CDK - Prerequisites e instale o AWS CDK iniciando:
npm install -g aws-cdk
Etapa 1: Configurar o projeto do AWS CDK
Primeiro, crie um diretório para a nova aplicação do AWS CDK e inicialize o projeto.
- TypeScript
-
mkdir stepfunctions-rest-api
cd stepfunctions-rest-api
cdk init --language typescript
- JavaScript
-
mkdir stepfunctions-rest-api
cd stepfunctions-rest-api
cdk init --language javascript
- Python
-
mkdir stepfunctions-rest-api
cd stepfunctions-rest-api
cdk init --language python
Depois que o projeto tiver sido inicializado, ative o ambiente virtual do projeto e instale as dependências de linha de base do AWS CDK.
source .venv/bin/activate
python -m pip install -r requirements.txt
- Java
-
mkdir stepfunctions-rest-api
cd stepfunctions-rest-api
cdk init --language java
- C#
-
mkdir stepfunctions-rest-api
cd stepfunctions-rest-api
cdk init --language csharp
- Go
-
mkdir stepfunctions-rest-api
cd stepfunctions-rest-api
cdk init --language go
Dê ao diretório o nome stepfunctions-rest-api. O modelo de aplicação do AWS CDK usa o nome do diretório para gerar nomes para arquivos e classes de origem. Se você escolher outro nome, sua aplicação não combinará com este tutorial.
Agora instale os módulos da biblioteca de estrutura para o AWS Step Functions e o Amazon API Gateway.
- TypeScript
-
npm install @aws-cdk/aws-stepfunctions @aws-cdk/aws-apigateway
- JavaScript
-
npm install @aws-cdk/aws-stepfunctions @aws-cdk/aws-apigateway
- Python
-
python -m pip install aws-cdk.aws-stepfunctions
python -m pip install aws-cdk.aws-apigateway
- Java
-
Edite o pom.xml do projeto para adicionar as seguintes dependências dentro do contêiner <dependencies> existente.
<dependency>
<groupId>software.amazon.awscdk</groupId>
<artifactId>stepfunctions</artifactId>
<version>${cdk.version}</version>
</dependency>
<dependency>
<groupId>software.amazon.awscdk</groupId>
<artifactId>apigateway</artifactId>
<version>${cdk.version}</version>
</dependency>
O Maven instala automaticamente essas dependências na próxima vez que você criar a aplicação. Para criar, inicie mvn compile ou use o comando Build (Criar) do Java IDE.
- C#
-
dotnet add src/StepfunctionsRestApi package Amazon.CDK.AWS.Stepfunctions
dotnet add src/StepfunctionsRestApi package Amazon.CDK.AWS.APIGateway
Você também pode instalar os pacotes indicados usando a GUI NuGet do Visual Studio, disponível em Tools > NuGet Package Manager > Manage NuGet Packages for Solution (Ferramentas > Gerenciador de pacotes do NuGet > Gerenciar pacotes do NuGet para solução).
Depois de instalar os módulos, você pode usá-los em seu aplicativo AWS CDK importando os pacotes a seguir.
- TypeScript
-
@aws-cdk/aws-stepfunctions
@aws-cdk/aws-apigateway
- JavaScript
-
@aws-cdk/aws-stepfunctions
@aws-cdk/aws-apigateway
- Python
-
aws_cdk.aws_stepfunctions
aws_cdk.aws_apigateway
- Java
-
software.amazon.awscdk.services.apigateway.StepFunctionsRestApi
software.amazon.awscdk.services.stepfunctions.Pass
software.amazon.awscdk.services.stepfunctions.StateMachine
software.amazon.awscdk.services.stepfunctions.StateMachineType
- C#
-
Amazon.CDK.AWS.StepFunctions
Amazon.CDK.AWS.APIGateway
- Go
-
Adicione o seguinte a import dentro de stepfunctions-rest-api.go.
"github.com/aws/aws-cdk-go/awscdk/awsapigateway"
"github.com/aws/aws-cdk-go/awscdk/awsstepfunctions"
Etapa 2: Usar o AWS CDK para criar uma API REST do API Gateway com integração de backend da Máquina estado expressa síncrona
Primeiro, vamos apresentar as partes individuais do código que definem a Máquina de estado expressa síncrona e a API REST do API Gateway e depois vamos explicar como reuni-las em sua aplicação AWS CDK. Então você verá como sintetizar e implantar esses recursos.
A Máquina de Estado que mostraremos aqui será uma Máquina de Estado simples com um estado Pass.
Para criar uma máquina de estado Express
Esse é o código AWS CDK que define uma máquina de estado simples com um estado Pass.
- TypeScript
-
const machineDefinition = new stepfunctions.Pass(this, 'PassState', {
result: {value:"Hello!"},
})
const stateMachine = new stepfunctions.StateMachine(this, 'MyStateMachine', {
definition: machineDefinition,
stateMachineType: stepfunctions.StateMachineType.EXPRESS,
});
- JavaScript
-
const machineDefinition = new sfn.Pass(this, 'PassState', {
result: {value:"Hello!"},
})
const stateMachine = new sfn.StateMachine(this, 'MyStateMachine', {
definition: machineDefinition,
stateMachineType: stepfunctions.StateMachineType.EXPRESS,
});
- Python
-
machine_definition = sfn.Pass(self,"PassState",
result = sfn.Result("Hello"))
state_machine = sfn.StateMachine(self, 'MyStateMachine',
definition = machine_definition,
state_machine_type = sfn.StateMachineType.EXPRESS)
- Java
-
Pass machineDefinition = Pass.Builder.create(this, "PassState")
.result(Result.fromString("Hello"))
.build();
StateMachine stateMachine = StateMachine.Builder.create(this, "MyStateMachine")
.definition(machineDefinition)
.stateMachineType(StateMachineType.EXPRESS)
.build();
- C#
-
var machineDefinition = new Pass(this, "PassState", new PassProps
{
Result = Result.FromString("Hello")
});
var stateMachine = new StateMachine(this, "MyStateMachine", new StateMachineProps
{
Definition = machineDefinition,
StateMachineType = StateMachineType.EXPRESS
});
- Go
-
var machineDefinition = awsstepfunctions.NewPass(stack, jsii.String("PassState"), &awsstepfunctions.PassProps
{
Result: awsstepfunctions.NewResult(jsii.String("Hello")),
})
var stateMachine = awsstepfunctions.NewStateMachine(stack, jsii.String("StateMachine"), &awsstepfunctions.StateMachineProps
{
Definition: machineDefinition,
StateMachineType: awsstepfunctions.StateMachineType_EXPRESS,
})
Você pode ver, neste pequeno trecho:
-
A definição da máquina chamada PassState, que é um estado Pass.
-
O nome lógico da Máquina do estado, MyStateMachine.
-
A definição da máquina é usada como a definição da máquina de estado.
-
O Tipo de máquina de estado é definido como EXPRESS porque StepFunctionsRestApi só permitirá uma máquina de estado do Synchronous Express.
Para criar a API REST do API Gateway usando a estrutura StepFunctionsRestApi
Vamos usar a estrutura StepFunctionsRestApi para criar a API REST do API Gateway com as permissões necessárias e mapeamento padrão de entrada/saída.
- TypeScript
-
const api = new apigateway.StepFunctionsRestApi(this,
'StepFunctionsRestApi', { stateMachine: stateMachine });
- JavaScript
-
const api = new apigateway.StepFunctionsRestApi(this,
'StepFunctionsRestApi', { stateMachine: stateMachine });
- Python
-
api = apigw.StepFunctionsRestApi(self, "StepFunctionsRestApi",
state_machine = state_machine)
- Java
-
StepFunctionsRestApi api = StepFunctionsRestApi.Builder.create(this, "StepFunctionsRestApi")
.stateMachine(stateMachine)
.build();
- C#
-
var api = new StepFunctionsRestApi(this, "StepFunctionsRestApi", new StepFunctionsRestApiProps
{
StateMachine = stateMachine
});
- Go
-
awsapigateway.NewStepFunctionsRestApi(stack, jsii.String("StepFunctionsRestApi"), &awsapigateway.StepFunctionsRestApiProps
{
StateMachine = stateMachine,
})
Para criar e implantar a aplicação AWS CDK
No projeto do AWS CDK que você criou, edite o arquivo que contém a definição da pilha para ter a aparência do código abaixo. Você vai reconhecer as definições da máquina de estado do Step Functions e do API Gateway apresentadas acima.
- TypeScript
-
Atualizar lib/stepfunctions-rest-api-stack.ts para ler conforme mostrado a seguir.
import * as cdk from 'aws-cdk-lib';
import * as stepfunctions from 'aws-cdk-lib/aws-stepfunctions'
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
export class StepfunctionsRestApiStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const machineDefinition = new stepfunctions.Pass(this, 'PassState', {
result: {value:"Hello!"},
});
const stateMachine = new stepfunctions.StateMachine(this, 'MyStateMachine', {
definition: machineDefinition,
stateMachineType: stepfunctions.StateMachineType.EXPRESS,
});
const api = new apigateway.StepFunctionsRestApi(this,
'StepFunctionsRestApi', { stateMachine: stateMachine });
- JavaScript
-
Atualizar lib/stepfunctions-rest-api-stack.js para ler conforme mostrado a seguir.
const cdk = require('@aws-cdk/core');
const stepfunctions = require('@aws-cdk/aws-stepfunctions');
const apigateway = require('@aws-cdk/aws-apigateway');
class StepfunctionsRestApiStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const machineDefinition = new stepfunctions.Pass(this, "PassState", {
result: {value:"Hello!"},
})
const stateMachine = new sfn.StateMachine(this, 'MyStateMachine', {
definition: machineDefinition,
stateMachineType: stepfunctions.StateMachineType.EXPRESS,
});
const api = new apigateway.StepFunctionsRestApi(this,
'StepFunctionsRestApi', { stateMachine: stateMachine });
}
}
module.exports = { StepStack }
- Python
-
Atualizar stepfunctions_rest_api/stepfunctions_rest_api_stack.py para ler conforme mostrado a seguir.
from aws_cdk import App, Stack
from constructs import Construct
from aws_cdk import aws_stepfunctions as sfn
from aws_cdk import aws_apigateway as apigw
class StepfunctionsRestApiStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
machine_definition = sfn.Pass(self,"PassState",
result = sfn.Result("Hello"))
state_machine = sfn.StateMachine(self, 'MyStateMachine',
definition = machine_definition,
state_machine_type = sfn.StateMachineType.EXPRESS)
api = apigw.StepFunctionsRestApi(self,
"StepFunctionsRestApi",
state_machine = state_machine)
- Java
-
Atualizar src/main/java/com.myorg/StepfunctionsRestApiStack.java para ler conforme mostrado a seguir.
package com.myorg;
import software.amazon.awscdk.core.Construct;
import software.amazon.awscdk.core.Stack;
import software.amazon.awscdk.core.StackProps;
import software.amazon.awscdk.services.stepfunctions.Pass;
import software.amazon.awscdk.services.stepfunctions.StateMachine;
import software.amazon.awscdk.services.stepfunctions.StateMachineType;
import software.amazon.awscdk.services.apigateway.StepFunctionsRestApi;
public class StepfunctionsRestApiStack extends Stack {
public StepfunctionsRestApiStack(final Construct scope, final String id) {
this(scope, id, null);
}
public StepfunctionsRestApiStack(final Construct scope, final String id, final StackProps props) {
super(scope, id, props);
Pass machineDefinition = Pass.Builder.create(this, "PassState")
.result(Result.fromString("Hello"))
.build();
StateMachine stateMachine = StateMachine.Builder.create(this, "MyStateMachine")
.definition(machineDefinition)
.stateMachineType(StateMachineType.EXPRESS)
.build();
StepFunctionsRestApi api = StepFunctionsRestApi.Builder.create(this, "StepFunctionsRestApi")
.stateMachine(stateMachine)
.build();
}
}
- C#
-
Atualizar src/StepfunctionsRestApi/StepfunctionsRestApiStack.cs para ler conforme mostrado a seguir.
using Amazon.CDK;
using Amazon.CDK.AWS.StepFunctions;
using Amazon.CDK.AWS.APIGateway;
namespace StepfunctionsRestApi
{
public class StepfunctionsRestApiStack : Stack
{
internal StepfunctionsRestApi(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
{
var machineDefinition = new Pass(this, "PassState", new PassProps
{
Result = Result.FromString("Hello")
});
var stateMachine = new StateMachine(this, "MyStateMachine", new StateMachineProps
{
Definition = machineDefinition,
StateMachineType = StateMachineType.EXPRESS
});
var api = new StepFunctionsRestApi(this, "StepFunctionsRestApi", new StepFunctionsRestApiProps
{
StateMachine = stateMachine
});
}
}
}
- Go
-
Atualizar stepfunctions-rest-api.go para ler conforme mostrado a seguir.
package main
import (
"github.com/aws/aws-cdk-go/awscdk"
"github.com/aws/aws-cdk-go/awscdk/awsapigateway"
"github.com/aws/aws-cdk-go/awscdk/awsstepfunctions"
"github.com/aws/constructs-go/constructs/v3"
"github.com/aws/jsii-runtime-go"
)
type StepfunctionsRestApiGoStackProps struct {
awscdk.StackProps
}
func NewStepfunctionsRestApiGoStack(scope constructs.Construct, id string, props *StepfunctionsRestApiGoStackProps) awscdk.Stack {
var sprops awscdk.StackProps
if props != nil {
sprops = props.StackProps
}
stack := awscdk.NewStack(scope, &id, &sprops)
// The code that defines your stack goes here
var machineDefinition = awsstepfunctions.NewPass(stack, jsii.String("PassState"), &awsstepfunctions.PassProps
{
Result: awsstepfunctions.NewResult(jsii.String("Hello")),
})
var stateMachine = awsstepfunctions.NewStateMachine(stack, jsii.String("StateMachine"), &awsstepfunctions.StateMachineProps{
Definition: machineDefinition,
StateMachineType: awsstepfunctions.StateMachineType_EXPRESS,
});
awsapigateway.NewStepFunctionsRestApi(stack, jsii.String("StepFunctionsRestApi"), &awsapigateway.StepFunctionsRestApiProps{
StateMachine = stateMachine,
})
return stack
}
func main() {
app := awscdk.NewApp(nil)
NewStepfunctionsRestApiGoStack(app, "StepfunctionsRestApiGoStack", &StepfunctionsRestApiGoStackProps{
awscdk.StackProps{
Env: env(),
},
})
app.Synth(nil)
}
// env determines the AWS environment (account+region) in which our stack is to
// be deployed. For more information see: https://docs.aws.amazon.com/cdk/latest/guide/environments.html
func env() *awscdk.Environment {
// If unspecified, this stack will be "environment-agnostic".
// Account/Region-dependent features and context lookups will not work, but a
// single synthesized template can be deployed anywhere.
//---------------------------------------------------------------------------
return nil
// Uncomment if you know exactly what account and region you want to deploy
// the stack to. This is the recommendation for production stacks.
//---------------------------------------------------------------------------
// return &awscdk.Environment{
// Account: jsii.String("account-id"),
// Region: jsii.String("us-east-1"),
// }
// Uncomment to specialize this stack for the AWS Account and Region that are
// implied by the current CLI configuration. This is recommended for dev
// stacks.
//---------------------------------------------------------------------------
// return &awscdk.Environment{
// Account: jsii.String(os.Getenv("CDK_DEFAULT_ACCOUNT")),
// Region: jsii.String(os.Getenv("CDK_DEFAULT_REGION")),
// }
}
Salve o arquivo de origem e emita cdk synth no diretório principal da aplicação. O AWS CDK executa a aplicação e sintetiza um modelo do CloudFormation a partir dela e exibe o modelo.
Para de fato implantar o Amazon API Gateway e a máquina de estado AWS Step Functions em sua conta da AWS, emita cdk deploy. Você será solicitado a aprovar as políticas do IAM que o AWS CDK gerou.
Etapa 3: Testar o API Gateway
Depois de criar sua API REST do API Gateway com a máquina de estado síncrona expressa como integração de back-end, você pode testar o API Gateway.
Para testar o API Gateway implantado usando o console do API Gateway
-
Abra o console do Amazon API Gateway e faça login.
-
Selecione a API REST denominada StepFunctionsRestApi.
-
No painel Recursos, selecione o método ANY.
-
Selecione a guia Testar. Talvez seja necessário selecionar o botão de seta para a direita para mostrar a guia.
-
Em Method (Método), selecione POST.
-
Em Corpo da solicitação, copie os parâmetros da solicitação a seguir.
{
"key": "Hello"
}
-
Escolha Test (Testar). As informações a seguir serão exibidas:
-
Request (Solicitação) é o caminho do recurso que foi chamado para o método.
-
Status é o código de status HTTP da resposta.
-
Latency (Latência) é o tempo entre a recepção da solicitação do autor da chamada e a resposta retornada.
-
Corpo da resposta é o corpo de resposta HTTP.
-
Cabeçalhos de resposta são os cabeçalhos de resposta HTTP.
-
O log mostra as entradas simuladas do Amazon CloudWatch Logs que teriam sido gravadas se esse método fosse chamado fora do console do API Gateway.
Embora as entradas do CloudWatch Logs sejam simuladas, os resultados da chamada do método são reais.
A saída do Corpo da resposta deve ser mais ou menos assim:
"Hello"
Experimente o API Gateway com métodos diferentes e uma entrada inválida para ver a saída do erro. É recomendável alterar a máquina de estado para procurar uma chave específica e, durante o teste, fornecer a chave errada para provocar uma falha na execução da máquina de estado e gerar uma mensagem de erro na saída do Corpo da resposta.
Para testar a API implantada usando cURL
-
Abra uma janela do terminal.
-
Copie o seguinte comando cURL e cole-o na janela do terminal, substituindo <api-id> pelo ID de API da sua API e <region> pela região em que a API foi implantada.
curl -X POST\
'https://<api-id>.execute-api.<region>.amazonaws.com/prod' \
-d '{"key":"Hello"}' \
-H 'Content-Type: application/json'
A saída do Corpo da resposta deve ser mais ou menos assim:
"Hello"
Experimente o API Gateway com métodos diferentes e uma entrada inválida para ver a saída do erro. Talvez você queira alterar a máquina de estado para procurar uma chave específica e, durante o teste, fornecer a chave errada para falhar na execução da Máquina de Estado e gerar uma mensagem de erro na saída do Corpo de Resposta.
Etapa 4: Limpeza
Ao terminar de testar seu API Gateway, você pode derrubar tanto a máquina de estado quanto o API Gateway usando o AWS CDK. Inicie cdk destroy no diretório principal da aplicação.