

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

# Saiba como usar a descoberta AWS Cloud Map de serviços com atributos personalizados usando o AWS CLI
<a name="tutorial-microservices-cli"></a>

Este tutorial demonstra como você pode usar a descoberta AWS Cloud Map de serviços com atributos personalizados. Você criará um aplicativo de microsserviços usado AWS Cloud Map para descobrir recursos dinamicamente usando atributos personalizados. O aplicativo consiste em duas funções Lambda que gravam e lêem dados em uma tabela do DynamoDB, com todos os recursos registrados em. AWS Cloud Map

Para obter uma Console de gerenciamento da AWS versão do tutorial, consulte[Saiba como usar a descoberta AWS Cloud Map de serviços com atributos personalizados](tutorial-microservices.md).

## Pré-requisitos
<a name="prerequisites"></a>

Antes de começar este tutorial, conclua as etapas em[Configurado para usar AWS Cloud Map](setting-up-cloud-map.md).

## Crie um AWS Cloud Map namespace
<a name="create-an-aws-cloud-map-namespace"></a>

Um namespace é uma construção usada para agrupar serviços para um aplicativo. Nesta etapa, você criará um namespace que permite que os recursos sejam descobertos por meio AWS Cloud Map de chamadas de API.

1. Execute o comando a seguir para criar um namespace HTTP:

   ```
   aws servicediscovery create-http-namespace \
     --name cloudmap-tutorial \
     --creator-request-id cloudmap-tutorial-request
   ```

   O comando retorna um ID de operação. Você pode verificar o status da operação com o seguinte comando:

   ```
   aws servicediscovery get-operation \
     --operation-id operation-id
   ```

1. Depois que o namespace for criado, você poderá recuperar seu ID para uso nos comandos subsequentes:

   ```
   aws servicediscovery list-namespaces \
     --query "Namespaces[?Name=='cloudmap-tutorial'].Id" \
     --output text
   ```

1. Armazene o ID do namespace em uma variável para uso posterior:

   ```
   NAMESPACE_ID=$(aws servicediscovery list-namespaces \
     --query "Namespaces[?Name=='cloudmap-tutorial'].Id" \
     --output text)
   ```

## Criar uma tabela do DynamoDB
<a name="create-a-dynamodb-table"></a>

Em seguida, crie uma tabela do DynamoDB que armazenará dados para seu aplicativo:

1. Execute o comando a seguir para criar a tabela:

   ```
   aws dynamodb create-table \
     --table-name cloudmap \
     --attribute-definitions AttributeName=id,AttributeType=S \
     --key-schema AttributeName=id,KeyType=HASH \
     --billing-mode PAY_PER_REQUEST
   ```

1. Aguarde até que a tabela fique ativa antes de continuar:

   ```
   aws dynamodb wait table-exists --table-name cloudmap
   ```

   Esse comando espera até que a tabela esteja totalmente criada e pronta para uso.

## Crie um serviço de AWS Cloud Map dados e registre a tabela do DynamoDB
<a name="create-an-aws-cloud-map-data-service-and-register-the-dynamodb-table"></a>

Agora, crie um serviço em seu namespace para representar os recursos de armazenamento de dados:

1. Execute o comando a seguir para criar um AWS Cloud Map serviço para recursos de armazenamento de dados:

   ```
   aws servicediscovery create-service \
     --name data-service \
     --namespace-id $NAMESPACE_ID \
     --creator-request-id data-service-request
   ```

1. Obtenha o ID do serviço de dados:

   ```
   DATA_SERVICE_ID=$(aws servicediscovery list-services \
     --query "Services[?Name=='data-service'].Id" \
     --output text)
   ```

1. Registre a tabela do DynamoDB como uma instância de serviço com um atributo personalizado que especifica o nome da tabela:

   ```
   aws servicediscovery register-instance \
     --service-id $DATA_SERVICE_ID \
     --instance-id data-instance \
     --attributes tablename=cloudmap
   ```

   O atributo personalizado `tablename=cloudmap` permite que outros serviços descubram dinamicamente o nome da tabela do DynamoDB.

## Crie uma função do IAM para funções Lambda
<a name="create-an-iam-role-for-lambda-functions"></a>

Crie uma função do IAM que as funções do Lambda usarão para acessar AWS recursos:

1. Crie o documento de política de confiança para a função do IAM usando o seguinte JSON:

------
#### [ JSON ]

