-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add env file #2176
Add env file #2176
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,7 @@ import ( | |
"errors" | ||
"flag" | ||
"fmt" | ||
"io" | ||
"io/ioutil" | ||
"log" | ||
"os" | ||
|
@@ -50,6 +51,7 @@ func init() { | |
flag.StringVar(&disabledMetrics, "disabled-metrics", "", "Comma-separated list of telemetry metrics to disable") | ||
flag.StringVar(&conf, "conf", "", "Caddyfile to load (default \""+caddy.DefaultConfigFile+"\")") | ||
flag.StringVar(&cpu, "cpu", "100%", "CPU cap") | ||
flag.StringVar(&envFile, "env", "", "Path to file with environment variables to load in KEY=VALUE format") | ||
flag.BoolVar(&plugins, "plugins", false, "List installed plugins") | ||
flag.StringVar(&caddytls.DefaultEmail, "email", "", "Default ACME CA account email address") | ||
flag.DurationVar(&acme.HTTPClient.Timeout, "catimeout", acme.HTTPClient.Timeout, "Default ACME CA HTTP timeout") | ||
|
@@ -90,6 +92,11 @@ func Run() { | |
}) | ||
} | ||
|
||
//Load all additional envs as soon as possible | ||
if err := LoadEnvFromFile(envFile); err != nil { | ||
mustLogFatalf("%v", err) | ||
} | ||
|
||
// initialize telemetry client | ||
if enableTelemetry { | ||
err := initTelemetry() | ||
|
@@ -409,13 +416,88 @@ func initTelemetry() error { | |
return nil | ||
} | ||
|
||
// LoadEnvFromFile loads additional envs if file provided and exists | ||
// Envs in file should be in KEY=VALUE format | ||
func LoadEnvFromFile(envFile string) error { | ||
if envFile == "" { | ||
return nil | ||
} | ||
|
||
file, err := os.Open(envFile) | ||
if err != nil { | ||
return err | ||
} | ||
defer file.Close() | ||
|
||
envMap, err := ParseEnvFile(file) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
for k, v := range envMap { | ||
if err := os.Setenv(k, v); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// ParseEnvFile implements parse logic for environment files | ||
func ParseEnvFile(envInput io.Reader) (map[string]string, error) { | ||
envMap := make(map[string]string) | ||
|
||
scanner := bufio.NewScanner(envInput) | ||
var line string | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to declare this outside the loop; can use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, i will look up for this kind of things in future:) thanks |
||
lineNumber := 0 | ||
|
||
for scanner.Scan() { | ||
line = strings.TrimSpace(scanner.Text()) | ||
lineNumber++ | ||
|
||
// skip lines starting with comment | ||
if strings.HasPrefix(line, "#") { | ||
continue | ||
} | ||
|
||
// skip empty line | ||
if len(line) == 0 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another thing that would be handled by trimming the line of whitespaces. With this, a line containing only whitespace characters will (wrongfully) not be skipped. |
||
continue | ||
} | ||
|
||
fields := strings.SplitN(line, "=", 2) | ||
if len(fields) != 2 { | ||
return nil, fmt.Errorf("Can't parse line %d; line should be in KEY=VALUE format", lineNumber) | ||
} | ||
|
||
if strings.Contains(fields[0], " ") { | ||
return nil, fmt.Errorf("Can't parse line %d; KEY contains whitespace", lineNumber) | ||
} | ||
|
||
key := fields[0] | ||
val := fields[1] | ||
|
||
if key == "" { | ||
return nil, fmt.Errorf("Can't parse line %d; KEY can't be empty string", lineNumber) | ||
} | ||
envMap[key] = val | ||
} | ||
|
||
if err := scanner.Err(); err != nil { | ||
return nil, err | ||
} | ||
|
||
return envMap, nil | ||
} | ||
|
||
const appName = "Caddy" | ||
|
||
// Flags that control program flow or startup | ||
var ( | ||
serverType string | ||
conf string | ||
cpu string | ||
envFile string | ||
logfile string | ||
revoke string | ||
version bool | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,7 +15,9 @@ | |
package caddymain | ||
|
||
import ( | ||
"reflect" | ||
"runtime" | ||
"strings" | ||
"testing" | ||
) | ||
|
||
|
@@ -57,3 +59,34 @@ func TestSetCPU(t *testing.T) { | |
runtime.GOMAXPROCS(currentCPU) | ||
} | ||
} | ||
|
||
func TestParseEnvFile(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
input string | ||
want map[string]string | ||
wantErr bool | ||
}{ | ||
{"parsing KEY=VALUE", "PORT=4096", map[string]string{"PORT": "4096"}, false}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like your test with a comment explaining what it is testing. |
||
{"empty KEY", "=4096", nil, true}, | ||
{"one value", "test", nil, true}, | ||
{"comments skipped", "#TEST=1\nPORT=8888", map[string]string{"PORT": "8888"}, false}, | ||
{"empty line", "\nPORT=7777", map[string]string{"PORT": "7777"}, false}, | ||
{"comments with space skipped", " #TEST=1", map[string]string{}, false}, | ||
{"KEY with space", "PORT =8888", nil, true}, | ||
{"only spaces", " ", map[string]string{}, false}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
reader := strings.NewReader(tt.input) | ||
got, err := ParseEnvFile(reader) | ||
if (err != nil) != tt.wantErr { | ||
t.Errorf("ParseEnvFile() error = %v, wantErr %v", err, tt.wantErr) | ||
return | ||
} | ||
if !reflect.DeepEqual(got, tt.want) { | ||
t.Errorf("ParseEnvFile() = %v, want %v", got, tt.want) | ||
} | ||
}) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a
defer file.Close()
here to close the file after reading.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, add it after the error check below instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, sorry, i missed it:)