first commit
This commit is contained in:
86
config/config.go
Normal file
86
config/config.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log/slog"
|
||||
"os"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
const (
|
||||
LoggingOutputJson = "JSON"
|
||||
LoggingOutputText = "TEXT"
|
||||
)
|
||||
|
||||
type config struct {
|
||||
Credentials Credentials `yaml:"credentials"`
|
||||
Directory string `yaml:"directory"`
|
||||
WatchDebounceSeconds int `yaml:"watch_debounce_seconds"`
|
||||
LoggingConfig LoggingConfig `yaml:"logging" json:"logging"`
|
||||
}
|
||||
|
||||
type LoggingConfig struct {
|
||||
Level string
|
||||
}
|
||||
|
||||
func (lc LoggingConfig) ToLogger() *slog.Logger {
|
||||
var level slog.Level
|
||||
if err := level.UnmarshalText([]byte(lc.Level)); err != nil {
|
||||
level = slog.LevelInfo
|
||||
}
|
||||
|
||||
leveler := new(slog.LevelVar)
|
||||
leveler.Set(level)
|
||||
return slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
|
||||
Level: leveler,
|
||||
}))
|
||||
}
|
||||
|
||||
type Credentials struct {
|
||||
SecretKey string `yaml:"secret_key"`
|
||||
TTDApiKey string `yaml:"ttd_api_key"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Credentials Credentials
|
||||
Directory string
|
||||
WatchDebounceSeconds int
|
||||
Logger *slog.Logger
|
||||
}
|
||||
|
||||
func LoadConfig(filePath string) (*Config, error) {
|
||||
// Set up slog as the main logger with default JSON handler
|
||||
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
|
||||
slog.SetDefault(logger)
|
||||
|
||||
data, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
slog.Error("Failed to read configuration file", "error", err, "file", filePath)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var cfg config
|
||||
if err := yaml.Unmarshal(data, &cfg); err != nil {
|
||||
slog.Error("Failed to unmarshal YAML configuration", "error", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := new(Config)
|
||||
c.Logger = cfg.LoggingConfig.ToLogger()
|
||||
|
||||
if cfg.Credentials.SecretKey == "" || cfg.Credentials.TTDApiKey == "" {
|
||||
c.Logger.Error("Missing required credentials in configuration")
|
||||
return nil, errors.New("missing required credentials in configuration")
|
||||
}
|
||||
c.Credentials = cfg.Credentials
|
||||
|
||||
c.Directory = cfg.Directory
|
||||
c.WatchDebounceSeconds = cfg.WatchDebounceSeconds
|
||||
// Log the selected provider data
|
||||
slog.Info("Successfully loaded configuration",
|
||||
"directory", c.Directory,
|
||||
"watch_debounce_seconds", c.WatchDebounceSeconds,
|
||||
)
|
||||
return c, nil
|
||||
}
|
108
config/config_test.go
Normal file
108
config/config_test.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package config_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.savin.nyc/alex/go-iar-notificator/config"
|
||||
)
|
||||
|
||||
func TestLoadConfig_Success(t *testing.T) {
|
||||
// Create a temporary config file
|
||||
tempDir := t.TempDir()
|
||||
configFile := filepath.Join(tempDir, "test_config.yml")
|
||||
yamlContent := `
|
||||
credentials:
|
||||
secret_key: "test_secret"
|
||||
ttd_api_key: "test_api_key"
|
||||
directory: "/test/dir"
|
||||
watch_debounce_seconds: 5
|
||||
logging:
|
||||
level: "INFO"
|
||||
`
|
||||
err := os.WriteFile(configFile, []byte(yamlContent), 0644)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temp config file: %v", err)
|
||||
}
|
||||
|
||||
// Test LoadConfig
|
||||
cfg, err := config.LoadConfig(configFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got %v", err)
|
||||
}
|
||||
|
||||
// Verify the config
|
||||
if cfg.Credentials.SecretKey != "test_secret" {
|
||||
t.Errorf("Expected SecretKey 'test_secret', got %s", cfg.Credentials.SecretKey)
|
||||
}
|
||||
if cfg.Credentials.TTDApiKey != "test_api_key" {
|
||||
t.Errorf("Expected TTDApiKey 'test_api_key', got %s", cfg.Credentials.TTDApiKey)
|
||||
}
|
||||
if cfg.Directory != "/test/dir" {
|
||||
t.Errorf("Expected Directory '/test/dir', got %s", cfg.Directory)
|
||||
}
|
||||
if cfg.WatchDebounceSeconds != 5 {
|
||||
t.Errorf("Expected WatchDebounceSeconds 5, got %d", cfg.WatchDebounceSeconds)
|
||||
}
|
||||
if cfg.Logger == nil {
|
||||
t.Error("Expected Logger to be set, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadConfig_FileNotFound(t *testing.T) {
|
||||
_, err := config.LoadConfig("/nonexistent/config.yml")
|
||||
if err == nil {
|
||||
t.Error("Expected error for non-existent file, got nil")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "no such file") {
|
||||
t.Errorf("Expected error message to contain 'no such file', got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadConfig_InvalidYAML(t *testing.T) {
|
||||
// Create a temporary file with invalid YAML
|
||||
tempDir := t.TempDir()
|
||||
configFile := filepath.Join(tempDir, "invalid_config.yml")
|
||||
invalidYAML := `
|
||||
credentials:
|
||||
secret_key: "test"
|
||||
invalid yaml here
|
||||
`
|
||||
err := os.WriteFile(configFile, []byte(invalidYAML), 0644)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temp config file: %v", err)
|
||||
}
|
||||
|
||||
_, err = config.LoadConfig(configFile)
|
||||
if err == nil {
|
||||
t.Error("Expected error for invalid YAML, got nil")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "yaml") {
|
||||
t.Errorf("Expected error message to contain 'yaml', got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadConfig_MissingCredentials(t *testing.T) {
|
||||
// Create a temporary config file with missing credentials
|
||||
tempDir := t.TempDir()
|
||||
configFile := filepath.Join(tempDir, "missing_creds_config.yml")
|
||||
yamlContent := `
|
||||
directory: "/test/dir"
|
||||
watch_debounce_seconds: 5
|
||||
logging:
|
||||
level: "INFO"
|
||||
`
|
||||
err := os.WriteFile(configFile, []byte(yamlContent), 0644)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temp config file: %v", err)
|
||||
}
|
||||
|
||||
_, err = config.LoadConfig(configFile)
|
||||
if err == nil {
|
||||
t.Error("Expected error for missing credentials, got nil")
|
||||
} else if !strings.Contains(err.Error(), "missing required credentials") {
|
||||
t.Errorf("Expected error message to contain 'missing required credentials', got %v", err)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user