mirror of
https://github.com/lorsanstand/HomeOps-Hub.git
synced 2026-06-19 14:25:16 +03:00
refactor: change structure project
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/lorsanstand/HomeOps-Hub/hub/internal/app"
|
||||
)
|
||||
|
||||
func main() {
|
||||
start := app.NewApp()
|
||||
|
||||
start.Run()
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
standartlog "log"
|
||||
"net"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
hubdir "github.com/lorsanstand/HomeOps-Hub/hub/internal"
|
||||
"github.com/lorsanstand/HomeOps-Hub/hub/internal/migrator"
|
||||
grpcserv "github.com/lorsanstand/HomeOps-Hub/hub/internal/rpc"
|
||||
"github.com/lorsanstand/HomeOps-Hub/hub/internal/service/hub_service"
|
||||
"github.com/lorsanstand/HomeOps-Hub/hub/internal/store"
|
||||
"github.com/lorsanstand/HomeOps-Hub/shared/config"
|
||||
"github.com/lorsanstand/HomeOps-Hub/shared/log"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type App struct {
|
||||
cfg *config.Config
|
||||
log zerolog.Logger
|
||||
}
|
||||
|
||||
func NewApp() *App {
|
||||
cfg, err := config.NewConfig()
|
||||
if err != nil {
|
||||
standartlog.Fatalf("failed get config: %v", err)
|
||||
}
|
||||
|
||||
logger := log.NewLogger(cfg)
|
||||
|
||||
return &App{cfg: cfg, log: logger}
|
||||
}
|
||||
|
||||
func (a *App) Run() {
|
||||
ctx := context.Background()
|
||||
a.log.Info().Str("host", a.cfg.DBHost).Int("port", a.cfg.DBPort).Msg("connecting to database")
|
||||
migratePGConn, err := sql.Open("pgx", a.cfg.GetURLPostgres())
|
||||
if err != nil {
|
||||
a.log.Error().Err(err).Msg("failed to connect to the database for migrations")
|
||||
return
|
||||
}
|
||||
defer migratePGConn.Close()
|
||||
|
||||
mgrt, err := migrator.NewMigrator(hubdir.MigrationsFS, "migrations")
|
||||
if err != nil {
|
||||
a.log.Error().Err(err).Msg("failed to create migrator")
|
||||
return
|
||||
}
|
||||
|
||||
a.log.Info().Msg("applying database migrations")
|
||||
if err = mgrt.ApplyMigrations(migratePGConn); err != nil {
|
||||
a.log.Error().Err(err).Msg("migrations failed to apply")
|
||||
return
|
||||
}
|
||||
a.log.Info().Msg("migrations applied successfully")
|
||||
migratePGConn.Close()
|
||||
|
||||
a.log.Info().Msg("creating database connection pool")
|
||||
pool, err := pgxpool.New(ctx, a.cfg.GetURLPostgres())
|
||||
if err != nil {
|
||||
a.log.Error().Err(err).Msg("failed to create database connection pool")
|
||||
return
|
||||
}
|
||||
defer pool.Close()
|
||||
a.log.Info().Msg("database connection pool created")
|
||||
|
||||
hubStore := store.NewHubStore(pool)
|
||||
hubService := hub_service.NewHubService(hubStore, a.log)
|
||||
|
||||
a.log.Info().Msg("starting hub service")
|
||||
err = a.hubServe(hubService)
|
||||
if err != nil {
|
||||
a.log.Error().Err(err).Msg("hub service failed to start")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) hubServe(hubService *hub_service.HubService) error {
|
||||
address := fmt.Sprintf("0.0.0.0:%v", a.cfg.Port)
|
||||
a.log.Info().Str("address", address).Msg("starting gRPC server")
|
||||
|
||||
server := grpcserv.NewHubHandler(hubService, a.log)
|
||||
|
||||
lis, err := net.Listen("tcp", address)
|
||||
if err != nil {
|
||||
a.log.Error().Err(err).Str("address", address).Msg("failed to listen on address")
|
||||
return err
|
||||
}
|
||||
a.log.Info().Str("address", address).Msg("listening on address")
|
||||
|
||||
a.log.Info().Msg("gRPC server is running")
|
||||
err = server.GrpcServer.Serve(lis)
|
||||
if err != nil {
|
||||
a.log.Error().Err(err).Msg("gRPC server error")
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/lorsanstand/HomeOps-Hub/shared/domain"
|
||||
)
|
||||
|
||||
type CreateAgentModel struct {
|
||||
AgentID string
|
||||
AgentName string
|
||||
Architecture string
|
||||
System string
|
||||
Hostname string
|
||||
Version string
|
||||
Capabilities []domain.Capability
|
||||
}
|
||||
|
||||
type AgentModel struct {
|
||||
ID int
|
||||
AgentID string
|
||||
AgentName string
|
||||
Architecture string
|
||||
System string
|
||||
Hostname string
|
||||
Version string
|
||||
Capabilities []domain.Capability
|
||||
RegisteredAt time.Time
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package internal
|
||||
|
||||
import "embed"
|
||||
|
||||
//go:embed migrations/*.sql
|
||||
var MigrationsFS embed.FS
|
||||
@@ -0,0 +1,4 @@
|
||||
DROP INDEX idx_agent_id_id;
|
||||
DROP INDEX idx_agent_id;
|
||||
|
||||
DROP TABLE agents IF EXISTS agents;
|
||||
@@ -0,0 +1,14 @@
|
||||
CREATE TABLE agents (
|
||||
id SERIAL PRIMARY KEY,
|
||||
agent_id VARCHAR(32) UNIQUE NOT NULL,
|
||||
agent_name VARCHAR(255),
|
||||
architecture VARCHAR(10) NOT NULL,
|
||||
system VARCHAR(10) NOT NULL,
|
||||
hostname VARCHAR(100) NOT NULL,
|
||||
version VARCHAR(10) NOT NULL,
|
||||
capabilities JSON,
|
||||
registered_at timestamp without time zone DEFAULT now() NOT NULL
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX idx_agent_id ON agents (id);
|
||||
CREATE UNIQUE INDEX idx_agent_id_id On agents (agent_id)
|
||||
@@ -0,0 +1,47 @@
|
||||
package migrator
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
_ "github.com/jackc/pgx/v5/stdlib"
|
||||
|
||||
"github.com/golang-migrate/migrate/v4"
|
||||
"github.com/golang-migrate/migrate/v4/database/postgres"
|
||||
"github.com/golang-migrate/migrate/v4/source"
|
||||
"github.com/golang-migrate/migrate/v4/source/iofs"
|
||||
)
|
||||
|
||||
type Migrator struct {
|
||||
srcDriver source.Driver
|
||||
}
|
||||
|
||||
func NewMigrator(sqlFiles embed.FS, dirname string) (*Migrator, error) {
|
||||
d, err := iofs.New(sqlFiles, dirname)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to initialize migration driver: %w", err)
|
||||
}
|
||||
return &Migrator{srcDriver: d}, nil
|
||||
}
|
||||
|
||||
func (m *Migrator) ApplyMigrations(db *sql.DB) error {
|
||||
driver, err := postgres.WithInstance(db, &postgres.Config{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create db instance: %w", err)
|
||||
}
|
||||
|
||||
migrator, err := migrate.NewWithInstance("migration_embeded_sql_files", m.srcDriver, "psql_db", driver)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create migration: %w", err)
|
||||
}
|
||||
|
||||
defer migrator.Close()
|
||||
|
||||
if err = migrator.Up(); err != nil && !errors.Is(err, migrate.ErrNoChange) {
|
||||
return fmt.Errorf("unable to apply migrations: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package rpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
pb "github.com/lorsanstand/HomeOps-Hub/api/gen/homeops"
|
||||
"github.com/lorsanstand/HomeOps-Hub/shared/domain"
|
||||
"github.com/rs/zerolog"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
)
|
||||
|
||||
type HubService interface {
|
||||
RegisterAgent(ctx context.Context, data domain.RegisterAgentRequest) (domain.RegisterAgentResponse, error)
|
||||
}
|
||||
|
||||
type HubHandler struct {
|
||||
pb.UnimplementedHubServer
|
||||
log zerolog.Logger
|
||||
GrpcServer *grpc.Server
|
||||
hub HubService
|
||||
}
|
||||
|
||||
func NewHubHandler(HubServ HubService, logger zerolog.Logger) *HubHandler {
|
||||
hub := &HubHandler{log: logger, hub: HubServ}
|
||||
|
||||
grpcServer := grpc.NewServer()
|
||||
pb.RegisterHubServer(grpcServer, hub)
|
||||
|
||||
hub.GrpcServer = grpcServer
|
||||
|
||||
return hub
|
||||
}
|
||||
|
||||
func (h *HubHandler) Ping(ctx context.Context, _ *emptypb.Empty) (*pb.PongResponse, error) {
|
||||
h.log.Debug().Msg("ping request received")
|
||||
return &pb.PongResponse{Pong: "Pong"}, nil
|
||||
}
|
||||
|
||||
func (h *HubHandler) RegisterAgent(ctx context.Context, request *pb.RegisterAgentRequest) (*pb.RegisterAgentResponse, error) {
|
||||
h.log.Debug().Str("agentId", request.AgentId).Str("agentName", request.AgentName).Msg("register agent request received")
|
||||
data := domain.ToDomainAgentRequest(request)
|
||||
resp, err := h.hub.RegisterAgent(ctx, data)
|
||||
if err != nil {
|
||||
h.log.Error().Err(err).Str("agentId", request.AgentId).Msg("register agent request failed")
|
||||
return domain.ToGRPCAgentResponse(resp), err
|
||||
}
|
||||
h.log.Debug().Str("agentId", resp.AgentID).Msg("register agent request completed")
|
||||
return domain.ToGRPCAgentResponse(resp), nil
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package hub_service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
domainHub "github.com/lorsanstand/HomeOps-Hub/hub/internal/domain"
|
||||
"github.com/lorsanstand/HomeOps-Hub/hub/internal/utils/hasher"
|
||||
"github.com/lorsanstand/HomeOps-Hub/shared/domain"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type Store interface {
|
||||
NewAgent(ctx context.Context, agent domainHub.CreateAgentModel) error
|
||||
GetAgentByAgentID(ctx context.Context, AgentID string) (domainHub.AgentModel, error)
|
||||
UpdateAgentByID(ctx context.Context, ID int, updateAgent domainHub.CreateAgentModel) error
|
||||
}
|
||||
|
||||
type HubService struct {
|
||||
store Store
|
||||
log zerolog.Logger
|
||||
}
|
||||
|
||||
func NewHubService(store Store, logger zerolog.Logger) *HubService {
|
||||
return &HubService{log: logger, store: store}
|
||||
}
|
||||
|
||||
func (h *HubService) RegisterAgent(ctx context.Context, data domain.RegisterAgentRequest) (domain.RegisterAgentResponse, error) {
|
||||
h.log.Debug().Str("agentId", data.AgentId).Str("agentName", data.AgentName).Msg("started registering agent")
|
||||
agent, err := h.store.GetAgentByAgentID(ctx, data.AgentId)
|
||||
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||
h.log.Error().Err(err).Str("agentId", data.AgentId).Msg("failed to get agent from database")
|
||||
return domain.RegisterAgentResponse{}, fmt.Errorf("failed select agent to db: %w", err)
|
||||
}
|
||||
|
||||
if data.AgentId != "" && !errors.Is(err, sql.ErrNoRows) {
|
||||
h.log.Debug().Str("agentId", agent.AgentID).Str("agentName", data.AgentName).Msg("agent exists, updating")
|
||||
|
||||
data.AgentId = agent.AgentID
|
||||
|
||||
agentStore := toCreateAgentModel(data)
|
||||
|
||||
if err := h.store.UpdateAgentByID(ctx, agent.ID, agentStore); err != nil {
|
||||
h.log.Error().Err(err).Str("agentId", agent.AgentID).Msg("failed to update agent in database")
|
||||
return domain.RegisterAgentResponse{}, err
|
||||
}
|
||||
h.log.Info().Str("agentId", agent.AgentID).Msg("agent updated successfully")
|
||||
return domain.RegisterAgentResponse{AgentID: agent.AgentID, Heartbeat: 5}, nil
|
||||
}
|
||||
|
||||
AgentID, err := hasher.MakeID(data.Host, data.AgentName)
|
||||
if err != nil {
|
||||
h.log.Error().Err(err).Str("agentName", data.AgentName).Str("hostname", data.Host.Hostname).Msg("failed to generate agent id")
|
||||
return domain.RegisterAgentResponse{}, err
|
||||
}
|
||||
|
||||
data.AgentId = AgentID
|
||||
|
||||
agentStore := toCreateAgentModel(data)
|
||||
|
||||
if err := h.store.NewAgent(ctx, agentStore); err != nil {
|
||||
h.log.Error().Err(err).Str("agentId", AgentID).Str("agentName", data.AgentName).Msg("failed to create new agent in database")
|
||||
return domain.RegisterAgentResponse{}, err
|
||||
}
|
||||
|
||||
h.log.Info().Str("agentId", AgentID).Str("agentName", data.AgentName).Str("hostname", data.Host.Hostname).Msg("agent registered successfully")
|
||||
return domain.RegisterAgentResponse{AgentID: AgentID, Heartbeat: 5}, nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package hub_service
|
||||
|
||||
import (
|
||||
domainHub "github.com/lorsanstand/HomeOps-Hub/hub/internal/domain"
|
||||
"github.com/lorsanstand/HomeOps-Hub/shared/domain"
|
||||
)
|
||||
|
||||
func toCreateAgentModel(agent domain.RegisterAgentRequest) domainHub.CreateAgentModel {
|
||||
return domainHub.CreateAgentModel{
|
||||
AgentID: agent.AgentId,
|
||||
AgentName: agent.AgentName,
|
||||
Architecture: agent.Host.Arch,
|
||||
System: agent.Host.System,
|
||||
Hostname: agent.Host.Hostname,
|
||||
Version: agent.AgentVersion,
|
||||
Capabilities: agent.Capabilities,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
domainHub "github.com/lorsanstand/HomeOps-Hub/hub/internal/domain"
|
||||
gen2 "github.com/lorsanstand/HomeOps-Hub/hub/internal/store/sqlc/gen"
|
||||
"github.com/lorsanstand/HomeOps-Hub/shared/domain"
|
||||
)
|
||||
|
||||
func toDBAgent(agent domainHub.CreateAgentModel) gen2.CreateAgentParams {
|
||||
return gen2.CreateAgentParams{
|
||||
AgentID: agent.AgentID,
|
||||
AgentName: &agent.AgentName,
|
||||
Architecture: agent.Architecture,
|
||||
System: agent.System,
|
||||
Hostname: agent.Hostname,
|
||||
Version: agent.Version,
|
||||
Capabilities: toJsonCapabilities(agent.Capabilities),
|
||||
}
|
||||
}
|
||||
|
||||
func toUpdateDBAgent(agent domainHub.CreateAgentModel) gen2.UpdateAgentByIDParams {
|
||||
return gen2.UpdateAgentByIDParams{
|
||||
AgentID: agent.AgentID,
|
||||
AgentName: &agent.AgentName,
|
||||
Architecture: agent.Architecture,
|
||||
System: agent.System,
|
||||
Hostname: agent.Hostname,
|
||||
Version: agent.Version,
|
||||
Capabilities: toJsonCapabilities(agent.Capabilities),
|
||||
}
|
||||
}
|
||||
|
||||
func toJsonCapabilities(caps []domain.Capability) []byte {
|
||||
data, err := json.Marshal(caps)
|
||||
if err != nil {
|
||||
// Note: Error is silently handled - consider logging in production
|
||||
return []byte{}
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func toAgentModel(dbAgent gen2.Agent) domainHub.AgentModel {
|
||||
var dbAgentName string
|
||||
if dbAgent.AgentName != nil {
|
||||
dbAgentName = *dbAgent.AgentName
|
||||
}
|
||||
|
||||
return domainHub.AgentModel{
|
||||
ID: int(dbAgent.ID),
|
||||
AgentID: dbAgent.AgentID,
|
||||
AgentName: dbAgentName,
|
||||
Architecture: dbAgent.Architecture,
|
||||
System: dbAgent.System,
|
||||
Hostname: dbAgent.Hostname,
|
||||
Capabilities: toDomainCapabilities(dbAgent.Capabilities),
|
||||
}
|
||||
}
|
||||
|
||||
func toDomainCapabilities(caps []byte) []domain.Capability {
|
||||
var capabilities []domain.Capability
|
||||
err := json.Unmarshal(caps, &capabilities)
|
||||
if err != nil {
|
||||
// Note: Error is silently handled - consider logging in production
|
||||
return []domain.Capability{}
|
||||
}
|
||||
return capabilities
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: cmd.sql
|
||||
|
||||
package gen
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const createAgent = `-- name: CreateAgent :exec
|
||||
INSERT INTO agents (agent_id, agent_name, architecture, system, hostname, version, capabilities)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
`
|
||||
|
||||
type CreateAgentParams struct {
|
||||
AgentID string
|
||||
AgentName *string
|
||||
Architecture string
|
||||
System string
|
||||
Hostname string
|
||||
Version string
|
||||
Capabilities []byte
|
||||
}
|
||||
|
||||
func (q *Queries) CreateAgent(ctx context.Context, arg CreateAgentParams) error {
|
||||
_, err := q.db.Exec(ctx, createAgent,
|
||||
arg.AgentID,
|
||||
arg.AgentName,
|
||||
arg.Architecture,
|
||||
arg.System,
|
||||
arg.Hostname,
|
||||
arg.Version,
|
||||
arg.Capabilities,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const getAgentByAgentID = `-- name: GetAgentByAgentID :one
|
||||
SELECT id, agent_id, agent_name, architecture, system, hostname, version, capabilities, registered_at from agents
|
||||
WHERE agent_id=$1
|
||||
`
|
||||
|
||||
func (q *Queries) GetAgentByAgentID(ctx context.Context, agentID string) (Agent, error) {
|
||||
row := q.db.QueryRow(ctx, getAgentByAgentID, agentID)
|
||||
var i Agent
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.AgentID,
|
||||
&i.AgentName,
|
||||
&i.Architecture,
|
||||
&i.System,
|
||||
&i.Hostname,
|
||||
&i.Version,
|
||||
&i.Capabilities,
|
||||
&i.RegisteredAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getAgentByID = `-- name: GetAgentByID :one
|
||||
SELECT id, agent_id, agent_name, architecture, system, hostname, version, capabilities, registered_at from agents
|
||||
WHERE id=$1
|
||||
`
|
||||
|
||||
func (q *Queries) GetAgentByID(ctx context.Context, id int32) (Agent, error) {
|
||||
row := q.db.QueryRow(ctx, getAgentByID, id)
|
||||
var i Agent
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.AgentID,
|
||||
&i.AgentName,
|
||||
&i.Architecture,
|
||||
&i.System,
|
||||
&i.Hostname,
|
||||
&i.Version,
|
||||
&i.Capabilities,
|
||||
&i.RegisteredAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateAgentByID = `-- name: UpdateAgentByID :exec
|
||||
UPDATE agents
|
||||
SET agent_id=$1, agent_name=$2, architecture=$3, system=$4, hostname=$5, version=$6, capabilities=$7
|
||||
WHERE id=$8
|
||||
`
|
||||
|
||||
type UpdateAgentByIDParams struct {
|
||||
AgentID string
|
||||
AgentName *string
|
||||
Architecture string
|
||||
System string
|
||||
Hostname string
|
||||
Version string
|
||||
Capabilities []byte
|
||||
ID int32
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateAgentByID(ctx context.Context, arg UpdateAgentByIDParams) error {
|
||||
_, err := q.db.Exec(ctx, updateAgentByID,
|
||||
arg.AgentID,
|
||||
arg.AgentName,
|
||||
arg.Architecture,
|
||||
arg.System,
|
||||
arg.Hostname,
|
||||
arg.Version,
|
||||
arg.Capabilities,
|
||||
arg.ID,
|
||||
)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
|
||||
package gen
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
)
|
||||
|
||||
type DBTX interface {
|
||||
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
|
||||
Query(context.Context, string, ...interface{}) (pgx.Rows, error)
|
||||
QueryRow(context.Context, string, ...interface{}) pgx.Row
|
||||
}
|
||||
|
||||
func New(db DBTX) *Queries {
|
||||
return &Queries{db: db}
|
||||
}
|
||||
|
||||
type Queries struct {
|
||||
db DBTX
|
||||
}
|
||||
|
||||
func (q *Queries) WithTx(tx pgx.Tx) *Queries {
|
||||
return &Queries{
|
||||
db: tx,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
|
||||
package gen
|
||||
|
||||
import (
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
type Agent struct {
|
||||
ID int32
|
||||
AgentID string
|
||||
AgentName *string
|
||||
Architecture string
|
||||
System string
|
||||
Hostname string
|
||||
Version string
|
||||
Capabilities []byte
|
||||
RegisteredAt pgtype.Timestamp
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
-- name: CreateAgent :exec
|
||||
INSERT INTO agents (agent_id, agent_name, architecture, system, hostname, version, capabilities)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7);
|
||||
|
||||
-- name: GetAgentByID :one
|
||||
SELECT * from agents
|
||||
WHERE id=$1;
|
||||
|
||||
-- name: GetAgentByAgentID :one
|
||||
SELECT * from agents
|
||||
WHERE agent_id=$1;
|
||||
|
||||
-- name: UpdateAgentByID :exec
|
||||
UPDATE agents
|
||||
SET agent_id=$1, agent_name=$2, architecture=$3, system=$4, hostname=$5, version=$6, capabilities=$7
|
||||
WHERE id=$8;
|
||||
@@ -0,0 +1,36 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
domainHub "github.com/lorsanstand/HomeOps-Hub/hub/internal/domain"
|
||||
"github.com/lorsanstand/HomeOps-Hub/hub/internal/store/sqlc/gen"
|
||||
)
|
||||
|
||||
type HubStore struct {
|
||||
queries *gen.Queries
|
||||
}
|
||||
|
||||
func NewHubStore(db *pgxpool.Pool) *HubStore {
|
||||
queries := gen.New(db)
|
||||
return &HubStore{queries}
|
||||
}
|
||||
|
||||
func (h *HubStore) NewAgent(ctx context.Context, agent domainHub.CreateAgentModel) error {
|
||||
return h.queries.CreateAgent(ctx, toDBAgent(agent))
|
||||
}
|
||||
|
||||
func (h *HubStore) GetAgentByAgentID(ctx context.Context, AgentID string) (domainHub.AgentModel, error) {
|
||||
data, err := h.queries.GetAgentByAgentID(ctx, AgentID)
|
||||
if err != nil {
|
||||
return domainHub.AgentModel{}, err
|
||||
}
|
||||
return toAgentModel(data), nil
|
||||
}
|
||||
|
||||
func (h *HubStore) UpdateAgentByID(ctx context.Context, ID int, updateAgent domainHub.CreateAgentModel) error {
|
||||
data := toUpdateDBAgent(updateAgent)
|
||||
data.ID = int32(ID)
|
||||
return h.queries.UpdateAgentByID(ctx, data)
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package hasher
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"github.com/lorsanstand/HomeOps-Hub/shared/domain"
|
||||
)
|
||||
|
||||
func newSalt(n int) ([]byte, error) {
|
||||
b := make([]byte, n)
|
||||
_, err := rand.Read(b)
|
||||
return b, err
|
||||
}
|
||||
|
||||
func MakeID(info domain.HostInfo, AgentName string) (string, error) {
|
||||
salt, err := newSalt(10)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
s := fmt.Sprintf("v1|host=%s|distro=%s|name=%s|", info.Hostname, info.Arch, AgentName)
|
||||
h := sha256.Sum256(append([]byte(s), salt...))
|
||||
return hex.EncodeToString(h[:16]), nil
|
||||
}
|
||||
Reference in New Issue
Block a user