Yandex Cloud
  • Services
  • Solutions
  • Why Yandex Cloud
  • Blog
  • Pricing
  • Documentation
  • Contact us
Get started
Language / Region
Yandex project
© 2023 Yandex.Cloud LLC
Yandex Serverless Containers
  • Comparison with other Yandex Cloud services
  • Getting started
  • Step-by-step instructions
  • Concepts
  • Practical guidelines
    • Developing CRUD APIs for movie services
  • Access management
  • Pricing policy
  • Containers API reference
  • API Triggers reference
  • Questions and answers
  1. Practical guidelines
  2. Developing CRUD APIs for movie services

Developing CRUD APIs for movie services

Written by
Yandex Cloud
  • Before you begin
    • Required paid resources
  • Configure the environment
  • Initiate Terraform
  • Create a Managed Service for YDB database
  • Run CRUD operations
    • Create a service account
    • Compile the application source code in TypeScript
  • Develop the REST API
    • Deploy the application in Serverless Containers
    • Deploy the API in API Gateway
  • Check the performance of the created CRUD API
  • How to delete created resources

Using serverless technology, you can create CRUD APIs for services that keep movie data.

The implementation of CRUD APIs employs the Yandex Serverless Containers container, which is designed for a movie database deployed in Yandex Managed Service for YDB.

The container is configured in the Yandex API Gateway API gateway specifications supporting OpenAPI 3.0 to execute specific HTTP requests.

The container interacts with Managed Service for YDB and processes external HTTP requests via the API gateway using the Amazon DynamoDB-compatible HTTP API. The CRUD API source code language is TypeScript, the runtime environment is Node.js 16.

To deploy a project:

  1. Configure the environment.
  2. Initiate Terraform.
  3. Create a Managed Service for YDB database.
  4. Run CRUD operations.
  5. Develop the REST API.
  6. Check the performance of the CRUD API.

If you no longer need the created resources, delete them.

Before you begin

Before you start, sign up for Yandex Cloud and create a billing account:

  1. Go to the management console and log in to Yandex Cloud or register if you don't have an account yet.
  2. On the billing page, make sure you linked a billing account and it has the ACTIVE or TRIAL_ACTIVE status. If you don't have a billing account, create one.

If you have an active billing account, you can go to the cloud page to create or select a folder to run your infrastructure.

Learn more about clouds and folders.

Required paid resources

The cost of CRUD API resources includes:

  • A fee for YDB operations and data storage (see Managed Service for YDB pricing for serverless mode).
  • A fee for the number of container calls, computing resources allocated to execute the application, and outgoing traffic (see Serverless Containers pricing).
  • A fee for the number of requests to the API gateway and outgoing traffic (see API Gateway pricing).

Configure the environment

Windows
Linux
MacOS
  1. Install the WSL utility to run a Linux environment.
  2. Run the Linux subsystem (by default, Ubuntu).
  3. Configure the environment as described in the Linux manual.

Note

If you use a distribution other than Ubuntu, install the specified utilities using your package manager commands.

  1. Install the following utilities in the specified order using commands in the terminal:

    • Curl and Git:

      sudo apt-get install curl git -y
      
    • WebStorm or any other development environment that supports TypeScript:

      sudo snap install webstorm --classic
      
    • Node.js 16.9.1 or higher:

      curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash
      sudo apt-get install nodejs
      node -v
      npm -v
      
    • TypeScript:

      sudo npm install -g typescript
      
    • Yandex Cloud CLI:

      curl https://storage.yandexcloud.net/yandexcloud-yc/install.sh | bash
      exec -l $SHELL
      yc version
      
    • AWS CLI:

      curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
      unzip awscliv2.zip
      sudo ./aws/install
      
    • Docker:

      sudo apt-get update
      sudo apt-get install apt-transport-https ca-certificates curl gnupg lsb-release -y
      curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
      echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
      $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
      sudo apt-get update
      sudo apt-get install docker-ce docker-ce-cli containerd.io -y
      sudo docker run hello-world
      
    • Terraform 1.0.8 or higher:

      sudo apt-get update && sudo apt-get install -y gnupg software-properties-common curl
      curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
      sudo apt-add-repository "deb [arch=$(dpkg --print-architecture)] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
      sudo apt-get update && sudo apt-get install terraform -y
      terraform version
      
  2. Create a Yandex Cloud CLI profile with basic parameters.

  3. Set up the AWS CLI.

  4. Set up Docker management on behalf of a user without privileges.

    sudo groupadd docker
    sudo usermod -aG docker $USER
    newgrp docker
    docker run hello-world
    
  1. Install the following utilities in the specified order using commands in the terminal:

    • Homebrew:

      /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
      
    • Curl and Git:

      brew install curl git
      
    • WebStorm or any other development environment that supports TypeScript:

      brew install --cask webstorm
      
    • Node.js 16.9.1 or higher:

      brew install node
      node -v
      npm -v
      
    • TypeScript:

      npm install -g typescript
      
    • Yandex Cloud CLI:

      curl https://storage.yandexcloud.net/yandexcloud-yc/install.sh | bash
      exec -l $SHELL
      yc version
      
    • AWS CLI:

      curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
      sudo installer -pkg AWSCLIV2.pkg -target /
      
    • Docker:

      brew install --cask docker
      
    • Terraform 1.0.8 or higher:

      brew tap hashicorp/tap
      brew install hashicorp/tap/terraform
      terraform version
      
  2. Create a profile with basic parameters.

  3. Set up the AWS CLI.

