diff --git a/notes-python/code/notes-list/handler.py b/notes-python/code/notes-list/handler.py deleted file mode 100644 index 84a0cf4..0000000 --- a/notes-python/code/notes-list/handler.py +++ /dev/null @@ -1,22 +0,0 @@ -# 2026-03-09 -# handler.py — возвращает все записи из таблицы notes. -# GET/POST /fn/default/notes-list → JSON массив записей, сортировка по created_at DESC. -import os -import psycopg2 -import psycopg2.extras - - -def handle(event): - dsn = os.environ['PG_DSN'] - conn = psycopg2.connect(dsn) - try: - cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) - cur.execute( - "SELECT id, title, body, created_at::text FROM notes ORDER BY created_at DESC" - ) - rows = cur.fetchall() - return [dict(r) for r in rows] - except Exception as e: - return {'error': str(e)} - finally: - conn.close() diff --git a/notes-python/code/notes-list/notes_list.py b/notes-python/code/notes-list/notes_list.py new file mode 100644 index 0000000..af04860 --- /dev/null +++ b/notes-python/code/notes-list/notes_list.py @@ -0,0 +1,31 @@ +# 2026-03-09 +# notes_list.py — чтение всех записей из таблицы notes. +# +# Назначение: отдать полный список заметок одним запросом. +# Принимает GET или POST — тело/query параметры игнорируются. +# Возвращает JSON-массив, сортировка: новые записи первые (ORDER BY created_at DESC). +# +# Пример ответа: +# [ +# {"id": 3, "title": "Hello", "body": "World", "created_at": "2026-03-09 ..."}, +# {"id": 1, "title": "First", "body": "Note", "created_at": "2026-03-08 ..."} +# ] +import os +import psycopg2 +import psycopg2.extras + + +def handle(event): + dsn = os.environ['PG_DSN'] + conn = psycopg2.connect(dsn) + try: + cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) + cur.execute( + "SELECT id, title, body, created_at::text FROM notes ORDER BY created_at DESC" + ) + rows = cur.fetchall() + return [dict(r) for r in rows] + except Exception as e: + return {'error': str(e)} + finally: + conn.close() diff --git a/notes-python/code/notes/handler.py b/notes-python/code/notes/notes_crud.py similarity index 69% rename from notes-python/code/notes/handler.py rename to notes-python/code/notes/notes_crud.py index cce026f..23e307a 100644 --- a/notes-python/code/notes/handler.py +++ b/notes-python/code/notes/notes_crud.py @@ -1,10 +1,17 @@ # 2026-03-09 -# handler.py — CRUD роутер для таблицы notes. -# Роутинг по event._path (sub-path URL): -# POST /fn/default/notes/add?title=...&body=... → INSERT -# POST /fn/default/notes/update?id=1&title=... → UPDATE -# POST /fn/default/notes/delete?id=1 → DELETE -# _path и _query добавляет runtime из HTTP запроса (server.py). +# notes_crud.py — CRUD роутер для таблицы notes. +# +# Назначение: единая функция, которая обрабатывает все операции с записями. +# Роутинг осуществляется по sub-path URL (event._path), который runtime +# берёт из входящего HTTP-запроса и добавляет в event автоматически. +# +# Доступные маршруты (все POST): +# /fn/default/notes/add?title=...&body=... → создать запись +# /fn/default/notes/update?id=1&title=...&body=... → обновить запись +# /fn/default/notes/delete?id=1 → удалить запись +# +# Параметры берутся из query string (event._query) или из тела запроса (event). +# event._path и event._query добавляет Python runtime (server.py) автоматически. import os import psycopg2 import psycopg2.extras diff --git a/notes-python/code/sql-runner/handler.py b/notes-python/code/sql-runner/handler.py deleted file mode 100644 index 2b39304..0000000 --- a/notes-python/code/sql-runner/handler.py +++ /dev/null @@ -1,26 +0,0 @@ -# 2026-03-09 -# handler.py — универсальный исполнитель SQL запросов. -# Принимает event.statements — массив SQL строк, выполняет последовательно. -# Используется sless_job для DDL операций (CREATE TABLE, миграции и т.д.) -import os -import psycopg2 - - -def handle(event): - dsn = os.environ['PG_DSN'] - statements = event.get('statements', []) - if not statements: - return {'error': 'no statements provided'} - - conn = psycopg2.connect(dsn) - try: - cur = conn.cursor() - for sql in statements: - cur.execute(sql) - conn.commit() - return {'ok': True, 'executed': len(statements)} - except Exception as e: - conn.rollback() - return {'error': str(e)} - finally: - conn.close() diff --git a/notes-python/code/sql-runner/sql_runner.py b/notes-python/code/sql-runner/sql_runner.py new file mode 100644 index 0000000..d71828e --- /dev/null +++ b/notes-python/code/sql-runner/sql_runner.py @@ -0,0 +1,39 @@ +# 2026-03-09 +# sql_runner.py — универсальный DDL/SQL исполнитель. +# +# Назначение: выполнять произвольные SQL запросы переданные через event. +# Используется ТОЛЬКО через sless_job (init.tf) — HTTP-триггера нет намеренно, +# чтобы никто снаружи не мог выполнить произвольный SQL. +# +# Входящий event: +# { +# "statements": [ +# "CREATE TABLE IF NOT EXISTS ...", +# "CREATE INDEX IF NOT EXISTS ..." +# ] +# } +# +# Все statements выполняются последовательно в одной транзакции. +# Если хотя бы один упал — транзакция откатывается целиком. +import os +import psycopg2 + + +def handle(event): + dsn = os.environ['PG_DSN'] + statements = event.get('statements', []) + if not statements: + return {'error': 'no statements provided'} + + conn = psycopg2.connect(dsn) + try: + cur = conn.cursor() + for sql in statements: + cur.execute(sql) + conn.commit() + return {'ok': True, 'executed': len(statements)} + except Exception as e: + conn.rollback() + return {'error': str(e)} + finally: + conn.close() diff --git a/notes-python/dist/notes-list.zip b/notes-python/dist/notes-list.zip index 1e3b036..ee6206f 100644 Binary files a/notes-python/dist/notes-list.zip and b/notes-python/dist/notes-list.zip differ diff --git a/notes-python/dist/notes.zip b/notes-python/dist/notes.zip index 5402309..a282a90 100644 Binary files a/notes-python/dist/notes.zip and b/notes-python/dist/notes.zip differ diff --git a/notes-python/dist/sql-runner.zip b/notes-python/dist/sql-runner.zip index b684fdd..d2083fe 100644 Binary files a/notes-python/dist/sql-runner.zip and b/notes-python/dist/sql-runner.zip differ diff --git a/notes-python/init.tf b/notes-python/init.tf index a76760f..0924819 100644 --- a/notes-python/init.tf +++ b/notes-python/init.tf @@ -1,9 +1,19 @@ -# 2025-06-05 -# init.tf — джобы инициализации БД: создание таблицы + индекса. -# Запускаются один раз при terraform apply. -# Для повторного запуска (например после drop) — увеличь run_id. +# 2026-03-09 +# init.tf — однократная инициализация схемы БД через sless_job. +# +# Джобы запускаются один раз при terraform apply и ждут завершения. +# Использует функцию sql_runner (без HTTP-триггера) для безопасного DDL. +# +# Порядок выполнения гарантирован через depends_on: +# 1. notes_table_init — создаём таблицу +# 2. notes_index_init — создаём индекс (требует таблицу) +# +# Для повторного запуска (например, после DROP TABLE) — увеличь run_id. +# run_id отслеживается в state: при изменении terraform перезапустит джоб. -resource "sless_job" "create_table" { +# Джоб создания таблицы notes. +# CREATE TABLE IF NOT EXISTS — безопасно запускать повторно, таблица не пересоздаётся. +resource "sless_job" "notes_table_init" { namespace = "default" name = "notes-create-table" function = sless_function.sql_runner.name @@ -17,8 +27,10 @@ resource "sless_job" "create_table" { }) } -resource "sless_job" "create_index" { - depends_on = [sless_job.create_table] +# Джоб создания индекса для сортировки по дате. +# depends_on гарантирует, что таблица уже создана до создания индекса. +resource "sless_job" "notes_index_init" { + depends_on = [sless_job.notes_table_init] namespace = "default" name = "notes-create-index" diff --git a/notes-python/main.tf b/notes-python/main.tf index 5f5e71f..65124e0 100644 --- a/notes-python/main.tf +++ b/notes-python/main.tf @@ -1,13 +1,22 @@ -# 2025-06-05 -# main.tf — terraform{} + provider для notes-python примера. -# Ресурсы вынесены в отдельные .tf файлы. +# 2026-03-09 +# main.tf — конфигурация terraform и провайдеров. +# +# Все ресурсы вынесены в отдельные .tf файлы по назначению: +# variables.tf — входные переменные (pg_dsn) +# sql-runner.tf — служебная DDL-функция (без HTTP-триггера) +# init.tf — однократная инициализация схемы БД +# notes.tf — CRUD функция + HTTP-триггер +# notes-list.tf — read-only функция + HTTP-триггер +# outputs.tf — URLs развёрнутых эндпоинтов terraform { required_providers { + # Провайдер для управления serverless функциями через sless API sless = { source = "terra.k8c.ru/naeel/sless" version = "~> 0.1.7" } + # hashicorp/archive — для упаковки исходников в zip перед загрузкой archive = { source = "hashicorp/archive" version = "~> 2.0" @@ -15,6 +24,8 @@ terraform { } } +# sless провайдер подключается к API кластера. +# В продакшне token следует передавать через TF_VAR или secrets. provider "sless" { endpoint = "https://sless-api.kube5s.ru" token = "dev-token-change-me" diff --git a/notes-python/notes-list.tf b/notes-python/notes-list.tf index 2dc4fcf..3e5e2f7 100644 --- a/notes-python/notes-list.tf +++ b/notes-python/notes-list.tf @@ -1,18 +1,27 @@ -# 2025-06-05 -# notes-list.tf — функция для получения всех записей из таблицы notes. -# GET или POST /fn/default/notes-list → JSON массив всех записей, сортировка по дате (новые первые). +# 2026-03-09 +# notes-list.tf — функция для чтения всех заметок одним запросом. +# +# Отдельная от CRUD функция — «read-only» эндпоинт без роутинга. +# Принимает GET или POST, параметры игнорирует. +# Возвращает JSON-массив всех записей, сортировка: новые первые. +# +# Пример запроса: +# curl https://sless-api.kube5s.ru/fn/default/notes-list -data "archive_file" "notes_list" { +# Упаковка исходников notes_list.py в zip. +data "archive_file" "notes_list_zip" { type = "zip" source_dir = "${path.module}/code/notes-list" output_path = "${path.module}/dist/notes-list.zip" } +# Read-only функция в кластере. +# entrypoint = "notes_list.handle" → файл notes_list.py, функция handle(). resource "sless_function" "notes_list" { namespace = "default" name = "notes-list" runtime = "python3.11" - entrypoint = "handler.handle" + entrypoint = "notes_list.handle" memory_mb = 128 timeout_sec = 30 @@ -20,10 +29,12 @@ resource "sless_function" "notes_list" { PG_DSN = var.pg_dsn } - code_path = data.archive_file.notes_list.output_path - code_hash = filesha256("${path.module}/code/notes-list/handler.py") + code_path = data.archive_file.notes_list_zip.output_path + code_hash = filesha256("${path.module}/code/notes-list/notes_list.py") } +# HTTP-триггер для read-only функции. +# Создаёт Ingress, URL доступен в outputs.tf. resource "sless_trigger" "notes_list_http" { namespace = "default" name = "notes-list-http" diff --git a/notes-python/notes.tf b/notes-python/notes.tf index 9d0cb64..64e989f 100644 --- a/notes-python/notes.tf +++ b/notes-python/notes.tf @@ -1,21 +1,29 @@ -# 2025-06-05 -# notes.tf — CRUD функция для таблицы notes. -# Роутинг по sub-path URL: -# POST /fn/default/notes/add?title=...&body=... → INSERT записи -# POST /fn/default/notes/update?id=1&title=...&body=... → UPDATE записи -# POST /fn/default/notes/delete?id=1 → DELETE записи +# 2026-03-09 +# notes.tf — CRUD функция для управления заметками (CREATE / UPDATE / DELETE). +# +# Одна функция обрабатывает все операции — роутинг по sub-path URL. +# Sub-path и query string пробрасывает прокси (invoke.go) → runtime добавляет +# их в event как _path и _query. +# +# Маршруты (все методы принимаются, рекомендуется POST): +# /fn/default/notes/add?title=...&body=... → INSERT, возвращает запись +# /fn/default/notes/update?id=1&title=...&body=... → UPDATE, возвращает запись +# /fn/default/notes/delete?id=1 → DELETE, возвращает {deleted: id} -data "archive_file" "notes" { +# Упаковка исходников notes_crud.py в zip. +data "archive_file" "notes_crud_zip" { type = "zip" source_dir = "${path.module}/code/notes" output_path = "${path.module}/dist/notes.zip" } -resource "sless_function" "notes" { +# CRUD функция в кластере. +# entrypoint = "notes_crud.handle" → файл notes_crud.py, функция handle(). +resource "sless_function" "notes_crud" { namespace = "default" name = "notes" runtime = "python3.11" - entrypoint = "handler.handle" + entrypoint = "notes_crud.handle" memory_mb = 128 timeout_sec = 30 @@ -23,13 +31,16 @@ resource "sless_function" "notes" { PG_DSN = var.pg_dsn } - code_path = data.archive_file.notes.output_path - code_hash = filesha256("${path.module}/code/notes/handler.py") + code_path = data.archive_file.notes_crud_zip.output_path + code_hash = filesha256("${path.module}/code/notes/notes_crud.py") } -resource "sless_trigger" "notes_http" { +# HTTP-триггер для CRUD функции. +# Создаёт Ingress в кластере, URL доступен в outputs.tf. +# Базовый URL: https://sless-api.kube5s.ru/fn/default/notes +resource "sless_trigger" "notes_crud_http" { namespace = "default" name = "notes-http" type = "http" - function = sless_function.notes.name + function = sless_function.notes_crud.name } diff --git a/notes-python/outputs.tf b/notes-python/outputs.tf index d14f579..f89c48b 100644 --- a/notes-python/outputs.tf +++ b/notes-python/outputs.tf @@ -1,12 +1,23 @@ -# 2025-06-05 -# outputs.tf — URL эндпоинтов для notes-python примера. +# 2026-03-09 +# outputs.tf — публичные URL развёрнутых функций. +# +# После terraform apply используй эти URLs для тестирования: +# terraform output notes_url → базовый URL для CRUD +# terraform output notes_list_url → URL для получения всех записей +# URL CRUD-функции (notes_crud). +# Базовый URL — к нему добавляй sub-path: +# POST $(terraform output -raw notes_url)/add?title=Hello&body=World +# POST $(terraform output -raw notes_url)/update?id=1&title=Updated +# POST $(terraform output -raw notes_url)/delete?id=1 output "notes_url" { - value = sless_trigger.notes_http.url - description = "Базовый URL CRUD: /add?title=...&body=..., /update?id=X&title=...&body=..., /delete?id=X" + value = sless_trigger.notes_crud_http.url + description = "CRUD: /add?title=...&body=..., /update?id=X&title=...&body=..., /delete?id=X" } +# URL read-only функции (notes_list). +# Принимает GET или POST, параметры игнорирует, возвращает все записи. output "notes_list_url" { value = sless_trigger.notes_list_http.url - description = "URL для получения всех записей (GET или POST)" + description = "Список всех записей (GET или POST)" } diff --git a/notes-python/sql-runner.tf b/notes-python/sql-runner.tf index fe5a56c..86bcabc 100644 --- a/notes-python/sql-runner.tf +++ b/notes-python/sql-runner.tf @@ -1,19 +1,26 @@ -# 2025-06-05 -# sql-runner.tf — универсальная функция для выполнения SQL запросов. -# Используется джобами для DDL операций (CREATE TABLE, индексы, миграции). -# event.statements — массив SQL строк, выполняются последовательно в одной транзакции. +# 2026-03-09 +# sql-runner.tf — служебная DDL-функция для инициализации и миграций БД. +# +# ВАЖНО: эта функция не имеет HTTP-триггера — только вызов через sless_job. +# Это сделано намеренно: функция выполняет произвольный SQL, и открывать её +# наружу через HTTP было бы небезопасно. -data "archive_file" "sql_runner" { +# Упаковка исходников в zip для загрузки в кластер. +# archive_file пересоздаёт zip при изменении любого файла в source_dir. +data "archive_file" "sql_runner_zip" { type = "zip" source_dir = "${path.module}/code/sql-runner" output_path = "${path.module}/dist/sql-runner.zip" } +# Сама функция в кластере. +# entrypoint = "sql_runner.handle" → файл sql_runner.py, функция handle(). +# memory_mb=128 достаточно — DDL запросы не требуют памяти на вычисления. resource "sless_function" "sql_runner" { namespace = "default" name = "sql-runner" runtime = "python3.11" - entrypoint = "handler.handle" + entrypoint = "sql_runner.handle" memory_mb = 128 timeout_sec = 30 @@ -21,6 +28,7 @@ resource "sless_function" "sql_runner" { PG_DSN = var.pg_dsn } - code_path = data.archive_file.sql_runner.output_path - code_hash = filesha256("${path.module}/code/sql-runner/handler.py") + code_path = data.archive_file.sql_runner_zip.output_path + # code_hash — при изменении кода terraform пересобирает образ функции + code_hash = filesha256("${path.module}/code/sql-runner/sql_runner.py") } diff --git a/notes-python/terraform.tfstate.1773036471.backup b/notes-python/terraform.tfstate.1773036471.backup new file mode 100644 index 0000000..f0b6146 --- /dev/null +++ b/notes-python/terraform.tfstate.1773036471.backup @@ -0,0 +1,369 @@ +{ + "version": 4, + "terraform_version": "1.12.2", + "serial": 15, + "lineage": "46b43916-6d6b-060c-ad36-6176e18b5f7b", + "outputs": { + "notes_list_url": { + "value": "https://sless-api.kube5s.ru/fn/default/notes-list", + "type": "string" + }, + "notes_url": { + "value": "https://sless-api.kube5s.ru/fn/default/notes", + "type": "string" + } + }, + "resources": [ + { + "mode": "data", + "type": "archive_file", + "name": "notes", + "provider": "provider[\"registry.terraform.io/hashicorp/archive\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "exclude_symlink_directories": null, + "excludes": null, + "id": "d1fed6f90a4b4fde556aa2cd18e6ffaa9877c377", + "output_base64sha256": "HMlgBvSu0gccGVilru2ybzC7v31uzG1Zy96bK4p+C1E=", + "output_base64sha512": "GoV68HbQgbVaBtR4v1kLUhh+kMpJRIoBz30SrgYlVGz13SzV1wZ/lPvedqYvhmirG0fQf63wHYThOmvOR7lvgQ==", + "output_file_mode": null, + "output_md5": "cf96673e4f09c58d2e49c1664cdee1c2", + "output_path": "./dist/notes.zip", + "output_sha": "d1fed6f90a4b4fde556aa2cd18e6ffaa9877c377", + "output_sha256": "1cc96006f4aed2071c1958a5aeedb26f30bbbf7d6ecc6d59cbde9b2b8a7e0b51", + "output_sha512": "1a857af076d081b55a06d478bf590b52187e90ca49448a01cf7d12ae0625546cf5dd2cd5d7067f94fbde76a62f8668ab1b47d07fadf01d84e13a6bce47b96f81", + "output_size": 1226, + "source": [], + "source_content": null, + "source_content_filename": null, + "source_dir": "./code/notes", + "source_file": null, + "type": "zip" + }, + "sensitive_attributes": [], + "identity_schema_version": 0 + } + ] + }, + { + "mode": "data", + "type": "archive_file", + "name": "notes_list", + "provider": "provider[\"registry.terraform.io/hashicorp/archive\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "exclude_symlink_directories": null, + "excludes": null, + "id": "b5730a0d98ae778f80c27881147e14d060151fce", + "output_base64sha256": "1pbtfCE8qjpAP5Ddz9c9afhOUXq3aq56ordi5t4vX00=", + "output_base64sha512": "nTUnbRKT4d5g5g3HANTGxZi5FmUIaM3C660XzZmGQLJIQ+WNYNLJ/no/H30KzafwE1mJf2qkdcZ8cT3xZdciNg==", + "output_file_mode": null, + "output_md5": "090088f39e1ef9d8d7d152944441edb7", + "output_path": "./dist/notes-list.zip", + "output_sha": "b5730a0d98ae778f80c27881147e14d060151fce", + "output_sha256": "d696ed7c213caa3a403f90ddcfd73d69f84e517ab76aae7aa2b762e6de2f5f4d", + "output_sha512": "9d35276d1293e1de60e60dc700d4c6c598b916650868cdc2ebad17cd998640b24843e58d60d2c9fe7a3f1f7d0acda7f01359897f6aa475c67c713df165d72236", + "output_size": 746, + "source": [], + "source_content": null, + "source_content_filename": null, + "source_dir": "./code/notes-list", + "source_file": null, + "type": "zip" + }, + "sensitive_attributes": [], + "identity_schema_version": 0 + } + ] + }, + { + "mode": "data", + "type": "archive_file", + "name": "sql_runner", + "provider": "provider[\"registry.terraform.io/hashicorp/archive\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "exclude_symlink_directories": null, + "excludes": null, + "id": "241f12b31b5d970c697341292954b220e44f8d2a", + "output_base64sha256": "w/IUipIki9V1lf33x06/gHq+KWVdfJO9Ni98DkhC+Xw=", + "output_base64sha512": "aLpBXApQ5Nltm6ODUqQc6VZQCoxgn68mHlcrOF8bFrdem8psnz7dujkJE5PYvB5VDNKmdsViDAKPNTwHxut4XA==", + "output_file_mode": null, + "output_md5": "1fe2ab7afe4730b1141146363d69bd23", + "output_path": "./dist/sql-runner.zip", + "output_sha": "241f12b31b5d970c697341292954b220e44f8d2a", + "output_sha256": "c3f2148a92248bd57595fdf7c74ebf807abe29655d7c93bd362f7c0e4842f97c", + "output_sha512": "68ba415c0a50e4d96d9ba38352a41ce956500a8c609faf261e572b385f1b16b75e9bca6c9f3eddba39091393d8bc1e550cd2a676c5620c028f353c07c6eb785c", + "output_size": 796, + "source": [], + "source_content": null, + "source_content_filename": null, + "source_dir": "./code/sql-runner", + "source_file": null, + "type": "zip" + }, + "sensitive_attributes": [], + "identity_schema_version": 0 + } + ] + }, + { + "mode": "managed", + "type": "sless_function", + "name": "notes", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "build_timeout_sec": 300, + "code_hash": "aaefd6de16697af6ac7331c7e1795a5446c71e351e6cacc3f4b490b683feb0cb", + "code_path": "./dist/notes.zip", + "entrypoint": "handler.handle", + "env_vars": { + "PG_DSN": "postgres://sless:sless-pg-password@postgres.sless.svc.cluster.local:5432/sless?sslmode=disable" + }, + "image_ref": "naeel/sless-default-notes:80b15a8b73f5", + "memory_mb": 128, + "name": "notes", + "namespace": "default", + "phase": "Ready", + "runtime": "python3.11", + "timeout_sec": 30 + }, + "sensitive_attributes": [ + [ + { + "type": "get_attr", + "value": "env_vars" + }, + { + "type": "index", + "value": { + "value": "PG_DSN", + "type": "string" + } + } + ] + ], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.notes" + ] + } + ] + }, + { + "mode": "managed", + "type": "sless_function", + "name": "notes_list", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "build_timeout_sec": 300, + "code_hash": "4091f7c79ca8c9c5663c812eb08f25ef5257af217bf2b412add670a4737b9d7f", + "code_path": "./dist/notes-list.zip", + "entrypoint": "handler.handle", + "env_vars": { + "PG_DSN": "postgres://sless:sless-pg-password@postgres.sless.svc.cluster.local:5432/sless?sslmode=disable" + }, + "image_ref": "naeel/sless-default-notes-list:07f2d5ae5ee4", + "memory_mb": 128, + "name": "notes-list", + "namespace": "default", + "phase": "Ready", + "runtime": "python3.11", + "timeout_sec": 30 + }, + "sensitive_attributes": [ + [ + { + "type": "get_attr", + "value": "env_vars" + }, + { + "type": "index", + "value": { + "value": "PG_DSN", + "type": "string" + } + } + ] + ], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.notes_list" + ] + } + ] + }, + { + "mode": "managed", + "type": "sless_function", + "name": "sql_runner", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "build_timeout_sec": 300, + "code_hash": "fcde93e59e6fd7f3db426482da7667d5d402aaaaaf56f79a7a60bb1722ec603a", + "code_path": "./dist/sql-runner.zip", + "entrypoint": "handler.handle", + "env_vars": { + "PG_DSN": "postgres://sless:sless-pg-password@postgres.sless.svc.cluster.local:5432/sless?sslmode=disable" + }, + "image_ref": "naeel/sless-default-sql-runner:22bce581a299", + "memory_mb": 128, + "name": "sql-runner", + "namespace": "default", + "phase": "Ready", + "runtime": "python3.11", + "timeout_sec": 30 + }, + "sensitive_attributes": [ + [ + { + "type": "get_attr", + "value": "env_vars" + }, + { + "type": "index", + "value": { + "value": "PG_DSN", + "type": "string" + } + } + ] + ], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.sql_runner" + ] + } + ] + }, + { + "mode": "managed", + "type": "sless_job", + "name": "create_index", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "completion_time": "2026-03-09T05:44:59Z", + "event_json": "{\"statements\":[\"CREATE INDEX IF NOT EXISTS notes_created_idx ON notes(created_at DESC)\"]}", + "function": "sql-runner", + "message": "completed successfully", + "name": "notes-create-index", + "namespace": "default", + "phase": "Succeeded", + "run_id": 1, + "start_time": "2026-03-09T05:44:54Z", + "wait_timeout_sec": 60 + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.sql_runner", + "sless_function.sql_runner", + "sless_job.create_table" + ] + } + ] + }, + { + "mode": "managed", + "type": "sless_job", + "name": "create_table", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "completion_time": "2026-03-09T05:44:54Z", + "event_json": "{\"statements\":[\"CREATE TABLE IF NOT EXISTS notes (id serial PRIMARY KEY, title text NOT NULL, body text, created_at timestamp DEFAULT now())\"]}", + "function": "sql-runner", + "message": "completed successfully", + "name": "notes-create-table", + "namespace": "default", + "phase": "Succeeded", + "run_id": 1, + "start_time": "2026-03-09T05:44:39Z", + "wait_timeout_sec": 120 + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.sql_runner", + "sless_function.sql_runner" + ] + } + ] + }, + { + "mode": "managed", + "type": "sless_trigger", + "name": "notes_http", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "active": true, + "enabled": true, + "function": "notes", + "name": "notes-http", + "namespace": "default", + "schedule": null, + "type": "http", + "url": "https://sless-api.kube5s.ru/fn/default/notes" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.notes", + "sless_function.notes" + ] + } + ] + }, + { + "mode": "managed", + "type": "sless_trigger", + "name": "notes_list_http", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "active": true, + "enabled": true, + "function": "notes-list", + "name": "notes-list-http", + "namespace": "default", + "schedule": null, + "type": "http", + "url": "https://sless-api.kube5s.ru/fn/default/notes-list" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.notes_list", + "sless_function.notes_list" + ] + } + ] + } + ], + "check_results": null +} diff --git a/notes-python/terraform.tfstate.1773036482.backup b/notes-python/terraform.tfstate.1773036482.backup new file mode 100644 index 0000000..b6402da --- /dev/null +++ b/notes-python/terraform.tfstate.1773036482.backup @@ -0,0 +1,365 @@ +{ + "version": 4, + "terraform_version": "1.12.2", + "serial": 16, + "lineage": "46b43916-6d6b-060c-ad36-6176e18b5f7b", + "outputs": { + "notes_list_url": { + "value": "https://sless-api.kube5s.ru/fn/default/notes-list", + "type": "string" + }, + "notes_url": { + "value": "https://sless-api.kube5s.ru/fn/default/notes", + "type": "string" + } + }, + "resources": [ + { + "mode": "data", + "type": "archive_file", + "name": "notes", + "provider": "provider[\"registry.terraform.io/hashicorp/archive\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "exclude_symlink_directories": null, + "excludes": null, + "id": "d1fed6f90a4b4fde556aa2cd18e6ffaa9877c377", + "output_base64sha256": "HMlgBvSu0gccGVilru2ybzC7v31uzG1Zy96bK4p+C1E=", + "output_base64sha512": "GoV68HbQgbVaBtR4v1kLUhh+kMpJRIoBz30SrgYlVGz13SzV1wZ/lPvedqYvhmirG0fQf63wHYThOmvOR7lvgQ==", + "output_file_mode": null, + "output_md5": "cf96673e4f09c58d2e49c1664cdee1c2", + "output_path": "./dist/notes.zip", + "output_sha": "d1fed6f90a4b4fde556aa2cd18e6ffaa9877c377", + "output_sha256": "1cc96006f4aed2071c1958a5aeedb26f30bbbf7d6ecc6d59cbde9b2b8a7e0b51", + "output_sha512": "1a857af076d081b55a06d478bf590b52187e90ca49448a01cf7d12ae0625546cf5dd2cd5d7067f94fbde76a62f8668ab1b47d07fadf01d84e13a6bce47b96f81", + "output_size": 1226, + "source": [], + "source_content": null, + "source_content_filename": null, + "source_dir": "./code/notes", + "source_file": null, + "type": "zip" + }, + "sensitive_attributes": [], + "identity_schema_version": 0 + } + ] + }, + { + "mode": "data", + "type": "archive_file", + "name": "notes_list", + "provider": "provider[\"registry.terraform.io/hashicorp/archive\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "exclude_symlink_directories": null, + "excludes": null, + "id": "b5730a0d98ae778f80c27881147e14d060151fce", + "output_base64sha256": "1pbtfCE8qjpAP5Ddz9c9afhOUXq3aq56ordi5t4vX00=", + "output_base64sha512": "nTUnbRKT4d5g5g3HANTGxZi5FmUIaM3C660XzZmGQLJIQ+WNYNLJ/no/H30KzafwE1mJf2qkdcZ8cT3xZdciNg==", + "output_file_mode": null, + "output_md5": "090088f39e1ef9d8d7d152944441edb7", + "output_path": "./dist/notes-list.zip", + "output_sha": "b5730a0d98ae778f80c27881147e14d060151fce", + "output_sha256": "d696ed7c213caa3a403f90ddcfd73d69f84e517ab76aae7aa2b762e6de2f5f4d", + "output_sha512": "9d35276d1293e1de60e60dc700d4c6c598b916650868cdc2ebad17cd998640b24843e58d60d2c9fe7a3f1f7d0acda7f01359897f6aa475c67c713df165d72236", + "output_size": 746, + "source": [], + "source_content": null, + "source_content_filename": null, + "source_dir": "./code/notes-list", + "source_file": null, + "type": "zip" + }, + "sensitive_attributes": [], + "identity_schema_version": 0 + } + ] + }, + { + "mode": "data", + "type": "archive_file", + "name": "sql_runner", + "provider": "provider[\"registry.terraform.io/hashicorp/archive\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "exclude_symlink_directories": null, + "excludes": null, + "id": "241f12b31b5d970c697341292954b220e44f8d2a", + "output_base64sha256": "w/IUipIki9V1lf33x06/gHq+KWVdfJO9Ni98DkhC+Xw=", + "output_base64sha512": "aLpBXApQ5Nltm6ODUqQc6VZQCoxgn68mHlcrOF8bFrdem8psnz7dujkJE5PYvB5VDNKmdsViDAKPNTwHxut4XA==", + "output_file_mode": null, + "output_md5": "1fe2ab7afe4730b1141146363d69bd23", + "output_path": "./dist/sql-runner.zip", + "output_sha": "241f12b31b5d970c697341292954b220e44f8d2a", + "output_sha256": "c3f2148a92248bd57595fdf7c74ebf807abe29655d7c93bd362f7c0e4842f97c", + "output_sha512": "68ba415c0a50e4d96d9ba38352a41ce956500a8c609faf261e572b385f1b16b75e9bca6c9f3eddba39091393d8bc1e550cd2a676c5620c028f353c07c6eb785c", + "output_size": 796, + "source": [], + "source_content": null, + "source_content_filename": null, + "source_dir": "./code/sql-runner", + "source_file": null, + "type": "zip" + }, + "sensitive_attributes": [], + "identity_schema_version": 0 + } + ] + }, + { + "mode": "managed", + "type": "sless_function", + "name": "notes_crud", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "build_timeout_sec": 300, + "code_hash": "aaefd6de16697af6ac7331c7e1795a5446c71e351e6cacc3f4b490b683feb0cb", + "code_path": "./dist/notes.zip", + "entrypoint": "handler.handle", + "env_vars": { + "PG_DSN": "postgres://sless:sless-pg-password@postgres.sless.svc.cluster.local:5432/sless?sslmode=disable" + }, + "image_ref": "naeel/sless-default-notes:80b15a8b73f5", + "memory_mb": 128, + "name": "notes", + "namespace": "default", + "phase": "Ready", + "runtime": "python3.11", + "timeout_sec": 30 + }, + "sensitive_attributes": [ + [ + { + "type": "get_attr", + "value": "env_vars" + }, + { + "type": "index", + "value": { + "value": "PG_DSN", + "type": "string" + } + } + ] + ], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.notes" + ] + } + ] + }, + { + "mode": "managed", + "type": "sless_function", + "name": "notes_list", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "build_timeout_sec": 300, + "code_hash": "4091f7c79ca8c9c5663c812eb08f25ef5257af217bf2b412add670a4737b9d7f", + "code_path": "./dist/notes-list.zip", + "entrypoint": "handler.handle", + "env_vars": { + "PG_DSN": "postgres://sless:sless-pg-password@postgres.sless.svc.cluster.local:5432/sless?sslmode=disable" + }, + "image_ref": "naeel/sless-default-notes-list:07f2d5ae5ee4", + "memory_mb": 128, + "name": "notes-list", + "namespace": "default", + "phase": "Ready", + "runtime": "python3.11", + "timeout_sec": 30 + }, + "sensitive_attributes": [ + [ + { + "type": "get_attr", + "value": "env_vars" + }, + { + "type": "index", + "value": { + "value": "PG_DSN", + "type": "string" + } + } + ] + ], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.notes_list" + ] + } + ] + }, + { + "mode": "managed", + "type": "sless_function", + "name": "sql_runner", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "build_timeout_sec": 300, + "code_hash": "fcde93e59e6fd7f3db426482da7667d5d402aaaaaf56f79a7a60bb1722ec603a", + "code_path": "./dist/sql-runner.zip", + "entrypoint": "handler.handle", + "env_vars": { + "PG_DSN": "postgres://sless:sless-pg-password@postgres.sless.svc.cluster.local:5432/sless?sslmode=disable" + }, + "image_ref": "naeel/sless-default-sql-runner:22bce581a299", + "memory_mb": 128, + "name": "sql-runner", + "namespace": "default", + "phase": "Ready", + "runtime": "python3.11", + "timeout_sec": 30 + }, + "sensitive_attributes": [ + [ + { + "type": "get_attr", + "value": "env_vars" + }, + { + "type": "index", + "value": { + "value": "PG_DSN", + "type": "string" + } + } + ] + ], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.sql_runner" + ] + } + ] + }, + { + "mode": "managed", + "type": "sless_job", + "name": "create_index", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "completion_time": "2026-03-09T05:44:59Z", + "event_json": "{\"statements\":[\"CREATE INDEX IF NOT EXISTS notes_created_idx ON notes(created_at DESC)\"]}", + "function": "sql-runner", + "message": "completed successfully", + "name": "notes-create-index", + "namespace": "default", + "phase": "Succeeded", + "run_id": 1, + "start_time": "2026-03-09T05:44:54Z", + "wait_timeout_sec": 60 + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.sql_runner", + "sless_function.sql_runner", + "sless_job.create_table" + ] + } + ] + }, + { + "mode": "managed", + "type": "sless_job", + "name": "create_table", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "completion_time": "2026-03-09T05:44:54Z", + "event_json": "{\"statements\":[\"CREATE TABLE IF NOT EXISTS notes (id serial PRIMARY KEY, title text NOT NULL, body text, created_at timestamp DEFAULT now())\"]}", + "function": "sql-runner", + "message": "completed successfully", + "name": "notes-create-table", + "namespace": "default", + "phase": "Succeeded", + "run_id": 1, + "start_time": "2026-03-09T05:44:39Z", + "wait_timeout_sec": 120 + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.sql_runner", + "sless_function.sql_runner" + ] + } + ] + }, + { + "mode": "managed", + "type": "sless_trigger", + "name": "notes_http", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "active": true, + "enabled": true, + "function": "notes", + "name": "notes-http", + "namespace": "default", + "schedule": null, + "type": "http", + "url": "https://sless-api.kube5s.ru/fn/default/notes" + }, + "sensitive_attributes": [], + "identity_schema_version": 0 + } + ] + }, + { + "mode": "managed", + "type": "sless_trigger", + "name": "notes_list_http", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "active": true, + "enabled": true, + "function": "notes-list", + "name": "notes-list-http", + "namespace": "default", + "schedule": null, + "type": "http", + "url": "https://sless-api.kube5s.ru/fn/default/notes-list" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.notes_list", + "sless_function.notes_list" + ] + } + ] + } + ], + "check_results": null +} diff --git a/notes-python/terraform.tfstate.1773036493.backup b/notes-python/terraform.tfstate.1773036493.backup new file mode 100644 index 0000000..a4b3e6a --- /dev/null +++ b/notes-python/terraform.tfstate.1773036493.backup @@ -0,0 +1,365 @@ +{ + "version": 4, + "terraform_version": "1.12.2", + "serial": 17, + "lineage": "46b43916-6d6b-060c-ad36-6176e18b5f7b", + "outputs": { + "notes_list_url": { + "value": "https://sless-api.kube5s.ru/fn/default/notes-list", + "type": "string" + }, + "notes_url": { + "value": "https://sless-api.kube5s.ru/fn/default/notes", + "type": "string" + } + }, + "resources": [ + { + "mode": "data", + "type": "archive_file", + "name": "notes", + "provider": "provider[\"registry.terraform.io/hashicorp/archive\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "exclude_symlink_directories": null, + "excludes": null, + "id": "d1fed6f90a4b4fde556aa2cd18e6ffaa9877c377", + "output_base64sha256": "HMlgBvSu0gccGVilru2ybzC7v31uzG1Zy96bK4p+C1E=", + "output_base64sha512": "GoV68HbQgbVaBtR4v1kLUhh+kMpJRIoBz30SrgYlVGz13SzV1wZ/lPvedqYvhmirG0fQf63wHYThOmvOR7lvgQ==", + "output_file_mode": null, + "output_md5": "cf96673e4f09c58d2e49c1664cdee1c2", + "output_path": "./dist/notes.zip", + "output_sha": "d1fed6f90a4b4fde556aa2cd18e6ffaa9877c377", + "output_sha256": "1cc96006f4aed2071c1958a5aeedb26f30bbbf7d6ecc6d59cbde9b2b8a7e0b51", + "output_sha512": "1a857af076d081b55a06d478bf590b52187e90ca49448a01cf7d12ae0625546cf5dd2cd5d7067f94fbde76a62f8668ab1b47d07fadf01d84e13a6bce47b96f81", + "output_size": 1226, + "source": [], + "source_content": null, + "source_content_filename": null, + "source_dir": "./code/notes", + "source_file": null, + "type": "zip" + }, + "sensitive_attributes": [], + "identity_schema_version": 0 + } + ] + }, + { + "mode": "data", + "type": "archive_file", + "name": "notes_list", + "provider": "provider[\"registry.terraform.io/hashicorp/archive\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "exclude_symlink_directories": null, + "excludes": null, + "id": "b5730a0d98ae778f80c27881147e14d060151fce", + "output_base64sha256": "1pbtfCE8qjpAP5Ddz9c9afhOUXq3aq56ordi5t4vX00=", + "output_base64sha512": "nTUnbRKT4d5g5g3HANTGxZi5FmUIaM3C660XzZmGQLJIQ+WNYNLJ/no/H30KzafwE1mJf2qkdcZ8cT3xZdciNg==", + "output_file_mode": null, + "output_md5": "090088f39e1ef9d8d7d152944441edb7", + "output_path": "./dist/notes-list.zip", + "output_sha": "b5730a0d98ae778f80c27881147e14d060151fce", + "output_sha256": "d696ed7c213caa3a403f90ddcfd73d69f84e517ab76aae7aa2b762e6de2f5f4d", + "output_sha512": "9d35276d1293e1de60e60dc700d4c6c598b916650868cdc2ebad17cd998640b24843e58d60d2c9fe7a3f1f7d0acda7f01359897f6aa475c67c713df165d72236", + "output_size": 746, + "source": [], + "source_content": null, + "source_content_filename": null, + "source_dir": "./code/notes-list", + "source_file": null, + "type": "zip" + }, + "sensitive_attributes": [], + "identity_schema_version": 0 + } + ] + }, + { + "mode": "data", + "type": "archive_file", + "name": "sql_runner", + "provider": "provider[\"registry.terraform.io/hashicorp/archive\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "exclude_symlink_directories": null, + "excludes": null, + "id": "241f12b31b5d970c697341292954b220e44f8d2a", + "output_base64sha256": "w/IUipIki9V1lf33x06/gHq+KWVdfJO9Ni98DkhC+Xw=", + "output_base64sha512": "aLpBXApQ5Nltm6ODUqQc6VZQCoxgn68mHlcrOF8bFrdem8psnz7dujkJE5PYvB5VDNKmdsViDAKPNTwHxut4XA==", + "output_file_mode": null, + "output_md5": "1fe2ab7afe4730b1141146363d69bd23", + "output_path": "./dist/sql-runner.zip", + "output_sha": "241f12b31b5d970c697341292954b220e44f8d2a", + "output_sha256": "c3f2148a92248bd57595fdf7c74ebf807abe29655d7c93bd362f7c0e4842f97c", + "output_sha512": "68ba415c0a50e4d96d9ba38352a41ce956500a8c609faf261e572b385f1b16b75e9bca6c9f3eddba39091393d8bc1e550cd2a676c5620c028f353c07c6eb785c", + "output_size": 796, + "source": [], + "source_content": null, + "source_content_filename": null, + "source_dir": "./code/sql-runner", + "source_file": null, + "type": "zip" + }, + "sensitive_attributes": [], + "identity_schema_version": 0 + } + ] + }, + { + "mode": "managed", + "type": "sless_function", + "name": "notes_crud", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "build_timeout_sec": 300, + "code_hash": "aaefd6de16697af6ac7331c7e1795a5446c71e351e6cacc3f4b490b683feb0cb", + "code_path": "./dist/notes.zip", + "entrypoint": "handler.handle", + "env_vars": { + "PG_DSN": "postgres://sless:sless-pg-password@postgres.sless.svc.cluster.local:5432/sless?sslmode=disable" + }, + "image_ref": "naeel/sless-default-notes:80b15a8b73f5", + "memory_mb": 128, + "name": "notes", + "namespace": "default", + "phase": "Ready", + "runtime": "python3.11", + "timeout_sec": 30 + }, + "sensitive_attributes": [ + [ + { + "type": "get_attr", + "value": "env_vars" + }, + { + "type": "index", + "value": { + "value": "PG_DSN", + "type": "string" + } + } + ] + ], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.notes" + ] + } + ] + }, + { + "mode": "managed", + "type": "sless_function", + "name": "notes_list", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "build_timeout_sec": 300, + "code_hash": "4091f7c79ca8c9c5663c812eb08f25ef5257af217bf2b412add670a4737b9d7f", + "code_path": "./dist/notes-list.zip", + "entrypoint": "handler.handle", + "env_vars": { + "PG_DSN": "postgres://sless:sless-pg-password@postgres.sless.svc.cluster.local:5432/sless?sslmode=disable" + }, + "image_ref": "naeel/sless-default-notes-list:07f2d5ae5ee4", + "memory_mb": 128, + "name": "notes-list", + "namespace": "default", + "phase": "Ready", + "runtime": "python3.11", + "timeout_sec": 30 + }, + "sensitive_attributes": [ + [ + { + "type": "get_attr", + "value": "env_vars" + }, + { + "type": "index", + "value": { + "value": "PG_DSN", + "type": "string" + } + } + ] + ], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.notes_list" + ] + } + ] + }, + { + "mode": "managed", + "type": "sless_function", + "name": "sql_runner", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "build_timeout_sec": 300, + "code_hash": "fcde93e59e6fd7f3db426482da7667d5d402aaaaaf56f79a7a60bb1722ec603a", + "code_path": "./dist/sql-runner.zip", + "entrypoint": "handler.handle", + "env_vars": { + "PG_DSN": "postgres://sless:sless-pg-password@postgres.sless.svc.cluster.local:5432/sless?sslmode=disable" + }, + "image_ref": "naeel/sless-default-sql-runner:22bce581a299", + "memory_mb": 128, + "name": "sql-runner", + "namespace": "default", + "phase": "Ready", + "runtime": "python3.11", + "timeout_sec": 30 + }, + "sensitive_attributes": [ + [ + { + "type": "get_attr", + "value": "env_vars" + }, + { + "type": "index", + "value": { + "value": "PG_DSN", + "type": "string" + } + } + ] + ], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.sql_runner" + ] + } + ] + }, + { + "mode": "managed", + "type": "sless_job", + "name": "create_index", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "completion_time": "2026-03-09T05:44:59Z", + "event_json": "{\"statements\":[\"CREATE INDEX IF NOT EXISTS notes_created_idx ON notes(created_at DESC)\"]}", + "function": "sql-runner", + "message": "completed successfully", + "name": "notes-create-index", + "namespace": "default", + "phase": "Succeeded", + "run_id": 1, + "start_time": "2026-03-09T05:44:54Z", + "wait_timeout_sec": 60 + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.sql_runner", + "sless_function.sql_runner", + "sless_job.create_table" + ] + } + ] + }, + { + "mode": "managed", + "type": "sless_job", + "name": "create_table", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "completion_time": "2026-03-09T05:44:54Z", + "event_json": "{\"statements\":[\"CREATE TABLE IF NOT EXISTS notes (id serial PRIMARY KEY, title text NOT NULL, body text, created_at timestamp DEFAULT now())\"]}", + "function": "sql-runner", + "message": "completed successfully", + "name": "notes-create-table", + "namespace": "default", + "phase": "Succeeded", + "run_id": 1, + "start_time": "2026-03-09T05:44:39Z", + "wait_timeout_sec": 120 + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.sql_runner", + "sless_function.sql_runner" + ] + } + ] + }, + { + "mode": "managed", + "type": "sless_trigger", + "name": "notes_crud_http", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "active": true, + "enabled": true, + "function": "notes", + "name": "notes-http", + "namespace": "default", + "schedule": null, + "type": "http", + "url": "https://sless-api.kube5s.ru/fn/default/notes" + }, + "sensitive_attributes": [], + "identity_schema_version": 0 + } + ] + }, + { + "mode": "managed", + "type": "sless_trigger", + "name": "notes_list_http", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "active": true, + "enabled": true, + "function": "notes-list", + "name": "notes-list-http", + "namespace": "default", + "schedule": null, + "type": "http", + "url": "https://sless-api.kube5s.ru/fn/default/notes-list" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.notes_list", + "sless_function.notes_list" + ] + } + ] + } + ], + "check_results": null +} diff --git a/notes-python/terraform.tfstate.1773036504.backup b/notes-python/terraform.tfstate.1773036504.backup new file mode 100644 index 0000000..13a4818 --- /dev/null +++ b/notes-python/terraform.tfstate.1773036504.backup @@ -0,0 +1,360 @@ +{ + "version": 4, + "terraform_version": "1.12.2", + "serial": 18, + "lineage": "46b43916-6d6b-060c-ad36-6176e18b5f7b", + "outputs": { + "notes_list_url": { + "value": "https://sless-api.kube5s.ru/fn/default/notes-list", + "type": "string" + }, + "notes_url": { + "value": "https://sless-api.kube5s.ru/fn/default/notes", + "type": "string" + } + }, + "resources": [ + { + "mode": "data", + "type": "archive_file", + "name": "notes", + "provider": "provider[\"registry.terraform.io/hashicorp/archive\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "exclude_symlink_directories": null, + "excludes": null, + "id": "d1fed6f90a4b4fde556aa2cd18e6ffaa9877c377", + "output_base64sha256": "HMlgBvSu0gccGVilru2ybzC7v31uzG1Zy96bK4p+C1E=", + "output_base64sha512": "GoV68HbQgbVaBtR4v1kLUhh+kMpJRIoBz30SrgYlVGz13SzV1wZ/lPvedqYvhmirG0fQf63wHYThOmvOR7lvgQ==", + "output_file_mode": null, + "output_md5": "cf96673e4f09c58d2e49c1664cdee1c2", + "output_path": "./dist/notes.zip", + "output_sha": "d1fed6f90a4b4fde556aa2cd18e6ffaa9877c377", + "output_sha256": "1cc96006f4aed2071c1958a5aeedb26f30bbbf7d6ecc6d59cbde9b2b8a7e0b51", + "output_sha512": "1a857af076d081b55a06d478bf590b52187e90ca49448a01cf7d12ae0625546cf5dd2cd5d7067f94fbde76a62f8668ab1b47d07fadf01d84e13a6bce47b96f81", + "output_size": 1226, + "source": [], + "source_content": null, + "source_content_filename": null, + "source_dir": "./code/notes", + "source_file": null, + "type": "zip" + }, + "sensitive_attributes": [], + "identity_schema_version": 0 + } + ] + }, + { + "mode": "data", + "type": "archive_file", + "name": "notes_list", + "provider": "provider[\"registry.terraform.io/hashicorp/archive\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "exclude_symlink_directories": null, + "excludes": null, + "id": "b5730a0d98ae778f80c27881147e14d060151fce", + "output_base64sha256": "1pbtfCE8qjpAP5Ddz9c9afhOUXq3aq56ordi5t4vX00=", + "output_base64sha512": "nTUnbRKT4d5g5g3HANTGxZi5FmUIaM3C660XzZmGQLJIQ+WNYNLJ/no/H30KzafwE1mJf2qkdcZ8cT3xZdciNg==", + "output_file_mode": null, + "output_md5": "090088f39e1ef9d8d7d152944441edb7", + "output_path": "./dist/notes-list.zip", + "output_sha": "b5730a0d98ae778f80c27881147e14d060151fce", + "output_sha256": "d696ed7c213caa3a403f90ddcfd73d69f84e517ab76aae7aa2b762e6de2f5f4d", + "output_sha512": "9d35276d1293e1de60e60dc700d4c6c598b916650868cdc2ebad17cd998640b24843e58d60d2c9fe7a3f1f7d0acda7f01359897f6aa475c67c713df165d72236", + "output_size": 746, + "source": [], + "source_content": null, + "source_content_filename": null, + "source_dir": "./code/notes-list", + "source_file": null, + "type": "zip" + }, + "sensitive_attributes": [], + "identity_schema_version": 0 + } + ] + }, + { + "mode": "data", + "type": "archive_file", + "name": "sql_runner", + "provider": "provider[\"registry.terraform.io/hashicorp/archive\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "exclude_symlink_directories": null, + "excludes": null, + "id": "241f12b31b5d970c697341292954b220e44f8d2a", + "output_base64sha256": "w/IUipIki9V1lf33x06/gHq+KWVdfJO9Ni98DkhC+Xw=", + "output_base64sha512": "aLpBXApQ5Nltm6ODUqQc6VZQCoxgn68mHlcrOF8bFrdem8psnz7dujkJE5PYvB5VDNKmdsViDAKPNTwHxut4XA==", + "output_file_mode": null, + "output_md5": "1fe2ab7afe4730b1141146363d69bd23", + "output_path": "./dist/sql-runner.zip", + "output_sha": "241f12b31b5d970c697341292954b220e44f8d2a", + "output_sha256": "c3f2148a92248bd57595fdf7c74ebf807abe29655d7c93bd362f7c0e4842f97c", + "output_sha512": "68ba415c0a50e4d96d9ba38352a41ce956500a8c609faf261e572b385f1b16b75e9bca6c9f3eddba39091393d8bc1e550cd2a676c5620c028f353c07c6eb785c", + "output_size": 796, + "source": [], + "source_content": null, + "source_content_filename": null, + "source_dir": "./code/sql-runner", + "source_file": null, + "type": "zip" + }, + "sensitive_attributes": [], + "identity_schema_version": 0 + } + ] + }, + { + "mode": "managed", + "type": "sless_function", + "name": "notes_crud", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "build_timeout_sec": 300, + "code_hash": "aaefd6de16697af6ac7331c7e1795a5446c71e351e6cacc3f4b490b683feb0cb", + "code_path": "./dist/notes.zip", + "entrypoint": "handler.handle", + "env_vars": { + "PG_DSN": "postgres://sless:sless-pg-password@postgres.sless.svc.cluster.local:5432/sless?sslmode=disable" + }, + "image_ref": "naeel/sless-default-notes:80b15a8b73f5", + "memory_mb": 128, + "name": "notes", + "namespace": "default", + "phase": "Ready", + "runtime": "python3.11", + "timeout_sec": 30 + }, + "sensitive_attributes": [ + [ + { + "type": "get_attr", + "value": "env_vars" + }, + { + "type": "index", + "value": { + "value": "PG_DSN", + "type": "string" + } + } + ] + ], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.notes" + ] + } + ] + }, + { + "mode": "managed", + "type": "sless_function", + "name": "notes_list", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "build_timeout_sec": 300, + "code_hash": "4091f7c79ca8c9c5663c812eb08f25ef5257af217bf2b412add670a4737b9d7f", + "code_path": "./dist/notes-list.zip", + "entrypoint": "handler.handle", + "env_vars": { + "PG_DSN": "postgres://sless:sless-pg-password@postgres.sless.svc.cluster.local:5432/sless?sslmode=disable" + }, + "image_ref": "naeel/sless-default-notes-list:07f2d5ae5ee4", + "memory_mb": 128, + "name": "notes-list", + "namespace": "default", + "phase": "Ready", + "runtime": "python3.11", + "timeout_sec": 30 + }, + "sensitive_attributes": [ + [ + { + "type": "get_attr", + "value": "env_vars" + }, + { + "type": "index", + "value": { + "value": "PG_DSN", + "type": "string" + } + } + ] + ], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.notes_list" + ] + } + ] + }, + { + "mode": "managed", + "type": "sless_function", + "name": "sql_runner", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "build_timeout_sec": 300, + "code_hash": "fcde93e59e6fd7f3db426482da7667d5d402aaaaaf56f79a7a60bb1722ec603a", + "code_path": "./dist/sql-runner.zip", + "entrypoint": "handler.handle", + "env_vars": { + "PG_DSN": "postgres://sless:sless-pg-password@postgres.sless.svc.cluster.local:5432/sless?sslmode=disable" + }, + "image_ref": "naeel/sless-default-sql-runner:22bce581a299", + "memory_mb": 128, + "name": "sql-runner", + "namespace": "default", + "phase": "Ready", + "runtime": "python3.11", + "timeout_sec": 30 + }, + "sensitive_attributes": [ + [ + { + "type": "get_attr", + "value": "env_vars" + }, + { + "type": "index", + "value": { + "value": "PG_DSN", + "type": "string" + } + } + ] + ], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.sql_runner" + ] + } + ] + }, + { + "mode": "managed", + "type": "sless_job", + "name": "create_index", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "completion_time": "2026-03-09T05:44:59Z", + "event_json": "{\"statements\":[\"CREATE INDEX IF NOT EXISTS notes_created_idx ON notes(created_at DESC)\"]}", + "function": "sql-runner", + "message": "completed successfully", + "name": "notes-create-index", + "namespace": "default", + "phase": "Succeeded", + "run_id": 1, + "start_time": "2026-03-09T05:44:54Z", + "wait_timeout_sec": 60 + }, + "sensitive_attributes": [], + "identity_schema_version": 0 + } + ] + }, + { + "mode": "managed", + "type": "sless_job", + "name": "notes_table_init", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "completion_time": "2026-03-09T05:44:54Z", + "event_json": "{\"statements\":[\"CREATE TABLE IF NOT EXISTS notes (id serial PRIMARY KEY, title text NOT NULL, body text, created_at timestamp DEFAULT now())\"]}", + "function": "sql-runner", + "message": "completed successfully", + "name": "notes-create-table", + "namespace": "default", + "phase": "Succeeded", + "run_id": 1, + "start_time": "2026-03-09T05:44:39Z", + "wait_timeout_sec": 120 + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.sql_runner", + "sless_function.sql_runner" + ] + } + ] + }, + { + "mode": "managed", + "type": "sless_trigger", + "name": "notes_crud_http", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "active": true, + "enabled": true, + "function": "notes", + "name": "notes-http", + "namespace": "default", + "schedule": null, + "type": "http", + "url": "https://sless-api.kube5s.ru/fn/default/notes" + }, + "sensitive_attributes": [], + "identity_schema_version": 0 + } + ] + }, + { + "mode": "managed", + "type": "sless_trigger", + "name": "notes_list_http", + "provider": "provider[\"terra.k8c.ru/naeel/sless\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "active": true, + "enabled": true, + "function": "notes-list", + "name": "notes-list-http", + "namespace": "default", + "schedule": null, + "type": "http", + "url": "https://sless-api.kube5s.ru/fn/default/notes-list" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "dependencies": [ + "data.archive_file.notes_list", + "sless_function.notes_list" + ] + } + ] + } + ], + "check_results": null +} diff --git a/notes-python/variables.tf b/notes-python/variables.tf index d0ffeb4..d4e0af0 100644 --- a/notes-python/variables.tf +++ b/notes-python/variables.tf @@ -1,6 +1,12 @@ -# 2025-06-05 +# 2026-03-09 # variables.tf — входные переменные для notes-python примера. +# +# PG_DSN передаётся во все функции через env_vars. +# Хранится как sensitive чтобы не светился в terraform output и логах. +# В продакшне — не хардкоди DSN здесь, используй TF_VAR_pg_dsn или secrets manager. +# DSN для подключения к PostgreSQL внутри кластера. +# Формат: postgres://user:password@host:port/dbname?sslmode=... variable "pg_dsn" { description = "PostgreSQL DSN для подключения к БД внутри кластера" type = string