****  

   ```
   {
     "Version":"2012-10-17",		 	 	 		 	 	 
     "Statement": [
       {
         "Effect": "Allow",
         "Principal": {
           "Service": "lambda.amazonaws.com"
         },
         "Action": "sts:AssumeRole"
       }
     ]
   }
   ```

------

1. Execute o comando a seguir para criar a função do IAM usando a política de confiança:

   ```
   aws iam create-role \
     --role-name cloudmap-tutorial-role \
     --assume-role-policy-document file://lambda-trust-policy.json
   ```

1. Crie um arquivo para uma política personalizada do IAM com menos permissões de privilégio usando o seguinte JSON:

------
#### [ JSON ]

****  

   ```
   {
     "Version":"2012-10-17",		 	 	 		 	 	 
     "Statement": [
       {
         "Effect": "Allow",
         "Action": [
           "logs:CreateLogGroup",
           "logs:CreateLogStream",
           "logs:PutLogEvents"
         ],
         "Resource": "arn:aws:logs:*:*:*"
       },
       {
         "Effect": "Allow",
         "Action": [
           "servicediscovery:DiscoverInstances"
         ],
         "Resource": "*"
       },
       {
         "Effect": "Allow",
         "Action": [
           "dynamodb:PutItem",
           "dynamodb:Scan"
         ],
         "Resource": "arn:aws:dynamodb:*:*:table/cloudmap"
       }
     ]
   }
   ```

------

1. Crie e anexe a política à função do IAM:

   ```
   aws iam create-policy \
     --policy-name CloudMapTutorialPolicy \
     --policy-document file://cloudmap-policy.json
   
   POLICY_ARN=$(aws iam list-policies \
     --query "Policies[?PolicyName=='CloudMapTutorialPolicy'].Arn" \
     --output text)
   
   aws iam attach-role-policy \
     --role-name cloudmap-tutorial-role \
     --policy-arn $POLICY_ARN
   
   aws iam attach-role-policy \
     --role-name cloudmap-tutorial-role \
     --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
   ```

## Crie a função Lambda para gravar dados
<a name="create-the-lambda-function-to-write-data"></a>

Para criar uma função Lambda que grava dados na tabela do DynamoDB, siga estas etapas:

1. Crie o arquivo Python para a função de gravação:

   ```
   cat > writefunction.py << EOF
   import json
   import boto3
   import random
   
   def lambda_handler(event, context):
       try:
           serviceclient = boto3.client('servicediscovery')
           
           response = serviceclient.discover_instances(
               NamespaceName='cloudmap-tutorial',
               ServiceName='data-service')
           
           if not response.get("Instances"):
               return {
                   'statusCode': 500,
                   'body': json.dumps({"error": "No instances found"})
               }
               
           tablename = response["Instances"][0]["Attributes"].get("tablename")
           if not tablename:
               return {
                   'statusCode': 500,
                   'body': json.dumps({"error": "Table name attribute not found"})
               }
              
           dynamodbclient = boto3.resource('dynamodb')
              
           table = dynamodbclient.Table(tablename)
           
           # Validate input
           if not isinstance(event, str):
               return {
                   'statusCode': 400,
                   'body': json.dumps({"error": "Input must be a string"})
               }
              
           response = table.put_item(
               Item={ 'id': str(random.randint(1,100)), 'todo': event })
              
           return {
               'statusCode': 200,
               'body': json.dumps(response)
           }
       except Exception as e:
           return {
               'statusCode': 500,
               'body': json.dumps({"error": str(e)})
           }
   EOF
   ```

   Essa função é usada AWS Cloud Map para descobrir o nome da tabela do DynamoDB a partir do atributo personalizado e, em seguida, grava dados na tabela.

1. Package e implante a função Lambda:

   ```
   zip writefunction.zip writefunction.py
   
   ROLE_ARN=$(aws iam get-role --role-name cloudmap-tutorial-role \
     --query 'Role.Arn' --output text)
   
   aws lambda create-function \
     --function-name writefunction \
     --runtime python3.12 \
     --role $ROLE_ARN \
     --handler writefunction.lambda_handler \
     --zip-file fileb://writefunction.zip \
     --architectures x86_64
   ```

1. Atualize o tempo limite da função para evitar erros de tempo limite:

   ```
   aws lambda update-function-configuration \
     --function-name writefunction \
     --timeout 5
   ```

## Crie um serviço de AWS Cloud Map aplicativo e registre a função de gravação do Lambda
<a name="create-an-aws-cloud-map-app-service-and-register-the-lambda-write-function"></a>