Initiate Terraform

  1. Clone a repository with source files for the CRUD API project:

    git clone https://github.com/yandex-cloud-examples/yc-serverless-web-application-movie-website.git
    

    Open the folder project in WebStorm and review the source files.

  2. Go to the deploy folder:

    cd <path_to_deploy_folder>
    
  3. Find out the name of the ACTIVE profile of the Yandex Cloud CLI command line interface. In the terminal, run the command:

    yc config profile list
    
  4. Get the active profile parameters:

    yc config profile get <profile_name>
    
  5. Copy the parameters to provider.tf:

    • token: OAuth token.
    • cloud-id: ID of the cloud.
    • folder-id: ID of the folder.
  6. Export the folder ID to the environment variable:

    export FOLDER_ID=<folder_ID>
    echo $FOLDER_ID
    
  7. Run the Terraform initialization command:

    terraform init
    

    Note

    Run all the Terraform commands in the deploy folder.

Create a Managed Service for YDB database

The project uses a YDB database in serverless mode. The database consists of two tables: movies to keep movie data and votes to keep user rates. Each table entry contains the ID and the final set of attributes.

  1. The Terraform configuration for database creation is described in ydb.tf. Create a database:

    terraform apply -target=yandex_ydb_database_serverless.movies_database
    

    Confirm resource creation: type yes in the terminal and press Enter.

    The command result contains the variables:

    • movies_database_document_api_endpoint: The Document API endpoint of a database.
    • movies_database_path: The relative path to the database.

    You can make sure the movies-database DB is created in the management console or using the CLI command yc ydb database list.

  2. Export the values movies_database_document_api_endpoint and movies_database_path from the previous command result to environment variables:

    export DOCUMENT_API_ENDPOINT=<movies_database_document_api_endpoint>
    echo $DOCUMENT_API_ENDPOINT
    
    export MOVIES_DATABASE_PATH=<movies_database_path>
    echo $MOVIES_DATABASE_PATH
    
  3. Create the movies and votes tables in the movies-database DB:

    aws dynamodb create-table \
      --table-name movies \
      --attribute-definitions \
        AttributeName=id,AttributeType=N \
        AttributeName=title,AttributeType=S \
        AttributeName=type,AttributeType=S \
        AttributeName=original_title,AttributeType=S \
        AttributeName=original_language,AttributeType=S \
        AttributeName=release_date,AttributeType=S \
        AttributeName=poster_path,AttributeType=S \
        AttributeName=popularity,AttributeType=N \
        AttributeName=video,AttributeType=S \
        AttributeName=vote_count,AttributeType=N \
        AttributeName=vote_average,AttributeType=N \
        AttributeName=genres,AttributeType=S \
        AttributeName=backdrop_path,AttributeType=S \
        AttributeName=adult,AttributeType=S \
        AttributeName=overview,AttributeType=S \
      --key-schema \
        AttributeName=id,KeyType=HASH \
      --global-secondary-indexes \
        "[
          {
            \"IndexName\": \"PopularityIndex\",
            \"KeySchema\": [{\"AttributeName\":\"type\",\"KeyType\":\"HASH\"}, {\"AttributeName\":\"popularity\",\"KeyType\":\"RANGE\"}],
            \"Projection\":{
              \"ProjectionType\":\"ALL\"
            }
          }
        ]" \
      --endpoint ${DOCUMENT_API_ENDPOINT}
    
    aws dynamodb create-table \
      --table-name votes \
      --attribute-definitions \
        AttributeName=id,AttributeType=S \
        AttributeName=user_id,AttributeType=S \
        AttributeName=movie_id,AttributeType=N \
        AttributeName=value,AttributeType=N \
      --key-schema \
        AttributeName=id,KeyType=HASH \
      --global-secondary-indexes \
        "[
          {
            \"IndexName\": \"MovieIndex\",
            \"KeySchema\": [{\"AttributeName\":\"movie_id\",\"KeyType\":\"HASH\"}],
            \"Projection\":{
              \"ProjectionType\":\"ALL\"
            }
          }
        ]" \
      --endpoint ${DOCUMENT_API_ENDPOINT}
    
  4. Make sure the tables are created:

    aws dynamodb describe-table \
      --table-name movies \
      --endpoint ${DOCUMENT_API_ENDPOINT}
    
    aws dynamodb describe-table \
      --table-name votes \
      --endpoint ${DOCUMENT_API_ENDPOINT}
    

    Each table supports two indexes:

    • Movies: The index for quickly searching for a movie by ID, and index for sorting movies by popularity.
    • Votes: The index for searching for a user's votes by movie, and index for getting all movie rates.

