Créons une API qui récupère les données DynamoDB avec AWS SAM
Bref, à partir d'une table comme celle-ci ...
group(Hash) | name(Range) |
---|---|
group1 | name1 |
group1 | name2 |
group2 | name3 |
Je veux prendre ça comme ça.
curl https://hogehoge/Prod/dynamo-api/v1/?group=group1&name=name1
{
"result": [
{
"name": "group1",
"group": "name1"
}
]
}
Pour la construction, reportez-vous à la précédente [AWS SAM] Introduction à la version Python. (Il s'agit de la procédure d'initialisation d'une application AWS SAM à l'aide de Pipenv.)
Les ressources à créer cette fois sont les suivantes
Maintenant, écrivons template.yaml pour créer les ressources ci-dessus.
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
dynamo-api
Sample SAM Template for dynamo-api
#Paramètres de délai d'expiration Lambda
Globals:
Function:
Timeout: 60
#Définition du nom de la table, du nom de la fonction, etc.
Parameters:
DynamoAPIFunctionName:
Type: String
Default: dynamo-api
DynamoTableName:
Type: String
Default: DynamoApiTable
#Définition des ressources
Resources
DynamoTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: !Ref DynamoTableName
#Définition de la clé de hachage et de la clé de plage (nom et type de colonne)
AttributeDefinitions:
- AttributeName: group
AttributeType: S
- AttributeName: name
AttributeType: S
KeySchema:
- AttributeName: group
KeyType: HASH
- AttributeName: name
KeyType: RANGE
#Désignation du mode de charge (PAY_PER_REQUEST est pay-as-you-go)
BillingMode: PAY_PER_REQUEST
DynamoAPIFunctionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- 'lambda.amazonaws.com'
Action:
- 'sts:AssumeRole'
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/CloudWatchLogsFullAccess'
#Autorisation de lire la table DynamoDB (cela vous permet de lire uniquement la table que vous créez cette fois)
Policies:
- PolicyName: 'DynamoApiTablePolicy'
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- dynamodb:Get*
- dynamodb:Query
Resource: !GetAtt DynamoTable.Arn
DynamoAPIFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: !Ref DynamoAPIFunctionName
Role: !GetAtt DynamoAPIFunctionRole.Arn
# app.Chemin du répertoire où se trouve py
CodeUri: dynamo-api/
#Chemin du gestionnaire (il est facile de se tromper si vous le changez négligemment ... c'est bien de le laisser tranquille)
Handler: app.lambda_handler
Runtime: python3.7
#Paramètres de la passerelle API (description spécifique à SAM)
Events:
DynamoApi:
Type: Api
Properties:
Path: /dynamo-api/v1/
Method: get
#Le rôle d'origine des paramètres spécifiés dans Outputs est de transmettre des données à d'autres modèles.
#Cette fois, il est utilisé pour générer le point de terminaison de l'API lorsque le déploiement est terminé.
Outputs:
DynamoApi:
Description: "API Gateway endpoint URL for Prod stage for Dynamo API function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/dynamo-api/v1/"
Les paramètres de Lambda et d'API Gateway sont presque identiques à ceux du modèle, il est donc facile à écrire.
Tout d'abord, installez les bibliothèques requises.
$ pipenv install requests boto3
Ensuite, nous allons créer un processus qui récupère réellement les données de la table Dynamo.
Recherchez la table Dynamo avec le groupe
et le nom` spécifiés dans le paramètre GET et renvoyez sa valeur
C'est un mécanisme simple.
J'ai essayé de faire de «nom» le premier.
app.py
import json
import json
import boto3
from boto3.dynamodb.conditions import Key
from http import HTTPStatus as status
DYNAMODB_TABLE_NAME = 'DynamoApiTable'
def lambda_handler(event, context):
table = boto3.resource('dynamodb').Table(DYNAMODB_TABLE_NAME)
params = event.get('queryStringParameters')
results = dynamo_search(table, params)
if results is None:
return {
"statusCode": status.BAD_REQUEST,
"body": json.dumps({
"error": "Bad Request"
}, ensure_ascii=False),
}
return {
"statusCode": status.OK,
"body": json.dumps({
"results": results
}, ensure_ascii=False),
}
def dynamo_search(table, params):
if params.get('group'):
keyConditionExpression = Key('group').eq(params.get('group'))
if params.get('name'):
keyConditionExpression &= Key('name').begins_with(params.get('name'))
return table.query(
KeyConditionExpression=keyConditionExpression).get('Items', [])
return None
Je veux convertir de Pipfile
en requirements.txt
...
Dans un tel cas, vous pouvez convertir avec cette commande.
(Boto3 est également préparé dans Lambda depuis le début, donc il peut ne pas être beaucoup utilisé ..: penser :)
$ pipenv lock -r > requirements.txt
Cette fois, vous pouvez conserver la valeur par défaut requirements.txt
: sweat_smile:
$ sam build
Building resource 'DynamoAPIFunction'
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource
Build Succeeded
Built Artifacts : .aws-sam/build
Built Template : .aws-sam/build/template.yaml
Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided
Si vous avez des paramètres séparés pour ~ / .aws / credentials
, ajoutez l'option --profile.
L'option --guided
n'est valide que pour la première fois. (Parce que les paramètres sont enregistrés dans samconfig.toml
)
$ sam deploy --guided
Stack dynamo-api-stack outputs:
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
OutputKey-Description OutputValue
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
DynamoApi - API Gateway endpoint URL for Prod stage for Dynamo API function https://hogehoge/Prod/dynamo-api/v1/
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Le point de terminaison est également affiché correctement ~
Cette fois (également), j'ai enregistré le nom et le nom du groupe recommandé.
group(Hash) | name(Range) |
---|---|
Bracelet miel | Suo Patra |
Bracelet miel | Miko Weir |
Holo en direct | Fubuki Shirakami |
... | ... |
Essayez d'envoyer une demande au point de terminaison de sortie. C'est difficile à voir, alors formatez-le avec jq
.
(Les gens dans le navigateur parce que curl
est gênant: information_desk_person :)
Tout d'abord, spécifiez group
(clé de hachage).
$ curl https://hogehoge/Prod/dynamo-api/v1/ \
--get \
--data-urlencode 'group=Bracelet miel' | jq
{
"results": [
{
"name": "Suo Patra",
"group": "Bracelet miel"
},
{
"name": "Miko Weir",
"group": "Bracelet miel"
},
{
"name": "Charlotte Shimamura",
"group": "Bracelet miel"
},
{
"name": "Saizonoji Mary",
"group": "Bracelet miel"
}
]
}
Je l'ai: clap:
Bien sûr, vous pouvez également rechercher nom
(clé de plage) avec une correspondance de préfixe.
$ curl https://hogehoge/Prod/dynamo-api/v1/ \
--get \
--data-urlencode 'group=Bracelet miel' \
--data-urlencode 'name=Suo' | jq
{
"results": [
{
"name": "Suo Patra",
"group": "Bracelet miel"
}
]
}
Je l'ai, c'est parfait!
Cette fois, j'ai fait une API simple. La prochaine fois, je testerai avec pytest
.
Merci d'avoir lu jusqu'au bout!