ПР. Создание триггера от Object Storage
Кратко:
- Создание триггера на Object Storage с использованием Python и boto3.
- Создание ключа доступа и секретного ключа для доступа к Object Storage.
- Выбор способа создания бакета в Object Storage: через консоль управления или с помощью Terraform.
- Модификация функции my-first-function и загрузка новой версии в облако.
- Создание триггера my-first-trigger для вызова функции my-trigger-function при создании объекта в бакете BUCKET_NAME.
- Вызов цепочки событий и запись содержимого переменной event в логи функции my-trigger-function.
Практическая работа. Создание триггера от Object Storage
В предыдущем практическом уроке вы познакомились с созданием одной функции с помощью интерфейса командной строки (
yc
). В этом уроке мы продолжим разработку этой функции: модифицируем её содержание, добавим переменные окружения и т.д.Важно выполнить предыдущий практический урок, так как вы будете опираться на знания и результаты, полученные в нём.
Шаг 1. Модификация сервисного аккаунта
Добавление роли сервисному аккаунту
По итогам прохождения предыдущей практической работы у вас есть сервисный аккаунт с именем
service-account-for-cf
. Для работы с Object Storage добавьте этому сервисному аккаунту роль storage.editor
:
yc resource-manager folder add-access-binding $FOLDER_ID \
--role storage.editor \
--subject serviceAccount:$SERVICE_ACCOUNT_ID
Создание ключа доступа для сервисного аккаунта
Этот этап нужен для получения идентификатора ключа доступа и секретного ключа, которые будут использованы для загрузки файлов в Object Storage, а также в том случае, если на следующем шаге для создания бакета в Object Storage вы планируете использовать Terraform.
Для создания ключа доступа необходимо вызвать следующую команду:
yc iam access-key create --service-account-name service-account-for-cf
В результате вы получите примерно следующее:
access_key:
id: ajefraollq5puj2tir1o
service_account_id: ajetdv28pl0a1a8r41f0
created_at: "2021-08-23T21:13:05.677319393Z"
key_id: BTPNvWthv0ZX2xVmlPIU
secret: cWLQ0HrTM0k_qAac43cwMNJA8VV_rfTg_kd4xVPi
Где:
key_id
— идентификатор ключа доступа,ACCESS_KEY
.secret
— секретный ключ,SECRET_KEY
.
Переменные
ACCESS_KEY
и SECRET_KEY
будут использованы для задания соответствующих значений aws_access_key_id
и aws_secret_access_key
при использовании библиотеки boto3
на следующих этапах.Шаг 2. Object Storage
Самый простой способ создания бакета в Object Storage — через консоль управления. Более сложный, позволяющий автоматизировать разработку, — использование Terraform. Вы можете выбрать любой из них.
Способ 1. Консоль управления
В консоли управления в вашем рабочем каталоге выберите сервис Object Storage. Нажмите кнопку Создать бакет.
На странице создания бакета:
- Введите имя бакета, пусть это будет
bucket-for-trigger
. - При необходимости ограничьте максимальный размер бакета, установив значение, например, 1 ГБ.
- Выберите тип доступа, в нашем уроке установим значения в Публичный во всех случаях.
- Выберите класс хранилища, по умолчанию используется Стандартное.
Нажмите кнопку Создать бакет для завершения операции. Далее вы всегда сможете поменять класс хранилища, его размер и настройки доступа.

