149 lines
4.6 KiB
Go
149 lines
4.6 KiB
Go
// ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (оператор, CRD-контроллер). В новой архитектуре не используется.
|
|
// Актуальное: HISTORY/2026-08-16-session-log.md
|
|
|
|
// Создано: 2026-04-12
|
|
// main.go — точка входа IoT managed service.
|
|
// Запускает controller-manager (IoTDevice CRD) и REST API сервер (порт 9090) в одном процессе.
|
|
// Перенесено из sless/main.go — только IoT-специфичная часть.
|
|
//
|
|
// Компоненты:
|
|
// 1. Controller-Manager (controller-runtime) — reconcile IoTDevice CRD
|
|
// 2. REST API Server (gorilla/mux) — CRUD устройств, телеметрия, MQTT auth, admin
|
|
//
|
|
// Конфигурация через env vars:
|
|
// IOT_PG_DSN — DSN для IoT Postgres (опционально)
|
|
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log/slog"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
"time"
|
|
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
|
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
|
ctrl "sigs.k8s.io/controller-runtime"
|
|
"sigs.k8s.io/controller-runtime/pkg/healthz"
|
|
"sigs.k8s.io/controller-runtime/pkg/log/zap"
|
|
|
|
iotv1alpha1 "gitea.services.ngcloud.ru/Nail/IoT/api/v1alpha1"
|
|
iotcontrollers "gitea.services.ngcloud.ru/Nail/IoT/controllers"
|
|
iotapi "gitea.services.ngcloud.ru/Nail/IoT/internal/api"
|
|
"gitea.services.ngcloud.ru/Nail/IoT/internal/api/handler"
|
|
"gitea.services.ngcloud.ru/Nail/IoT/internal/storage/iotpg"
|
|
)
|
|
|
|
var scheme = runtime.NewScheme()
|
|
|
|
func init() {
|
|
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
|
|
// IoT API group iot.kube5s.ru/v1alpha1
|
|
utilruntime.Must(iotv1alpha1.AddToScheme(scheme))
|
|
}
|
|
|
|
func main() {
|
|
log := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}))
|
|
ctrl.SetLogger(zap.New(zap.UseDevMode(true)))
|
|
|
|
log.Info("starting IoT managed service operator")
|
|
|
|
// Controller Manager — управляет reconcile loop для IoTDevice CRD
|
|
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
|
|
Scheme: scheme,
|
|
HealthProbeBindAddress: ":8081",
|
|
LeaderElection: false,
|
|
})
|
|
if err != nil {
|
|
log.Error("unable to create controller manager", "err", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Регистрируем IoTDevice controller
|
|
if err = (&iotcontrollers.IoTDeviceReconciler{
|
|
Client: mgr.GetClient(),
|
|
Scheme: mgr.GetScheme(),
|
|
}).SetupWithManager(mgr); err != nil {
|
|
log.Error("unable to create IoTDevice controller", "err", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Health/ready пробы для k8s
|
|
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
|
|
log.Error("unable to set up health check", "err", err)
|
|
os.Exit(1)
|
|
}
|
|
if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil {
|
|
log.Error("unable to set up ready check", "err", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// IoT Postgres — опционален (если IOT_PG_DSN не задан — телеметрия отключена)
|
|
iotPGStore, err := iotpg.NewFromEnv(log)
|
|
if err != nil {
|
|
log.Error("failed to init IoT Postgres", "err", err)
|
|
os.Exit(1)
|
|
}
|
|
if iotPGStore != nil {
|
|
defer iotPGStore.Close()
|
|
}
|
|
|
|
// REST API handler
|
|
h := &handler.Handler{
|
|
K8s: mgr.GetClient(),
|
|
Scheme: mgr.GetScheme(),
|
|
IoTPG: iotPGStore,
|
|
Log: log,
|
|
BridgeUsername: os.Getenv("MQTT_BRIDGE_USERNAME"),
|
|
BridgePassword: os.Getenv("MQTT_BRIDGE_PASSWORD"),
|
|
}
|
|
|
|
router := iotapi.NewRouter(h, log)
|
|
|
|
// HTTP API сервер на порту 9090
|
|
apiServer := &http.Server{
|
|
Addr: ":9090",
|
|
Handler: router,
|
|
ReadTimeout: 30 * time.Second,
|
|
WriteTimeout: 60 * time.Second,
|
|
}
|
|
|
|
// Запускаем API сервер в горутине
|
|
go func() {
|
|
log.Info("starting REST API server", "addr", ":9090")
|
|
if err := apiServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
log.Error("API server failed", "err", err)
|
|
os.Exit(1)
|
|
}
|
|
}()
|
|
|
|
// Graceful shutdown
|
|
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGTERM, syscall.SIGINT)
|
|
defer cancel()
|
|
|
|
// Запускаем controller-manager (блокирует до ctx.Done)
|
|
go func() {
|
|
log.Info("starting controller manager")
|
|
if err := mgr.Start(ctx); err != nil {
|
|
log.Error("controller manager failed", "err", err)
|
|
os.Exit(1)
|
|
}
|
|
}()
|
|
|
|
<-ctx.Done()
|
|
log.Info("shutting down IoT operator")
|
|
|
|
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer shutdownCancel()
|
|
if err := apiServer.Shutdown(shutdownCtx); err != nil {
|
|
log.Error("API server shutdown error", "err", err)
|
|
}
|
|
|
|
fmt.Println("IoT operator stopped")
|
|
}
|