diff --git a/.gitignore b/.gitignore index f60a6ab..185c936 100644 --- a/.gitignore +++ b/.gitignore @@ -66,3 +66,8 @@ POSTGRES/chaos_marathon.sh POSTGRES/test_cache_matrix.sh POSTGRES/deploy_and_run_chaos.sh POSTGRES/scripts/ + +# ---- Примеры в разработке (временно скрыты) ---- +POSTGRES/ +NODEJS/ +DEVfromGround/ diff --git a/DEVfromGround/main.tf b/DEVfromGround/main.tf deleted file mode 100644 index e17eacc..0000000 --- a/DEVfromGround/main.tf +++ /dev/null @@ -1,28 +0,0 @@ -// 2026-03-26 — main.tf: провайдер Nubes для DEV-стенда. -// DEV API endpoint: https://deck-api-dev.ngcloud.ru/api/v1 -// Токен: secrets/dev.token (tazet@narod.ru) - -terraform { - required_providers { - nubes = { - source = "terra.k8c.ru/nubes/nubes" - version = "5.0.31" - } - } -} - -variable "api_token" { - type = string - sensitive = true - description = "Nubes API токен (DEV-стенд). Значение — в terraform.tfvars." -} - -variable "resource_realm" { - type = string - description = "Платформа развёртывания (например k8s-3.ext.nubes.ru). Уточнить у сервис-менеджера." -} - -provider "nubes" { - api_token = var.api_token - api_endpoint = "https://deck-api-dev.ngcloud.ru/api/v1/index.cfm" -} diff --git a/DEVfromGround/vc_org.tf b/DEVfromGround/vc_org.tf deleted file mode 100644 index ee696aa..0000000 --- a/DEVfromGround/vc_org.tf +++ /dev/null @@ -1,34 +0,0 @@ -// 2026-03-26 — vc_org.tf: ресурс «Организация в Cloud Director» для DEV-стенда. -// nubes_vc_org — тенант vCloud Director (organization_type = "iaas"). -// resource_realm задаётся через переменную (terraform.tfvars или -var). - -resource "nubes_vc_org" "dev_org" { - resource_name = "vcOrg-2" - resource_realm = var.resource_realm - - # organization_type "iaas" — единственный вариант с доступом к организации. - # Значение по умолчанию "iaas", явно прописано для читаемости. - organization_type = "iaas" - - # v_i_p_configure — JSON-список ipSpaces для операции modify. - # При create провайдер не передаёт его в API, но требует non-null значение в плане. - v_i_p_configure = "" - - # adopt_existing_on_create = true — берёт существующий инстанс (dev-org-sless-demo уже создан с null realm от предыдущей попытки). - adopt_existing_on_create = true - - # suspend_on_destroy = true (по умолчанию) — при destroy инстанс уходит в Suspend, не удаляется. - suspend_on_destroy = true -} - -# ─── Outputs ───────────────────────────────────────────────────────────────── - -output "dev_org_id" { - description = "ID созданной организации (используется в зависимых ресурсах)" - value = nubes_vc_org.dev_org.id -} - -output "dev_org_state_flat" { - description = "Плоский state организации — endpoints, статусы" - value = nubes_vc_org.dev_org.state_out_flat -} diff --git a/NODEJS/main.tf b/NODEJS/main.tf deleted file mode 100644 index 442dfba..0000000 --- a/NODEJS/main.tf +++ /dev/null @@ -1,32 +0,0 @@ -// Создано: 2026-03-23 -// main.tf — провайдер Nubes + переменные для примера NODEJS. -// Ресурс nubes_nodejs: managed Node.js приложение в облаке (не sless-функция). - -terraform { - required_providers { - nubes = { - source = "terra.k8c.ru/nubes/nubes" - version = "5.0.19" - } - } -} - -variable "api_token" { - type = string - sensitive = true -} - -variable "realm" { - type = string - description = "resource_realm — зона размещения ресурса (например: k8s-3-sandbox-nubes-ru)" -} - -variable "git_path" { - type = string - description = "URL git-репозитория с кодом приложения" -} - -provider "nubes" { - api_token = var.api_token - api_endpoint = "https://deck-api-test.ngcloud.ru/api/v1/index.cfm" -} diff --git a/NODEJS/nodejs.tf b/NODEJS/nodejs.tf deleted file mode 100644 index 0e1102a..0000000 --- a/NODEJS/nodejs.tf +++ /dev/null @@ -1,22 +0,0 @@ -# Создано: 2026-03-23 -# nodejs.tf — ресурс nubes_nodejs: managed Node.js приложение. -# Параметры взяты из документации terra.k8c.ru/docs/nubes/nubes/5.0.19/30_registry/resources/nodejs_params_create/ - -resource "nubes_nodejs" "app" { - resource_name = "nodejsdemo1" - domain = "domma" - resource_realm = var.realm - git_path = var.git_path - app_version = "23" - resource_c_p_u = 500 - resource_memory = 1024 - resource_instances = 1 - json_env = jsonencode({}) - adopt_existing_on_create = true - # health_path не задан — используется дефолтный / -} - -output "nodejs_domain" { - description = "Домен развёрнутого Node.js приложения" - value = nubes_nodejs.app.domain -} diff --git a/POSTGRES/README.md b/POSTGRES/README.md deleted file mode 100644 index ea5d451..0000000 --- a/POSTGRES/README.md +++ /dev/null @@ -1,100 +0,0 @@ -# POSTGRES — Пример: Serverless-функции с Managed PostgreSQL - -Демонстрирует интеграцию sless (serverless functions) с управляемым PostgreSQL (nubes_postgres). - -## Что делает этот пример - -1. **Создаёт Managed PostgreSQL** через Terraform (nubes_postgres + nubes_postgres_user + nubes_postgres_database) -2. **Инициализирует БД**: одноразовый `sless_job` создаёт таблицу `terraform_demo_table` -3. **Запускает 3 HTTP-сервиса**: - - `pg-info` (Node.js 20) — версия PostgreSQL-сервера + количество строк в таблице - - `pg-table-reader` (Python 3.11) — чтение всех строк из таблицы - - `pg-table-writer` (Python 3.11) — добавление новой строки - -## Структура файлов - -``` -POSTGRES/ -├── main.tf # terraform + провайдеры (sless, nubes_cloud) -├── postgres.tf # Managed PostgreSQL: DB, пользователь, locals с credentials -├── resources.tf # Namespace и сетевые ресурсы -├── functions.tf # sless_job (init) + 3 x sless_service -├── terraform.tfvars # Переменные: realm, s3_uid, token -├── stress_test.sh # Стресс-тест функций (не трогает PG lifecycle) -├── stress_destroy_apply.sh.disabled # ОТКЛЮЧЁН — стресс-тест PG lifecycle -├── code/ -│ ├── sql-runner/ # Python: одноразовое выполнение SQL (CREATE TABLE) -│ ├── pg-info/ # Node.js: версия PG + строки -│ ├── table-rw/ # Python: list_rows + add_row -│ ├── pg-stats/ # Python: расширенная статистика PG -│ ├── funcs-list/ # Утилита: листинг функций -│ └── stress-*/ # Функции для стресс-тестирования -└── scripts/ # Вспомогательные скрипты -``` - -## Как запустить - -### Предварительные требования - -- Terraform >= 1.3 -- Токен sless: `SLESS_TOKEN` (или в `terraform.tfvars`) -- Токен nubes_cloud: `NUBES_TOKEN` -- Доступ к realm (например, `ffd1f598c169b0ae`) - -### Запуск - -```bash -# 1. Инициализация -terraform init - -# 2. Проверка плана -terraform plan - -# 3. Применение (создаст PG + сервисы, запустит init job) -terraform apply -``` - -> Первый `apply` может занять 10–15 минут: создание PG-инстанса + kaniko-сборка образов. - -### Переменные (`terraform.tfvars`) - -```hcl -realm = "ffd1f598c169b0ae" # Реалм (namespace в sless) -s3_uid = "s01234" # S3 bucket для nubes_postgres бэкапов -sless_token = "..." # Bearer-токен для sless API -nubes_token = "..." # Bearer-токен для nubes_cloud API -``` - -### Вывод после apply - -``` -Outputs: - table_reader_url = "https://sless.kube5s.ru/v1/namespaces/.../services/pg-table-reader/invoke" - table_writer_url = "https://sless.kube5s.ru/v1/namespaces/.../services/pg-table-writer/invoke" -``` - -### Вызов функций - -```bash -# Информация о PG (Node.js) -curl https://.../services/pg-info/invoke - -# Список строк таблицы (Python) -curl https://.../services/pg-table-reader/invoke - -# Добавить строку (Python) -curl -X POST https://.../services/pg-table-writer/invoke \ - -H "Content-Type: application/json" \ - -d '{"title": "Hello from sless!"}' -``` - -## Стресс-тест - -`stress_test.sh` — нагружает функции HTTP-запросами. Запускать после `terraform apply`: - -```bash -./stress_test.sh -``` - -> `stress_destroy_apply.sh.disabled` — ранний тест PG lifecycle (destroy+apply цикл). -> **Отключён** из-за проблем с удалением postgres_user в определённых сценариях. diff --git a/POSTGRES/code/calc-node/handler.js b/POSTGRES/code/calc-node/handler.js deleted file mode 100644 index 29bed1f..0000000 --- a/POSTGRES/code/calc-node/handler.js +++ /dev/null @@ -1,9 +0,0 @@ -// Создано: 2026-04-10 -// Демо-функция: возвращает текущее время сервера. -// Юзер меняет код под себя и перебилдит через terraform apply. - -'use strict'; - -module.exports.handler = function handler(event) { - return `Текущее время: ${new Date().toISOString()}`; -}; diff --git a/POSTGRES/code/calc-node/package.json b/POSTGRES/code/calc-node/package.json deleted file mode 100644 index 18a1e41..0000000 --- a/POSTGRES/code/calc-node/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "dependencies": {} -} diff --git a/POSTGRES/code/calc-python/handler.py b/POSTGRES/code/calc-python/handler.py deleted file mode 100644 index f775f35..0000000 --- a/POSTGRES/code/calc-python/handler.py +++ /dev/null @@ -1,105 +0,0 @@ -# Создано: 2026-04-10 -# Изменено: 2026-03-23 — упрощён до поля ввода выражения (демонстрация деплоя). -# Принимает произвольное математическое выражение: "2+2*(3-1)", "(10/3)**2" и т.д. -# GET → HTML страница с формой; POST с {expr} → вычисление через безопасный eval. -# Безопасность eval: __builtins__=None, только math-функции в locals. - -import math - -_PAGE = """ - - - - -Калькулятор — Python 3.11 - - - -
-

