feat: demo managed functions with harbor-backed operator setup
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
# Изменено: 2026-03-14
|
||||
# Node-RED для визуального управления demo сценарием Event Log.
|
||||
# Образ: nodered/node-red:4 (официальный, всегда есть на DockerHub)
|
||||
# UI доступен по http://<ingress-ip>/nodered/
|
||||
# Для AMQP нужен плагин node-red-contrib-amqp — ставится через initContainer.
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: nodered-data
|
||||
namespace: sless
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nodered
|
||||
namespace: sless
|
||||
labels:
|
||||
app: nodered
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nodered
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nodered
|
||||
spec:
|
||||
securityContext:
|
||||
fsGroup: 1000
|
||||
# initContainer устанавливает AMQP-плагин в PVC до старта основного контейнера
|
||||
initContainers:
|
||||
- name: install-nodes
|
||||
image: nodered/node-red:latest
|
||||
securityContext:
|
||||
runAsUser: 0
|
||||
runAsGroup: 0
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
chown -R 1000:1000 /data || true
|
||||
cd /data
|
||||
npm install --prefix /data node-red-contrib-amqp node-red-dashboard 2>&1 || true
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /data
|
||||
containers:
|
||||
- name: nodered
|
||||
image: nodered/node-red:latest
|
||||
ports:
|
||||
- containerPort: 1880
|
||||
env:
|
||||
- name: NODE_RED_ENABLE_PROJECTS
|
||||
value: "false"
|
||||
- name: TZ
|
||||
value: "Europe/Moscow"
|
||||
securityContext:
|
||||
runAsUser: 1000
|
||||
runAsGroup: 1000
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /data
|
||||
resources:
|
||||
requests:
|
||||
memory: "256Mi"
|
||||
cpu: "100m"
|
||||
limits:
|
||||
memory: "512Mi"
|
||||
cpu: "500m"
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 1880
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 10
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: nodered-data
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nodered
|
||||
namespace: sless
|
||||
spec:
|
||||
selector:
|
||||
app: nodered
|
||||
ports:
|
||||
- port: 1880
|
||||
targetPort: 1880
|
||||
---
|
||||
# Ingress на Node-RED — доступен снаружи по http://nodered.185.247.187.147.nip.io
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nodered
|
||||
namespace: sless
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
|
||||
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
|
||||
spec:
|
||||
ingressClassName: nginx
|
||||
rules:
|
||||
- host: nodered.185.247.187.147.nip.io
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nodered
|
||||
port:
|
||||
number: 1880
|
||||
@@ -0,0 +1,125 @@
|
||||
# Изменено: 2026-03-14
|
||||
# Деплой sless оператора на demo-стенде (naeel-test-3, nip.io, без TLS).
|
||||
# Отличия от production operator.yaml:
|
||||
# - REGISTRY_HOST=naeel (DockerHub, не Harbor)
|
||||
# - INGRESS_HOST и EXTERNAL_URL — через nip.io без TLS
|
||||
# - cert-manager аннотации убраны
|
||||
# - API_TOKEN берётся из sless-operator-secret (совпадает с secrets/test.token)
|
||||
#
|
||||
# Перед apply нужно создать секреты:
|
||||
# kubectl create secret generic sless-operator-secret -n sless \
|
||||
# --from-literal=POSTGRES_DSN="postgres://sless:sless-pg-password@postgres.sless.svc.cluster.local:5432/sless?sslmode=disable" \
|
||||
# --from-literal=S3_ACCESS_KEY="0GLQRD38H4I6RBDB0EWJ" \
|
||||
# --from-literal=S3_SECRET_KEY="eTFibiHmBd96IApj9PYsboTR6OBoD7osxoarHykw" \
|
||||
# --from-literal=SLESS_API_TOKEN="<token from secrets/test.token>" \
|
||||
# --from-literal=HARBOR_PASS=""
|
||||
#
|
||||
# kubectl create secret docker-registry sless-registry-auth -n sless \
|
||||
# --docker-server=https://index.docker.io/v1/ \
|
||||
# --docker-username=naeel \
|
||||
# --docker-password=<DOCKERHUB_TOKEN>
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: sless-operator-config
|
||||
namespace: sless
|
||||
data:
|
||||
S3_ENDPOINT: "s3.msk-1.ngcloud.ru"
|
||||
S3_BUCKET: "sless-functions"
|
||||
S3_USE_SSL: "true"
|
||||
# Harbor как registry для demo
|
||||
REGISTRY_HOST: "pearlharbor.registryk8s.services.ngcloud.ru"
|
||||
REGISTRY_SECRET: "sless-registry-auth"
|
||||
HARBOR_USER: "admin"
|
||||
API_PORT: "9090"
|
||||
# nip.io домен без TLS — работает без настройки DNS
|
||||
INGRESS_HOST: "fn.185.247.187.147.nip.io"
|
||||
EXTERNAL_URL: "http://sless-api.185.247.187.147.nip.io"
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: sless-operator
|
||||
namespace: sless
|
||||
labels:
|
||||
app: sless-operator
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: sless-operator
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: sless-operator
|
||||
spec:
|
||||
serviceAccountName: sless-operator
|
||||
containers:
|
||||
- name: operator
|
||||
image: naeel/sless-operator:v0.1.29
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- name: api
|
||||
containerPort: 9090
|
||||
- name: metrics
|
||||
containerPort: 8080
|
||||
- name: health
|
||||
containerPort: 8081
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: sless-operator-config
|
||||
- secretRef:
|
||||
name: sless-operator-secret
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 8081
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 8081
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 20
|
||||
resources:
|
||||
requests:
|
||||
memory: "64Mi"
|
||||
cpu: "50m"
|
||||
limits:
|
||||
memory: "256Mi"
|
||||
cpu: "500m"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: sless-operator
|
||||
namespace: sless
|
||||
spec:
|
||||
selector:
|
||||
app: sless-operator
|
||||
ports:
|
||||
- name: api
|
||||
port: 9090
|
||||
targetPort: 9090
|
||||
---
|
||||
# Ingress без TLS — demo стенд через nip.io
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: sless-operator
|
||||
namespace: sless
|
||||
spec:
|
||||
ingressClassName: nginx
|
||||
rules:
|
||||
- host: sless-api.185.247.187.147.nip.io
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: sless-operator
|
||||
port:
|
||||
number: 9090
|
||||
@@ -0,0 +1,73 @@
|
||||
# Изменено: 2026-03-14
|
||||
# RabbitMQ для demo сценария Event Log.
|
||||
# Используется официальный образ с management-плагином для веб-UI.
|
||||
# credentials: sless / sless123
|
||||
# AMQP: amqp://sless:sless123@rabbitmq.sless.svc.cluster.local:5672/
|
||||
# Management UI: http://rabbitmq.sless.svc.cluster.local:15672/
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: rabbitmq-secret
|
||||
namespace: sless
|
||||
stringData:
|
||||
RABBITMQ_DEFAULT_USER: "sless"
|
||||
RABBITMQ_DEFAULT_PASS: "sless123"
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: rabbitmq
|
||||
namespace: sless
|
||||
labels:
|
||||
app: rabbitmq
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: rabbitmq
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: rabbitmq
|
||||
spec:
|
||||
containers:
|
||||
- name: rabbitmq
|
||||
image: rabbitmq:3.13-management-alpine
|
||||
ports:
|
||||
- name: amqp
|
||||
containerPort: 5672
|
||||
- name: management
|
||||
containerPort: 15672
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: rabbitmq-secret
|
||||
resources:
|
||||
requests:
|
||||
memory: "256Mi"
|
||||
cpu: "100m"
|
||||
limits:
|
||||
memory: "512Mi"
|
||||
cpu: "500m"
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 5672
|
||||
initialDelaySeconds: 40
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 10
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: rabbitmq
|
||||
namespace: sless
|
||||
spec:
|
||||
selector:
|
||||
app: rabbitmq
|
||||
ports:
|
||||
- name: amqp
|
||||
port: 5672
|
||||
targetPort: 5672
|
||||
- name: management
|
||||
port: 15672
|
||||
targetPort: 15672
|
||||
@@ -0,0 +1,45 @@
|
||||
# Изменено: 2026-03-14
|
||||
# Функция event-cleaner: удаляет N самых старых строк из таблицы events.
|
||||
# Вызывается через HTTP POST из Node-RED (который слушает RabbitMQ).
|
||||
# Env: POSTGRES_DSN — строка подключения к PostgreSQL.
|
||||
|
||||
import os
|
||||
import json
|
||||
import psycopg2
|
||||
|
||||
def handle(request):
|
||||
"""Удаляет N старейших строк из таблицы events."""
|
||||
dsn = os.environ["POSTGRES_DSN"]
|
||||
|
||||
body = {}
|
||||
if request.get_data():
|
||||
try:
|
||||
body = json.loads(request.get_data())
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Количество строк для удаления — из тела запроса или дефолт 10
|
||||
delete_n = int(body.get("delete_n", 10))
|
||||
# Защита от случайного удаления слишком большого количества строк
|
||||
delete_n = min(delete_n, 100)
|
||||
|
||||
conn = psycopg2.connect(dsn)
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("""
|
||||
DELETE FROM events
|
||||
WHERE id IN (
|
||||
SELECT id FROM events ORDER BY created_at ASC LIMIT %s
|
||||
)
|
||||
""", (delete_n,))
|
||||
deleted = cur.rowcount
|
||||
cur.execute("SELECT COUNT(*) FROM events")
|
||||
remaining = cur.fetchone()[0]
|
||||
conn.commit()
|
||||
return json.dumps({
|
||||
"ok": True,
|
||||
"deleted": deleted,
|
||||
"remaining": remaining
|
||||
}), 200, {"Content-Type": "application/json"}
|
||||
finally:
|
||||
conn.close()
|
||||
@@ -0,0 +1,47 @@
|
||||
# Изменено: 2026-03-14
|
||||
# Функция event-monitor: считает строки в events.
|
||||
# Если больше 50 — публикует сообщение в RabbitMQ queue "cleanup-needed".
|
||||
# Запускается по cron (каждую минуту).
|
||||
# Env:
|
||||
# POSTGRES_DSN — строка подключения к PostgreSQL
|
||||
# RABBITMQ_URL — amqp://sless:sless123@rabbitmq.sless.svc.cluster.local:5672/
|
||||
|
||||
import os
|
||||
import json
|
||||
import psycopg2
|
||||
import pika
|
||||
|
||||
THRESHOLD = 50
|
||||
|
||||
def handle(request):
|
||||
"""Мониторит таблицу events. При переполнении шлёт в RabbitMQ."""
|
||||
dsn = os.environ["POSTGRES_DSN"]
|
||||
rabbit_url = os.environ["RABBITMQ_URL"]
|
||||
|
||||
conn = psycopg2.connect(dsn)
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
# Считаем количество событий
|
||||
cur.execute("SELECT COUNT(*) FROM events")
|
||||
count = cur.fetchone()[0]
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
result = {"count": count, "threshold": THRESHOLD, "action": "none"}
|
||||
|
||||
if count > THRESHOLD:
|
||||
# Публикуем в очередь — event-cleaner получит и удалит старые строки
|
||||
params = pika.URLParameters(rabbit_url)
|
||||
connection = pika.BlockingConnection(params)
|
||||
channel = connection.channel()
|
||||
channel.queue_declare(queue="cleanup-needed", durable=True)
|
||||
channel.basic_publish(
|
||||
exchange="",
|
||||
routing_key="cleanup-needed",
|
||||
body=json.dumps({"count": count, "delete_n": 10}),
|
||||
properties=pika.BasicProperties(delivery_mode=2) # persistent
|
||||
)
|
||||
connection.close()
|
||||
result["action"] = "cleanup_requested"
|
||||
|
||||
return json.dumps(result), 200, {"Content-Type": "application/json"}
|
||||
@@ -0,0 +1,49 @@
|
||||
# Изменено: 2026-03-14
|
||||
# Функция event-writer: принимает HTTP POST, пишет одну строку в таблицу events.
|
||||
# Таблица создаётся автоматически при первом запуске.
|
||||
# Env: POSTGRES_DSN — строка подключения к PostgreSQL.
|
||||
|
||||
import os
|
||||
import json
|
||||
import psycopg2
|
||||
from datetime import datetime, timezone
|
||||
|
||||
def handle(request):
|
||||
"""Записывает одно событие в таблицу events."""
|
||||
dsn = os.environ["POSTGRES_DSN"]
|
||||
|
||||
body = {}
|
||||
if request.get_data():
|
||||
try:
|
||||
body = json.loads(request.get_data())
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
source = body.get("source", "node-red")
|
||||
message = body.get("message", "ping")
|
||||
|
||||
conn = psycopg2.connect(dsn)
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
# Создаём таблицу если нет — безопасно вызывать при каждом запросе
|
||||
cur.execute("""
|
||||
CREATE TABLE IF NOT EXISTS events (
|
||||
id SERIAL PRIMARY KEY,
|
||||
source VARCHAR(100) NOT NULL DEFAULT 'unknown',
|
||||
message TEXT NOT NULL DEFAULT '',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
)
|
||||
""")
|
||||
cur.execute(
|
||||
"INSERT INTO events (source, message) VALUES (%s, %s) RETURNING id, created_at",
|
||||
(source, message)
|
||||
)
|
||||
row = cur.fetchone()
|
||||
conn.commit()
|
||||
return json.dumps({
|
||||
"ok": True,
|
||||
"id": row[0],
|
||||
"created_at": row[1].isoformat()
|
||||
}), 200, {"Content-Type": "application/json"}
|
||||
finally:
|
||||
conn.close()
|
||||
@@ -0,0 +1,26 @@
|
||||
# Изменено: 2026-03-14
|
||||
# event-cleaner: HTTP функция для демонстрации контролируемого изменения логики.
|
||||
# Работает без внешних пакетов.
|
||||
|
||||
import json
|
||||
from datetime import datetime, timezone
|
||||
|
||||
|
||||
def handle(event):
|
||||
"""Принимает delete_n и возвращает подтверждение обработки."""
|
||||
|
||||
payload = event if isinstance(event, dict) else {}
|
||||
|
||||
delete_n = int(payload.get("delete_n", 10))
|
||||
delete_n = max(1, min(delete_n, 100))
|
||||
|
||||
now = datetime.now(timezone.utc).isoformat()
|
||||
# Здесь intentionally имитируем очистку, чтобы показать реакцию на входные параметры.
|
||||
return json.dumps(
|
||||
{
|
||||
"ok": True,
|
||||
"accepted_delete_n": delete_n,
|
||||
"status": "simulated-cleanup",
|
||||
"generated_at": now,
|
||||
}
|
||||
), 200, {"Content-Type": "application/json"}
|
||||
@@ -0,0 +1,25 @@
|
||||
# Изменено: 2026-03-14
|
||||
# event-monitor: cron-функция для демонстрации расписания и управления кодом.
|
||||
# Работает без внешних библиотек и возвращает диагностический JSON.
|
||||
|
||||
import json
|
||||
import os
|
||||
from datetime import datetime, timezone
|
||||
|
||||
|
||||
THRESHOLD = 50
|
||||
|
||||
|
||||
def handle(request):
|
||||
"""Отдаёт heartbeat для cron-запуска и видимой проверки после apply."""
|
||||
rabbitmq_url = os.environ.get("RABBITMQ_URL", "not-set")
|
||||
now = datetime.now(timezone.utc).isoformat()
|
||||
return json.dumps(
|
||||
{
|
||||
"ok": True,
|
||||
"monitor": "alive",
|
||||
"threshold": THRESHOLD,
|
||||
"rabbitmq_configured": rabbitmq_url != "not-set",
|
||||
"generated_at": now,
|
||||
}
|
||||
), 200, {"Content-Type": "application/json"}
|
||||
@@ -0,0 +1,28 @@
|
||||
# Изменено: 2026-03-14
|
||||
# event-writer: простая HTTP функция без внешних зависимостей.
|
||||
# Правка поля response_tag в коде сразу видна в ответе после terraform apply.
|
||||
|
||||
import json
|
||||
import os
|
||||
from datetime import datetime, timezone
|
||||
|
||||
|
||||
def handle(event):
|
||||
"""Возвращает полезный JSON-ответ для визуальной проверки выката кода."""
|
||||
default_message = os.environ.get("DEFAULT_MESSAGE", "writer-default")
|
||||
|
||||
payload = event if isinstance(event, dict) else {}
|
||||
|
||||
message = payload.get("message", default_message)
|
||||
source = payload.get("source", "event-writer")
|
||||
now = datetime.now(timezone.utc).isoformat()
|
||||
|
||||
# response_tag удобно менять для демонстрации hot-update кода через terraform apply.
|
||||
response_tag = "writer-v2"
|
||||
return {
|
||||
"ok": True,
|
||||
"source": source,
|
||||
"message": message,
|
||||
"response_tag": response_tag,
|
||||
"generated_at": now,
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
# 2026-03-14
|
||||
# function.tf — ресурсы managed serverless функций для демонстрации.
|
||||
# Пользователь правит код в code/* и запускает terraform apply — провайдер сам пересобирает и выкатывает функции.
|
||||
|
||||
resource "sless_function" "event_writer" {
|
||||
name = "event-writer"
|
||||
runtime = "python3.11"
|
||||
entrypoint = "handler.handle"
|
||||
memory_mb = 128
|
||||
timeout_sec = 20
|
||||
|
||||
source_dir = "${path.module}/code/event-writer"
|
||||
|
||||
env_vars = {
|
||||
POSTGRES_DSN = var.pg_dsn
|
||||
DEFAULT_MESSAGE = var.writer_message
|
||||
}
|
||||
}
|
||||
|
||||
resource "sless_trigger" "event_writer_http" {
|
||||
name = "event-writer-http"
|
||||
type = "http"
|
||||
function = sless_function.event_writer.name
|
||||
enabled = true
|
||||
}
|
||||
|
||||
resource "sless_function" "event_monitor" {
|
||||
name = "event-monitor"
|
||||
runtime = "python3.11"
|
||||
entrypoint = "handler.handle"
|
||||
memory_mb = 128
|
||||
timeout_sec = 20
|
||||
|
||||
source_dir = "${path.module}/code/event-monitor"
|
||||
|
||||
env_vars = {
|
||||
POSTGRES_DSN = var.pg_dsn
|
||||
RABBITMQ_URL = var.rabbitmq_url
|
||||
}
|
||||
}
|
||||
|
||||
resource "sless_trigger" "event_monitor_cron" {
|
||||
name = "event-monitor-cron"
|
||||
type = "cron"
|
||||
function = sless_function.event_monitor.name
|
||||
enabled = true
|
||||
schedule = "*/1 * * * *"
|
||||
}
|
||||
|
||||
resource "sless_function" "event_cleaner" {
|
||||
name = "event-cleaner"
|
||||
runtime = "python3.11"
|
||||
entrypoint = "handler.handle"
|
||||
memory_mb = 128
|
||||
timeout_sec = 20
|
||||
|
||||
source_dir = "${path.module}/code/event-cleaner"
|
||||
|
||||
env_vars = {
|
||||
POSTGRES_DSN = var.pg_dsn
|
||||
}
|
||||
}
|
||||
|
||||
resource "sless_trigger" "event_cleaner_http" {
|
||||
name = "event-cleaner-http"
|
||||
type = "http"
|
||||
function = sless_function.event_cleaner.name
|
||||
enabled = true
|
||||
}
|
||||
|
||||
output "event_writer_url" {
|
||||
value = sless_trigger.event_writer_http.url
|
||||
}
|
||||
|
||||
output "event_cleaner_url" {
|
||||
value = sless_trigger.event_cleaner_http.url
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
# 2026-03-14
|
||||
# Terraform demo: managed serverless functions.
|
||||
# Здесь управляем ТОЛЬКО функциями/триггерами, внешние сервисы считаем уже поднятыми.
|
||||
|
||||
terraform {
|
||||
required_providers {
|
||||
sless = {
|
||||
source = "terra.k8c.ru/naeel/sless"
|
||||
version = "~> 0.1.18"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "sless" {
|
||||
endpoint = var.sless_endpoint
|
||||
token = var.token
|
||||
nubes_endpoint = var.nubes_endpoint
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
# 2026-03-14
|
||||
# Скопируй в terraform.tfvars и подставь актуальный токен.
|
||||
|
||||
token = "PUT_TOKEN_HERE"
|
||||
sless_endpoint = "http://sless-api.185.247.187.147.nip.io"
|
||||
nubes_endpoint = "https://deck-test.ngcloud.ru/api/v1"
|
||||
|
||||
pg_dsn = "postgres://sless:sless-pg-password@postgres.sless.svc.cluster.local:5432/sless?sslmode=disable"
|
||||
rabbitmq_url = "amqp://sless:sless123@rabbitmq.sless.svc.cluster.local:5672/"
|
||||
|
||||
writer_message = "writer-default-v1"
|
||||
@@ -0,0 +1,38 @@
|
||||
# 2026-03-14
|
||||
# Переменные для demo-managed-functions.
|
||||
|
||||
variable "token" {
|
||||
description = "JWT токен API"
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "sless_endpoint" {
|
||||
description = "Endpoint sless API"
|
||||
type = string
|
||||
default = "http://sless-api.185.247.187.147.nip.io"
|
||||
}
|
||||
|
||||
variable "nubes_endpoint" {
|
||||
description = "Nubes endpoint (нужен провайдеру)"
|
||||
type = string
|
||||
default = "https://deck-test.ngcloud.ru/api/v1"
|
||||
}
|
||||
|
||||
variable "pg_dsn" {
|
||||
description = "PostgreSQL DSN для функций"
|
||||
type = string
|
||||
default = "postgres://sless:sless-pg-password@postgres.sless.svc.cluster.local:5432/sless?sslmode=disable"
|
||||
}
|
||||
|
||||
variable "rabbitmq_url" {
|
||||
description = "RabbitMQ URL для функций"
|
||||
type = string
|
||||
default = "amqp://sless:sless123@rabbitmq.sless.svc.cluster.local:5672/"
|
||||
}
|
||||
|
||||
variable "writer_message" {
|
||||
description = "Сообщение по умолчанию, которое пишет event-writer"
|
||||
type = string
|
||||
default = "writer-default-v1"
|
||||
}
|
||||
@@ -121,8 +121,10 @@ func main() {
|
||||
// Builder использует k8s client из manager'а
|
||||
// harborClient — nil если HARBOR_USER/HARBOR_PASS не заданы (EnsureProject пропускается).
|
||||
var harborClient *harbor.Client
|
||||
var harborProjecter builder.Projecter
|
||||
if cfg.HarborUser != "" && cfg.HarborPass != "" {
|
||||
harborClient = harbor.New(cfg.RegistryHost, cfg.HarborUser, cfg.HarborPass)
|
||||
harborProjecter = harborClient
|
||||
log.Info("harbor client configured", "host", cfg.RegistryHost)
|
||||
} else {
|
||||
log.Info("harbor client disabled (HARBOR_USER/HARBOR_PASS not set)")
|
||||
@@ -137,7 +139,7 @@ func main() {
|
||||
S3SecretKey: cfg.S3SecretKey,
|
||||
S3Bucket: cfg.S3Bucket,
|
||||
Namespace: "sless",
|
||||
HarborClient: harborClient,
|
||||
HarborClient: harborProjecter,
|
||||
})
|
||||
|
||||
if err = (&controllers.FunctionReconciler{
|
||||
|
||||
Reference in New Issue
Block a user