Yandex Cloud
  • Сервисы
  • Решения
  • Почему Yandex Cloud
  • Сообщество
  • Тарифы
  • Документация
  • Связаться с нами
Подключиться
Language / Region
Проект Яндекса
© 2023 ООО «Яндекс.Облако»
Практические руководства
  • Веб-сервис
  • Интернет-магазины
  • Хранение и восстановление данных
  • Тестовая среда
  • Управление инфраструктурой
  • Построение Data Platform
  • Продукты Microsoft в Yandex Cloud
  • Сетевая инфраструктура
  • Визуализация и анализ данных
  • Интернет вещей
  • Бессерверные технологии
    • Сокращатель ссылок
    • Ввод данных в системы хранения
    • Хранение журналов работы приложения
    • Развертывание веб-приложения с использованием Java Servlet API
    • Разработка Slack-бота
    • Разработка Telegram-бота
    • Разработка пользовательской интеграции в API Gateway
    • Разработка CRUD API для сервиса фильмов
    • Разработка навыка Алисы и сайта с авторизацией
  1. Бессерверные технологии
  2. Разработка пользовательской интеграции в API Gateway

Разработка пользовательской интеграции в API Gateway

Статья создана
Yandex Cloud
,
улучшена
Dmitry A.
  • Перед началом работы
    • Необходимые платные ресурсы
  • Настройте окружение
  • Скачайте проект с интеграцией
  • Скомпилируйте функцию
  • Загрузите файл функции в бакет
  • Подготовьте конфигурацию ресурсов для интеграции
  • Разверните ресурсы для интеграции
  • Проверьте работу созданного CRUD API
  • Как удалить созданные ресурсы

С помощью serverless-технологий можно создать собственную интеграцию с сервисами Yandex Cloud.

Пользовательская интеграция представляет собой функцию Yandex Cloud Functions или контейнер Yandex Serverless Containers, которые предназначены для решения типовой задачи.

Функция или контейнер могут быть сконфигурированы в спецификации API-шлюза API Gateway по стандарту OpenAPI 3.0 для выполнения определенных HTTP-запросов.

Разработайте функцию-интеграцию с Yandex Managed Service for YDB для работы с СУБД YDB. Функция будет взаимодействовать с Managed Service for YDB и обрабатывать внешние HTTP-запросы через API-шлюз с использованием HTTP API, совместимого с Amazon DynamoDB. Язык кода функции — TypeScript, среда выполнения — Node.js 16.

Интеграция будет применена для реализации CRUD API для работы с базой данных фильмов, развернутой в Managed Service for YDB.

Чтобы развернуть проект:

  1. Настройте окружение.
  2. Скачайте проект с интеграцией.
  3. Скомпилируйте функцию.
  4. Загрузите файл функции в бакет.
  5. Подготовьте конфигурацию ресурсов для интеграции.
  6. Разверните ресурсы для интеграции.
  7. Проверьте работу созданного CRUD API.

Если созданные ресурсы больше не нужны, удалите их.

Перед началом работы

Перед работой нужно зарегистрироваться в Yandex Cloud и создать платежный аккаунт:

  1. Перейдите в консоль управления, затем войдите в Yandex Cloud или зарегистрируйтесь, если вы еще не зарегистрированы.
  2. На странице биллинга убедитесь, что у вас подключен платежный аккаунт, и он находится в статусе ACTIVE или TRIAL_ACTIVE. Если платежного аккаунта нет, создайте его.

Если у вас есть активный платежный аккаунт, вы можете создать или выбрать каталог, в котором будет работать ваша инфраструктура, на странице облака.

Подробнее об облаках и каталогах.

Необходимые платные ресурсы

В стоимость ресурсов для интеграции входят:

  • Плата за объем хранилища, занятый данными, количество операций с данными и исходящий трафик (см. тарифы Yandex Object Storage).
  • Плата за операции с YDB и хранение данных (см. тарифы Managed Service for YDB в бессерверном режиме).
  • Плата за количество вызовов функции, вычислительные ресурсы, выделенные для выполнения функции, и исходящий трафик (см. тарифы Cloud Functions).
  • Плата за количество запросов к API-шлюзу и исходящий трафик (см. тарифы API Gateway).

