diff options
| author | Dave Henderson <dhenderson@gmail.com> | 2021-08-23 18:45:41 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-08-23 18:45:41 -0400 |
| commit | 5dd7df187aaef5a0b20cc012a143643e01210752 (patch) | |
| tree | bc75d895b201f7f480f4b9ab7720ced97c2a39bd | |
| parent | 11b59c7a4c30e9d72c71a63053853b932ed2677c (diff) | |
New functions net.ParseIP, net.ParseIPPrefix, and net.ParseIPRange (#1197)
Signed-off-by: Dave Henderson <dhenderson@gmail.com>
| -rw-r--r-- | docs-src/content/functions/net.yml | 77 | ||||
| -rw-r--r-- | docs/content/functions/net.md | 117 | ||||
| -rw-r--r-- | funcs/net.go | 17 | ||||
| -rw-r--r-- | funcs/net_test.go | 42 | ||||
| -rw-r--r-- | go.mod | 3 | ||||
| -rw-r--r-- | go.sum | 8 |
6 files changed, 262 insertions, 2 deletions
diff --git a/docs-src/content/functions/net.yml b/docs-src/content/functions/net.yml index 5f01cc2b..875698c9 100644 --- a/docs-src/content/functions/net.yml +++ b/docs-src/content/functions/net.yml @@ -1,5 +1,13 @@ ns: net -preamble: '' +preamble: | + The `net` namespace contains functions that can help deal with network-related + lookups and calculations. Some of these functions return specifically-typed + values that contain additional methods useful for formatting or further + calculations. + + [RFC 4632]: http://tools.ietf.org/html/rfc4632 + [RFC 4291]: http://tools.ietf.org/html/rfc4291 + [`inet.af/netaddr`]: https://pkg.go.dev/inet.af/netaddr funcs: - name: net.LookupIP description: | @@ -117,3 +125,70 @@ funcs: [ "v=spf1 -all" ] + - name: net.ParseIP + description: | + Parse the given string as an IP address (a `netaddr.IP` from the + [`inet.af/netaddr`](https://pkg.go.dev/inet.af/netaddr) package). + + Any of `netaddr.IP`'s methods may be called on the resulting value. See + [the docs](https://pkg.go.dev/inet.af/netaddr) for details. + pipeline: true + arguments: + - name: ip + required: true + description: The IP string to parse. It must be either an IPv4 or IPv6 address. + examples: + - | + $ gomplate -i '{{ (net.ParseIP "192.168.0.1").IsPrivate }}' + true + $ gomplate -i '{{ $ip := net.ParseIP (net.LookupIP "example.com") -}} + {{ $ip.Prefix 12 }}' + 93.176.0.0/12 + - name: net.ParseIPPrefix + description: | + Parse the given string as an IP address prefix (CIDR) representing an IP + network (a `netaddr.IPPrefix` from the + [`inet.af/netaddr`][] package). + + The string can be in the form `"192.168.1.0/24"` or `"2001::db8::/32"`, + the CIDR notations defined in [RFC 4632][] and [RFC 4291][]. + + Any of `netaddr.IPPrefix`'s methods may be called on the resulting value. + See [the docs][`inet.af/netaddr`] for details. + pipeline: true + arguments: + - name: ipprefix + required: true + description: The IP address prefix to parse. It must represent either an IPv4 or IPv6 prefix, containing a `/`. + examples: + - | + $ gomplate -i '{{ (net.ParseIPPrefix "192.168.0.0/24").Range }}' + 192.168.0.0-192.168.0.255 + $ gomplate -i '{{ $ip := net.ParseIP (net.LookupIP "example.com") -}} + {{ $net := net.ParseIPPrefix "93.184.0.0/16" -}} + {{ $net.Contains $ip }}' + true + $ gomplate -i '{{ $net := net.ParseIPPrefix "93.184.0.0/12" -}} + {{ $net.Range }}' + 93.176.0.0-93.191.255.255 + - name: net.ParseIPRange + description: | + Parse the given string as an inclusive range of IP addresses from the same + address family (a `netaddr.IPRange` from the [`inet.af/netaddr`][] package). + + The string must contain a hyphen (`-`). + + Any of `netaddr.IPRange`'s methods may be called on the resulting value. + See [the docs][`inet.af/netaddr`] for details. + pipeline: true + arguments: + - name: iprange + required: true + description: The IP address range to parse. It must represent either an IPv4 or IPv6 range, containing a `-`. + examples: + - | + $ gomplate -i '{{ (net.ParseIPRange "192.168.0.0-192.168.0.255").To }}' + 192.168.0.255 + $ gomplate -i '{{ $range := net.ParseIPRange "1.2.3.0-1.2.3.233" -}} + {{ $range.Prefixes }}' + [1.2.3.0/25 1.2.3.128/26 1.2.3.192/27] diff --git a/docs/content/functions/net.md b/docs/content/functions/net.md index 443e4e9d..bbea71e0 100644 --- a/docs/content/functions/net.md +++ b/docs/content/functions/net.md @@ -5,6 +5,14 @@ menu: parent: functions --- +The `net` namespace contains functions that can help deal with network-related +lookups and calculations. Some of these functions return specifically-typed +values that contain additional methods useful for formatting or further +calculations. + +[RFC 4632]: http://tools.ietf.org/html/rfc4632 +[RFC 4291]: http://tools.ietf.org/html/rfc4291 +[`inet.af/netaddr`]: https://pkg.go.dev/inet.af/netaddr ## `net.LookupIP` @@ -203,3 +211,112 @@ $ gomplate -i '{{net.LookupTXT "example.com" | data.ToJSONPretty " " }}' "v=spf1 -all" ] ``` + +## `net.ParseIP` + +Parse the given string as an IP address (a `netaddr.IP` from the +[`inet.af/netaddr`](https://pkg.go.dev/inet.af/netaddr) package). + +Any of `netaddr.IP`'s methods may be called on the resulting value. See +[the docs](https://pkg.go.dev/inet.af/netaddr) for details. + +### Usage + +```go +net.ParseIP ip +``` +```go +ip | net.ParseIP +``` + +### Arguments + +| name | description | +|------|-------------| +| `ip` | _(required)_ The IP string to parse. It must be either an IPv4 or IPv6 address. | + +### Examples + +```console +$ gomplate -i '{{ (net.ParseIP "192.168.0.1").IsPrivate }}' +true +$ gomplate -i '{{ $ip := net.ParseIP (net.LookupIP "example.com") -}} + {{ $ip.Prefix 12 }}' +93.176.0.0/12 +``` + +## `net.ParseIPPrefix` + +Parse the given string as an IP address prefix (CIDR) representing an IP +network (a `netaddr.IPPrefix` from the +[`inet.af/netaddr`][] package). + +The string can be in the form `"192.168.1.0/24"` or `"2001::db8::/32"`, +the CIDR notations defined in [RFC 4632][] and [RFC 4291][]. + +Any of `netaddr.IPPrefix`'s methods may be called on the resulting value. +See [the docs][`inet.af/netaddr`] for details. + +### Usage + +```go +net.ParseIPPrefix ipprefix +``` +```go +ipprefix | net.ParseIPPrefix +``` + +### Arguments + +| name | description | +|------|-------------| +| `ipprefix` | _(required)_ The IP address prefix to parse. It must represent either an IPv4 or IPv6 prefix, containing a `/`. | + +### Examples + +```console +$ gomplate -i '{{ (net.ParseIPPrefix "192.168.0.0/24").Range }}' +192.168.0.0-192.168.0.255 +$ gomplate -i '{{ $ip := net.ParseIP (net.LookupIP "example.com") -}} + {{ $net := net.ParseIPPrefix "93.184.0.0/16" -}} + {{ $net.Contains $ip }}' +true +$ gomplate -i '{{ $net := net.ParseIPPrefix "93.184.0.0/12" -}} + {{ $net.Range }}' +93.176.0.0-93.191.255.255 +``` + +## `net.ParseIPRange` + +Parse the given string as an inclusive range of IP addresses from the same +address family (a `netaddr.IPRange` from the [`inet.af/netaddr`][] package). + +The string must contain a hyphen (`-`). + +Any of `netaddr.IPRange`'s methods may be called on the resulting value. +See [the docs][`inet.af/netaddr`] for details. + +### Usage + +```go +net.ParseIPRange iprange +``` +```go +iprange | net.ParseIPRange +``` + +### Arguments + +| name | description | +|------|-------------| +| `iprange` | _(required)_ The IP address range to parse. It must represent either an IPv4 or IPv6 range, containing a `-`. | + +### Examples + +```console +$ gomplate -i '{{ (net.ParseIPRange "192.168.0.0-192.168.0.255").To }}' +192.168.0.255 +$ gomplate -i '{{ $range := net.ParseIPRange "1.2.3.0-1.2.3.233" -}} + {{ $range.Prefixes }}' +[1.2.3.0/25 1.2.3.128/26 1.2.3.192/27] +``` diff --git a/funcs/net.go b/funcs/net.go index 73481fe2..b110dbdf 100644 --- a/funcs/net.go +++ b/funcs/net.go @@ -5,8 +5,8 @@ import ( stdnet "net" "github.com/hairyhenderson/gomplate/v3/conv" - "github.com/hairyhenderson/gomplate/v3/net" + "inet.af/netaddr" ) // NetNS - the net namespace @@ -65,3 +65,18 @@ func (f NetFuncs) LookupSRVs(name interface{}) ([]*stdnet.SRV, error) { func (f NetFuncs) LookupTXT(name interface{}) ([]string, error) { return net.LookupTXT(conv.ToString(name)) } + +// ParseIP - +func (f NetFuncs) ParseIP(ip interface{}) (netaddr.IP, error) { + return netaddr.ParseIP(conv.ToString(ip)) +} + +// ParseIPPrefix - +func (f NetFuncs) ParseIPPrefix(ipprefix interface{}) (netaddr.IPPrefix, error) { + return netaddr.ParseIPPrefix(conv.ToString(ipprefix)) +} + +// ParseIPRange - +func (f NetFuncs) ParseIPRange(iprange interface{}) (netaddr.IPRange, error) { + return netaddr.ParseIPRange(conv.ToString(iprange)) +} diff --git a/funcs/net_test.go b/funcs/net_test.go index 54f032ae..0c556516 100644 --- a/funcs/net_test.go +++ b/funcs/net_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "inet.af/netaddr" ) func TestCreateNetFuncs(t *testing.T) { @@ -27,3 +28,44 @@ func TestNetLookupIP(t *testing.T) { n := NetFuncs{} assert.Equal(t, "127.0.0.1", must(n.LookupIP("localhost"))) } + +func TestParseIP(t *testing.T) { + n := NetFuncs{} + _, err := n.ParseIP("not an IP") + assert.Error(t, err) + + ip, err := n.ParseIP("2001:470:20::2") + assert.NoError(t, err) + assert.Equal(t, netaddr.IPFrom16([16]byte{ + 0x20, 0x01, 0x04, 0x70, + 0, 0x20, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0x02, + }), ip) +} + +func TestParseIPPrefix(t *testing.T) { + n := NetFuncs{} + _, err := n.ParseIPPrefix("not an IP") + assert.Error(t, err) + + _, err = n.ParseIPPrefix("1.1.1.1") + assert.Error(t, err) + + ipprefix, err := n.ParseIPPrefix("192.168.0.2/28") + assert.NoError(t, err) + assert.Equal(t, "192.168.0.0/28", ipprefix.Masked().String()) +} + +func TestParseIPRange(t *testing.T) { + n := NetFuncs{} + _, err := n.ParseIPRange("not an IP") + assert.Error(t, err) + + _, err = n.ParseIPRange("1.1.1.1") + assert.Error(t, err) + + iprange, err := n.ParseIPRange("192.168.0.2-192.168.23.255") + assert.NoError(t, err) + assert.Equal(t, "192.168.0.2-192.168.23.255", iprange.String()) +} @@ -32,6 +32,7 @@ require ( golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b gotest.tools/v3 v3.0.3 + inet.af/netaddr v0.0.0-20210729200904-31d5ee66059c k8s.io/client-go v0.22.1 ) @@ -84,6 +85,8 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/xanzy/ssh-agent v0.3.1 // indirect go.opencensus.io v0.23.0 // indirect + go4.org/intern v0.0.0-20210108033219-3eb7198706b2 // indirect + go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222180813-1025295fd063 // indirect golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d // indirect golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect golang.org/x/text v0.3.7 // indirect @@ -192,6 +192,7 @@ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3 github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad h1:Qk76DOWdOp+GlyDKBAG3Klr9cn7N+LcYc82AZ2S7+cA= github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad/go.mod h1:mPKfmRa823oBIgl2r20LeMSpTAteW5j7FLkc0vjmzyQ= +github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= @@ -716,6 +717,11 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +go4.org/intern v0.0.0-20210108033219-3eb7198706b2 h1:VFTf+jjIgsldaz/Mr00VaCSswHJrI2hIjQygE/W4IMg= +go4.org/intern v0.0.0-20210108033219-3eb7198706b2/go.mod h1:vLqJ+12kCw61iCWsPto0EOHhBS+o4rO5VIucbc9g2Cc= +go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222175341-b30ae309168e/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E= +go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222180813-1025295fd063 h1:1tk03FUNpulq2cuWpXZWj649rwJpk0d20rxWiopKRmc= +go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222180813-1025295fd063/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E= gocloud.dev v0.23.0 h1:u/6F8slWwaZPgGpjpNp0jzH+1P/M2ri7qEP3lFgbqBE= gocloud.dev v0.23.0/go.mod h1:zklCCIIo1N9ELkU2S2E7tW8P8eeMU7oGLeQCXdDwx9Q= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1236,6 +1242,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +inet.af/netaddr v0.0.0-20210729200904-31d5ee66059c h1:AmHBNAHZCfyMGFk5kd060kpnQ6GJLHmGwdJGGQgr1Y8= +inet.af/netaddr v0.0.0-20210729200904-31d5ee66059c/go.mod h1:z0nx+Dh+7N7CC8V5ayHtHGpZpxLQZZxkIaaz6HN65Ls= k8s.io/api v0.22.1/go.mod h1:bh13rkTp3F1XEaLGykbyRD2QaTTzPm0e/BMd8ptFONY= k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= k8s.io/client-go v0.22.1 h1:jW0ZSHi8wW260FvcXHkIa0NLxFBQszTlhiAVsU5mopw= |
