Разработка пользовательской интеграции в API Gateway
С помощью serverless-технологий можно создать собственную интеграцию с сервисами Yandex Cloud.
Пользовательская интеграция представляет собой функцию Yandex Cloud Functions или контейнер Yandex Serverless Containers, которые предназначены для решения типовой задачи.
Функция или контейнер могут быть сконфигурированы в спецификации API-шлюза API Gateway по стандарту OpenAPI 3.0
Разработайте функцию-интеграцию с Yandex Managed Service for YDB для работы с СУБД YDB. Функция будет взаимодействовать с Managed Service for YDB и обрабатывать внешние HTTP-запросы через API-шлюз с использованием HTTP API
Интеграция будет применена для реализации CRUD
Чтобы развернуть проект:
- Настройте окружение.
- Скачайте проект с интеграцией.
- Скомпилируйте функцию.
- Загрузите файл функции в бакет.
- Подготовьте конфигурацию ресурсов для интеграции.
- Разверните ресурсы для интеграции.
- Проверьте работу созданного CRUD API.
Если созданные ресурсы больше не нужны, удалите их.
Перед началом работы
Зарегистрируйтесь в Yandex Cloud и создайте платежный аккаунт:
- Перейдите в консоль управления
, затем войдите в Yandex Cloud или зарегистрируйтесь. - На странице Yandex Cloud Billing
убедитесь, что у вас подключен платежный аккаунт, и он находится в статусеACTIVE
илиTRIAL_ACTIVE
. Если платежного аккаунта нет, создайте его и привяжите к нему облако.
Если у вас есть активный платежный аккаунт, вы можете создать или выбрать каталог, в котором будет работать ваша инфраструктура, на странице облака
Подробнее об облаках и каталогах.
Необходимые платные ресурсы
В стоимость ресурсов для интеграции входят:
- Плата за объем хранилища, занятый данными, количество операций с данными и исходящий трафик (см. тарифы Yandex Object Storage).
- Плата за операции с YDB и хранение данных (см. тарифы Managed Service for YDB в бессерверном режиме).
- Плата за количество вызовов функции, вычислительные ресурсы, выделенные для выполнения функции, и исходящий трафик (см. тарифы Cloud Functions).
- Плата за количество запросов к API-шлюзу и исходящий трафик (см. тарифы API Gateway).
Настройте окружение
- Установите утилиту WSL
для использования окружения Linux. - Запустите подсистему Linux (по умолчанию — Ubuntu).
- Настройте окружение так, как описано в инструкции для операционной системы Linux.
Примечание
Если вы используете дистрибутив, отличный от Ubuntu, установите указанные утилиты с помощью команд вашего пакетного менеджера.
-
Последовательно установите следующие утилиты с помощью команд в терминале:
-
sudo apt-get install curl git -y
-
WebStorm
или другая среда разработки с поддержкой TypeScript :sudo snap install webstorm --classic
-
Node.js
не ниже версии16.9.1
:curl --silent --location https://deb.nodesource.com/setup_16.x | sudo -E bash sudo apt-get install nodejs node -v npm -v
-
sudo npm install -g typescript
-
curl https://storage.yandexcloud.net/yandexcloud-yc/install.sh | bash exec -l $SHELL yc version
-
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" --output "awscliv2.zip" unzip awscliv2.zip sudo ./aws/install
-
-
Установите Terraform не ниже версии
1.0.8
. -
Создайте профиль Yandex Cloud CLI с базовыми параметрами.
-
Настройте AWS CLI.
-
Последовательно установите следующие утилиты с помощью команд в терминале:
-
/bin/bash -c "$(curl --fail --silent --show-error --location https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
-
brew install curl git
-
WebStorm
или другая среда разработки с поддержкой TypeScript :brew install --cask webstorm
-
Node.js
не ниже версии16.9.1
:brew install node node -v npm -v
-
npm install -g typescript
-
curl https://storage.yandexcloud.net/yandexcloud-yc/install.sh | bash exec -l $SHELL yc version
-
curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" --output "AWSCLIV2.pkg" sudo installer -pkg AWSCLIV2.pkg -target /
-
-
Установите Terraform не ниже версии
1.0.8
. -
Создайте профиль с базовыми параметрами.
-
Настройте 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.tsrequestContext.apiGateway.operationContext
объекта event
передается контекст операции.
Контекст операции определяется в параметре context
в спецификации API-шлюза, вызывающего функцию-интеграцию.
Примечание
При интеграции с помощью контейнера контекст операции передается через специальный заголовок X-Yc-ApiGateway-Operation-Context
.
В файле event.ts
Скомпилируйте функцию
-
Откройте терминал и перейдите в корневую директорию проекта:
cd <путь_к_корневой_директории_проекта>
-
Установите необходимые проекту зависимости:
npm ci
-
Выполните компиляцию и сборку кода функции:
npm run build
-
Упакуйте собранный код функции в ZIP-архив:
npm run package
Загрузите файл функции в бакет
- Создайте бакет с публичным доступом. Сохраните имя бакета, оно потребуется в дальнейшем.
- Загрузите в бакет ZIP-архив
apigw-dynamodb-connector-0.0.1.zip
с кодом функции из директорииbuild
.
Подготовьте конфигурацию ресурсов для интеграции
Для развертывания CRUD API с помощью функции-интеграции будет использоваться инструмент Terraform
Специальный Terraform-модуль
- Бессерверная база данных YDB.
- Функция-интеграция.
- Сервисный аккаунт для доступа функции к базе данных.
- API-шлюз.
Чтобы подготовить конфигурационные файлы для Terraform:
-
Узнайте имя активного профиля (
ACTIVE
) интерфейса командной строки Yandex Cloud CLI. В терминале выполните команду:yc config profile list
-
Получите параметры активного профиля:
yc config profile get <имя_профиля>
Сохраните полученные параметры:
token
— OAuth-токен.cloud-id
— идентификатор облака.folder-id
— идентификатор каталога.
-
Создайте директорию
crud-api
и перейдите в нее:mkdir crud-api cd crud-api
В дальнейшем все команды Terraform выполняйте в директории
crud-api
. -
Создайте файл
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 }
-
Создайте файл
table.json
и скопируйте в него спецификацию схемы таблицы создаваемой YDB:{ "TableName": "movie", "KeySchema": [ { "AttributeName": "id", "KeyType": "HASH" } ], "AttributeDefinitions": [ { "AttributeName": "id", "AttributeType": "S" }, { "AttributeName": "title", "AttributeType": "S" }, { "AttributeName": "year", "AttributeType": "N" } ] }
-
Создайте файл
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
Разверните ресурсы для интеграции
-
Инициализируйте Terraform. В терминале выполните команду:
terraform init
-
Разверните облачные ресурсы:
terraform apply
-
Подтвердите создание ресурсов: введите в терминале
yes
и нажмите Enter.В выводе команды в переменной
crud_api_domain
будет указан доменный адрес созданного CRUD API. Сохраните этот адрес, он потребуется в дальнейшем.Проверить созданные ресурсы можно в консоли управления
.
Проверьте работу созданного CRUD API
Для проверки работы созданного CRUD API выполните следующие HTTP-запросы:
-
Добавьте информацию о фильме. В терминале выполните команду:
curl \ --location \ --request POST 'https://<доменный_адрес_CRUD_API>/movies' \ --header 'Content-Type: application/json' \ --data-raw '{ "id": "301", "title": "The Matrix", "year": 1999 }'
-
Получите информацию о фильме:
curl \ --location \ --request GET 'https://<доменный_адрес_CRUD_API>/movies/301'
-
Измените информацию о фильме:
curl \ --location \ --request PUT 'https://<доменный_адрес_CRUD_API>/movies/301' \ --header 'Content-Type: application/json' \ --data-raw '{ "title": "Матрица" }'
-
Добавьте информацию о другом фильме:
curl \ --location \ --request POST 'https://<доменный_адрес_CRUD_API>/movies' \ --header 'Content-Type: application/json' \ --data-raw '{ "id": "299", "title": "The Matrix Reloaded", "year": 2003 }'
-
Получите список фильмов:
curl \ --location \ --request GET 'https://<доменный_адрес_CRUD_API>/movies?from=1&limit=5'
-
Удалите информацию об одном из фильмов:
curl \ --location \ --request DELETE 'https://<доменный_адрес_CRUD_API>/movies/301' \ --data-raw ''
Как удалить созданные ресурсы
Чтобы перестать платить за созданные ресурсы:
-
Удалите ресурсы, созданные с помощью Terraform. В терминале выполните команду:
terraform destroy
Подтвердите удаление ресурсов: введите в терминале
yes
и нажмите Enter. -
Удалите бакет с файлом функции.