Настройте окружение

Windows
Linux
macOS
  1. Установите утилиту WSL для использования окружения Linux.
  2. Запустите подсистему Linux (по умолчанию — Ubuntu).
  3. Настройте окружение так, как описано в инструкции для операционной системы Linux.

Примечание

Если вы используете дистрибутив, отличный от Ubuntu, установите указанные утилиты с помощью команд вашего пакетного менеджера.

  1. Последовательно установите следующие утилиты с помощью команд в терминале:

    • Curl и Git:

      sudo apt-get install curl git -y
      
    • WebStorm или другая среда разработки с поддержкой TypeScript:

      sudo snap install webstorm --classic
      
    • Node.js не ниже версии 16.9.1:

      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
      
  2. Установите Terraform не ниже версии 1.0.8.

  3. Создайте профиль Yandex Cloud CLI с базовыми параметрами.

  4. Настройте AWS CLI.

  1. Последовательно установите следующие утилиты с помощью команд в терминале:

    • Homebrew:

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

      brew install curl git
      
    • WebStorm или другая среда разработки с поддержкой TypeScript:

      brew install --cask webstorm
      
    • Node.js не ниже версии 16.9.1:

      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 /
      
  2. Установите Terraform не ниже версии 1.0.8.

  3. Создайте профиль с базовыми параметрами.

  4. Настройте AWS CLI.

Скачайте проект с интеграцией

Склонируйте репозиторий с проектом для интеграции:

git clone https://github.com/yandex-cloud-examples/yc-serverless-apigw-dynamodb-connector.git

В директории src находятся исходные файлы для создания функции:

  • event.ts — код интерфейса Event, описывающий структуру запроса, и интерфейса RequestContext, описывающий контекст запроса.
  • dynamodb.ts — код обработки вызова функции и основных команд.
  • iam.ts — код получения IAM-токенов, необходимых для авторизации при запросах к YDB.

При вызове функции в файле dynamodb.ts в поле requestContext.apiGateway.operationContext объекта event передается контекст операции.

Контекст операции определяется в параметре context в спецификации API-шлюза, вызывающего функцию-интеграцию.

Примечание

При интеграции с помощью контейнера контекст операции передается через специальный заголовок X-Yc-ApiGateway-Operation-Context.

В файле event.ts определены интерфейсы для основных команд Amazon DynamoDB и их параметров, которые будут реализованы в данной интеграции. Это нужно для спецификации формата контекста операции и работы с ним внутри функции.

Скомпилируйте функцию

  1. Откройте терминал и перейдите в корневую директорию проекта:

    cd <путь_к_корневой_директории_проекта>
    
  2. Установите необходимые проекту зависимости:

    npm ci
    
  3. Выполните компиляцию и сборку кода функции:

    npm run build
    
  4. Упакуйте собранный код функции в ZIP-архив:

    npm run package
    

Загрузите файл функции в бакет

  1. Создайте бакет с публичным доступом. Сохраните имя бакета, оно потребуется в дальнейшем.
  2. Загрузите в бакет ZIP-архив apigw-dynamodb-connector-0.0.1.zip с кодом функции из директории build.

Подготовьте конфигурацию ресурсов для интеграции

Для развертывания CRUD API с помощью функции-интеграции будет использоваться инструмент Terraform.

Специальный Terraform-модуль, разработанный для этого примера интеграции, упрощает процесс конфигурации ресурсов Yandex Cloud. Создаваемые Terraform ресурсы:

  • Бессерверная база данных YDB.
  • Функция-интеграция.
  • Сервисный аккаунт для доступа функции к базе данных.
  • API-шлюз.