Калькулятор

-
Python 3.11 · runtime: sless
- - -
-
- - -""" - -# Разрешённые math-функции в eval — без __builtins__ нет доступа к exec/open/etc. -_MATH_LOCALS = {k: getattr(math, k) for k in dir(math) if not k.startswith('_')} - - -def handler(event): - if event.get('_method') == 'POST': - expr = str(event.get('expr', '')).strip() - return _compute(expr) - # GET → HTML страница - return _PAGE - - -def _compute(expr): - if not expr: - return {'error': 'Введите выражение'} - try: - result = eval(expr, {'__builtins__': None}, _MATH_LOCALS) # noqa: S307 - if not isinstance(result, (int, float)): - return {'error': 'Результат не является числом'} - return {'expr': expr, 'result': result} - except ZeroDivisionError: - return {'error': 'Деление на ноль'} - except Exception as exc: - return {'error': f'Ошибка: {exc}'} - - -def _esc(s): - # Экранируем HTML-спецсимволы — безопасный вывод в атрибут и тело. - return s.replace('&', '&').replace('<', '<').replace('>', '>').replace('"', '"') diff --git a/POSTGRES/code/calc-python/requirements.txt b/POSTGRES/code/calc-python/requirements.txt deleted file mode 100644 index d45663c..0000000 --- a/POSTGRES/code/calc-python/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -# нет внешних зависимостей diff --git a/POSTGRES/code/js-idempotent/js_idempotent.js b/POSTGRES/code/js-idempotent/js_idempotent.js deleted file mode 100644 index b19d7da..0000000 --- a/POSTGRES/code/js-idempotent/js_idempotent.js +++ /dev/null @@ -1,58 +0,0 @@ -// 2026-03-21 — js-idempotent: INSERT с проверкой по idempotency_key. -// Повторный вызов с тем же key НЕ создаёт дубль — возвращает существующую запись. -// Тестирует: идемпотентность через SELECT ... FOR UPDATE + условный INSERT. -const { Client } = require('pg'); - -async function run(event) { - const key = String(event.idempotency_key ?? `auto-${Date.now()}`).slice(0, 200); - const title = String(event.title ?? key).slice(0, 255); - - const client = new Client({ - host: process.env.PGHOST, - port: parseInt(process.env.PGPORT ?? '5432'), - database: process.env.PGDATABASE, - user: process.env.PGUSER, - password: process.env.PGPASSWORD, - ssl: { rejectUnauthorized: false }, - }); - await client.connect(); - - try { - await client.query('BEGIN'); - - // Ищем существующую запись по title (используем как idempotency key) - const existing = await client.query( - 'SELECT id, title, created_at FROM terraform_demo_table WHERE title = $1 LIMIT 1 FOR UPDATE', - [key] - ); - - let action, row; - if (existing.rows.length > 0) { - action = 'existing'; - row = existing.rows[0]; - } else { - const ins = await client.query( - 'INSERT INTO terraform_demo_table (title) VALUES ($1) RETURNING id, title, created_at', - [key] - ); - action = 'created'; - row = ins.rows[0]; - } - - await client.query('COMMIT'); - return { - action, - id: row.id, - title: row.title, - created_at: row.created_at, - idempotency_key: key, - }; - } catch (e) { - await client.query('ROLLBACK'); - throw e; - } finally { - await client.end(); - } -} - -module.exports = { run }; diff --git a/POSTGRES/code/js-idempotent/package.json b/POSTGRES/code/js-idempotent/package.json deleted file mode 100644 index 1ad69de..0000000 --- a/POSTGRES/code/js-idempotent/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "js-idempotent", - "version": "1.0.0", - "dependencies": { - "pg": "^8.11.3" - } -} diff --git a/POSTGRES/code/pg-counter/pg_counter.py b/POSTGRES/code/pg-counter/pg_counter.py deleted file mode 100644 index b7a7080..0000000 --- a/POSTGRES/code/pg-counter/pg_counter.py +++ /dev/null @@ -1,23 +0,0 @@ -# 2026-03-21 — pg-counter: считает строки по prefix, возвращает статистику. -# Тестирует: SELECT COUNT с WHERE LIKE, агрегация, concurrent reads. -import os, psycopg2 - -def count(event): - prefix = event.get("prefix", "") - conn = psycopg2.connect( - host=os.environ["PGHOST"], port=int(os.environ.get("PGPORT", 5432)), - dbname=os.environ["PGDATABASE"], user=os.environ["PGUSER"], - password=os.environ["PGPASSWORD"], sslmode=os.environ.get("PGSSLMODE", "require"), - ) - try: - with conn.cursor() as cur: - if prefix: - cur.execute("SELECT COUNT(*) FROM terraform_demo_table WHERE title LIKE %s", (f"{prefix}%",)) - else: - cur.execute("SELECT COUNT(*) FROM terraform_demo_table") - total = cur.fetchone()[0] - cur.execute("SELECT COUNT(*) FROM terraform_demo_table WHERE created_at > now() - interval '1 hour'") - last_hour = cur.fetchone()[0] - return {"total": total, "last_hour": last_hour, "prefix": prefix or "*"} - finally: - conn.close() diff --git a/POSTGRES/code/pg-counter/requirements.txt b/POSTGRES/code/pg-counter/requirements.txt deleted file mode 100644 index 37ec460..0000000 --- a/POSTGRES/code/pg-counter/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -psycopg2-binary diff --git a/POSTGRES/code/pg-info/package.json b/POSTGRES/code/pg-info/package.json deleted file mode 100644 index 5e6394d..0000000 --- a/POSTGRES/code/pg-info/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "pg-info", - "version": "1.0.0", - "description": "sless nodejs20 function: pg version + table info", - "dependencies": { - "pg": "8.11.0" - } -} \ No newline at end of file diff --git a/POSTGRES/code/pg-info/pg_info.js b/POSTGRES/code/pg-info/pg_info.js deleted file mode 100644 index 9468076..0000000 --- a/POSTGRES/code/pg-info/pg_info.js +++ /dev/null @@ -1,44 +0,0 @@ -// 2026-03-18 -// pg_info.js — NodeJS-функция: проверка работы JS runtime + чтение мета-данных БД. -// Подключается к PostgreSQL через пакет pg, возвращает версию сервера и счётчик строк. -// Демонстрирует: nodejs20 runtime, npm-зависимость (package.json), PG из JS. -// -// ENV (те же что у python-функций): -// PGHOST, PGPORT, PGDATABASE, PGUSER, PGPASSWORD, PGSSLMODE -// -// Entrypoint: pg_info.info - -'use strict'; - -const { Client } = require('pg'); - -exports.info = async (event) => { - const client = new Client({ - host: process.env.PGHOST, - port: parseInt(process.env.PGPORT || '5432'), - database: process.env.PGDATABASE, - user: process.env.PGUSER, - password: process.env.PGPASSWORD, - // pg-пакет требует явного ssl-объекта; rejectUnauthorized: false — т.к. - // self-signed cert на nubes managed PG, но канал всё равно шифруется. - ssl: process.env.PGSSLMODE === 'require' ? { rejectUnauthorized: false } : false, - }); - - await client.connect(); - try { - const [versionRes, countRes] = await Promise.all([ - client.query('SELECT version() AS v'), - client.query('SELECT COUNT(*) AS cnt FROM terraform_demo_table'), - ]); - - return { - runtime: 'nodejs20', - node_version: process.version, - pg_version: versionRes.rows[0].v, - table_rows: parseInt(countRes.rows[0].cnt, 10), - code_version: 'v2-agent-test', - }; - } finally { - await client.end(); - } -}; diff --git a/POSTGRES/code/pg-stats/pg_stats.py b/POSTGRES/code/pg-stats/pg_stats.py deleted file mode 100644 index 225f41b..0000000 --- a/POSTGRES/code/pg-stats/pg_stats.py +++ /dev/null @@ -1,38 +0,0 @@ -# 2026-03-19 -# pg_stats.py — тестовая функция (Test 7): возвращает агрегированную статистику -# по таблице terraform_demo_table: кол-во строк, дата первой и последней записи. -# Создаётся и удаляется в рамках тестового прогона. -# -# Entrypoint: pg_stats.get_stats - -import os -import psycopg2 -import json - -_CODE_VERSION = "v1-test7" - - -def get_stats(event): - conn = psycopg2.connect( - host=os.environ["PGHOST"], - port=int(os.environ.get("PGPORT", "5432")), - dbname=os.environ["PGDATABASE"], - user=os.environ["PGUSER"], - password=os.environ["PGPASSWORD"], - sslmode=os.environ.get("PGSSLMODE", "require"), - ) - try: - with conn.cursor() as cur: - cur.execute( - "SELECT COUNT(*) AS cnt, MIN(created_at) AS first, MAX(created_at) AS last " - "FROM terraform_demo_table" - ) - row = cur.fetchone() - return { - "version": _CODE_VERSION, - "total_rows": row[0], - "first_row_at": str(row[1]) if row[1] else None, - "last_row_at": str(row[2]) if row[2] else None, - } - finally: - conn.close() diff --git a/POSTGRES/code/pg-stats/requirements.txt b/POSTGRES/code/pg-stats/requirements.txt deleted file mode 100644 index 58ab769..0000000 --- a/POSTGRES/code/pg-stats/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -psycopg2-binary==2.9.9 diff --git a/POSTGRES/functions.tf b/POSTGRES/functions.tf deleted file mode 100644 index 89263cf..0000000 --- a/POSTGRES/functions.tf +++ /dev/null @@ -1,36 +0,0 @@ -# Создано: 2026-04-10 -# functions.tf — sless_service ресурсы для примера POSTGRES. -# Здесь: два калькуляторa — Python и Node.js. -# sless_service = long-running Deployment + постоянный URL (в отличие от sless_function). - -# ─── Python-калькулятор ────────────────────────────────────────────────────── - -resource "sless_service" "calc_python" { - name = "calc-python" - runtime = "python3.11" - entrypoint = "handler.handler" - memory_mb = 128 - timeout_sec = 30 - source_dir = "${path.module}/code/calc-python" -} - -output "calc_python_url" { - description = "URL Python-калькулятора" - value = sless_service.calc_python.url -} - -# ─── Node.js-калькулятор ───────────────────────────────────────────────────── - -resource "sless_service" "calc_node" { - name = "calc-node" - runtime = "nodejs20" - entrypoint = "handler.handler" - memory_mb = 128 - timeout_sec = 30 - source_dir = "${path.module}/code/calc-node" -} - -output "calc_node_url" { - description = "URL Node.js-калькулятора" - value = sless_service.calc_node.url -} diff --git a/POSTGRES/main.tf b/POSTGRES/main.tf deleted file mode 100644 index 834387f..0000000 --- a/POSTGRES/main.tf +++ /dev/null @@ -1,64 +0,0 @@ -// 2026-03-17 17:05 -// main.tf — провайдеры и переменные для Nubes + sless. -terraform { - required_providers { - nubes = { - source = "terra.k8c.ru/nubes/nubes" - version = "5.0.31" - } - sless = { - source = "terra.k8c.ru/naeel/sless" - version = "~> 0.1.19" - } - } -} - -variable "api_token" { - type = string - sensitive = true - description = "Nubes API token" -} -variable "s3_uid" { - type = string - sensitive = true - description = "Nubes S3 UID" -} -variable "realm" { - type = string - sensitive = true - description = "resource_realm parameter for nubes_postgres resource" -} - -// 2026-03-18 — pg_user/pg_password помечены optional (default="") для сверки. -// Реальные credentials берутся из vault_secrets через locals в resources.tf. -variable "pg_user" { - type = string - sensitive = true - default = "" - description = "Только для сверки. Реальный username из nubes_postgres_user.pg_user.username. Должен совпадать с vault." -} - -variable "pg_password" { - type = string - sensitive = true - default = "" - description = "Только для сверки. Реальный пароль из vault_secrets. Должен совпадать с tfvars." -} - -# Nubes endpoints — не путать: -# API Dashboard (для Terraform-провайдеров): https://deck-api-test.ngcloud.ru/api/v1/index.cfm -# UI облака (только браузер, не для кода): https://deck-test.ngcloud.ru/ -# ВАЖНО: nubes и sless провайдеры требуют API endpoint, НЕ UI! - -provider "nubes" { - api_token = var.api_token - api_endpoint = "https://deck-api-test.ngcloud.ru/api/v1/index.cfm" -} - -provider "sless" { - endpoint = "https://sless.kube5s.ru" - token = var.api_token - nubes_endpoint = "https://deck-api-test.ngcloud.ru/api/v1" -} - - diff --git a/POSTGRES/postgres.tf b/POSTGRES/postgres.tf deleted file mode 100644 index 0315443..0000000 --- a/POSTGRES/postgres.tf +++ /dev/null @@ -1,58 +0,0 @@ -// 2026-03-20 — выделено из resources.tf: только managed PostgreSQL ресурсы. - -# Актуальные credentials из vault_secrets (authoritatively) — vault синхронизирован с кластером. -# Структура vault_secrets["users"]: JSON-строка {"username": {"password": "...", "username": "..."}} - -locals { - # try() нужен: vault_secrets["users"] появляется только ПОСЛЕ создания первого пользователя. - # На первом apply ключа ещё нет → пустая map. Пароль подтянется при следующем apply. - pg_creds_map = try(jsondecode(lookup(nubes_postgres.npg.vault_secrets, "users", "{}")), {}) - pg_username = nubes_postgres_user.pg_user.username - pg_password = try(local.pg_creds_map[local.pg_username]["password"], "") - pg_host = nubes_postgres.npg.state_out_flat["internalConnect.master"] - pg_database = nubes_postgres_database.db.db_name -} - - -resource "nubes_postgres" "npg" { - resource_name = "pg-sless-demo" - # s3_uid = "s01325" - s3_uid = var.s3_uid - resource_realm = var.realm - resource_instances = 1 - resource_memory = 512 - resource_c_p_u = 500 - resource_disk = "1" - app_version = "17" - json_parameters = jsonencode({ - log_connections = "off" - log_disconnections = "off" - }) - enable_pg_pooler_master = false - enable_pg_pooler_slave = false - allow_no_s_s_l = false - auto_scale = false - auto_scale_percentage = 10 - auto_scale_tech_window = 0 - auto_scale_quota_gb = "1" - need_external_address_master = false - - # suspend_on_destroy = false - operation_timeout = "11m" - adopt_existing_on_create = true -} - -resource "nubes_postgres_user" "pg_user" { - postgres_id = nubes_postgres.npg.id - username = "user0" - role = "ddl_user" - adopt_existing_on_create = true -} - -resource "nubes_postgres_database" "db" { - postgres_id = nubes_postgres.npg.id - db_name = "db0" - db_owner = nubes_postgres_user.pg_user.username - adopt_existing_on_create = true - # suspend_on_destroy = false -} diff --git a/POSTGRES/resources.tf b/POSTGRES/resources.tf deleted file mode 100644 index cd662b8..0000000 --- a/POSTGRES/resources.tf +++ /dev/null @@ -1,3 +0,0 @@ -// 2026-03-20 — содержимое перенесено в два файла: -// postgres.tf — managed PostgreSQL ресурсы (nubes_postgres, user, database, locals) -// functions.tf — sless функции, сервисы, джобы, outputs diff --git a/README.md b/README.md index 96dfaae..5c9fa2a 100644 --- a/README.md +++ b/README.md @@ -1,75 +1,55 @@ -# Примеры использования sless +# sless — примеры -## Обзор платформы - -**sless** — система управления serverless-функциями на базе Kubernetes. Разработчик загружает код функции, платформа собирает из него Docker-образ, разворачивает его в кластере и предоставляет HTTP-эндпоинт для вызова. Всё описывается декларативно через Terraform. - -### Основные ресурсы провайдера - -| Ресурс | Назначение | -|---|---| -| `sless_service` | Long-running HTTP-сервис: всегда активен, отвечает на запросы. Имеет свой URL после деплоя. | -| `sless_job` | Одноразовый запуск функции: собирает образ, выполняет код, завершается. Используется для миграций БД, batch-обработки и т.д. | - -Namespace функций вычисляется автоматически из JWT-токена: `sless-{sha256[:8]}`. +**sless** — платформа для запуска serverless-функций на базе Kubernetes. +Разработчик загружает код, платформа собирает Docker-образ и разворачивает его в кластере. +Всё описывается декларативно через Terraform. --- -## Требования +## Ресурсы Terraform-провайдера -- Terraform >= 1.3 -- JWT-токен для аутентификации в sless API -- JWT-токен для Nubes Cloud API (если используются managed-ресурсы: PostgreSQL и т.д.) -- Доступ к `https://sless.kube5s.ru` +| Ресурс | Что делает | +|---|---| +| `sless_service` | HTTP-сервис: всегда запущен, отвечает на запросы, имеет постоянный URL | +| `sless_job` | Разовый запуск: выполняет код один раз и завершается (установка ПО, миграции и т.д.) | + +--- ## Конфигурация провайдера ```hcl provider "sless" { endpoint = "https://sless.kube5s.ru" - token = var.sless_token -} - -provider "nubes_cloud" { - base_url = "https://deck-api-test.ngcloud.ru/api/v1" - token = var.nubes_token + token = var.api_token } ``` -> Токены задаются в `terraform.tfvars` — этот файл добавлен в `.gitignore`. +Токен задаётся в `terraform.tfvars` (файл в `.gitignore`, не попадает в git). --- ## Примеры -### `POSTGRES` — Serverless-функции с Managed PostgreSQL +### [`VM/`](VM/) — Виртуальная машина в Nubes vDC -Полный пример: managed PostgreSQL + одноразовый init-job + 3 HTTP-сервиса (чтение/запись данных и информация о PG). +Создаёт vApp + Ubuntu 22.04 VM в облаке Nubes. После создания — автоматически устанавливает ПО (nginx, Docker, пакеты) через serverless-джобы по SSH. -Языки: Python 3.11, Node.js 20. - -```bash -cd POSTGRES -terraform init -terraform apply -``` - -Подробности: [POSTGRES/README.md](POSTGRES/README.md) +**→ [Начать здесь](VM/README.md)** --- ## Полезные команды ```bash -# Посмотреть состояние задеплоенных ресурсов: +# Посмотреть состояние ресурсов: terraform show -# Принудительно пересобрать сервис (после изменения кода): -terraform apply -replace=sless_service.<имя> - -# Повторно запустить job: увеличить run_id в .tf-файле, затем: +# Повторно запустить job: увеличить run_id в terraform.tfvars, затем: terraform apply -# Удалить все ресурсы примера: +# Принудительно пересобрать сервис после изменения кода: +terraform apply -replace=sless_service.<имя> + +# Удалить все ресурсы: terraform destroy ```