-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Alex Demin <[email protected]>
- Loading branch information
Showing
7 changed files
with
282 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package config_test | ||
|
||
import ( | ||
"fmt" | ||
"sync" | ||
"testing" | ||
|
||
"github.com/beatlabs/harvester/config" | ||
stdTypes "github.com/beatlabs/harvester/sync" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestCustomField(t *testing.T) { | ||
c := &testConfig{} | ||
cfg, err := config.New(c) | ||
assert.NoError(t, err) | ||
err = cfg.Fields[0].Set("expected", 1) | ||
assert.NoError(t, err) | ||
err = cfg.Fields[1].Set("bar", 1) | ||
assert.NoError(t, err) | ||
assert.Equal(t, "expected", c.CustomValue.Get()) | ||
assert.Equal(t, "bar", c.SomeString.Get()) | ||
} | ||
|
||
func TestErrorValidationOnCustomField(t *testing.T) { | ||
c := &testConfig{} | ||
cfg, err := config.New(c) | ||
assert.NoError(t, err) | ||
err = cfg.Fields[0].Set("not_expected", 1) | ||
assert.Error(t, err) | ||
} | ||
|
||
type testConcreteValue struct { | ||
m sync.Mutex | ||
value string | ||
} | ||
|
||
func (f *testConcreteValue) Set(value string) { | ||
f.m.Lock() | ||
defer f.m.Unlock() | ||
f.value = value | ||
} | ||
|
||
func (f *testConcreteValue) Get() string { | ||
f.m.Lock() | ||
defer f.m.Unlock() | ||
return f.value | ||
} | ||
|
||
func (f *testConcreteValue) String() string { | ||
return f.Get() | ||
} | ||
|
||
func (f *testConcreteValue) SetString(value string) error { | ||
if value != "expected" { | ||
return fmt.Errorf("unable to store provided value") | ||
} | ||
f.Set(value) | ||
return nil | ||
} | ||
|
||
type testConfig struct { | ||
CustomValue testConcreteValue `seed:"expected"` | ||
SomeString stdTypes.String `seed:"foo"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"log" | ||
"os" | ||
"regexp" | ||
"strings" | ||
|
||
gosync "sync" | ||
|
||
"github.com/beatlabs/harvester" | ||
"github.com/beatlabs/harvester/sync" | ||
) | ||
|
||
type config struct { | ||
IndexName sync.String `seed:"customers-v1"` | ||
Email Email `seed:"[email protected]" env:"ENV_EMAIL"` | ||
} | ||
|
||
func main() { | ||
ctx, cnl := context.WithCancel(context.Background()) | ||
defer cnl() | ||
|
||
err := os.Setenv("ENV_EMAIL", "[email protected]") | ||
if err != nil { | ||
log.Fatalf("failed to set env var: %v", err) | ||
} | ||
|
||
cfg := config{} | ||
|
||
h, err := harvester.New(&cfg).Create() | ||
if err != nil { | ||
log.Fatalf("failed to create harvester: %v", err) | ||
} | ||
|
||
err = h.Harvest(ctx) | ||
if err != nil { | ||
log.Fatalf("failed to harvest configuration: %v", err) | ||
} | ||
|
||
log.Printf("Config : IndexName: %s, Email: %s, Email.Name: %s, Email.Domain: %s\n", cfg.IndexName.Get(), cfg.Email.Get(), cfg.Email.GetName(), cfg.Email.GetDomain()) | ||
} | ||
|
||
// regex to validate an email value. | ||
const emailPattern = "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$" | ||
|
||
// Email represents a custom config structure. | ||
type Email struct { | ||
m gosync.RWMutex | ||
v string | ||
name string | ||
domain string | ||
} | ||
|
||
// SetString performs basic validation and sets a config value from string typed value. | ||
func (t *Email) SetString(v string) error { | ||
re := regexp.MustCompile(emailPattern) | ||
if !re.MatchString(v) { | ||
return fmt.Errorf("%s is not a valid email address", v) | ||
} | ||
|
||
t.m.Lock() | ||
defer t.m.Unlock() | ||
|
||
t.v = v | ||
parts := strings.Split(v, "@") | ||
t.name = parts[0] | ||
t.domain = parts[1] | ||
|
||
return nil | ||
} | ||
|
||
// Get returns the stored value. | ||
func (t *Email) Get() string { | ||
t.m.RLock() | ||
defer t.m.RUnlock() | ||
|
||
return t.v | ||
} | ||
|
||
// GetName returns name part of the stored email. | ||
func (t *Email) GetName() string { | ||
t.m.RLock() | ||
defer t.m.RUnlock() | ||
|
||
return t.name | ||
} | ||
|
||
// GetDomain returns domain part of the stored email. | ||
func (t *Email) GetDomain() string { | ||
t.m.RLock() | ||
defer t.m.RUnlock() | ||
|
||
return t.domain | ||
} | ||
|
||
// String represents golang Stringer interface. | ||
func (t *Email) String() string { | ||
return t.Get() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -88,3 +88,15 @@ A fast way to get consul is the following: | |
2019/09/24 16:40:14 WARN: version 135 is older or same as the field's AccessToken | ||
2019/09/24 16:40:15 INFO: field AccessToken updated with value ***, version: 136 | ||
2019/09/24 16:40:16 Config: IndexName: customers-v1, CacheRetention: 86400, LogLevel: DEBUG, AccessToken: newaccesstoken | ||
|
||
## 05 Custom config types with complex structure and validation | ||
|
||
go run examples/05_custom_types/main.go | ||
|
||
2020/01/21 13:39:34 INFO: field IndexName updated with value customers-v1, version: 0 | ||
2020/01/21 13:39:34 INFO: seed value customers-v1 applied on field IndexName | ||
2020/01/21 13:39:34 INFO: field EMail updated with value [email protected], version: 0 | ||
2020/01/21 13:39:34 INFO: seed value [email protected] applied on field EMail | ||
2020/01/21 13:39:34 INFO: field EMail updated with value [email protected], version: 0 | ||
2020/01/21 13:39:34 INFO: env var value [email protected] applied on field EMail | ||
2020/01/21 13:39:34 Config : IndexName: customers-v1, EMail: [email protected], EMail.Name: bar, EMail.Domain: example.com |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.