Skip to content

Commit 75de0ef

Browse files
author
Piotr
committed
added support for env vars as config values
1 parent 1904321 commit 75de0ef

File tree

6 files changed

+149
-35
lines changed

6 files changed

+149
-35
lines changed

config.go

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package main
2+
3+
import (
4+
"os"
5+
6+
"github.com/logdyhq/logdy-core/http"
7+
"github.com/logdyhq/logdy-core/modes"
8+
"github.com/spf13/cobra"
9+
)
10+
11+
type ConfVal interface {
12+
string | int64 | bool
13+
}
14+
15+
func getConfigValue[T ConfVal](arg ...T) T {
16+
var zero T
17+
18+
for _, v := range arg {
19+
// Check if v is not the zero value of its type
20+
switch any(v).(type) {
21+
case string:
22+
if any(v).(string) != "" {
23+
return v
24+
}
25+
case int64:
26+
if any(v).(int64) != 0 {
27+
return v
28+
}
29+
case bool:
30+
// For bool, we consider true as non-zero
31+
// If you want to treat false as valid too, adjust this condition
32+
if any(v).(bool) {
33+
return v
34+
}
35+
}
36+
}
37+
38+
return zero
39+
}
40+
41+
func getFlagString(name string, cmd *cobra.Command, def bool) string {
42+
v, _ := cmd.Flags().GetString(name)
43+
if def {
44+
return v
45+
}
46+
if !def && cmd.Flags().Changed(name) {
47+
return v
48+
}
49+
return ""
50+
}
51+
52+
func getFlagBool(name string, cmd *cobra.Command, def bool) bool {
53+
v, _ := cmd.Flags().GetBool(name)
54+
if def {
55+
return v
56+
}
57+
if !def && cmd.Flags().Changed(name) {
58+
return v
59+
}
60+
return false
61+
}
62+
63+
func getFlagInt(name string, cmd *cobra.Command, def bool) int64 {
64+
v, _ := cmd.Flags().GetInt64(name)
65+
if def {
66+
return v
67+
}
68+
if !def && cmd.Flags().Changed(name) {
69+
return v
70+
}
71+
return 0
72+
}
73+
74+
// this function controls the precedence of arguments for string values passed:
75+
// 1. cli
76+
// 2. env
77+
// 3. default
78+
func getStringCfgVal(cli, env string, cmd *cobra.Command) string {
79+
return getConfigValue(getFlagString(cli, cmd, false), os.Getenv(env), getFlagString(cli, cmd, true))
80+
}
81+
82+
// this function controls the precedence of arguments for bool values passed:
83+
// 1. cli
84+
// 2. default
85+
func getBoolCfgVal(cli string, cmd *cobra.Command) bool {
86+
return getConfigValue(getFlagBool(cli, cmd, false), getFlagBool(cli, cmd, true))
87+
}
88+
89+
// this function controls the precedence of arguments for int values passed:
90+
// 1. cli
91+
// 2. default
92+
func getIntCfgVal(cli string, cmd *cobra.Command) int64 {
93+
return getConfigValue(getFlagInt(cli, cmd, false), getFlagInt(cli, cmd, true))
94+
}
95+
96+
func parseConfig(cmd *cobra.Command) {
97+
config = &http.Config{
98+
HttpPathPrefix: "",
99+
}
100+
101+
const prefix = "LOGDY_"
102+
103+
config.ServerPort = getStringCfgVal("port", prefix+"PORT", cmd)
104+
config.ServerIp = getStringCfgVal("ui-ip", prefix+"UI_IP", cmd)
105+
config.UiPass = getStringCfgVal("ui-pass", prefix+"UI_PASS", cmd)
106+
config.ConfigFilePath = getStringCfgVal("config", prefix+"CONFIG", cmd)
107+
config.AppendToFile = getStringCfgVal("append-to-file", prefix+"APPEND_TO_FILE", cmd)
108+
config.ApiKey = getStringCfgVal("api-key", prefix+"API_KEY", cmd)
109+
110+
config.BulkWindowMs = getIntCfgVal("bulk-window", cmd)
111+
config.MaxMessageCount = getIntCfgVal("max-message-count", cmd)
112+
113+
config.AppendToFileRaw = getBoolCfgVal("append-to-file-raw", cmd)
114+
config.AnalyticsDisabled = getBoolCfgVal("no-analytics", cmd)
115+
modes.FallthroughGlobal = getBoolCfgVal("fallthrough", cmd)
116+
modes.DisableANSICodeStripping = getBoolCfgVal("disable-ansi-code-stripping", cmd)
117+
}