Чтобы подготовить конфигурационные файлы для Terraform:

  1. Узнайте имя активного профиля (ACTIVE) интерфейса командной строки Yandex Cloud CLI. В терминале выполните команду:

    yc config profile list
    
  2. Получите параметры активного профиля:

    yc config profile get <имя_профиля>
    

    Сохраните полученные параметры:

    • token — OAuth-токен.
    • cloud-id — идентификатор облака.
    • folder-id — идентификатор каталога.
  3. Создайте директорию crud-api и перейдите в нее:

    mkdir crud-api
    cd crud-api
    

    В дальнейшем все команды Terraform выполняйте в директории crud-api.

  4. Создайте файл main.tf и скопируйте в него конфигурацию Terraform-модуля. Укажите параметры создаваемых ресурсов:

    • cloud_id — идентификатор облака.
    • folder_id — идентификатор каталога.
    • oauth_token — OAuth-токен.
    • database_connector_bucket — имя бакета с функцией-интеграцией.
    locals {
      cloud_id    = "<идентификатор_облака>"
      folder_id   = "<идентификатор_каталога>"
      oauth_token = "<OAuth-токен>"
      zone        = "ru-central1-a"
    }
    
    module "crud-api" {
      source = "github.com/yandex-cloud-examples/yc-serverless-ydb-api"
    
      folder_id                 = local.folder_id
      api_name                  = "movies-api"
      database_name             = "movies-db"
      service_account_name      = "movies-api-service-account"
      region                    = "region-id"
      openapi_spec              = "api.yaml"
      table_specs               = ["file://table.json"]
      database_connector_bucket = "<имя_бакета_с_функцией-интеграцией>"
      database_connector_object = "apigw-dynamodb-connector-0.0.1.zip"
    }
    
    terraform {
      required_providers {
        yandex = {
          source = "yandex-cloud/yandex"
        }
        null   = {
          source = "registry.terraform.io/hashicorp/null"
        }
      }
      required_version = ">= 0.13"
    }
    
    provider "yandex" {
      token     = local.oauth_token
      cloud_id  = local.cloud_id
      folder_id = local.folder_id
      zone      = local.zone
    }
    
    output "crud_api_domain" {
      value = module.crud-api.api_gateway_domain
    }
    
  5. Создайте файл table.json и скопируйте в него спецификацию схемы таблицы создаваемой YDB:

    {
      "TableName": "movie",
      "KeySchema": [
        {
          "AttributeName": "id",
          "KeyType": "HASH"
        }
      ],
      "AttributeDefinitions": [
        {
          "AttributeName": "id",
          "AttributeType": "S"
        },
        {
          "AttributeName": "title",
          "AttributeType": "S"
        },
        {
          "AttributeName": "year",
          "AttributeType": "N"
        }
      ]
    }
    
  6. Создайте файл api.yaml и скопируйте в него OpenAPI-спецификацию создаваемого API-шлюза:

    openapi: "3.0.0"
    info:
      version: 1.0.0
      title: Movies API
    x-yc-apigateway:
      service_account_id: ${SERVICE_ACCOUNT_ID}
    
    paths:
      /movies:
        post:
          description: Create movie
          operationId: createMovie
          requestBody:
            description: Movie to create
            required: true
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/Movie'
          responses:
            '200':
              description: Created or updated movie
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Movie'
            default:
              description: error
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Error'
          x-yc-apigateway-integration:
            type: cloud_functions
            function_id: ${FUNCTION_ID}
            context:
              command: PutItem
              endpoint: ${DATABASE_ENDPOINT}
              tableName: movie
        get:
          description: Get movies
          operationId: getMovies
          parameters:
            - name: from
              in: query
              description: Identifier from which will be queried movies in ascending order
              required: true
              schema:
                type: string
            - name: limit
              in: query
              description: Maximum number of movies in response
              required: false
              schema:
                type: number
                default: 10
          responses:
            '200':
             description: Movies
              content:
                application/json:
                  schema:
                    type: array
                    items:
                      $ref: '#/components/schemas/Movie'
            default:
              description: error
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Error'
          x-yc-apigateway-integration:
            type: cloud_functions
            function_id: ${FUNCTION_ID}
            context:
              command: Scan
              endpoint: ${DATABASE_ENDPOINT}
              tableName: movie
              limit: '{limit}'
              exclusiveStartKey: '{"id": "{from}"}'
      /movies/{movieId}:
        parameters:
          - name: movieId
            in: path
            description: Identifier of movie
            required: true
            schema:
              type: string
        get:
          description: Get movie by id
          operationId: getMovieById
          responses:
            '200':
              description: Movie
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Movie'
            default:
              description: error
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Error'
          x-yc-apigateway-integration:
            type: cloud_functions
            function_id: ${FUNCTION_ID}
            context:
              command: GetItem
              endpoint: ${DATABASE_ENDPOINT}
              tableName: movie
              key: '{"id": "{movieId}"}'
        put:
          description: Update movie by id
          operationId: updateMovieById
          requestBody:
            description: Movie or attributes to update
            required: true
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/Movie'
          responses:
            '200':
              description: Updated movie
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Movie'
            default:
              description: error
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Error'
          x-yc-apigateway-integration:
            type: cloud_functions
            function_id: ${FUNCTION_ID}
            context:
              command: UpdateItem
              endpoint: ${DATABASE_ENDPOINT}
              tableName: movie
              key: '{"id": "{movieId}"}'
        delete:
          description: Delete movie by id
          operationId: deleteMovieById
          responses:
            '200':
              description: Deleted movie
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Movie'
            default:
              description: error
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Error'
          x-yc-apigateway-integration:
            type: cloud_functions
            function_id: ${FUNCTION_ID}
            context:
              command: DeleteItem
              endpoint: ${DATABASE_ENDPOINT}
              tableName: movie
              key: '{"id": "{movieId}"}'
    components:
      schemas:
        Movie:
          type: object
          required:
            - id
            - title
            - year
          properties:
            id:
              type: string
            title:
              type: string
            year:
              type: integer
    
        Error:
          type: object
          required:
            - message
          properties:
            message:
              type: string
    