Способ 2. Terraform
Прежде всего необходимо получить OAuth-токен для работы с Yandex Cloud. Для этого можно сделать запрос к сервису Яндекс.OAuth. Подробнее прочитать можно в документации.
Сохраните OAuth-токен в переменную
OAuth
, но никому не передавайте. Также вам потребуются значения переменных: идентификатор облака — CLOUD_ID
и идентификатор каталога FOLDER_ID
(сохранен в переменную ранее).Также на предыдущем шаге вы получили ключ доступа для сервисного аккаунта. Нам потребуется идентификатор ключа доступа
ACCESS_KEY
и секретный ключ SECRET_KEY
.В файл
main.tf
, представленный далее, внесём все собранные переменные. Важно: переменная BUCKET_NAME
содержит имя создаваемого бакета в Object Storage, куда будем загружать файлы. Допустим, переменная будет равна bucket-for-trigger
. Сохраним все значения:
terraform {
required_providers {
yandex = {
source = "yandex-cloud/yandex"
}
}
required_version = ">= 0.13"
}
provider "yandex" {
token = "<OAuth>"
cloud_id = "<CLOUD_ID>"
folder_id = "<FOLDER_ID>"
}
resource "yandex_storage_bucket" "bucket" {
access_key = "<ACCESS_KEY>"
secret_key = "<SECRET_KEY>"
bucket = "<BUCKET_NAME>"
}
После внесения правок, находясь в каталоге с файлом
main.tf
, последовательно выполните следующие команды:
terraform init
terraform plan
terraform apply
Успешное выполнение команд приведёт к созданию бакета
bucket-for-trigger
в объектном хранилище в вашем рабочем каталоге.Шаг 3. Модификация функции
В предыдущей практической работе мы создали функцию с именем
my-first-function
с помощью следующей команды:
yc serverless function create --name my-first-function
При создании функции вы получили URL, по которому можно будет сделать вызов функции
http_invoke_url
.Загрузка кода новой версии
Новая версия функции имеет зависимости, которые описаны в файле
requirements.txt
, а это значит, что для загрузки функции в облако необходимо файлы index.py
и requirements.txt
заархивировать и получить файл my-first-function.zip
.Новая версия
index.py
:
import os
import datetime
import boto3
import pytz
ACCESS_KEY = os.getenv("ACCESS_KEY")
SECRET_KEY = os.getenv("SECRET_KEY")
BUCKET_NAME = os.getenv("BUCKET_NAME")
TIME_ZONE = os.getenv("TIME_ZONE", "Europe/Moscow")
TEMP_FILENAME = "/tmp/temp_file"
TEXT_FOR_TEMP_FILE = "This is text file"
def write_temp_file():
temp_file = open(TEMP_FILENAME, 'w')
temp_file.write(TEXT_FOR_TEMP_FILE)
temp_file.close()
print("\U0001f680 Temp file is written")
def get_now_datetime_str():
now = datetime.datetime.now(pytz.timezone(TIME_ZONE))
return now.strftime('%Y-%m-%d__%H-%M-%S')
def get_s3_instance():
session = boto3.session.Session()
return session.client(
aws_access_key_id=ACCESS_KEY,
aws_secret_access_key=SECRET_KEY,
service_name='s3',
endpoint_url='https://storage.yandexcloud.net'
)
def upload_dump_to_s3():
print("\U0001F4C2 Starting upload to Object Storage")
get_s3_instance().upload_file(
Filename=TEMP_FILENAME,
Bucket=BUCKET_NAME,
Key=f'file-{get_now_datetime_str()}.txt'
)
print("\U0001f680 Uploaded")
def remove_temp_files():
os.remove(TEMP_FILENAME)
print("\U0001F44D That's all!")
def handler(event, context):
write_temp_file()
upload_dump_to_s3()
remove_temp_files()
return {
'statusCode': 200,
'body': 'File is uploaded',
}
Первая версия
requirements.txt
:
boto3==1.13.10
botocore==1.16.10
python-dateutil==2.8.1
pytz==2020.1
Находясь в каталоге с файлом
my-first-function.zip
вызовите следующую команду, это позволит вам загрузить код функции в облако и создать её версию:
yc serverless function version create \
--function-name my-first-function \
--memory 256m \
--execution-timeout 5s \
--runtime python37 \
--entrypoint index.handler \
--service-account-id $SERVICE_ACCOUNT_ID \
--source-path my-first-function.zip
Новая версия функции при вызове будет загружать в Object Storage новый файл. Для создания этой версии необходимо подготовить несколько переменных. Переменные
ACCESS_KEY
и SECRET_KEY
вы получили на первом шаге, а значение BUCKET_NAME
на втором:
echo "export ACCESS_KEY=<ACCESS_KEY>" >> ~/.bashrc && . ~/.bashrc
echo "export SECRET_KEY=<SECRET_KEY>" >> ~/.bashrc && . ~/.bashrc
echo "export BUCKET_NAME=bucket-for-trigger" >> ~/.bashrc && . ~/.bashrc
Определим идентификатор (
ID
) для последней загруженной версии функции:
yc serverless function version list --function-name my-first-function
Создадим новую версию функции, задав при этом переменные окружения. Для этого выставим значение параметра
source-version-id
равное полученному ID
в следующей команде:
yc serverless function version create \
--function-name my-first-function \
--memory 256m \
--execution-timeout 5s \
--runtime python37 \
--entrypoint index.handler \
--service-account-id $SERVICE_ACCOUNT_ID \
--source-version-id <ID> \
--environment ACCESS_KEY=$ACCESS_KEY \
--environment SECRET_KEY=$SECRET_KEY \
--environment BUCKET_NAME=$BUCKET_NAME
Успешное выполнение команды приведёт к созданию версии функции.
Вызов функции
Получите список функций и информацию о функции
my-first-function
:
yc serverless function list
yc serverless function version list --function-name my-first-function
В результате вызова последней команды в столбце
FUNCTION ID
вы узнаете идентификатор функции и сможете сделать вызов функции с помощью следующей команды:
yc serverless function invoke <идентификатор_функции>
В предыдущей практической работе мы сделали функцию
my-first-function
публичной с помощью команды:
yc serverless function allow-unauthenticated-invoke my-first-function
Теперь мы можем сделать её вызов в браузере. Получите параметр
http_invoke_url
для функции my-first-function
yc serverless function get my-first-function
Введите значение параметра http_invoke_url
в браузере и наслаждайтесь вызовом вашей функции. Во время её вызова в Object Storage будет создан новый файл.Шаг 4. Создание триггера
Создание функции
Для создания триггера нам необходима функция, которую триггер будет запускать. Аналогично предыдущему шагу создадим функцию
my-trigger-function
и её версию на основе файла index.py
.
def handler(event, context):
print("\U0001F4C2 Starting function after trigger")
print(event)
return {
'statusCode': 200,
'body': 'File is uploaded',
}
Находясь в каталоге с файлом
index.py
, вызовите следующие команды:
yc serverless function create --name my-trigger-function
yc serverless function version create \
--function-name my-trigger-function \
--memory 256m \
--execution-timeout 5s \
--runtime python37 \
--entrypoint index.handler \
--service-account-id $SERVICE_ACCOUNT_ID \
--source-path index.py
yc serverless function version list --function-name my-trigger-function
Создание триггера
Чтобы создать триггер
my-first-trigger
, который вызывает функцию my-trigger-function
при создании нового объекта в бакете BUCKET_NAME
, выполните команду:
yc serverless trigger create object-storage \
--name my-first-trigger \
--bucket-id $BUCKET_NAME \
--events 'create-object' \
--invoke-function-name my-trigger-function \
--invoke-function-service-account-id $SERVICE_ACCOUNT_ID
Вызов цепочки событий
Чтобы запустить цепочку событий, вызовем первую функцию
my-first-function
. Получите список функций и информацию о функции my-first-function
:
yc serverless function list
yc serverless function version list --function-name my-first-function
В результате вызова последней команды в столбце
FUNCTION ID
вы узнаете идентификатор функции и сможете сделать вызов функции с помощью команды:
yc serverless function invoke <идентификатор_функции>
После этого вы можете сделать её вызов в браузере. Получите параметр
http_invoke_url
для функции my-first-function
yc serverless function get my-first-function
Введите значение параметра
http_invoke_url
в браузере. Во время вызова функции в Object Storage будет создан новый объект. Сразу после этого сработает триггер my-first-trigger
, который вызовет функцию my-trigger-function
. В итоге, наша вторая функция запишет в логи содержание переменной event
. Убедиться в этом вы сможете как в UI, так и через CLI.
yc serverless function logs my-trigger-function
На следующем практическом занятии мы создадим навык Алисы с помощью Cloud Functions.