From aaa1b9a82dc7976a84552524fe69be4efdc9e668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Sun, 10 May 2026 08:26:42 +0400 Subject: [PATCH] =?UTF-8?q?feat:=20billing=20layer=20v1.3.86=20=E2=80=94?= =?UTF-8?q?=20PostgreSQL=20statistics?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - internal/billing: Store interface + pgStore (pgx/v5 pool) + NoopStore - factory.go: NewStore() from BILLING_DSN env var (NoopStore fallback) - Server.billing: injected into Config, initialized in main - handleInvokeFunction: record invocation (TriggerConsole) - invokeInternalFunction: record invocation (TriggerHTTP) - handleCreateFunction: record event_type=create - handleCloneFunction: record event_type=clone - handleDeleteFunction: record event_type=delete - table: invocations (namespace, function_name, trigger_type, duration_ms, status_code...) - BILLING_DSN added to console.yaml - pgx/v5 added to go.mod/go.sum --- console/cmd/server/main.go | 4 ++ console/deploy/console.yaml | 4 +- console/go.mod | 5 ++ console/go.sum | 11 +++ console/internal/api/function_clone.go | 11 +++ console/internal/api/function_code.go | 11 +++ console/internal/api/function_crud.go | 11 +++ console/internal/api/function_invoke.go | 39 ++++++++++- console/internal/api/server.go | 6 ++ console/internal/billing/billing.go | 42 ++++++++++++ console/internal/billing/factory.go | 23 +++++++ console/internal/billing/noop.go | 8 +++ console/internal/billing/pg.go | 90 +++++++++++++++++++++++++ console/ui/index.html | 4 +- token.txt | 64 +++++++++++++++++- 15 files changed, 327 insertions(+), 6 deletions(-) create mode 100644 console/internal/billing/billing.go create mode 100644 console/internal/billing/factory.go create mode 100644 console/internal/billing/noop.go create mode 100644 console/internal/billing/pg.go diff --git a/console/cmd/server/main.go b/console/cmd/server/main.go index 7afae4a..7579d33 100644 --- a/console/cmd/server/main.go +++ b/console/cmd/server/main.go @@ -12,6 +12,7 @@ import ( "fission-console/internal/api" "fission-console/internal/auth" + "fission-console/internal/billing" "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" @@ -48,6 +49,8 @@ func main() { Demo: &auth.DemoAuthenticator{}, } + billingStore := billing.NewStore() + srv := api.NewServer(api.Config{ Dyn: dyn, Kube: kube, @@ -64,6 +67,7 @@ func main() { LLMUrl: envDefault("FISSION_LLM_URL", "https://api.aillm.ru"), LLMKey: os.Getenv("FISSION_LLM_KEY"), // --- end ai/ask feature --- + Billing: billingStore, }) // Запускаем фоновые горутины: reaper истёкших функций diff --git a/console/deploy/console.yaml b/console/deploy/console.yaml index 7894314..ff59969 100644 --- a/console/deploy/console.yaml +++ b/console/deploy/console.yaml @@ -55,7 +55,7 @@ spec: serviceAccountName: fission-console containers: - name: console - image: naeel/fission-console:v1.3.85 + image: naeel/fission-console:v1.3.86 imagePullPolicy: Always ports: - containerPort: 8090 @@ -82,6 +82,8 @@ spec: key: password - name: FISSION_STORAGESVC_URL value: "http://storagesvc.fission.svc.cluster.local" + - name: BILLING_DSN + value: "postgres://super:BQUF5ruECa1ZFlq4wYt3gPJUEmtBMkA9QNK4MM5Sd8al4ArMDlmT16DIKHYBPyif@postgresqlk8s-master.dc5db45d-f8b4-4fd0-ad33-ec4dd017f2d5.svc.cluster.local:5432/sqsdb" livenessProbe: httpGet: path: /health diff --git a/console/go.mod b/console/go.mod index 842e855..0ed6ced 100644 --- a/console/go.mod +++ b/console/go.mod @@ -20,6 +20,10 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/google/gnostic-models v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect + github.com/jackc/pgx/v5 v5.9.2 // indirect + github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/mailru/easyjson v0.7.7 // indirect @@ -32,6 +36,7 @@ require ( go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/sync v0.18.0 // indirect golang.org/x/sys v0.38.0 // indirect golang.org/x/term v0.37.0 // indirect golang.org/x/text v0.31.0 // indirect diff --git a/console/go.sum b/console/go.sum index 778ac55..7a99a78 100644 --- a/console/go.sum +++ b/console/go.sum @@ -29,6 +29,14 @@ github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgY github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.9.2 h1:3ZhOzMWnR4yJ+RW1XImIPsD1aNSz4T4fyP7zlQb56hw= +github.com/jackc/pgx/v5 v5.9.2/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4= +github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= +github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -70,6 +78,7 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= @@ -99,6 +108,8 @@ golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKl golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/console/internal/api/function_clone.go b/console/internal/api/function_clone.go index beed743..4069a26 100644 --- a/console/internal/api/function_clone.go +++ b/console/internal/api/function_clone.go @@ -19,6 +19,7 @@ import ( "strings" "time" + "fission-console/internal/billing" "fission-console/internal/fission" "fission-console/internal/runtime" @@ -241,6 +242,16 @@ func (s *Server) handleCloneFunction(w http.ResponseWriter, r *http.Request, src return } + s.billing.RecordInvocation(billing.Invocation{ + Namespace: ns, + FunctionName: req.NewName, + TriggerType: billing.TriggerEvent, + StartedAt: now, + StatusCode: http.StatusCreated, + RecordedBy: "console", + EventType: "clone", + }) + writeAnyJSON(w, http.StatusCreated, map[string]any{ "name": req.NewName, "cloned_from": srcName, diff --git a/console/internal/api/function_code.go b/console/internal/api/function_code.go index c622c8c..91fa34a 100644 --- a/console/internal/api/function_code.go +++ b/console/internal/api/function_code.go @@ -22,6 +22,7 @@ import ( "strings" "time" + "fission-console/internal/billing" "fission-console/internal/fission" "fission-console/internal/model" "fission-console/internal/runtime" @@ -275,6 +276,16 @@ func (s *Server) handleCreateFunction(w http.ResponseWriter, r *http.Request) { return } + s.billing.RecordInvocation(billing.Invocation{ + Namespace: ns, + FunctionName: req.Name, + TriggerType: billing.TriggerEvent, + StartedAt: now, + StatusCode: http.StatusCreated, + RecordedBy: "console", + EventType: "create", + }) + writeAnyJSON(w, http.StatusCreated, map[string]any{ "name": req.Name, "package": pkgName, diff --git a/console/internal/api/function_crud.go b/console/internal/api/function_crud.go index 1a094fe..8e316b7 100644 --- a/console/internal/api/function_crud.go +++ b/console/internal/api/function_crud.go @@ -21,6 +21,7 @@ import ( "strings" "time" + "fission-console/internal/billing" "fission-console/internal/fission" corev1 "k8s.io/api/core/v1" @@ -228,6 +229,16 @@ func (s *Server) handleDeleteFunction(w http.ResponseWriter, r *http.Request, na // (reconciler NS удалён — за FISSION_RESOURCE_NAMESPACES теперь отвечает Layer 1 NSWatcher) + s.billing.RecordInvocation(billing.Invocation{ + Namespace: ns, + FunctionName: name, + TriggerType: billing.TriggerEvent, + StartedAt: time.Now(), + StatusCode: http.StatusOK, + RecordedBy: "console", + EventType: "delete", + }) + writeAnyJSON(w, http.StatusOK, map[string]any{"deleted": true, "name": name, "package": pkgName}) } diff --git a/console/internal/api/function_invoke.go b/console/internal/api/function_invoke.go index 224da47..51b0335 100644 --- a/console/internal/api/function_invoke.go +++ b/console/internal/api/function_invoke.go @@ -22,6 +22,7 @@ import ( "strings" "time" + "fission-console/internal/billing" "fission-console/internal/fission" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -202,9 +203,26 @@ func (s *Server) handleInvokeFunction(w http.ResponseWriter, r *http.Request, na defer resp.Body.Close() respBody, _ := io.ReadAll(resp.Body) + + durationMS := time.Since(start).Milliseconds() + s.billing.RecordInvocation(billing.Invocation{ + Namespace: ns, + FunctionName: name, + TriggerType: billing.TriggerConsole, + Route: invokeURL, + HTTPMethod: invokeMethod, + StartedAt: start, + DurationMS: durationMS, + StatusCode: resp.StatusCode, + RequestBytes: int64(len(bodyBytes)), + ResponseBytes: int64(len(respBody)), + RecordedBy: "console", + EventType: "invoke", + }) + writeAnyJSON(w, http.StatusOK, map[string]any{ "status": resp.StatusCode, - "latency_ms": time.Since(start).Milliseconds(), + "latency_ms": durationMS, "response_raw": string(respBody), }) } @@ -311,9 +329,26 @@ func (s *Server) invokeInternalFunction(w http.ResponseWriter, r *http.Request, defer resp.Body.Close() respBody, _ := io.ReadAll(resp.Body) + + durationMS := time.Since(start).Milliseconds() + s.billing.RecordInvocation(billing.Invocation{ + Namespace: namespace, + FunctionName: functionName, + TriggerType: billing.TriggerHTTP, + Route: extraPath, + HTTPMethod: r.Method, + StartedAt: start, + DurationMS: durationMS, + StatusCode: resp.StatusCode, + RequestBytes: int64(len(bodyBytes)), + ResponseBytes: int64(len(respBody)), + RecordedBy: "console", + EventType: "invoke", + }) + writeAnyJSON(w, http.StatusOK, map[string]any{ "status": resp.StatusCode, - "latency_ms": time.Since(start).Milliseconds(), + "latency_ms": durationMS, "response_raw": string(respBody), }) } diff --git a/console/internal/api/server.go b/console/internal/api/server.go index 1f69533..77eed0f 100644 --- a/console/internal/api/server.go +++ b/console/internal/api/server.go @@ -13,6 +13,7 @@ import ( "time" "fission-console/internal/auth" + "fission-console/internal/billing" "fission-console/internal/cloud" "fission-console/internal/fission" "fission-console/ui" @@ -59,6 +60,9 @@ type Server struct { // nsManager управляет жизненным циклом пользовательских namespace-ов. nsManager *cloud.NSManager + + // billing — слой записи статистики вызовов. NoopStore если BILLING_DSN не задан. + billing billing.Store } // Config содержит все параметры для создания Server. @@ -76,6 +80,7 @@ type Config struct { Authenticator auth.Authenticator // слой аутентификации LLMUrl string LLMKey string + Billing billing.Store // слой статистики (NoopStore если не задан) } // NewServer создаёт и настраивает HTTP Server со всеми зависимостями. @@ -96,6 +101,7 @@ func NewServer(cfg Config) *Server { llmURL: cfg.LLMUrl, llmKey: cfg.LLMKey, nsManager: cloud.NewNSManager(cfg.Dyn), + billing: cfg.Billing, } } diff --git a/console/internal/billing/billing.go b/console/internal/billing/billing.go new file mode 100644 index 0000000..d727d68 --- /dev/null +++ b/console/internal/billing/billing.go @@ -0,0 +1,42 @@ +// Package billing — слой записи статистики вызовов функций. +// +// Независим от типа БД: снаружи виден только интерфейс Store. +// Если BILLING_DSN не задан — работает NoopStore (тихо, не крашит). +package billing + +import "time" + +// TriggerType описывает источник вызова. +const ( + TriggerHTTP = "http" // вызов через /fn/... снаружи + TriggerCron = "cron" // вызов по расписанию + TriggerConsole = "console" // вызов через кнопку «Вызов» в UI + TriggerEvent = "event" // lifecycle: create/delete/clone/update +) + +// Invocation — одна запись о вызове или событии функции. +type Invocation struct { + Namespace string // пользовательский namespace (= пользователь) + FunctionName string // имя функции + TriggerType string // TriggerHTTP / TriggerCron / TriggerConsole / TriggerEvent + Route string // HTTP маршрут (/abc123/my-func), пусто для event + HTTPMethod string // GET/POST/... пусто для event + StartedAt time.Time // время начала + DurationMS int64 // длительность в миллисекундах (0 для event) + StatusCode int // HTTP статус ответа (0 для event) + ColdStart bool // true = первый вызов после создания/простоя + RequestBytes int64 // размер тела запроса + ResponseBytes int64 // размер тела ответа + ErrorMsg string // сообщение об ошибке, пусто если успех + RecordedBy string // "console" | "router" + EventType string // для TriggerEvent: "create" | "delete" | "clone" | "update" | "invoke" +} + +// Store — интерфейс записи статистики. +// Реализации: pgStore (PostgreSQL через pgx), NoopStore (заглушка). +type Store interface { + // RecordInvocation записывает одно событие асинхронно (fire-and-forget). + RecordInvocation(inv Invocation) + // Close освобождает ресурсы (пул соединений и т.д.). + Close() +} diff --git a/console/internal/billing/factory.go b/console/internal/billing/factory.go new file mode 100644 index 0000000..dfe7976 --- /dev/null +++ b/console/internal/billing/factory.go @@ -0,0 +1,23 @@ +package billing + +import ( + "context" + "log" + "os" +) + +// NewStore создаёт Store из переменной окружения BILLING_DSN. +// Если DSN пустой — возвращает NoopStore (статистика отключена, сервер работает нормально). +func NewStore() Store { + dsn := os.Getenv("BILLING_DSN") + if dsn == "" { + log.Printf("billing: BILLING_DSN not set, statistics disabled") + return NoopStore{} + } + store, err := NewPostgresStore(context.Background(), dsn) + if err != nil { + log.Printf("billing: failed to connect to PostgreSQL: %v — statistics disabled", err) + return NoopStore{} + } + return store +} diff --git a/console/internal/billing/noop.go b/console/internal/billing/noop.go new file mode 100644 index 0000000..c9980e1 --- /dev/null +++ b/console/internal/billing/noop.go @@ -0,0 +1,8 @@ +package billing + +// NoopStore — заглушка Store, которая тихо игнорирует все записи. +// Используется когда BILLING_DSN не задан. +type NoopStore struct{} + +func (NoopStore) RecordInvocation(_ Invocation) {} +func (NoopStore) Close() {} diff --git a/console/internal/billing/pg.go b/console/internal/billing/pg.go new file mode 100644 index 0000000..cdd19ea --- /dev/null +++ b/console/internal/billing/pg.go @@ -0,0 +1,90 @@ +package billing + +import ( + "context" + "log" + "time" + + "github.com/jackc/pgx/v5/pgxpool" +) + +// pgStore — реализация Store поверх PostgreSQL через pgx connection pool. +type pgStore struct { + pool *pgxpool.Pool +} + +// NewPostgresStore создаёт Store с пулом соединений к PostgreSQL. +// dsn — строка вида postgres://user:pass@host:5432/dbname +// При ошибке подключения — возвращает ошибку, вызывающий код решает как реагировать. +func NewPostgresStore(ctx context.Context, dsn string) (Store, error) { + cfg, err := pgxpool.ParseConfig(dsn) + if err != nil { + return nil, err + } + cfg.MaxConns = 4 + cfg.MinConns = 1 + cfg.MaxConnIdleTime = 5 * time.Minute + + pool, err := pgxpool.NewWithConfig(ctx, cfg) + if err != nil { + return nil, err + } + // Проверяем живость соединения + if err := pool.Ping(ctx); err != nil { + pool.Close() + return nil, err + } + log.Printf("billing: connected to PostgreSQL") + return &pgStore{pool: pool}, nil +} + +// RecordInvocation вставляет запись асинхронно — не блокирует основной поток. +func (s *pgStore) RecordInvocation(inv Invocation) { + go func() { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + _, err := s.pool.Exec(ctx, ` + INSERT INTO invocations ( + namespace, function_name, trigger_type, route, http_method, + started_at, duration_ms, status_code, cold_start, + request_bytes, response_bytes, error_msg, recorded_by, event_type + ) VALUES ( + $1,$2,$3,$4,$5, + $6,$7,$8,$9, + $10,$11,$12,$13,$14 + )`, + inv.Namespace, + inv.FunctionName, + inv.TriggerType, + inv.Route, + inv.HTTPMethod, + inv.StartedAt, + inv.DurationMS, + inv.StatusCode, + inv.ColdStart, + inv.RequestBytes, + inv.ResponseBytes, + nullIfEmpty(inv.ErrorMsg), + inv.RecordedBy, + nullIfEmpty(inv.EventType), + ) + if err != nil { + log.Printf("billing: insert invocation: %v", err) + } + }() +} + +// Close закрывает пул соединений. +func (s *pgStore) Close() { + s.pool.Close() + log.Printf("billing: connection pool closed") +} + +// nullIfEmpty возвращает nil для пустой строки (SQL NULL вместо пустой строки). +func nullIfEmpty(s string) interface{} { + if s == "" { + return nil + } + return s +} diff --git a/console/ui/index.html b/console/ui/index.html index e941ee4..b0972c0 100644 --- a/console/ui/index.html +++ b/console/ui/index.html @@ -102,7 +102,7 @@
NUBES
FISSION CONSOLE
-
v1.3.85
+
v1.3.86
@@ -542,7 +542,7 @@
- v1.3.85 + v1.3.86
diff --git a/token.txt b/token.txt index 723e905..9bf6c95 100644 --- a/token.txt +++ b/token.txt @@ -1,4 +1,66 @@ ntazetdinov@nubes.ru stxVxLvM9eqssgZ -eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoLWFwaSIsInN1YiI6IjAxOWQ3NmM1LTQyNGMtN2MyYy04OWI3LWUzZjA5OTQ5YTk4ZiIsImV4cCI6MTc5MzA3ODQzOSwiaWF0IjoxNzc3NTI2NDM5LCJqdGkiOiI4MTU1ODNkNy0xZTRkLTRiMmMtOGM5ZS0wZDZmMGU2NmJjNTciLCJhdXRoX3RpbWUiOjAsInR5cCI6IiIsImF6cCI6IiIsInNlc3Npb25fc3RhdGUiOiIiLCJhY3IiOiIiLCJhbGxvd2VkLW9yaWdpbnMiOm51bGwsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6bnVsbH0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpudWxsfX0sInNjb3BlIjoiIiwic2lkIjoiIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoiIiwiQ2xpZW50SUQiOiJXWjAxMTEyIiwiY29tcGFueV9pZCI6IjhlYzcwYWMwLTU0NmQtNDJhNy04Y2ZmLTMzOWM4ZmI1MWEyMyIsImNvbXBhbnlfbmFtZSI6ItCe0J7QniDCq9Cd0KPQkdCV0KHCuyIsImlkcF91c3JfdWlkIjoiMDE5ZDc2YzUtNDI0Yy03YzJjLTg5YjctZTNmMDk5NDlhOThmIiwibG9naW4iOiJudGF6ZXRkaW5vdkBudWJlcy5ydSIsImZpcnN0bmFtZSI6ItCd0LDQuNC70YwiLCJtaWRkbGVuYW1lIjoi0KTQsNGA0LjRgtC-0LLQuNGHIiwibGFzdG5hbWUiOiLQotCw0LfQtdGC0LTQuNC90L7QsiIsImdyb3VwcyI6bnVsbCwicHJlZmVycmVkX3VzZXJuYW1lIjoiIiwiZ2l2ZW5fbmFtZSI6IiIsImZhbWlseV9uYW1lIjoiIiwiZW1haWwiOiJudGF6ZXRkaW5vdkBudWJlcy5ydSJ9.SaZsKAha45-fvKuJkLHUe_09AFsbH5QpzBVdPnjiEDQGIhl1A3ThgnM-oEh_H6CBXXfnOs2QDczzgCD8K8_tYzZKU1Wgk5lj04YW_fbTI89kHTO5wLtrAht9tFEjzBQZ-kmnG8mUK5tgqyNEjsngdQcfqVWRvneF366TiiRXk_76poUPpXWQmqdgCCKb3wq1rRgWcKDZcUC3JvDpOaqYL40zITZlM855drlJhMut4Gkg-EEk7ZGykl6YCsTRWVjFKGQ-7C-BDU2dkmIWhxzBAkvzzM2kBwvtlczCEDiUin7bXE-F_io89oJUYDzY4yPeHzwREwxCp6x9eD1NAIKKuA \ No newline at end of file +eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhdXRoLWFwaSIsInN1YiI6IjAxOWQ3NmM1LTQyNGMtN2MyYy04OWI3LWUzZjA5OTQ5YTk4ZiIsImV4cCI6MTc5MzA3ODQzOSwiaWF0IjoxNzc3NTI2NDM5LCJqdGkiOiI4MTU1ODNkNy0xZTRkLTRiMmMtOGM5ZS0wZDZmMGU2NmJjNTciLCJhdXRoX3RpbWUiOjAsInR5cCI6IiIsImF6cCI6IiIsInNlc3Npb25fc3RhdGUiOiIiLCJhY3IiOiIiLCJhbGxvd2VkLW9yaWdpbnMiOm51bGwsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6bnVsbH0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpudWxsfX0sInNjb3BlIjoiIiwic2lkIjoiIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoiIiwiQ2xpZW50SUQiOiJXWjAxMTEyIiwiY29tcGFueV9pZCI6IjhlYzcwYWMwLTU0NmQtNDJhNy04Y2ZmLTMzOWM4ZmI1MWEyMyIsImNvbXBhbnlfbmFtZSI6ItCe0J7QniDCq9Cd0KPQkdCV0KHCuyIsImlkcF91c3JfdWlkIjoiMDE5ZDc2YzUtNDI0Yy03YzJjLTg5YjctZTNmMDk5NDlhOThmIiwibG9naW4iOiJudGF6ZXRkaW5vdkBudWJlcy5ydSIsImZpcnN0bmFtZSI6ItCd0LDQuNC70YwiLCJtaWRkbGVuYW1lIjoi0KTQsNGA0LjRgtC-0LLQuNGHIiwibGFzdG5hbWUiOiLQotCw0LfQtdGC0LTQuNC90L7QsiIsImdyb3VwcyI6bnVsbCwicHJlZmVycmVkX3VzZXJuYW1lIjoiIiwiZ2l2ZW5fbmFtZSI6IiIsImZhbWlseV9uYW1lIjoiIiwiZW1haWwiOiJudGF6ZXRkaW5vdkBudWJlcy5ydSJ9.SaZsKAha45-fvKuJkLHUe_09AFsbH5QpzBVdPnjiEDQGIhl1A3ThgnM-oEh_H6CBXXfnOs2QDczzgCD8K8_tYzZKU1Wgk5lj04YW_fbTI89kHTO5wLtrAht9tFEjzBQZ-kmnG8mUK5tgqyNEjsngdQcfqVWRvneF366TiiRXk_76poUPpXWQmqdgCCKb3wq1rRgWcKDZcUC3JvDpOaqYL40zITZlM855drlJhMut4Gkg-EEk7ZGykl6YCsTRWVjFKGQ-7C-BDU2dkmIWhxzBAkvzzM2kBwvtlczCEDiUin7bXE-F_io89oJUYDzY4yPeHzwREwxCp6x9eD1NAIKKuA + +----------- token on VM -------------- +https://deck-api-test.ngcloud.ru/api/v1 - для тест стенда где постгрес, файл с токеном - +naeel@naeel-vm:~/terra/sless$ ll test.token +-rw-r--r-- 1 naeel naeel 998 Feb 28 07:18 test.token + +--------------------- pg IoT-PG ----------------------- +users +JSON объект (раскройте для просмотра) + +password: +BQUF5ruECa1ZFlq4wYt3gPJUEmtBMkA9QNK4MM5Sd8al4ArMDlmT16DIKHYBPyif + +username: +super + +Поля состояния (сгенерированные значения) +monitoring +{ + "resourceMetrics": "https://grafana.ngcloud.ru/d/vzjb4zd/kubernetes-pods?orgId=954&var-namespace=dc5db45d-f8b4-4fd0-ad33-ec4dd017f2d5&var-resource_realm=iot-naeel" +} + +users +{ + "super": { + "role": "ddl_user", + "username": "super" + } +} + +backups +{} + +databases +{ + "sqsdb": { + "dbName": "sqsdb", + "dbOwner": "super" + } +} + +externalConnect +{ + "slave": { + "ip": "", + "fqdn": "", + "uuid": "", + "isExternal": false + }, + "master": { + "ip": "", + "fqdn": "", + "uuid": "", + "isExternal": false + } +} + +internalConnect +{ + "slave": "", + "master": "postgresqlk8s-master.dc5db45d-f8b4-4fd0-ad33-ec4dd017f2d5.svc.cluster.local" +} \ No newline at end of file