Run CRUD operations

A database layer is used every time data is retrieved, updated, or deleted. These actions are called CRUD operations.

Interaction with the database via the Document API is performed using the AWS SDK for JavaScript v3 library:

  • model.ts defines the models of a Movie movie and Vote rates via the TypeScript interface.
  • repository.ws implements CRUD operations for using these entities.

IAM tokens are used for authorization when data operations are executed. To get an IAM token before the operation, the metadata service is called.

Create a service account

  1. The Terraform configuration to create a service account is described in sa.tf. Create a service account:

    terraform apply -target=yandex_iam_service_account.movies_api_sa
    

    Confirm resource creation: type yes in the terminal and press Enter.

  2. In the command result, the movies_api_sa_id shows the ID of the created service account. Export it to the environment variable:

    export MOVIES_API_SA_ID=<service_account_ID>
    echo $MOVIES_API_SA_ID
    
  3. Assign roles to the service account:

    yc resource-manager folder add-access-binding ${FOLDER_ID} \
      --role ydb.admin \
      --subject serviceAccount:${MOVIES_API_SA_ID}
    
    yc resource-manager folder add-access-binding ${FOLDER_ID} \
      --role container-registry.images.puller \
      --subject serviceAccount:${MOVIES_API_SA_ID}
    
    yc resource-manager folder add-access-binding ${FOLDER_ID} \
      --role serverless.containers.invoker \
      --subject serviceAccount:${MOVIES_API_SA_ID}
    

    Where:

    • role: The role assigned.
    • -subject serviceAccount: Service account ID.

    The service account is assigned roles for the following actions:

    • Calling the container in Serverless Containers.
    • Executing operations in YDB.

    The roles are assigned to the whole folder rather than an individual resource.

Compile the application source code in TypeScript

  1. Go to the repository root folder and install all the necessary dependencies:

    cd <path_to_folder_sls-web-application>
    npm ci
    

    After the command is executed, the node_modules with all the necessary dependencies appears in the folder.

  2. Run the project build:

    npm run build
    

    After the command is executed, the dist folder with the compiled JS files appears in the folder.

Develop the REST API

The file openapi/api.yaml already has the OpenAPI specifications, which describe the chief operations with movies and rates.

To implement the service according to the specifications, the OpenAPI Backend library is used in combination with the Express framework. The file app.ts describes required classes, operation mapping, and the starting of an HTTP service.

Deploy the application in Serverless Containers

Build the application as a Docker image and run it in Serverless Containers:

  1. In the OpenAPI specifications api.yaml, in the x-yc-apigateway.service_account_id field, type the ID of the created service account.

  2. The file container-registry.tf describes a configuration of the registry and repository to which an application Docker image is uploaded. Go to the deploy folder and create resources in Yandex Container Registry:

    cd <path_to_folder_deploy>
    terraform apply -target=yandex_container_registry.default
    terraform apply -target=yandex_container_repository.movies_api_repository
    

    Confirm resource creation: type yes in the terminal and press Enter.

  3. In the command result, the movies_api_repository_name variable shows the name of the repository to which a Docker image will be uploaded. Export it to the environment variable:

    export MOVIES_API_REPOSITORY_NAME=<repository_name>
    echo $MOVIES_API_REPOSITORY_NAME
    
  4. Set up Docker for the created repository:

    yc container registry configure-docker
    
  5. The file Dockerfile describes a configuration to build a Docker image. Build the image and upload it to the repository created in the previous step:

    docker build -t ${MOVIES_API_REPOSITORY_NAME}:0.0.1 .
    docker push ${MOVIES_API_REPOSITORY_NAME}:0.0.1
    
  6. Create a Serverless Containers container:

    yc sls container create \
      --name movies-api-container \
      --folder-id ${FOLDER_ID}
    

    Where:

    • name is the container name.
    • folder-id: ID of the folder.
  7. The command result shows the ID of the container. Export it to the environment variable:

    export MOVIES_API_CONTAINER_ID=<container_ID>
    echo $MOVIES_API_CONTAINER_ID
    
  8. Create a container revision from a Docker image version 0.0.1:

    yc sls container revisions deploy \
      --folder-id ${FOLDER_ID} \
      --container-id ${MOVIES_API_CONTAINER_ID} \
      --memory 512M \
      --cores 1 \
      --execution-timeout 5s \
      --concurrency 4 \
      --environment AWS_ACCESS_KEY_ID=FAKE_AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY=FAKE_AWS_SECRET_ACCESS_KEY,DOCUMENT_API_ENDPOINT=${DOCUMENT_API_ENDPOINT} \
      --service-account-id ${MOVIES_API_SA_ID} \
      --image ${MOVIES_API_REPOSITORY_NAME}:0.0.1
    

    Where:

    • folder-id: ID of the folder.
    • container-id: Container ID.
    • memory: Amount of memory available for the container.
    • cores: Number of vCPU cores available for the container.
    • execution-timeout: Execution timeout.
    • concurrency: Maximum number of concurrent container calls. If the number of requests to a container exceeds the value of the concurrency parameter, the service scales the container up by launching additional copies.
    • environment: Environment variables. The Document API endpoint of a database is passed to the application via the DOCUMENT_API_ENDPOINT environment variable.
    • service-account-id: The ID of your service account.
    • image: Repository name.