Para criar outro serviço em seu namespace para representar as funções do aplicativo, siga estas etapas:

1. Crie um serviço para funções do aplicativo:

   ```
   aws servicediscovery create-service \
     --name app-service \
     --namespace-id $NAMESPACE_ID \
     --creator-request-id app-service-request
   ```

1. Obtenha o ID do serviço do aplicativo:

   ```
   APP_SERVICE_ID=$(aws servicediscovery list-services \
     --query "Services[?Name=='app-service'].Id" \
     --output text)
   ```

1. Registre a função de gravação do Lambda como uma instância de serviço com atributos personalizados:

   ```
   aws servicediscovery register-instance \
     --service-id $APP_SERVICE_ID \
     --instance-id write-instance \
     --attributes action=write,functionname=writefunction
   ```

   Os atributos personalizados `functionname=writefunction` permitem que `action=write` os clientes descubram essa função com base em sua finalidade.

## Crie a função Lambda para ler dados
<a name="create-the-lambda-function-to-read-data"></a>

Para criar uma função Lambda que leia dados da tabela do DynamoDB, siga estas etapas:

1. Crie o arquivo Python para a função de leitura:

   ```
   cat > readfunction.py << EOF
   import json
   import boto3
   
   def lambda_handler(event, context):
       try:
           serviceclient = boto3.client('servicediscovery')
   
           response = serviceclient.discover_instances(
               NamespaceName='cloudmap-tutorial', 
               ServiceName='data-service')
           
           if not response.get("Instances"):
               return {
                   'statusCode': 500,
                   'body': json.dumps({"error": "No instances found"})
               }
               
           tablename = response["Instances"][0]["Attributes"].get("tablename")
           if not tablename:
               return {
                   'statusCode': 500,
                   'body': json.dumps({"error": "Table name attribute not found"})
               }
              
           dynamodbclient = boto3.resource('dynamodb')
              
           table = dynamodbclient.Table(tablename)
           
           # Use pagination for larger tables
           response = table.scan(
               Select='ALL_ATTRIBUTES',
               Limit=50  # Limit results for demonstration purposes
           )
           
           # For production, you would implement pagination like this:
           # items = []
           # while 'LastEvaluatedKey' in response:
           #     items.extend(response['Items'])
           #     response = table.scan(
           #         Select='ALL_ATTRIBUTES',
           #         ExclusiveStartKey=response['LastEvaluatedKey']
           #     )
           # items.extend(response['Items'])
   
           return {
               'statusCode': 200,
               'body': json.dumps(response)
           }
       except Exception as e:
           return {
               'statusCode': 500,
               'body': json.dumps({"error": str(e)})
           }
   EOF
   ```

   Essa função também é usada AWS Cloud Map para descobrir o nome da tabela do DynamoDB e depois ler os dados da tabela. Inclui tratamento de erros e comentários de paginação.

1. Package e implante a função Lambda:

   ```
   zip readfunction.zip readfunction.py
   
   aws lambda create-function \
     --function-name readfunction \
     --runtime python3.12 \
     --role $ROLE_ARN \
     --handler readfunction.lambda_handler \
     --zip-file fileb://readfunction.zip \
     --architectures x86_64
   ```

1. Atualize o tempo limite da função:

   ```
   aws lambda update-function-configuration \
     --function-name readfunction \
     --timeout 5
   ```

## Registre a função de leitura do Lambda como uma instância de serviço
<a name="register-the-lambda-read-function-as-a-service-instance"></a>

Para registrar a função de leitura do Lambda como outra instância de serviço no serviço de aplicativo, siga esta etapa:

```
aws servicediscovery register-instance \
  --service-id $APP_SERVICE_ID \
  --instance-id read-instance \
  --attributes action=read,functionname=readfunction
```

Os atributos personalizados `functionname=readfunction` permitem que `action=read` os clientes descubram essa função com base em sua finalidade.

## Crie e execute aplicativos cliente
<a name="create-and-run-client-applications"></a>

Para criar um aplicativo cliente Python que use AWS Cloud Map para descobrir e invocar a função de gravação, siga estas etapas:

1. Crie um arquivo Python para o aplicativo cliente de gravação:

   ```
   cat > writeclient.py << EOF
   import boto3
   import json
   
   try:
       serviceclient = boto3.client('servicediscovery')
   
       print("Discovering write function...")
       response = serviceclient.discover_instances(
           NamespaceName='cloudmap-tutorial', 
           ServiceName='app-service', 
           QueryParameters={ 'action': 'write' }
       )
   
       if not response.get("Instances"):
           print("Error: No instances found")
           exit(1)
           
       functionname = response["Instances"][0]["Attributes"].get("functionname")
       if not functionname:
           print("Error: Function name attribute not found")
           exit(1)
           
       print(f"Found function: {functionname}")
   
       lambdaclient = boto3.client('lambda')
   
       print("Invoking Lambda function...")
       resp = lambdaclient.invoke(
           FunctionName=functionname, 
           Payload='"This is a test data"'
       )
   
       payload = resp["Payload"].read()
       print(f"Response: {payload.decode('utf-8')}")
       
   except Exception as e:
       print(f"Error: {str(e)}")
   EOF
   ```

   Esse cliente usa a `QueryParameters` opção de encontrar instâncias de serviço com o `action=write` atributo.

1. Crie um arquivo Python para o aplicativo cliente de leitura:

   ```
   cat > readclient.py << EOF
   import boto3
   import json
   
   try:
       serviceclient = boto3.client('servicediscovery')
   
       print("Discovering read function...")
       response = serviceclient.discover_instances(
           NamespaceName='cloudmap-tutorial', 
           ServiceName='app-service', 
           QueryParameters={ 'action': 'read' }
       )
   
       if not response.get("Instances"):
           print("Error: No instances found")
           exit(1)
           
       functionname = response["Instances"][0]["Attributes"].get("functionname")
       if not functionname:
           print("Error: Function name attribute not found")
           exit(1)
           
       print(f"Found function: {functionname}")
   
       lambdaclient = boto3.client('lambda')
   
       print("Invoking Lambda function...")
       resp = lambdaclient.invoke(
           FunctionName=functionname, 
           InvocationType='RequestResponse'
       )
   
       payload = resp["Payload"].read()
       print(f"Response: {payload.decode('utf-8')}")
       
   except Exception as e:
       print(f"Error: {str(e)}")
   EOF
   ```

1. Execute o cliente de gravação para adicionar dados à tabela do DynamoDB:

   ```
   python3 writeclient.py
   ```

   A saída deve mostrar uma resposta bem-sucedida com o código de status HTTP 200.

1. Execute o cliente de leitura para recuperar dados da tabela do DynamoDB:

   ```
   python3 readclient.py
   ```

   A saída deve mostrar os dados que foram gravados na tabela, incluindo o ID gerado aleatoriamente e o valor “Isto é um dado de teste”.

## Limpar os recursos
<a name="clean-up-resources"></a>

Ao concluir o tutorial, limpe os recursos para evitar cobranças adicionais.

1. Primeiro, execute o comando a seguir para cancelar o registro das instâncias do serviço:

   ```
   aws servicediscovery deregister-instance \
     --service-id $APP_SERVICE_ID \
     --instance-id read-instance
   
   aws servicediscovery deregister-instance \
     --service-id $APP_SERVICE_ID \
     --instance-id write-instance
   
   aws servicediscovery deregister-instance \
     --service-id $DATA_SERVICE_ID \
     --instance-id data-instance
   ```

1. Execute o comando a seguir para excluir os serviços:

   ```
   aws servicediscovery delete-service \
     --id $APP_SERVICE_ID
   
   aws servicediscovery delete-service \
     --id $DATA_SERVICE_ID
   ```

1. Execute o comando a seguir para excluir o namespace:

   ```
   aws servicediscovery delete-namespace \
     --id $NAMESPACE_ID
   ```

1. Execute o comando a seguir para excluir as funções do Lambda:

   ```
   aws lambda delete-function --function-name writefunction
   aws lambda delete-function --function-name readfunction
   ```

1. Execute o comando a seguir para excluir a função e a política do IAM:

   ```
   aws iam detach-role-policy \
     --role-name cloudmap-tutorial-role \
     --policy-arn $POLICY_ARN
   
   aws iam detach-role-policy \
     --role-name cloudmap-tutorial-role \
     --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
   
   aws iam delete-policy \
     --policy-arn $POLICY_ARN
   
   aws iam delete-role --role-name cloudmap-tutorial-role
   ```

1. Execute o comando a seguir para excluir a tabela do DynamoDB:

   ```
   aws dynamodb delete-table --table-name cloudmap
   ```

1. Execute o comando a seguir para limpar arquivos temporários:

   ```
   rm -f lambda-trust-policy.json cloudmap-policy.json writefunction.py readfunction.py writefunction.zip readfunction.zip writeclient.py readclient.py
   ```