diff options
| author | Paul Buetow <paul@buetow.org> | 2024-09-21 14:03:45 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2024-09-21 14:03:45 +0300 |
| commit | dff4d455e07d639b82a0bed814f41d0656e9b6d0 (patch) | |
| tree | 56289a6fd80a00a9724992ab9cb8b3d7215ebedf /internal/config | |
| parent | 780ade3dc066afb8a43be824373414f3d316ebd6 (diff) | |
cleanup
Diffstat (limited to 'internal/config')
| -rw-r--r-- | internal/config/client/client.go | 41 | ||||
| -rw-r--r-- | internal/config/config.go | 38 | ||||
| -rw-r--r-- | internal/config/config_test.go | 195 | ||||
| -rw-r--r-- | internal/config/enver.go | 104 | ||||
| -rw-r--r-- | internal/config/server/mastodon.go | 1 | ||||
| -rw-r--r-- | internal/config/server/secrets.go | 44 | ||||
| -rw-r--r-- | internal/config/server/server.go | 62 |
7 files changed, 0 insertions, 485 deletions
diff --git a/internal/config/client/client.go b/internal/config/client/client.go deleted file mode 100644 index f551686..0000000 --- a/internal/config/client/client.go +++ /dev/null @@ -1,41 +0,0 @@ -package client - -import ( - "fmt" - "log" - "os" - - "codeberg.org/snonux/gos/internal/config" -) - -type ClientConfig struct { - Servers []string `json:"Servers,omitempty"` - APIKey string `json:"APIKey,omitempty"` - Editor string `json:"Editor,omitempty"` - DataDir string `json:"StateDir,omitempty"` - ComposeFile string `json:"ComposeFile,omitempty"` - LogFile string `json:"LogFile,omitempty"` -} - -func New(configFile string) (ClientConfig, error) { - conf, err := config.FromFile[ClientConfig](configFile) - if err != nil { - if _, ok := err.(*os.PathError); !ok { - return conf, err - } - log.Println("Skipping config file:", err) - } - - conf.Servers = config.StrSlice("GOS_SERVERS", conf.Servers) - conf.APIKey = config.Str("GOS_API_KEY", conf.APIKey) - conf.Editor = config.Str("GOS_EDITOR", "EDITOR", conf.Editor, "vi") - - defaultDataDir := fmt.Sprintf("%s/.gos/data", os.Getenv("HOME")) - conf.DataDir = config.Str("GOS_DATA_DIR", conf.DataDir, defaultDataDir) - conf.ComposeFile = config.Str("GOS_COMPOSE_FILE", conf.ComposeFile, "compose.txt") - - defaultLogFile := fmt.Sprintf("%s/.gos/gos.log", os.Getenv("HOME")) - conf.LogFile = config.Str("GOS_LOG_FILE", conf.LogFile, defaultLogFile) - - return conf, nil -} diff --git a/internal/config/config.go b/internal/config/config.go deleted file mode 100644 index 6f697e7..0000000 --- a/internal/config/config.go +++ /dev/null @@ -1,38 +0,0 @@ -package config - -import ( - "encoding/json" - "io" - "os" - "unicode" -) - -func FromFile[T any](configFile string) (T, error) { - var conf T - - file, err := os.Open(configFile) - if err != nil { - return conf, err - } - defer file.Close() - - bytes, err := io.ReadAll(file) - if err != nil { - return conf, err - } - - err = json.Unmarshal(bytes, &conf) - return conf, err -} - -func isAllUpperCase(s string) bool { - for _, r := range s { - if unicode.IsLetter(r) && !unicode.IsUpper(r) { - return false - } - if unicode.IsDigit(r) { - return false - } - } - return true -} diff --git a/internal/config/config_test.go b/internal/config/config_test.go deleted file mode 100644 index eca163f..0000000 --- a/internal/config/config_test.go +++ /dev/null @@ -1,195 +0,0 @@ -package config - -import ( - "os" - "slices" - "testing" -) - -func TestEnvToStr(t *testing.T) { - t.Parallel() - - os.Unsetenv("NON_EXISTENT_ENV") - os.Setenv("GOS_TEST_FROM_ENV", "foobarbaz") - - var ( - expected = "foobarbaz" - got = Str("GOS_TEST_FROM_ENV") - ) - - if got != expected { - t.Errorf("got '%s' but expected '%s'", got, expected) - } - - expected = "default value" - got = Str("NON_EXISTENT_ENV", expected) - if got != expected { - t.Errorf("got '%s' but expected '%s'", got, expected) - } - - if got = Str("NON_EXISTENT_ENV"); got != "" { - t.Errorf("got '%s' but expected empty string", got) - } - - expected = "casio g-shock" - os.Setenv("GOS_WATCH", expected) - got = Str("GOS_WATCH", "", "", "", expected, "") - if got != expected { - t.Errorf("got '%s' but expected '%s'", got, expected) - } -} - -func TestEnvToStrSlice(t *testing.T) { - t.Parallel() - - os.Setenv("GOS_TEST_SLICE_FROM_ENV", "foo,bar,baz") - - var ( - expected = []string{"foo", "bar", "baz"} - got = StrSlice("GOS_TEST_SLICE_FROM_ENV") - ) - if !slices.Equal(got, expected) { - t.Errorf("got '%v' but expected '%v'", got, expected) - } - - expected = []string{"default value"} - got = StrSlice("NON_EXISTENT_ENV_SLICE", "default value") - if !slices.Equal(got, expected) { - t.Errorf("got '%v' but expected '%v'", got, expected) - } - - os.Unsetenv("NON_EXISTENT_ENV") - if got = StrSlice("NON_EXISTENT_ENV"); len(got) > 0 { - t.Errorf("got '%s' of len '%d' but expected empty slice", got, len(got)) - } - - expected = []string{"casio", "g-shock"} - got = StrSlice("NON_EXISTENT_ENV", "", "", "", "casio,g-shock", "") - if !slices.Equal(got, expected) { - t.Errorf("got '%v' but expected '%v'", got, expected) - } -} - -func TestEnvToInt(t *testing.T) { - t.Parallel() - - os.Unsetenv("NON_EXISTENT_ENV") - os.Setenv("GOS_TEST_INT_FROM_ENV", "1") - - var ( - expected = 1 - got = Int(t, "GOS_TEST_INT_FROM_ENV") - ) - - if got != expected { - t.Errorf("got '%d' but expected '%d'", got, expected) - } - - expected = 999 - got = Int("NON_EXISTENT_ENV", expected) - if got != expected { - t.Errorf("got '%d' but expected '%d'", got, expected) - } - - if got = Int("NON_EXISTENT_ENV"); got != 0 { - t.Errorf("got '%d' but expected zero", got) - } - - expected = 1234 - got = Int("GOS_WATCH", "", "", "", expected, "") - if got != expected { - t.Errorf("got '%d' but expected '%d'", got, expected) - } -} - -func TestEnvToBool(t *testing.T) { - t.Parallel() - - os.Unsetenv("NON_EXISTENT_ENV") - os.Setenv("GOS_TEST_BOOL_FROM_ENV", "true") - - var ( - expected = true - got = Bool("GOS_TEST_BOOL_FROM_ENV") - ) - - if got != expected { - t.Errorf("got '%t' but expected '%t'", got, expected) - } - - expected = false - got = Bool("NON_EXISTENT_ENV", expected) - if got != expected { - t.Errorf("got '%t' but expected '%t'", got, expected) - } - - if got = Bool("NON_EXISTENT_ENV"); got { - t.Errorf("got '%t' but expected false", got) - } - - expected = true - got = Bool("NON_EXISTENT_ENV", "", "", "", expected, "") - if got != expected { - t.Errorf("got '%t' but expected '%t'", got, expected) - } -} - -func TestSecondENV(t *testing.T) { - t.Parallel() - - os.Unsetenv("GOS_NONEXISTANT") - os.Setenv("EDITOR", "hx") - - var ( - expected = "hx" - got = Str("GOS_NONEXISTANT", "EDITOR", "notepad.exe") - ) - - if expected != got { - t.Errorf("got '%s' but expected '%s'", got, expected) - } -} - -func TestIsAllUpperCase(t *testing.T) { - if isAllUpperCase("foo_bar") { - t.Errorf("lowercas letters in test case") - } - if isAllUpperCase("FOO123") { - t.Errorf("numbers in string should not evaluate to is all upper") - } - if !isAllUpperCase("FOO_BAR") { - t.Errorf("should be all upper") - } -} - -func TestDefaultStrCB(t *testing.T) { - t.Parallel() - os.Unsetenv("GOS_NONEXISTANT") - - var ( - expected = "hello" - got = Str("GOS_NONEXISTANT", func() string { - return "hello" - }) - ) - - if expected != got { - t.Errorf("got '%s' but expected '%s'", got, expected) - } -} - -func TestDefaultIntCB(t *testing.T) { - t.Parallel() - os.Unsetenv("GOS_NONEXISTANT") - - var ( - expected = 666 - got = Int("GOS_NONEXISTANT", func() int { - return 666 - }) - ) - - if expected != got { - t.Errorf("got '%d' but expected '%d'", got, expected) - } -} diff --git a/internal/config/enver.go b/internal/config/enver.go deleted file mode 100644 index f3f8d29..0000000 --- a/internal/config/enver.go +++ /dev/null @@ -1,104 +0,0 @@ -package config - -import ( - "os" - "strconv" - "strings" -) - -type configTypes interface { - ~int | ~bool | ~string | []string -} - -type enver[T configTypes] interface { - fromStr(value string) (T, error) // Return T value from input string - zero() T // Return T's zero value -} - -func Str(keys ...any) string { - return fromEnv[toStr](keys...) -} - -func StrSlice(keys ...any) []string { - return fromEnv[toStrSlice](keys...) -} - -func Int(keys ...any) int { - return fromEnv[toInt](keys...) -} - -func Bool(keys ...any) bool { - return fromEnv[toBool](keys...) -} - -func fromEnv[U enver[T], T configTypes](keys ...any) T { - var enver U - - for _, key := range keys { - switch key := key.(type) { - case string: - if key == "" { - continue - } - if !isAllUpperCase(key) { - if val, err := enver.fromStr(key); err == nil { - return val - } - } else if strVal := os.Getenv(key); strVal != "" { - if val, err := enver.fromStr(strVal); err == nil { - return val - } - } - case T: - return key - case func() T: - return key() - } - } - - return enver.zero() -} - -type toStr struct{} - -func (toStr) fromStr(str string) (string, error) { - return str, nil -} - -func (toStr) zero() string { - return "" -} - -type toStrSlice struct{} - -func (s toStrSlice) fromStr(str string) ([]string, error) { - result := strings.Split(str, ",") - if len(result) == 1 && result[0] == "" { - return s.zero(), nil - } - return result, nil -} - -func (toStrSlice) zero() []string { - return []string{} -} - -type toInt struct{} - -func (toInt) fromStr(str string) (int, error) { - return strconv.Atoi(str) -} - -func (toInt) zero() int { - return 0 -} - -type toBool struct{} - -func (toBool) fromStr(str string) (bool, error) { - return strconv.ParseBool(str) -} - -func (toBool) zero() bool { - return false -} diff --git a/internal/config/server/mastodon.go b/internal/config/server/mastodon.go deleted file mode 100644 index abb4e43..0000000 --- a/internal/config/server/mastodon.go +++ /dev/null @@ -1 +0,0 @@ -package server diff --git a/internal/config/server/secrets.go b/internal/config/server/secrets.go deleted file mode 100644 index 0e8aab2..0000000 --- a/internal/config/server/secrets.go +++ /dev/null @@ -1,44 +0,0 @@ -package server - -import ( - "fmt" - "log" - "os" - - "codeberg.org/snonux/gos/internal/config" -) - -type SecretsConfig struct { - MastodonEnable bool `json:"MastodonEnable,omitempty"` - MastodonDomain string `json:"MastodonDomain,omitempty"` - MastodonAccessToken string `json:"MastodonAccessToken,omitempty"` -} - -func newSecretsConfig(secretsFile string) (SecretsConfig, error) { - if isWorldReadable(secretsFile) { - return SecretsConfig{}, fmt.Errorf("config '%s' is world readable", secretsFile) - } - - conf, err := config.FromFile[SecretsConfig](secretsFile) - if err != nil { - if _, ok := err.(*os.PathError); !ok { - return conf, err - } - log.Println("Skipping config file:", err) - } - - conf.MastodonEnable = config.Bool("GOS_MASTODON_ENABLE", conf.MastodonEnable) - conf.MastodonDomain = config.Str("GOS_MASTODON_DOMAIN", conf.MastodonDomain) - conf.MastodonAccessToken = config.Str("GOS_MASTODON_ACCESS_TOKEN", conf.MastodonAccessToken) - - return conf, nil -} - -func isWorldReadable(file string) bool { - fileInfo, err := os.Stat(file) - if err != nil { - return false - } - - return fileInfo.Mode().Perm()&00004 != 0 -} diff --git a/internal/config/server/server.go b/internal/config/server/server.go deleted file mode 100644 index 16da14c..0000000 --- a/internal/config/server/server.go +++ /dev/null @@ -1,62 +0,0 @@ -package server - -import ( - "fmt" - "log" - "os" - - "codeberg.org/snonux/gos/internal/config" - "codeberg.org/snonux/gos/internal/types" -) - -type ServerConfig struct { - ListenAddr string `json:"ListenAddr,omitempty"` - Partners []string `json:"Partners,omitempty"` - APIKey string `json:"APIKey,omitempty"` - DataDir string `json:"StateDir,omitempty"` - EmailTo string `json:"EmailTo,omitempty"` - EmailFrom string `json:"EmailFrom,omitempty"` - SMTPServer string `json:"SMTPServer,omitempty"` - MergeIntervalS int `json:"MergeInterval,omitempty"` - ScheduleIntervalS int `json:"ScheduleInterval,omitempty"` - SocialPlatformsEnabled []string `json:"SocialPlatformsEnabled,omitempty"` - PostsPerWeek int `json:"PostsPerWeek,omitempty"` - Secrets SecretsConfig `json:"Secrets,omitempty"` -} - -func New(configFile, secretsFile string) (ServerConfig, error) { - conf, err := config.FromFile[ServerConfig](configFile) - if err != nil { - if _, ok := err.(*os.PathError); !ok { - return conf, err - } - log.Println("Skipping config file:", err) - } - - if conf.Secrets, err = newSecretsConfig(secretsFile); err != nil { - return conf, err - } - - conf.ListenAddr = config.Str("GOS_LISTEN_ADDR", conf.ListenAddr, "localhost:8080") - conf.Partners = config.StrSlice("GOS_PARTNERS", conf.Partners) - conf.APIKey = config.Str("GOS_API_KEY", conf.APIKey) - conf.DataDir = config.Str("GOS_DATA_DIR", conf.DataDir, "data") - conf.EmailTo = config.Str("GOS_EMAIL_TO", conf.EmailTo) - conf.EmailFrom = config.Str("GOS_EMAIL_FROM", conf.EmailFrom) - conf.SocialPlatformsEnabled = config.StrSlice("GOS_SOCIAL_PLATFORMS_ENABLED", - []string{types.Mastodon, types.LinkedIn, types.Textfile}) - conf.PostsPerWeek = config.Int("GOS_POSTS_PER_WEEK", conf.PostsPerWeek, 2) - conf.SMTPServer = config.Str("GOS_SMTP_SERVER", conf.SMTPServer, func() string { - hostname, err := os.Hostname() - if err != nil { - log.Fatal(err) - } - return fmt.Sprintf("%s:25", hostname) - }) - - const oneHour = 3600 - conf.MergeIntervalS = config.Int("GOS_MERGE_INTERVAL", oneHour) - conf.ScheduleIntervalS = config.Int("GOS_SCHEDULER_INTERVAL", oneHour*6) - - return conf, nil -} |
