Lambda function đọc dữ liệu

Chúng ta sẽ tạo một hàm Lambda để đọc tất cả dữ liệu trong bảng DynamoDB.

Yêu cầu - Cài đặt Python

Bạn phải cài đặt Python trên máy tính với cùng phiên bản với Lambda runtime được chỉ định trong SAM template (trong workshop này, chúng ta sử dụng Python 3.13).

Tại sao cần phải cài?

AWS SAM CLI sử dụng Python cục bộ trên máy của bạn để build deployment package cho Lambda function. Trong quá trình sam build, SAM sẽ cài đặt các dependency trong requirements.txt bằng Python runtime trên máy. Nếu phiên bản Python trên máy không khớp với phiên bản runtime được chỉ định trong template.yaml, quá trình build có thể thất bại hoặc tạo ra các package không tương thích, gây lỗi khi Lambda function chạy trên AWS.

Cách cài đặt Python 3.13 trên Windows:

  1. Truy cập trang tải Python chính thức: https://www.python.org/downloads/

  2. Tải xuống Python 3.13.x (phiên bản 3.13 mới nhất).

  3. Chạy trình cài đặt:

    • ✅ Đánh dấu “Add python.exe to PATH” ở cuối trình cài đặt.

    • Nhấp “Install Now” hoặc “Customize installation” nếu cần.

  4. Sau khi cài đặt, kiểm tra phiên bản bằng cách mở terminal và chạy:

    python --version
    

    Bạn sẽ thấy output như: Python 3.13.x

Đối với macOS/Linux, bạn có thể sử dụng pyenv để cài đặt và quản lý nhiều phiên bản Python:

# Cài đặt pyenv (macOS với Homebrew)
brew install pyenv

# Cài đặt Python 3.13
pyenv install 3.13

# Đặt làm phiên bản cục bộ
pyenv local 3.13

Kiểm tra phiên bản Python trước khi tiếp tục:

python --version

Python Version

Chỉnh sửa SAM Template

  1. Mở tệp template.yaml trong thư mục fcaj-book-shop.

  2. Thêm tài nguyên sau vào phần Resources:

    BooksList:
      Type: AWS::Serverless::Function
      Properties:
        CodeUri: fcaj-book-shop/books_list
        Handler: books_list.lambda_handler
        Runtime: python3.13
        FunctionName: books_list
        Environment:
          Variables:
            TABLE_NAME: !Ref BooksTable
        Architectures:
          - x86_64
        Policies:
          - Statement:
              - Sid: ReadDynamoDB
                Effect: Allow
                Action:
                  - dynamodb:Scan
                  - dynamodb:Query
                Resource:
                  - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${booksTableName}
                  - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${booksTableName}/index/*
    

    Thêm tài nguyên BooksList

Tài nguyên này định nghĩa một Lambda function tên books_list với:

  • Runtime Python 3.13 trên kiến trúc x86_64
  • Biến môi trường TABLE_NAME tham chiếu đến bảng DynamoDB BooksTable
  • Được cấp quyền dynamodb:Scandynamodb:Query trên bảng Books

Tạo mã Lambda Function

  1. Tạo cấu trúc thư mục như sau:

    fcaj-book-shop
    ├── fcaj-book-shop
    │   └── books_list
    │       └── books_list.py
    └── template.yaml
    
    • Tạo thư mục fcaj-book-shop/books_list trong thư mục fcaj-book-shop.
    • Tạo tệp books_list.py và sao chép đoạn mã sau vào đó:
    import json
    import os
    import boto3
    from decimal import *
    from boto3.dynamodb.types import TypeDeserializer
    
    client = boto3.client('dynamodb') 
    serializer = TypeDeserializer()
    
    table_name = os.environ['TABLE_NAME']
    
    class DecimalEncoder(json.JSONEncoder):
        def default(self, obj):
            if isinstance(obj, Decimal):
                return str(obj)
            return json.JSONEncoder.default(self, obj)
    
    def deserialize(data):
        if isinstance(data, list):
            return [deserialize(v) for v in data]
    
        if isinstance(data, dict):
            try:
                return serializer.deserialize(data)
            except TypeError:
                return {k: deserialize(v) for k, v in data.items()}
        else:
            return data
    
    def lambda_handler(event, context):
        data_books = client.scan(
            TableName=table_name,
            IndexName='name-index'
        )
        format_data_books = deserialize(data_books["Items"])
        for book in format_data_books:
            data_comment = client.query(
                TableName=table_name, 
                KeyConditionExpression="id = :id AND rv_id > :rv_id", 
                ExpressionAttributeValues={
                    ":id": {"S": book['id']}, 
                    ":rv_id": {"N": "0"}
                }
            )
            format_data_comment = deserialize(data_comment['Items'])
            print(data_comment['Items'])
            book["comments"] = format_data_comment
    
        print (format_data_books)
        return {
            "statusCode": 200,
            "headers": {
                "Content-Type": "application/json",
                "Access-Control-Allow-Origin": "*",
                "Access-Control-Allow-Methods": "GET,PUT,POST,DELETE, OPTIONS",
                "Access-Control-Allow-Headers": "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method,X-Access-Token,XKey,Authorization"
            },
            "body": json.dumps(format_data_books, cls=DecimalEncoder)
        }
    

    Mã nguồn books_list.py

Build và Deploy

  1. Chạy các lệnh sau để build và validate SAM template:

    sam validate
    sam build
    

    SAM Validate và Build

  2. Triển khai stack đã cập nhật:

    sam deploy
    

    Changeset sẽ hiển thị hai tài nguyên mới được thêm:

    • BooksListRole (AWS::IAM::Role)
    • BooksList (AWS::Lambda::Function)

    Nhập y để xác nhận triển khai.

    SAM Deploy - Changeset

  3. Chờ quá trình triển khai hoàn tất. Bạn sẽ thấy thông báo Successfully created/updated stack.

    Deploy hoàn tất

Kiểm tra trên AWS Console

  1. Mở CloudFormation console, nhấp vào stack fcaj-book-shop và chuyển sang tab Resources. Bạn sẽ thấy 5 tài nguyên bao gồm BooksListBooksListRole.

    CloudFormation Resources

  2. Mở Lambda console. Nhấp vào hàm books_list.

    Lambda Functions

  3. Tại trang function books_list, bạn có thể xem:

    • Phần Code source hiển thị mã books_list.py đã được deploy.

    Code Source

    • Phần Function overview hiển thị sơ đồ và thông tin chi tiết của function.

    Function Overview

  4. Nhấp vào tab Configuration, sau đó chọn Environment variables từ menu bên trái. Xác nhận TABLE_NAME được đặt là Books.

    Environment Variables

  5. Chọn Permissions từ menu bên trái. Nhấp vào tên execution role (ví dụ: fcaj-book-shop-BooksListRole-...).

    Permissions - Execution Role

  6. Tại trang IAM Role, kiểm tra phần Permissions policies. Bạn sẽ thấy:

    • AWSLambdaBasicExecutionRole (AWS managed) - cho CloudWatch Logs
    • BooksListRolePolicy0 (Customer inline) - policy tùy chỉnh mà chúng ta đã định nghĩa

    IAM Role Permissions

  7. Nhấp vào BooksListRolePolicy0 để mở rộng. Xem chi tiết policy JSON cấp quyền dynamodb:Scandynamodb:Query trên bảng Books.

    BooksListRolePolicy0 JSON