Skip to content
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

feat: Add support of net.IP #85

Merged
merged 3 commits into from
Mar 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
[![Go Reference](https://pkg.go.dev/badge/github.com/obalunenko/getenv.svg)](https://pkg.go.dev/github.com/obalunenko/getenv)
[![Go Report Card](https://goreportcard.com/badge/github.com/obalunenko/getenv)](https://goreportcard.com/report/github.com/obalunenko/getenv)
[![codecov](https://codecov.io/gh/obalunenko/getenv/branch/master/graph/badge.svg)](https://codecov.io/gh/obalunenko/getenv)
![coverbadger-tag-do-not-edit](https://img.shields.io/badge/coverage-98.25%25-brightgreen?longCache=true&style=flat)
![coverbadger-tag-do-not-edit](https://img.shields.io/badge/coverage-98.04%25-brightgreen?longCache=true&style=flat)
[![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)

# getenv
Expand Down Expand Up @@ -40,6 +40,7 @@ Types supported:
- time.Duration
- bool
- url.URL
- net.IP

## Examples

Expand Down Expand Up @@ -126,6 +127,14 @@ func main() {
val = getenv.EnvOrDefault(key, url.URL{})
fmt.Printf("[%T]: %v\n", val, val)

// net.IP
if err := os.Setenv(key, "2001:cb8::17"); err != nil {
panic(err)
}

val = getenv.EnvOrDefault(key, net.IP{})
fmt.Printf("[%T]: %v\n", val, val)

}

```
Expand All @@ -139,4 +148,5 @@ Output:
[[]float64]: [26.89 0.67]
[time.Duration]: 2h35m0s
[url.URL]: {https test:abcd123 golangbyexample.com:8000 /tutorials/intro false false type=advance&compact=false history }
[net.IP]: 2001:cb8::17
```
1 change: 1 addition & 0 deletions getenv.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
// - time.Duration
// - bool
// - url.URL
// - net.IP
package getenv

import (
Expand Down
10 changes: 10 additions & 0 deletions getenv_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package getenv_test

import (
"fmt"
"net"
"net/url"
"os"
"time"
Expand Down Expand Up @@ -74,11 +75,20 @@ func ExampleEnvOrDefault() {
val = getenv.EnvOrDefault(key, url.URL{})
fmt.Printf("[%T]: %v\n", val, val)

// net.IP
if err := os.Setenv(key, "2001:cb8::17"); err != nil {
panic(err)
}

val = getenv.EnvOrDefault(key, net.IP{})
fmt.Printf("[%T]: %v\n", val, val)

// Output:
// [string]: golly
// [int]: 123
// [time.Time]: 2022-01-20 00:00:00 +0000 UTC
// [[]float64]: [26.89 0.67]
// [time.Duration]: 2h35m0s
// [url.URL]: {https test:abcd123 golangbyexample.com:8000 /tutorials/intro false false type=advance&compact=false history }
// [net.IP]: 2001:cb8::17
}
87 changes: 87 additions & 0 deletions getenv_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package getenv_test

import (
"net"
"net/url"
"testing"
"time"
Expand Down Expand Up @@ -2684,6 +2685,8 @@ func TestInt16SliceOrDefault(t *testing.T) {
}

func getURL(tb testing.TB, rawURL string) url.URL {
tb.Helper()

val, err := url.Parse(rawURL)
require.NoError(tb, err)

Expand Down Expand Up @@ -2767,3 +2770,87 @@ func TestURLOrDefault(t *testing.T) {
})
}
}

func getIP(tb testing.TB, raw string) net.IP {
tb.Helper()

return net.ParseIP(raw)
}

func TestIPOrDefault(t *testing.T) {
const rawDefault = "0.0.0.0"

type args struct {
key string
defaultVal net.IP
}

type expected struct {
val net.IP
}

var tests = []struct {
name string
precond precondition
args args
expected expected
}{
{
name: "env not set - default returned",
precond: precondition{
setenv: setenv{
isSet: false,
val: "192.168.8.0",
},
},
args: args{
key: testEnvKey,
defaultVal: getIP(t, rawDefault),
},
expected: expected{
val: getIP(t, rawDefault),
},
},
{
name: "env set - env value returned",
precond: precondition{
setenv: setenv{
isSet: true,
val: "192.168.8.0",
},
},
args: args{
key: testEnvKey,
defaultVal: getIP(t, rawDefault),
},
expected: expected{
val: getIP(t, "192.168.8.0"),
},
},
{
name: "empty env value set - default returned",
precond: precondition{
setenv: setenv{
isSet: true,
val: "",
},
},
args: args{
key: testEnvKey,
defaultVal: getIP(t, rawDefault),
},
expected: expected{
val: getIP(t, rawDefault),
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.precond.maybeSetEnv(t, tt.args.key)

got := getenv.EnvOrDefault(tt.args.key, tt.args.defaultVal)
assert.Equal(t, tt.expected.val, got)
})
}
}
9 changes: 9 additions & 0 deletions internal/common_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package internal

import (
"net"
"net/url"
"testing"

Expand Down Expand Up @@ -28,8 +29,16 @@ func (p precondition) maybeSetEnv(tb testing.TB, key string) {
}

func getURL(tb testing.TB, rawURL string) url.URL {
tb.Helper()

val, err := url.Parse(rawURL)
require.NoError(tb, err)

return *val
}

func getIP(tb testing.TB, raw string) net.IP {
tb.Helper()

return net.ParseIP(raw)
}
3 changes: 2 additions & 1 deletion internal/constraint.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package internal

import (
"net"
"net/url"
"time"
)

type (
// EnvParsable is a constraint for supported environment variable types parsers.
EnvParsable interface {
String | Int | Uint | Float | Time | bool | url.URL
String | Int | Uint | Float | Time | bool | url.URL | net.IP
}

// String is a constraint for strings and slice of strings.
Expand Down
11 changes: 11 additions & 0 deletions internal/iface.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package internal

import (
"fmt"
"net"
"net/url"
"time"
)
Expand Down Expand Up @@ -30,6 +31,8 @@ func NewEnvParser(v any) EnvParser {
p = durationParser(t)
case url.URL:
p = urlParser(t)
case net.IP:
p = ipParser(t)
default:
p = nil
}
Expand Down Expand Up @@ -392,3 +395,11 @@ func (t urlParser) ParseEnv(key string, defaltVal any, _ Parameters) any {

return val
}

type ipParser net.IP

func (t ipParser) ParseEnv(key string, defaltVal any, _ Parameters) any {
val := ipOrDefault(key, defaltVal.(net.IP))

return val
}
28 changes: 28 additions & 0 deletions internal/iface_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package internal

import (
"net"
"net/url"
"testing"
"time"
Expand Down Expand Up @@ -263,6 +264,14 @@ func TestNewEnvParser(t *testing.T) {
want: urlParser(url.URL{}),
wantPanic: assert.NotPanics,
},
{
name: "net.IP",
args: args{
v: net.IP{},
},
want: ipParser(net.IP{}),
wantPanic: assert.NotPanics,
},
{
name: "not supported - panics",
args: args{
Expand Down Expand Up @@ -865,6 +874,25 @@ func Test_ParseEnv(t *testing.T) {
},
want: getURL(t, "https.google.com"),
},
{
name: "ipParser",
s: ipParser(net.IP{}),
precond: precondition{
setenv: setenv{
isSet: true,
val: "2001:cb8::17",
},
},
args: args{
key: testEnvKey,
defaltVal: net.IP{},
in2: Parameters{
Separator: "",
Layout: time.DateOnly,
},
},
want: getIP(t, "2001:cb8::17"),
},
}

for _, tt := range tests {
Expand Down
18 changes: 18 additions & 0 deletions internal/parsers.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package internal

import (
"net"
"net/url"
"os"
"strconv"
Expand Down Expand Up @@ -687,3 +688,20 @@ func urlOrDefault(key string, defaultVal url.URL) url.URL {

return *val
}

// ipOrDefault retrieves the net.IP value of the environment variable named
// by the key represented by layout.
// If variable not set or value is empty - defaultVal will be returned.
func ipOrDefault(key string, defaultVal net.IP) net.IP {
env := stringOrDefault(key, "")
if env == "" {
return defaultVal
}

val := net.ParseIP(env)
if val == nil {
return defaultVal
}

return val
}
Loading