-
Notifications
You must be signed in to change notification settings - Fork 1
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
[WIP] Read env variables from file #5
base: master
Are you sure you want to change the base?
Changes from 3 commits
509d5cb
56ab5bd
0d12cff
7b1e337
089e8d2
24933c1
407d5b9
df1d81e
435d55c
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 |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package envconf | ||
|
||
import ( | ||
"bufio" | ||
"bytes" | ||
"errors" | ||
"io" | ||
"os" | ||
"strings" | ||
) | ||
|
||
var ( | ||
ErrInvalidPair = errors.New("invalid pair for env variable") | ||
) | ||
|
||
const ( | ||
commentSymbol = '#' | ||
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. can be defined in Parse func scope 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. @antonmashko I think this comment relates more to the style of the code. 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. yep, it is |
||
) | ||
|
||
type EnvConfig struct { | ||
envs map[string]string | ||
} | ||
|
||
func NewEnvConf() *EnvConfig { | ||
return &EnvConfig{envs: map[string]string{}} | ||
} | ||
|
||
func (e *EnvConfig) Parse(data io.Reader) error { | ||
b := bufio.NewReader(data) | ||
for { | ||
n, err := b.ReadBytes('\n') | ||
if err != nil { | ||
if err != io.EOF { | ||
return err | ||
} | ||
if len(n) == 0 { | ||
return nil | ||
} | ||
} | ||
n = bytes.Trim(n, " ") | ||
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. simply use strings.TrimSpace |
||
n = bytes.Trim(n, "\n") | ||
n = bytes.Trim(n, "\t") | ||
if n[0] == commentSymbol { | ||
continue | ||
} | ||
i := bytes.Index(n, []byte("=")) | ||
if i == -1 { | ||
return ErrInvalidPair | ||
} | ||
key := string(n[:i]) | ||
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.
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.
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.
|
||
value := string(n[i+1 : len(n)]) | ||
if isEmptyLine(value) { | ||
e.envs[key] = "" | ||
continue | ||
} | ||
if isQuotes(value, 0, len(value)-1) { | ||
value = cutQuotes(value) | ||
} | ||
e.envs[key] = value | ||
} | ||
} | ||
|
||
func (e *EnvConfig) Set() error { | ||
for k, v := range e.envs { | ||
err := os.Setenv(k, v) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func isEmptyLine(s string) bool { | ||
return isQuotes(s, 0, 1) | ||
} | ||
|
||
func cutQuotes(s string) string { | ||
if isQuotes(s, 0, len(s)-1) { | ||
if string(s[0]) == `"` { | ||
s = strings.Trim(s, `"`) | ||
} else { | ||
s = strings.Trim(s, `'`) | ||
} | ||
} | ||
return s | ||
} | ||
|
||
func isQuotes(s string, first, second int) bool { | ||
open := string(s[first]) | ||
close := string(s[second]) | ||
if (open == `"` || open == `'`) && open == close { | ||
return true | ||
} | ||
return false | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
package envconf | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"os" | ||
"testing" | ||
) | ||
|
||
func TestSimpleExternalEnvConfigOK(t *testing.T) { | ||
env := bytes.NewBuffer([]byte("Foo=Bar")) | ||
tc := struct { | ||
Foo string `env:"Foo"` | ||
}{} | ||
envf := NewEnvConf() | ||
if err := envf.Parse(env); err != nil { | ||
t.Error("invalid parse env data:", err) | ||
} | ||
if err := envf.Set(); err != nil { | ||
t.Error("invalid set env variables:", err) | ||
} | ||
err := Parse(&tc) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
if tc.Foo != "Bar" { | ||
t.Errorf("incorrect values was set. %#v", tc.Foo) | ||
} | ||
fmt.Println(os.Getenv("Name")) | ||
} | ||
|
||
func TestSimpleExternalEnvConfigFieldWithUnderscoreOK(t *testing.T) { | ||
env := bytes.NewBuffer([]byte("FOO_BAR=FOO_BAR")) | ||
tc := struct { | ||
FooBar string `env:"FOO_BAR"` | ||
}{} | ||
envf := NewEnvConf() | ||
if err := envf.Parse(env); err != nil { | ||
t.Error("invalid parse env data:", err) | ||
} | ||
if err := envf.Set(); err != nil { | ||
t.Error("invalid set env variables:", err) | ||
} | ||
err := Parse(&tc) | ||
if err != nil { | ||
t.Errorf("failed to external parse. err=%s", err) | ||
} | ||
if tc.FooBar != "FOO_BAR" { | ||
t.Errorf("incorrect values was set. %#v", tc.FooBar) | ||
} | ||
} | ||
|
||
func TestSimpleExternaEnvConfigTwoVariablesOK(t *testing.T) { | ||
env := bytes.NewBuffer([]byte("FOO_FIRST=FOO_FIRST\nFOO_SECOND=FOO_SECOND\n")) | ||
tc := struct { | ||
FooFirst string `env:"FOO_FIRST"` | ||
FooSecond string `env:"FOO_SECOND"` | ||
}{} | ||
envf := NewEnvConf() | ||
envf.Parse(env) | ||
envf.Set() | ||
err := Parse(&tc) | ||
if err != nil { | ||
t.Errorf("failed to external parse. err=%s", err) | ||
} | ||
if tc.FooFirst != "FOO_FIRST" { | ||
t.Errorf("incorrect first values was set. %#v", tc.FooFirst) | ||
} | ||
if tc.FooSecond != "FOO_SECOND" { | ||
t.Errorf("incorrect value was set. %#v", tc.FooSecond) | ||
} | ||
} | ||
|
||
func TestSimpleExternaEnvConfigTwoVariablesWithCommentOK(t *testing.T) { | ||
env := bytes.NewBuffer([]byte("# COMMENT=COMMENT\nFOO_FIRST=FOO_FIRST\nFOO_SECOND=FOO_SECOND\n")) | ||
tc := struct { | ||
Comment string `env:"COMMENT"` | ||
FooFirst string `env:"FOO_FIRST"` | ||
FooSecond string `env:"FOO_SECOND"` | ||
}{} | ||
envf := NewEnvConf() | ||
if err := envf.Parse(env); err != nil { | ||
t.Error("invalid parse env data:", err) | ||
} | ||
if err := envf.Set(); err != nil { | ||
t.Error("invalid set env variables:", err) | ||
} | ||
err := Parse(&tc) | ||
if err != nil { | ||
t.Errorf("failed to external parse. err=%s", err) | ||
} | ||
if tc.FooFirst != "FOO_FIRST" { | ||
t.Errorf("incorrect first values was set. %#v", tc.FooFirst) | ||
} | ||
if tc.FooSecond != "FOO_SECOND" { | ||
t.Errorf("incorrect value was set. %#v", tc.FooSecond) | ||
} | ||
if tc.Comment != "" { | ||
t.Errorf("incorrect values was set. %#v", tc.Comment) | ||
} | ||
} | ||
|
||
func TestSimpleExternaEnvConfigTwoVariablesWithQueteOK(t *testing.T) { | ||
env := bytes.NewBuffer([]byte(`FOO_FIRST="FOO_FIRST" | ||
FOO_SECOND='FOO_SECOND'`)) | ||
tc := struct { | ||
FooFirst string `env:"FOO_FIRST"` | ||
FooSecond string `env:"FOO_SECOND"` | ||
}{} | ||
envf := NewEnvConf() | ||
if err := envf.Parse(env); err != nil { | ||
t.Error("invalid parse env data:", err) | ||
} | ||
if err := envf.Set(); err != nil { | ||
t.Error("invalid set env variables:", err) | ||
} | ||
err := Parse(&tc) | ||
if err != nil { | ||
t.Errorf("failed to external parse. err=%s", err) | ||
} | ||
if tc.FooFirst != "FOO_FIRST" { | ||
t.Errorf("incorrect first values was set. %#v", tc.FooFirst) | ||
} | ||
if tc.FooSecond != "FOO_SECOND" { | ||
t.Errorf("incorrect value was set. %#v", tc.FooSecond) | ||
} | ||
} | ||
|
||
func TestSimpleExternaEnvConfigTwoVariablesEmptyStringOK(t *testing.T) { | ||
env := bytes.NewBuffer([]byte(`FOO_FIRST="" | ||
FOO_SECOND=''`)) | ||
tc := struct { | ||
FooFirst string `env:"FOO_FIRST"` | ||
FooSecond string `env:"FOO_SECOND"` | ||
}{ | ||
FooFirst: "foo_first", | ||
FooSecond: "foo_second", | ||
} | ||
envf := NewEnvConf() | ||
if err := envf.Parse(env); err != nil { | ||
t.Error("invalid parse env data:", err) | ||
} | ||
if err := envf.Set(); err != nil { | ||
t.Error("invalid set env variables:", err) | ||
} | ||
err := Parse(&tc) | ||
if err != nil { | ||
t.Errorf("failed to external parse. err=%s", err) | ||
} | ||
if tc.FooFirst != "" { | ||
t.Errorf("incorrect first values was set. %#v", tc.FooFirst) | ||
} | ||
if tc.FooSecond != "" { | ||
t.Errorf("incorrect value was set. %#v", tc.FooSecond) | ||
} | ||
} | ||
|
||
func TestSimpleExternaEnvConfigTwoVariablesEmptySpaceStringOK(t *testing.T) { | ||
env := bytes.NewBuffer([]byte(`FOO_FIRST=" " | ||
FOO_SECOND=' '`)) | ||
tc := struct { | ||
FooFirst string `env:"FOO_FIRST"` | ||
FooSecond string `env:"FOO_SECOND"` | ||
}{} | ||
envf := NewEnvConf() | ||
if err := envf.Parse(env); err != nil { | ||
t.Error("invalid parse env data:", err) | ||
} | ||
if err := envf.Set(); err != nil { | ||
t.Error("invalid set env variables:", err) | ||
} | ||
err := Parse(&tc) | ||
if err != nil { | ||
t.Errorf("failed to external parse. err=%s", err) | ||
} | ||
if tc.FooFirst != " " { | ||
t.Errorf("incorrect first values was set. %#v", tc.FooFirst) | ||
} | ||
if tc.FooSecond != " " { | ||
t.Errorf("incorrect value was set. %#v", tc.FooSecond) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -186,15 +186,16 @@ func (v *value) define() error { | |
owner = owner.parent | ||
} | ||
value, exists = v.owner.external.Get(values...) | ||
if exists { | ||
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. this changes is not related to this commit |
||
return nil | ||
} else if value != nil { | ||
exists = true | ||
} | ||
case DefaultPriority: | ||
value, exists = v.defaultV.value() | ||
} | ||
if exists { | ||
debugLogger.Printf("envconf: set variable name=%s value=%v source=%s", v.fullname(), value, p) | ||
if p == ExternalPriority { | ||
// value setted in external source | ||
return nil | ||
} | ||
break | ||
} | ||
} | ||
|
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.
comment