Разверните ресурсы для интеграции

  1. Инициализируйте Terraform. В терминале выполните команду:

    terraform init
    
  2. Разверните облачные ресурсы:

    terraform apply
    
  3. Подтвердите создание ресурсов: введите в терминале yes и нажмите Enter.

    В выводе команды в переменной crud_api_domain будет указан доменный адрес созданного CRUD API. Сохраните этот адрес, он потребуется в дальнейшем.

    Проверить созданные ресурсы можно в консоли управления.

Проверьте работу созданного CRUD API

Для проверки работы созданного CRUD API выполните следующие HTTP-запросы:

  1. Добавьте информацию о фильме. В терминале выполните команду:

    curl \
      --location \
      --request POST 'https://<доменный_адрес_CRUD_API>/movies' \
      --header 'Content-Type: application/json' \
      --data-raw '{
        "id": "301",
        "title": "The Matrix",
        "year": 1999
      }'
    
  2. Получите информацию о фильме:

    curl \
      --location \
      --request GET 'https://<доменный_адрес_CRUD_API>/movies/301'
    
  3. Измените информацию о фильме:

    curl \
      --location \
      --request PUT 'https://<доменный_адрес_CRUD_API>/movies/301' \
      --header 'Content-Type: application/json' \
      --data-raw '{
        "title": "Матрица"
      }'
    
  4. Добавьте информацию о другом фильме:

    curl \
      --location \
      --request POST 'https://<доменный_адрес_CRUD_API>/movies' \
      --header 'Content-Type: application/json' \
      --data-raw '{
        "id": "299",
        "title": "The Matrix Reloaded",
        "year": 2003
      }'
    
  5. Получите список фильмов:

    curl \
      --location \
      --request GET 'https://<доменный_адрес_CRUD_API>/movies?from=1&limit=5'
    
  6. Удалите информацию об одном из фильмов:

    curl \
      --location \
      --request DELETE 'https://<доменный_адрес_CRUD_API>/movies/301' \
      --data-raw ''
    

Как удалить созданные ресурсы

Чтобы перестать платить за созданные ресурсы:

  • Удалите ресурсы, созданные с помощью Terraform. В терминале выполните команду:

    terraform destroy
    

    Подтвердите удаление ресурсов: введите в терминале yes и нажмите Enter.

  • Удалите бакет с файлом функции.

Была ли статья полезна?

Language / Region
Проект Яндекса
© 2023 ООО «Яндекс.Облако»
В этой статье:
  • Перед началом работы
  • Необходимые платные ресурсы
  • Настройте окружение
  • Скачайте проект с интеграцией
  • Скомпилируйте функцию
  • Загрузите файл функции в бакет
  • Подготовьте конфигурацию ресурсов для интеграции
  • Разверните ресурсы для интеграции
  • Проверьте работу созданного CRUD API
  • Как удалить созданные ресурсы