2023-10-12 17:23:35 +00:00
|
|
|
package config
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2023-10-17 19:58:34 +00:00
|
|
|
"log/slog"
|
2023-12-20 18:29:23 +00:00
|
|
|
"os"
|
|
|
|
"reflect"
|
2023-10-12 17:23:35 +00:00
|
|
|
"strconv"
|
2023-10-17 19:58:34 +00:00
|
|
|
"strings"
|
2023-10-12 17:23:35 +00:00
|
|
|
|
2023-12-20 18:29:23 +00:00
|
|
|
"code.jhot.me/jhot/hats/pkg/infisical"
|
2023-10-12 17:23:35 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type HatsConfig struct {
|
2023-12-20 18:29:23 +00:00
|
|
|
LogLevl string `config:"LOG_LEVEL" default:"INFO"`
|
2023-10-17 19:58:34 +00:00
|
|
|
|
2023-12-20 18:29:23 +00:00
|
|
|
InfisicalHost string `config:"INFISICAL_HOST" default:"http://infisical:8080"`
|
|
|
|
InfisicalClientID string `config:"INFISICAL_CLIENT" default:""`
|
|
|
|
InfisicalClientSecret string `config:"INFISICAL_SECRET" default:""`
|
|
|
|
InfisicalProjectID string `config:"INFISICAL_PROJECT" default:""`
|
|
|
|
InfisicalEnvironment string `config:"INFISICAL_ENVIRONMENT" default:"prod"`
|
2023-10-12 17:23:35 +00:00
|
|
|
|
2023-12-20 18:29:23 +00:00
|
|
|
HomeAssistantHost string `config:"HASS_HOST" default:"127.0.0.1"`
|
|
|
|
HomeAssistantPort string `config:"HASS_PORT" default:"8123"`
|
|
|
|
HomeAssistantSecure bool `config:"HASS_SECURE" default:"false"`
|
|
|
|
HomeAssistantToken string `config:"HASS_TOKEN" default:""`
|
2023-10-13 20:31:23 +00:00
|
|
|
|
2023-12-20 18:29:23 +00:00
|
|
|
NatsHost string `config:"NATS_HOST" default:"127.0.0.1"`
|
|
|
|
NatsPort string `config:"NATS_PORT" default:"4222"`
|
|
|
|
NatsToken string `config:"NATS_TOKEN" default:""`
|
|
|
|
NatsClientName string `config:"NATS_CLIENT_NAME" default:"hats"`
|
2023-11-08 23:12:04 +00:00
|
|
|
|
2023-12-20 18:29:23 +00:00
|
|
|
HatsHost string `config:"HATS_HOST" default:"hats"`
|
|
|
|
HatsPort string `config:"HATS_PORT" default:"8888"`
|
|
|
|
HatsToken string `config:"HATS_TOKEN" default:""`
|
|
|
|
HatsSecure bool `config:"HATS_SECURE" default:"false"`
|
2023-12-04 18:11:33 +00:00
|
|
|
|
2023-12-20 18:29:23 +00:00
|
|
|
NtfyHost string `config:"NTFY_HOST" default:"https://ntfy.sh"`
|
|
|
|
NtfyToken string `config:"NTFY_TOKEN" default:""`
|
|
|
|
|
|
|
|
SyncthingHost string `config:"SYNCTHING_HOST" default:"http://127.0.0.1:8384"`
|
|
|
|
SyncthingToken string `config:"SYNCTHING_TOKEN" default:""`
|
|
|
|
|
|
|
|
GokapiHost string `config:"GOKAPI_HOST" default:"http://gokapi:53842"`
|
|
|
|
GokapiToken string `config:"GOKAPI_TOKEN" default:""`
|
|
|
|
|
|
|
|
QbittorrentHost string `config:"QBITTORRENT_HOST" default:"http://qbittorrent:8080"`
|
|
|
|
QbittorrentUser string `config:"QBITTORRENT_USER" default:""`
|
|
|
|
QbittorrentPassword string `config:"QBITTORRENT_PASS" default:""`
|
|
|
|
|
|
|
|
ConfigDir string `config:"CONFIG_DIR" default:"/config"`
|
|
|
|
|
2024-01-04 16:55:57 +00:00
|
|
|
infisicalClient *infisical.InfisicalClient
|
2023-10-12 17:23:35 +00:00
|
|
|
}
|
|
|
|
|
2023-12-20 18:29:23 +00:00
|
|
|
func New() (*HatsConfig, error) {
|
|
|
|
cfg := &HatsConfig{}
|
|
|
|
cfg.SetValues(ConfigValueSourceDefault).SetValues(ConfigValueSourceEnv)
|
|
|
|
|
|
|
|
if cfg.InfisicalConfigured() {
|
|
|
|
cfg.infisicalClient = infisical.New(cfg.InfisicalHost, cfg.InfisicalClientID, cfg.InfisicalClientSecret)
|
|
|
|
|
|
|
|
err := cfg.infisicalClient.Login()
|
|
|
|
if err != nil {
|
|
|
|
cfg.infisicalClient = nil
|
|
|
|
return cfg, fmt.Errorf("error logging in to Infisical: %w", err)
|
|
|
|
}
|
|
|
|
|
2024-01-04 16:55:57 +00:00
|
|
|
secrets, err := cfg.infisicalClient.ListSecrets(cfg.InfisicalProjectID, cfg.InfisicalEnvironment)
|
2023-12-20 18:29:23 +00:00
|
|
|
if err != nil {
|
|
|
|
return cfg, fmt.Errorf("error getting Infisical secrets: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
secretsMap := make(map[string]string)
|
|
|
|
for _, secret := range secrets {
|
|
|
|
secretsMap[secret.SecretKey] = secret.SecretValue
|
|
|
|
}
|
|
|
|
|
|
|
|
cfg.SetValues(ConfigValueSourceInfisical, secretsMap)
|
|
|
|
}
|
2023-11-17 18:24:12 +00:00
|
|
|
|
2023-12-20 18:29:23 +00:00
|
|
|
return cfg, nil
|
|
|
|
}
|
2023-11-17 18:24:12 +00:00
|
|
|
|
2023-12-20 18:29:23 +00:00
|
|
|
type ConfigValueSource string
|
|
|
|
|
|
|
|
const ConfigValueSourceEnv ConfigValueSource = "env"
|
|
|
|
const ConfigValueSourceDefault ConfigValueSource = "default"
|
|
|
|
const ConfigValueSourceInfisical ConfigValueSource = "infisical"
|
|
|
|
|
|
|
|
func (c *HatsConfig) SetValues(source ConfigValueSource, inputs ...map[string]string) *HatsConfig {
|
|
|
|
fields := reflect.VisibleFields(reflect.TypeOf(*c))
|
|
|
|
|
|
|
|
for _, field := range fields {
|
|
|
|
envName := field.Tag.Get("config")
|
|
|
|
if envName == "" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
var envValue string
|
|
|
|
switch source {
|
|
|
|
case ConfigValueSourceDefault:
|
|
|
|
envValue = field.Tag.Get("default")
|
|
|
|
case ConfigValueSourceEnv:
|
|
|
|
envValue = os.Getenv(envName)
|
|
|
|
case ConfigValueSourceInfisical:
|
|
|
|
if len(inputs) == 0 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if val, found := inputs[0][envName]; found {
|
|
|
|
envValue = val
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if envValue == "" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
f := reflect.ValueOf(c).Elem().FieldByName(field.Name)
|
|
|
|
switch field.Type.Kind() {
|
|
|
|
case reflect.Bool:
|
|
|
|
f.SetBool(strings.EqualFold(envValue, "true"))
|
|
|
|
case reflect.Int:
|
|
|
|
parsed, err := strconv.ParseInt(envValue, 10, 64)
|
|
|
|
if err == nil {
|
|
|
|
f.SetInt(parsed)
|
|
|
|
}
|
|
|
|
case reflect.String:
|
|
|
|
f.SetString(envValue)
|
|
|
|
}
|
|
|
|
}
|
2023-11-17 18:24:12 +00:00
|
|
|
|
2023-12-20 18:29:23 +00:00
|
|
|
return c
|
|
|
|
}
|
2023-11-17 18:24:12 +00:00
|
|
|
|
2023-12-20 18:29:23 +00:00
|
|
|
func (c *HatsConfig) GetCustomSetting(name string, defaultValue string) string {
|
|
|
|
returnValue := defaultValue
|
2023-12-04 18:11:33 +00:00
|
|
|
|
2023-12-20 18:29:23 +00:00
|
|
|
envValue := os.Getenv(name)
|
|
|
|
if envValue != "" {
|
|
|
|
returnValue = envValue
|
2023-10-12 17:23:35 +00:00
|
|
|
}
|
|
|
|
|
2023-12-20 18:29:23 +00:00
|
|
|
if c.InfisicalConfigured() {
|
2024-01-04 16:55:57 +00:00
|
|
|
secret, _ := c.infisicalClient.GetSecret(name, c.InfisicalProjectID, c.InfisicalEnvironment)
|
2023-12-20 18:29:23 +00:00
|
|
|
if secret.SecretValue != "" {
|
|
|
|
returnValue = secret.SecretValue
|
|
|
|
}
|
|
|
|
}
|
2023-10-17 19:58:34 +00:00
|
|
|
|
2023-12-20 18:29:23 +00:00
|
|
|
return returnValue
|
2023-10-17 19:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *HatsConfig) GetHomeAssistantBaseUrl() string {
|
2023-12-20 18:29:23 +00:00
|
|
|
protocol := "http"
|
2023-10-17 19:58:34 +00:00
|
|
|
if c.HomeAssistantSecure {
|
2023-12-20 18:29:23 +00:00
|
|
|
protocol += "s"
|
2023-10-12 17:23:35 +00:00
|
|
|
}
|
2023-12-20 18:29:23 +00:00
|
|
|
return fmt.Sprintf("%s://%s:%s", protocol, c.HomeAssistantHost, c.HomeAssistantPort)
|
2023-10-17 19:58:34 +00:00
|
|
|
}
|
2023-10-13 20:31:23 +00:00
|
|
|
|
2023-10-17 19:58:34 +00:00
|
|
|
func (c *HatsConfig) GetHomeAssistantWebsocketUrl() string {
|
|
|
|
protocol := "ws"
|
|
|
|
if c.HomeAssistantSecure {
|
|
|
|
protocol += "s"
|
|
|
|
}
|
|
|
|
return fmt.Sprintf("%s://%s:%s/api/websocket", protocol, c.HomeAssistantHost, c.HomeAssistantPort)
|
|
|
|
}
|
2023-10-12 17:23:35 +00:00
|
|
|
|
2023-10-17 19:58:34 +00:00
|
|
|
func (c *HatsConfig) GetNatsBaseUrl() string {
|
|
|
|
return fmt.Sprintf("nats://%s:%s", c.NatsHost, c.NatsPort)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *HatsConfig) GetHatsBaseUrl() string {
|
|
|
|
protocol := "http"
|
2023-11-27 23:54:15 +00:00
|
|
|
if c.HatsSecure {
|
2023-10-17 19:58:34 +00:00
|
|
|
protocol += "s"
|
2023-10-13 20:31:23 +00:00
|
|
|
}
|
2023-10-17 19:58:34 +00:00
|
|
|
return fmt.Sprintf("%s://%s:%s", protocol, c.HatsHost, c.HatsPort)
|
|
|
|
}
|
2023-10-13 20:31:23 +00:00
|
|
|
|
2023-10-17 19:58:34 +00:00
|
|
|
func (c *HatsConfig) GetLogLevel() slog.Level {
|
|
|
|
switch strings.ToLower(c.LogLevl) {
|
|
|
|
case "error":
|
|
|
|
return slog.LevelError
|
|
|
|
case "warn":
|
|
|
|
return slog.LevelWarn
|
|
|
|
case "debug":
|
|
|
|
return slog.LevelDebug
|
|
|
|
default:
|
|
|
|
return slog.LevelInfo
|
|
|
|
}
|
2023-10-12 17:23:35 +00:00
|
|
|
}
|
2023-12-20 18:29:23 +00:00
|
|
|
|
|
|
|
func (c *HatsConfig) InfisicalConfigured() bool {
|
|
|
|
return c.InfisicalHost != "" &&
|
|
|
|
c.InfisicalClientID != "" &&
|
|
|
|
c.InfisicalClientSecret != "" &&
|
|
|
|
c.InfisicalProjectID != "" &&
|
|
|
|
c.InfisicalEnvironment != ""
|
|
|
|
}
|