main.go

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -191,26 +191,6 @@ func startWebServer(cmd *cobra.Command) {
191191
http.StartWebserver(config)
192192
}
193193

194-
func parseConfig(cmd *cobra.Command) {
195-
config = &http.Config{
196-
HttpPathPrefix: "",
197-
}
198-
199-
config.ServerPort, _ = cmd.Flags().GetString("port")
200-
config.ServerIp, _ = cmd.Flags().GetString("ui-ip")
201-
config.UiPass, _ = cmd.Flags().GetString("ui-pass")
202-
config.ConfigFilePath, _ = cmd.Flags().GetString("config")
203-
config.BulkWindowMs, _ = cmd.Flags().GetInt64("bulk-window")
204-
config.AppendToFile, _ = cmd.Flags().GetString("append-to-file")
205-
config.ApiKey, _ = cmd.Flags().GetString("api-key")
206-
config.AppendToFileRaw, _ = cmd.Flags().GetBool("append-to-file-raw")
207-
config.MaxMessageCount, _ = cmd.Flags().GetInt64("max-message-count")
208-
config.AnalyticsDisabled, _ = cmd.Flags().GetBool("no-analytics")
209-
210-
modes.FallthroughGlobal, _ = cmd.Flags().GetBool("fallthrough")
211-
modes.DisableANSICodeStripping, _ = cmd.Flags().GetBool("disable-ansi-code-stripping")
212-
}
213-
214194
func init() {
215195
utils.InitLogger()
216196
http.InitChannel()
@@ -220,12 +200,13 @@ func init() {
220200
UtilsCmd.AddCommand(utilsCutByDateCmd)
221201
UtilsCmd.AddCommand(utilsCutByLineNumberCmd)
222202

223-
rootCmd.PersistentFlags().StringP("port", "p", "8080", "Port on which the Web UI will be served")
224-
rootCmd.PersistentFlags().StringP("ui-ip", "", "127.0.0.1", "Bind Web UI server to a specific IP address")
225-
rootCmd.PersistentFlags().StringP("ui-pass", "", "", "Password that will be used to authenticate in the UI")
226-
rootCmd.PersistentFlags().StringP("config", "", "", "Path to a file where a config (json) for the UI is located")
227-
rootCmd.PersistentFlags().StringP("append-to-file", "", "", "Path to a file where message logs will be appended, the file will be created if it doesn't exist")
228-
rootCmd.PersistentFlags().StringP("api-key", "", "", "API key (send as a header "+http.API_KEY_HEADER_NAME+")")
203+
rootCmd.PersistentFlags().StringP("port", "p", "8080", "Port on which the Web UI will be served (env: LOGDY_PORT)")
204+
rootCmd.PersistentFlags().StringP("ui-ip", "", "127.0.0.1", "Bind Web UI server to a specific IP address (env: LOGDY_UI_IP)")
205+
rootCmd.PersistentFlags().StringP("ui-pass", "", "", "Password that will be used to authenticate in the UI (env: LOGDY_UI_PASS)")
206+
rootCmd.PersistentFlags().StringP("config", "", "", "Path to a file where a config (json) for the UI is located (env: LOGDY_CONFIG)")
207+
rootCmd.PersistentFlags().StringP("append-to-file", "", "", "Path to a file where message logs will be appended, the file will be created if it doesn't exist (env: LOGDY_APPEND_TO_FILE)")
208+
rootCmd.PersistentFlags().StringP("api-key", "", "", "API key (send as a header "+http.API_KEY_HEADER_NAME+") (env: LOGDY_API_KEY)")
209+
229210
rootCmd.PersistentFlags().Int64P("bulk-window", "", 100, "A time window during which log messages are gathered and send in a bulk to a client. Decreasing this window will improve the 'real-time' feeling of messages presented on the screen but could decrease UI performance")
230211
rootCmd.PersistentFlags().Int64P("max-message-count", "", 100_000, "Max number of messages that will be stored in a buffer for further retrieval. On buffer overflow, oldest messages will be removed.")
231212
rootCmd.PersistentFlags().BoolP("verbose", "v", false, "Verbose logs")

tests/follow_test.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515
)
1616

1717
func readOutput(t *testing.T, stdout io.ReadCloser, outputChan chan string, followChan chan bool, wg *sync.WaitGroup) {
18-
defer wg.Done()
1918
reader := bufio.NewReader(stdout)
2019
for {
2120
line, err := reader.ReadString('\n')
@@ -70,7 +69,7 @@ func TestLogdyE2E_FollowFullRead(t *testing.T) {
7069
}()
7170

7271
// Start logdy process in follow mode with full-read and fallthrough enabled
73-
cmd := exec.Command("go", "run", "../main.go", "follow", "--full-read", "-t", pipeName)
72+
cmd := exec.Command("go", "run", "../.", "follow", "--full-read", "-t", pipeName)
7473

7574
// Get stdout pipe
7675
stdout, err := cmd.StdoutPipe()
@@ -135,7 +134,7 @@ func TestLogdyE2E_FollowFullRead(t *testing.T) {
135134
if err := cmd.Process.Kill(); err != nil {
136135
t.Errorf("Failed to kill process: %v", err)
137136
}
138-
137+
cmd.Wait()
139138
// Wait for the output reader goroutine to finish
140139
wg.Wait()
141140

tests/forward_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func TestLogdyE2E_Forward(t *testing.T) {
4848
wgServer.Wait()
4949

5050
// Start logdy process
51-
cmd := exec.Command("go", "run", "../main.go", "forward", "8475")
51+
cmd := exec.Command("go", "run", "../.", "forward", "8475")
5252

5353
// Get stdin pipe
5454
stdin, err := cmd.StdinPipe()
@@ -104,7 +104,7 @@ func TestLogdyE2E_Forward(t *testing.T) {
104104
if err := cmd.Process.Kill(); err != nil {
105105
t.Errorf("Failed to kill process: %v", err)
106106
}
107-
107+
cmd.Wait()
108108
// Verify received messages
109109
assert.Equal(t, len(testLines), len(msgReceived))
110110
for i, testLine := range testLines {

tests/socket_test.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,12 @@ func TestLogdyE2E_Socket(t *testing.T) {
2424
wg.Add(3) // Expect 3 messages (1 from each port)
2525

2626
// Start logdy process with -t flag for stdout output
27-
cmd := exec.Command("go", "run", "../main.go", "socket", "-t", "8475", "8476", "8477")
27+
cmd := exec.Command("go", "run", "../.", "socket", "-t", "8475", "8476", "8477")
2828
// Get stdout pipe for verifying messages
2929
stdout, err := cmd.StdoutPipe()
3030
assert.NoError(t, err)
31+
stderr, err := cmd.StderrPipe()
32+
assert.NoError(t, err)
3133

3234
// Start reading stdout in background
3335
go func() {
@@ -46,6 +48,20 @@ func TestLogdyE2E_Socket(t *testing.T) {
4648
}
4749
}()
4850

51+
go func() {
52+
scanner := bufio.NewScanner(stderr)
53+
for scanner.Scan() {
54+
line := scanner.Text()
55+
if line != "exit status 1" {
56+
t.Log(line)
57+
t.Error("Stderr produced content!")
58+
// if error is: panic: listen tcp 127.0.0.1:8080: bind: address already in use
59+
// the previous test has not closed the process lsof -i :8080
60+
return
61+
}
62+
}
63+
}()
64+
4965
// Start the process
5066
err = cmd.Start()
5167
assert.NoError(t, err)
@@ -110,7 +126,7 @@ func TestLogdyE2E_Socket(t *testing.T) {
110126
if err := cmd.Process.Kill(); err != nil {
111127
t.Errorf("Failed to kill process: %v", err)
112128
}
113-
129+
cmd.Wait()
114130
// Verify we received messages from all ports
115131
assert.Equal(t, 3, len(msgReceived), "Expected 3 messages, got %d", len(msgReceived))
116132
for i, port := range ports {

tests/stdin_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ func runCmd(cmds []string, t *testing.T) {
121121
case <-time.After(2 * time.Second):
122122
// Force kill if it didn't exit cleanly
123123
cmd.Process.Kill()
124+
cmd.Wait()
124125
}
125126

126127
// Verify output matches input
@@ -131,9 +132,9 @@ func runCmd(cmds []string, t *testing.T) {
131132
}
132133

133134
func TestLogdyE2E_NoCommand(t *testing.T) {
134-
runCmd([]string{"run", "../main.go", "-t"}, t)
135+
runCmd([]string{"run", "../.", "-t"}, t)
135136
}
136137

137138
func TestLogdyE2E_StdinCommand(t *testing.T) {
138-
runCmd([]string{"run", "../main.go", "stdin", "-t"}, t)
139+
runCmd([]string{"run", "../.", "stdin", "-t"}, t)
139140
}

0 commit comments

Comments
 (0)