summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Henderson <dhenderson@gmail.com>2021-08-23 18:45:41 -0400
committerGitHub <noreply@github.com>2021-08-23 18:45:41 -0400
commit5dd7df187aaef5a0b20cc012a143643e01210752 (patch)
treebc75d895b201f7f480f4b9ab7720ced97c2a39bd
parent11b59c7a4c30e9d72c71a63053853b932ed2677c (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.yml77
-rw-r--r--docs/content/functions/net.md117
-rw-r--r--funcs/net.go17
-rw-r--r--funcs/net_test.go42
-rw-r--r--go.mod3
-rw-r--r--go.sum8
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())
+}
diff --git a/go.mod b/go.mod
index 9bc21b91..f6f86484 100644
--- a/go.mod
+++ b/go.mod
@@ -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
diff --git a/go.sum b/go.sum
index 31a7b64d..a781003b 100644
--- a/go.sum
+++ b/go.sum
@@ -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=