Deploy the API in API Gateway

  1. In the OpenAPI specifications api.yaml, replace the ${MOVIES_API_CONTAINER_ID} variable with the ID of the created container.

  2. The file api-gateway.tf describes a Terraform configuration for creating the API gateway. Deploy the API gateway:

    terraform apply -target=yandex_api_gateway.movies_api_gateway
    

    Confirm resource creation: type yes in the terminal and press Enter.

  3. In the command result, the movies_api_gateway_domain variable shows the domain name of the API gateway. Export it to the environment variable:

    export MOVIES_API_GATEWAY_DOMAIN=<API_gateway_domain_name>
    echo $MOVIES_API_GATEWAY_DOMAIN
    

Check the performance of the created CRUD API

To check the performance of the created CRUD API, run the following HTTP requests using the curl command:

  1. Retrieve a movie list:

    curl "${MOVIES_API_GATEWAY_DOMAIN}/movies?limit=10"
    

    The response must return an empty list [], because at the moment, there's no data in the database.

  2. Add movie details:

    curl \
      --location \
      --request POST 'https://${MOVIES_API_GATEWAY_DOMAIN}/movies' \
      --header 'Content-Type: application/json' \
      --data-raw '{
        "id": "301",
        "title": "The Matrix",
        "release_date": 1999
      }'
    
  3. Retrieve movie details:

    curl \
      --location \
      --request GET 'https://${MOVIES_API_GATEWAY_DOMAIN}/movies/301'
    
  4. Add details of another movie:

    curl \
      --location \
      --request POST 'https://${MOVIES_API_GATEWAY_DOMAIN}/movies' \
      --header 'Content-Type: application/json' \
      --data-raw '{
        "id": "299",
        "title": "The Matrix Reloaded",
        "release_date": 2003
      }'
    
  5. Retrieve a movie list:

    curl \
      --location \
      --request GET 'https://${MOVIES_API_GATEWAY_DOMAIN}/movies?from=1&limit=5'
    

You can also upload the specifications to Postman or SwaggerHub by adding the address of the created API gateway from the ${MOVIES_API_GATEWAY_DOMAIN} variable to the servers section. This enables you to easily run requests to the REST API.

View diagnostic information about the container. In the management console, go to the container page. The Logs tab shows messages about container calls and the Monitoring tab charts of container calls, average request processing times, and number of errors.

You can also view monitoring logs and charts on the API gateway page.

How to delete created resources

To stop paying for resources created using Terraform, delete them. In the terminal, run the command:

terraform destroy

Confirm resource deletion: type yes in the terminal and press Enter.

See also

  • Getting started with Terraform.
  • Terraform reference. Yandex Cloud provider.
  • Document table.
  • X-yc-apigateway-integration extension.
  • Container logs.
  • Viewing container monitoring charts.

Was the article helpful?

Language / Region
Yandex project
© 2023 Yandex.Cloud LLC
In this article:
  • Before you begin
  • Required paid resources
  • Configure the environment
  • Initiate Terraform
  • Create a Managed Service for YDB database
  • Run CRUD operations
  • Create a service account
  • Compile the application source code in TypeScript
  • Develop the REST API
  • Deploy the application in Serverless Containers
  • Deploy the API in API Gateway
  • Check the performance of the created CRUD API
  • How to delete created resources