Skip to content

Commit 35bea46

Browse files
authored
feat: Add support of []net.IP (#89)
1 parent 8bcac8d commit 35bea46

File tree

8 files changed

+451
-5
lines changed

8 files changed

+451
-5
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
[![Go Reference](https://pkg.go.dev/badge/github.com/obalunenko/getenv.svg)](https://pkg.go.dev/github.com/obalunenko/getenv)
33
[![Go Report Card](https://goreportcard.com/badge/github.com/obalunenko/getenv)](https://goreportcard.com/report/github.com/obalunenko/getenv)
44
[![codecov](https://codecov.io/gh/obalunenko/getenv/branch/master/graph/badge.svg)](https://codecov.io/gh/obalunenko/getenv)
5-
![coverbadger-tag-do-not-edit](https://img.shields.io/badge/coverage-97.58%25-brightgreen?longCache=true&style=flat)
5+
![coverbadger-tag-do-not-edit](https://img.shields.io/badge/coverage-98.93%25-brightgreen?longCache=true&style=flat)
66
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=obalunenko_getenv&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=obalunenko_getenv)
77

88
# getenv
@@ -44,6 +44,7 @@ Types supported:
4444
- url.URL
4545
- []url.URL
4646
- net.IP
47+
- []net.IP
4748

4849
## Examples
4950

getenv.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
// - url.URL
3636
// - []url.URL
3737
// - net.IP
38+
// - []net.IP
3839
package getenv
3940

4041
import (

getenv_test.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3050,6 +3050,91 @@ func TestIPOrDefault(t *testing.T) {
30503050
}
30513051
}
30523052

3053+
func TestIPSliceOrDefault(t *testing.T) {
3054+
const rawDefault = "0.0.0.0"
3055+
3056+
type args struct {
3057+
key string
3058+
defaultVal []net.IP
3059+
separator string
3060+
}
3061+
3062+
type expected struct {
3063+
val []net.IP
3064+
}
3065+
3066+
var tests = []struct {
3067+
name string
3068+
precond precondition
3069+
args args
3070+
expected expected
3071+
}{
3072+
{
3073+
name: "env not set - default returned",
3074+
precond: precondition{
3075+
setenv: setenv{
3076+
isSet: false,
3077+
val: "192.168.8.0,2001:cb8::17",
3078+
},
3079+
},
3080+
args: args{
3081+
key: testEnvKey,
3082+
defaultVal: []net.IP{getIP(t, rawDefault)},
3083+
separator: ",",
3084+
},
3085+
expected: expected{
3086+
val: []net.IP{getIP(t, rawDefault)},
3087+
},
3088+
},
3089+
{
3090+
name: "env set - env value returned",
3091+
precond: precondition{
3092+
setenv: setenv{
3093+
isSet: true,
3094+
val: "192.168.8.0,2001:cb8::17",
3095+
},
3096+
},
3097+
args: args{
3098+
key: testEnvKey,
3099+
defaultVal: []net.IP{getIP(t, rawDefault)},
3100+
separator: ",",
3101+
},
3102+
expected: expected{
3103+
val: []net.IP{
3104+
getIP(t, "192.168.8.0"),
3105+
getIP(t, "2001:cb8::17"),
3106+
},
3107+
},
3108+
},
3109+
{
3110+
name: "empty env value set - default returned",
3111+
precond: precondition{
3112+
setenv: setenv{
3113+
isSet: true,
3114+
val: "",
3115+
},
3116+
},
3117+
args: args{
3118+
key: testEnvKey,
3119+
defaultVal: []net.IP{getIP(t, rawDefault)},
3120+
separator: ",",
3121+
},
3122+
expected: expected{
3123+
val: []net.IP{getIP(t, rawDefault)},
3124+
},
3125+
},
3126+
}
3127+
3128+
for _, tt := range tests {
3129+
t.Run(tt.name, func(t *testing.T) {
3130+
tt.precond.maybeSetEnv(t, tt.args.key)
3131+
3132+
got := getenv.EnvOrDefault(tt.args.key, tt.args.defaultVal, option.WithSeparator(tt.args.separator))
3133+
assert.Equal(t, tt.expected.val, got)
3134+
})
3135+
}
3136+
}
3137+
30533138
func TestURLSliceOrDefault(t *testing.T) {
30543139
type args struct {
30553140
key string

internal/constraint.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
type (
1010
// EnvParsable is a constraint for supported environment variable types parsers.
1111
EnvParsable interface {
12-
String | Int | Uint | Float | Time | bool | url.URL | []url.URL | net.IP
12+
String | Int | Uint | Float | Time | bool | url.URL | []url.URL | net.IP | []net.IP
1313
}
1414

1515
// String is a constraint for strings and slice of strings.

internal/iface.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ func NewEnvParser(v any) EnvParser {
3131
p = urlSliceParser(t)
3232
case net.IP:
3333
p = ipParser(t)
34+
case []net.IP:
35+
p = ipSliceParser(t)
3436
default:
3537
p = nil
3638
}
@@ -448,3 +450,13 @@ func (t ipParser) ParseEnv(key string, defaltVal any, _ Parameters) any {
448450

449451
return val
450452
}
453+
454+
type ipSliceParser []net.IP
455+
456+
func (t ipSliceParser) ParseEnv(key string, defaltVal any, opts Parameters) any {
457+
separator := opts.Separator
458+
459+
val := ipSliceOrDefault(key, defaltVal.([]net.IP), separator)
460+
461+
return val
462+
}

internal/iface_test.go

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,14 @@ func TestNewEnvParser(t *testing.T) {
296296
want: ipParser(net.IP{}),
297297
wantPanic: assert.NotPanics,
298298
},
299+
{
300+
name: "[]net.IP",
301+
args: args{
302+
v: []net.IP{},
303+
},
304+
want: ipSliceParser([]net.IP{}),
305+
wantPanic: assert.NotPanics,
306+
},
299307
{
300308
name: "not supported - panics",
301309
args: args{
@@ -972,12 +980,30 @@ func Test_ParseEnv(t *testing.T) {
972980
args: args{
973981
key: testEnvKey,
974982
defaltVal: net.IP{},
983+
in2: Parameters{},
984+
},
985+
want: getIP(t, "2001:cb8::17"),
986+
},
987+
{
988+
name: "ipSliceParser",
989+
s: ipSliceParser([]net.IP{}),
990+
precond: precondition{
991+
setenv: setenv{
992+
isSet: true,
993+
val: "2001:cb8::17,192.168.0.1",
994+
},
995+
},
996+
args: args{
997+
key: testEnvKey,
998+
defaltVal: []net.IP{},
975999
in2: Parameters{
976-
Separator: "",
977-
Layout: time.DateOnly,
1000+
Separator: ",",
9781001
},
9791002
},
980-
want: getIP(t, "2001:cb8::17"),
1003+
want: []net.IP{
1004+
getIP(t, "2001:cb8::17"),
1005+
getIP(t, "192.168.0.1"),
1006+
},
9811007
},
9821008
}
9831009

internal/parsers.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -778,3 +778,26 @@ func ipOrDefault(key string, defaultVal net.IP) net.IP {
778778

779779
return val
780780
}
781+
782+
// ipSliceOrDefault retrieves the net.IP slice value of the environment variable named
783+
// by the key and separated by sep.
784+
// If variable not set or value is empty - defaultVal will be returned.
785+
func ipSliceOrDefault(key string, defaultVal []net.IP, sep string) []net.IP {
786+
valraw := stringSliceOrDefault(key, nil, sep)
787+
if valraw == nil {
788+
return defaultVal
789+
}
790+
791+
val := make([]net.IP, 0, len(valraw))
792+
793+
for _, s := range valraw {
794+
v := net.ParseIP(s)
795+
if v == nil {
796+
return defaultVal
797+
}
798+
799+
val = append(val, v)
800+
}
801+
802+
return val
803+
}

0 commit comments

Comments
 (0)