summaryrefslogtreecommitdiff
path: root/funcs
diff options
context:
space:
mode:
authorDave Henderson <dhenderson@gmail.com>2023-02-04 16:32:49 -0500
committerDave Henderson <dhenderson@gmail.com>2023-02-04 21:01:14 -0500
commitedf224ccf7c66498b2d9743fcfb29bf4c0960931 (patch)
tree33461cb75f2d63e91be1d8a7ec5a9e72ce962f12 /funcs
parentaf3e81ac52f93f07aea644b6397dbca97e5d30aa (diff)
Deprecate netaddr-based funcs
Signed-off-by: Dave Henderson <dhenderson@gmail.com>
Diffstat (limited to 'funcs')
-rw-r--r--funcs/net.go144
-rw-r--r--funcs/net_test.go124
2 files changed, 191 insertions, 77 deletions
diff --git a/funcs/net.go b/funcs/net.go
index 0d87b98a..ab692cc1 100644
--- a/funcs/net.go
+++ b/funcs/net.go
@@ -2,14 +2,16 @@ package funcs
import (
"context"
+ "fmt"
"math/big"
stdnet "net"
"net/netip"
- "github.com/apparentlymart/go-cidr/cidr"
"github.com/hairyhenderson/gomplate/v3/conv"
+ "github.com/hairyhenderson/gomplate/v3/internal/cidr"
+ "github.com/hairyhenderson/gomplate/v3/internal/deprecated"
"github.com/hairyhenderson/gomplate/v3/net"
- "github.com/pkg/errors"
+ "go4.org/netipx"
"inet.af/netaddr"
)
@@ -73,46 +75,76 @@ func (f NetFuncs) LookupTXT(name interface{}) ([]string, error) {
}
// ParseIP -
-func (f NetFuncs) ParseIP(ip interface{}) (netaddr.IP, error) {
+//
+// Deprecated: use [ParseAddr] instead
+func (f *NetFuncs) ParseIP(ip interface{}) (netaddr.IP, error) {
+ deprecated.WarnDeprecated(f.ctx, "net.ParseIP is deprecated - use net.ParseAddr instead")
return netaddr.ParseIP(conv.ToString(ip))
}
// ParseIPPrefix -
-func (f NetFuncs) ParseIPPrefix(ipprefix interface{}) (netaddr.IPPrefix, error) {
+//
+// Deprecated: use [ParsePrefix] instead
+func (f *NetFuncs) ParseIPPrefix(ipprefix interface{}) (netaddr.IPPrefix, error) {
+ deprecated.WarnDeprecated(f.ctx, "net.ParseIPPrefix is deprecated - use net.ParsePrefix instead")
return netaddr.ParseIPPrefix(conv.ToString(ipprefix))
}
// ParseIPRange -
-func (f NetFuncs) ParseIPRange(iprange interface{}) (netaddr.IPRange, error) {
+//
+// Deprecated: use [ParseRange] instead
+func (f *NetFuncs) ParseIPRange(iprange interface{}) (netaddr.IPRange, error) {
+ deprecated.WarnDeprecated(f.ctx, "net.ParseIPRange is deprecated - use net.ParseRange instead")
return netaddr.ParseIPRange(conv.ToString(iprange))
}
-func (f NetFuncs) parseStdnetIPNet(prefix interface{}) (*stdnet.IPNet, error) {
- switch p := prefix.(type) {
- case *stdnet.IPNet:
- return p, nil
- case netaddr.IPPrefix:
- return p.Masked().IPNet(), nil
- case netip.Prefix:
- net := &stdnet.IPNet{
- IP: p.Masked().Addr().AsSlice(),
- Mask: stdnet.CIDRMask(p.Bits(), p.Addr().BitLen()),
- }
- return net, nil
- default:
- _, network, err := stdnet.ParseCIDR(conv.ToString(prefix))
- return network, err
- }
+// ParseAddr -
+func (f NetFuncs) ParseAddr(ip interface{}) (netip.Addr, error) {
+ return netip.ParseAddr(conv.ToString(ip))
}
+// ParsePrefix -
+func (f NetFuncs) ParsePrefix(ipprefix interface{}) (netip.Prefix, error) {
+ return netip.ParsePrefix(conv.ToString(ipprefix))
+}
+
+// ParseRange -
+//
+// Experimental: this API may change in the future
+func (f NetFuncs) ParseRange(iprange interface{}) (netipx.IPRange, error) {
+ return netipx.ParseIPRange(conv.ToString(iprange))
+}
+
+// func (f *NetFuncs) parseStdnetIPNet(prefix interface{}) (*stdnet.IPNet, error) {
+// switch p := prefix.(type) {
+// case *stdnet.IPNet:
+// return p, nil
+// case netaddr.IPPrefix:
+// deprecated.WarnDeprecated(f.ctx,
+// "support for netaddr.IPPrefix is deprecated - use net.ParsePrefix to produce a netip.Prefix instead")
+// return p.Masked().IPNet(), nil
+// case netip.Prefix:
+// net := &stdnet.IPNet{
+// IP: p.Masked().Addr().AsSlice(),
+// Mask: stdnet.CIDRMask(p.Bits(), p.Addr().BitLen()),
+// }
+// return net, nil
+// default:
+// _, network, err := stdnet.ParseCIDR(conv.ToString(prefix))
+// return network, err
+// }
+// }
+
// TODO: look at using this instead of parseStdnetIPNet
//
//nolint:unused
-func (f NetFuncs) parseNetipPrefix(prefix interface{}) (netip.Prefix, error) {
+func (f *NetFuncs) parseNetipPrefix(prefix interface{}) (netip.Prefix, error) {
switch p := prefix.(type) {
case *stdnet.IPNet:
return f.ipPrefixFromIPNet(p), nil
case netaddr.IPPrefix:
+ deprecated.WarnDeprecated(f.ctx,
+ "support for netaddr.IPPrefix is deprecated - use net.ParsePrefix to produce a netip.Prefix instead")
return f.ipPrefixFromIPNet(p.Masked().IPNet()), nil
case netip.Prefix:
return p, nil
@@ -121,10 +153,10 @@ func (f NetFuncs) parseNetipPrefix(prefix interface{}) (netip.Prefix, error) {
}
}
-func (f NetFuncs) ipFromNetIP(n stdnet.IP) netip.Addr {
- ip, _ := netip.AddrFromSlice(n)
- return ip
-}
+// func (f NetFuncs) ipFromNetIP(n stdnet.IP) netip.Addr {
+// ip, _ := netip.AddrFromSlice(n)
+// return ip
+// }
func (f NetFuncs) ipPrefixFromIPNet(n *stdnet.IPNet) netip.Prefix {
ip, _ := netip.AddrFromSlice(n.IP)
@@ -134,52 +166,62 @@ func (f NetFuncs) ipPrefixFromIPNet(n *stdnet.IPNet) netip.Prefix {
// CIDRHost -
// Experimental!
-func (f NetFuncs) CIDRHost(hostnum interface{}, prefix interface{}) (netip.Addr, error) {
+func (f *NetFuncs) CIDRHost(hostnum interface{}, prefix interface{}) (netip.Addr, error) {
if err := checkExperimental(f.ctx); err != nil {
return netip.Addr{}, err
}
- network, err := f.parseStdnetIPNet(prefix)
+ network, err := f.parseNetipPrefix(prefix)
if err != nil {
return netip.Addr{}, err
}
ip, err := cidr.HostBig(network, big.NewInt(conv.ToInt64(hostnum)))
- return f.ipFromNetIP(ip), err
+ return ip, err
}
// CIDRNetmask -
// Experimental!
-func (f NetFuncs) CIDRNetmask(prefix interface{}) (netip.Addr, error) {
+func (f *NetFuncs) CIDRNetmask(prefix interface{}) (netip.Addr, error) {
if err := checkExperimental(f.ctx); err != nil {
return netip.Addr{}, err
}
- network, err := f.parseStdnetIPNet(prefix)
+ p, err := f.parseNetipPrefix(prefix)
if err != nil {
return netip.Addr{}, err
}
- netmask := stdnet.IP(network.Mask)
- return f.ipFromNetIP(netmask), nil
+ // fill an appropriately sized byte slice with as many 1s as prefix bits
+ b := make([]byte, p.Addr().BitLen()/8)
+ for i := 0; i < p.Bits(); i++ {
+ b[i/8] |= 1 << uint(7-i%8)
+ }
+
+ m, ok := netip.AddrFromSlice(b)
+ if !ok {
+ return netip.Addr{}, fmt.Errorf("invalid netmask")
+ }
+
+ return m, nil
}
// CIDRSubnets -
// Experimental!
-func (f NetFuncs) CIDRSubnets(newbits interface{}, prefix interface{}) ([]netip.Prefix, error) {
+func (f *NetFuncs) CIDRSubnets(newbits interface{}, prefix interface{}) ([]netip.Prefix, error) {
if err := checkExperimental(f.ctx); err != nil {
return nil, err
}
- network, err := f.parseStdnetIPNet(prefix)
+ network, err := f.parseNetipPrefix(prefix)
if err != nil {
return nil, err
}
nBits := conv.ToInt(newbits)
if nBits < 1 {
- return nil, errors.Errorf("must extend prefix by at least one bit")
+ return nil, fmt.Errorf("must extend prefix by at least one bit")
}
maxNetNum := int64(1 << uint64(nBits))
@@ -189,7 +231,7 @@ func (f NetFuncs) CIDRSubnets(newbits interface{}, prefix interface{}) ([]netip.
if err != nil {
return nil, err
}
- retValues[i] = f.ipPrefixFromIPNet(subnet)
+ retValues[i] = subnet
}
return retValues, nil
@@ -197,22 +239,22 @@ func (f NetFuncs) CIDRSubnets(newbits interface{}, prefix interface{}) ([]netip.
// CIDRSubnetSizes -
// Experimental!
-func (f NetFuncs) CIDRSubnetSizes(args ...interface{}) ([]netip.Prefix, error) {
+func (f *NetFuncs) CIDRSubnetSizes(args ...interface{}) ([]netip.Prefix, error) {
if err := checkExperimental(f.ctx); err != nil {
return nil, err
}
if len(args) < 2 {
- return nil, errors.Errorf("wrong number of args: want 2 or more, got %d", len(args))
+ return nil, fmt.Errorf("wrong number of args: want 2 or more, got %d", len(args))
}
- network, err := f.parseStdnetIPNet(args[len(args)-1])
+ network, err := f.parseNetipPrefix(args[len(args)-1])
if err != nil {
return nil, err
}
newbits := conv.ToInts(args[:len(args)-1]...)
- startPrefixLen, _ := network.Mask.Size()
+ startPrefixLen := network.Bits()
firstLength := newbits[0]
firstLength += startPrefixLen
@@ -222,38 +264,38 @@ func (f NetFuncs) CIDRSubnetSizes(args ...interface{}) ([]netip.Prefix, error) {
for i, length := range newbits {
if length < 1 {
- return nil, errors.Errorf("must extend prefix by at least one bit")
+ return nil, fmt.Errorf("must extend prefix by at least one bit")
}
// For portability with 32-bit systems where the subnet number
// will be a 32-bit int, we only allow extension of 32 bits in
// one call even if we're running on a 64-bit machine.
// (Of course, this is significant only for IPv6.)
if length > 32 {
- return nil, errors.Errorf("may not extend prefix by more than 32 bits")
+ return nil, fmt.Errorf("may not extend prefix by more than 32 bits")
}
length += startPrefixLen
- if length > (len(network.IP) * 8) {
+ if length > network.Addr().BitLen() {
protocol := "IP"
- switch len(network.IP) {
- case stdnet.IPv4len:
+ switch {
+ case network.Addr().Is4():
protocol = "IPv4"
- case stdnet.IPv6len:
+ case network.Addr().Is6():
protocol = "IPv6"
}
- return nil, errors.Errorf("would extend prefix to %d bits, which is too long for an %s address", length, protocol)
+ return nil, fmt.Errorf("would extend prefix to %d bits, which is too long for an %s address", length, protocol)
}
next, rollover := cidr.NextSubnet(current, length)
- if rollover || !network.Contains(next.IP) {
+ if rollover || !network.Contains(next.Addr()) {
// If we run out of suffix bits in the base CIDR prefix then
// NextSubnet will start incrementing the prefix bits, which
// we don't allow because it would then allocate addresses
// outside of the caller's given prefix.
- return nil, errors.Errorf("not enough remaining address space for a subnet with a prefix of %d bits after %s", length, current.String())
+ return nil, fmt.Errorf("not enough remaining address space for a subnet with a prefix of %d bits after %s", length, current.String())
}
current = next
- retValues[i] = f.ipPrefixFromIPNet(current)
+ retValues[i] = current
}
return retValues, nil
diff --git a/funcs/net_test.go b/funcs/net_test.go
index e8914fa6..642a356c 100644
--- a/funcs/net_test.go
+++ b/funcs/net_test.go
@@ -9,6 +9,7 @@ import (
"github.com/hairyhenderson/gomplate/v3/internal/config"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
"inet.af/netaddr"
)
@@ -39,12 +40,12 @@ func TestNetLookupIP(t *testing.T) {
func TestParseIP(t *testing.T) {
t.Parallel()
- n := NetFuncs{}
+ n := testNetNS()
_, err := n.ParseIP("not an IP")
assert.Error(t, err)
ip, err := n.ParseIP("2001:470:20::2")
- assert.NoError(t, err)
+ require.NoError(t, err)
assert.Equal(t, netaddr.IPFrom16([16]byte{
0x20, 0x01, 0x04, 0x70,
0, 0x20, 0, 0,
@@ -56,7 +57,7 @@ func TestParseIP(t *testing.T) {
func TestParseIPPrefix(t *testing.T) {
t.Parallel()
- n := NetFuncs{}
+ n := testNetNS()
_, err := n.ParseIPPrefix("not an IP")
assert.Error(t, err)
@@ -64,14 +65,14 @@ func TestParseIPPrefix(t *testing.T) {
assert.Error(t, err)
ipprefix, err := n.ParseIPPrefix("192.168.0.2/28")
- assert.NoError(t, err)
+ require.NoError(t, err)
assert.Equal(t, "192.168.0.0/28", ipprefix.Masked().String())
}
func TestParseIPRange(t *testing.T) {
t.Parallel()
- n := NetFuncs{}
+ n := testNetNS()
_, err := n.ParseIPRange("not an IP")
assert.Error(t, err)
@@ -79,10 +80,56 @@ func TestParseIPRange(t *testing.T) {
assert.Error(t, err)
iprange, err := n.ParseIPRange("192.168.0.2-192.168.23.255")
- assert.NoError(t, err)
+ require.NoError(t, err)
assert.Equal(t, "192.168.0.2-192.168.23.255", iprange.String())
}
+func TestParseAddr(t *testing.T) {
+ t.Parallel()
+
+ n := testNetNS()
+ _, err := n.ParseAddr("not an IP")
+ assert.Error(t, err)
+
+ ip, err := n.ParseAddr("2001:470:20::2")
+ require.NoError(t, err)
+ assert.Equal(t, netip.AddrFrom16([16]byte{
+ 0x20, 0x01, 0x04, 0x70,
+ 0, 0x20, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0x02,
+ }), ip)
+}
+
+func TestParsePrefix(t *testing.T) {
+ t.Parallel()
+
+ n := testNetNS()
+ _, err := n.ParsePrefix("not an IP")
+ assert.Error(t, err)
+
+ _, err = n.ParsePrefix("1.1.1.1")
+ assert.Error(t, err)
+
+ ipprefix, err := n.ParsePrefix("192.168.0.2/28")
+ require.NoError(t, err)
+ assert.Equal(t, "192.168.0.0/28", ipprefix.Masked().String())
+}
+
+func TestParseRange(t *testing.T) {
+ t.Parallel()
+
+ n := testNetNS()
+ _, err := n.ParseRange("not an IP")
+ assert.Error(t, err)
+
+ _, err = n.ParseRange("1.1.1.1")
+ assert.Error(t, err)
+
+ iprange, err := n.ParseRange("192.168.0.2-192.168.23.255")
+ require.NoError(t, err)
+ assert.Equal(t, "192.168.0.2-192.168.23.255", iprange.String())
+}
func testNetNS() *NetFuncs {
return &NetFuncs{ctx: config.SetExperimental(context.Background())}
}
@@ -94,48 +141,48 @@ func TestCIDRHost(t *testing.T) {
_, netIP, _ := stdnet.ParseCIDR("10.12.127.0/20")
ip, err := n.CIDRHost(16, netIP)
- assert.NoError(t, err)
+ require.NoError(t, err)
assert.Equal(t, "10.12.112.16", ip.String())
ip, err = n.CIDRHost(268, netIP)
- assert.NoError(t, err)
+ require.NoError(t, err)
assert.Equal(t, "10.12.113.12", ip.String())
_, netIP, _ = stdnet.ParseCIDR("fd00:fd12:3456:7890:00a2::/72")
ip, err = n.CIDRHost(34, netIP)
- assert.NoError(t, err)
+ require.NoError(t, err)
assert.Equal(t, "fd00:fd12:3456:7890::22", ip.String())
// inet.af/netaddr.IPPrefix
ipPrefix, _ := n.ParseIPPrefix("10.12.127.0/20")
ip, err = n.CIDRHost(16, ipPrefix)
- assert.NoError(t, err)
+ require.NoError(t, err)
assert.Equal(t, "10.12.112.16", ip.String())
ip, err = n.CIDRHost(268, ipPrefix)
- assert.NoError(t, err)
+ require.NoError(t, err)
assert.Equal(t, "10.12.113.12", ip.String())
ipPrefix, _ = n.ParseIPPrefix("fd00:fd12:3456:7890:00a2::/72")
ip, err = n.CIDRHost(34, ipPrefix)
- assert.NoError(t, err)
+ require.NoError(t, err)
assert.Equal(t, "fd00:fd12:3456:7890::22", ip.String())
// net/netip.Prefix
prefix := netip.MustParsePrefix("10.12.127.0/20")
ip, err = n.CIDRHost(16, prefix)
- assert.NoError(t, err)
+ require.NoError(t, err)
assert.Equal(t, "10.12.112.16", ip.String())
ip, err = n.CIDRHost(268, prefix)
- assert.NoError(t, err)
+ require.NoError(t, err)
assert.Equal(t, "10.12.113.12", ip.String())
prefix = netip.MustParsePrefix("fd00:fd12:3456:7890:00a2::/72")
ip, err = n.CIDRHost(34, prefix)
- assert.NoError(t, err)
+ require.NoError(t, err)
assert.Equal(t, "fd00:fd12:3456:7890::22", ip.String())
}
@@ -143,11 +190,11 @@ func TestCIDRNetmask(t *testing.T) {
n := testNetNS()
ip, err := n.CIDRNetmask("10.0.0.0/12")
- assert.NoError(t, err)
+ require.NoError(t, err)
assert.Equal(t, "255.240.0.0", ip.String())
ip, err = n.CIDRNetmask("fd00:fd12:3456:7890:00a2::/72")
- assert.NoError(t, err)
+ require.NoError(t, err)
assert.Equal(t, "ffff:ffff:ffff:ffff:ff00::", ip.String())
}
@@ -156,11 +203,11 @@ func TestCIDRSubnets(t *testing.T) {
network := netip.MustParsePrefix("10.0.0.0/16")
subnets, err := n.CIDRSubnets(-1, network)
- assert.Nil(t, subnets)
assert.Error(t, err)
+ assert.Nil(t, subnets)
subnets, err = n.CIDRSubnets(2, network)
- assert.NoError(t, err)
+ require.NoError(t, err)
assert.Len(t, subnets, 4)
assert.Equal(t, "10.0.0.0/18", subnets[0].String())
assert.Equal(t, "10.0.64.0/18", subnets[1].String())
@@ -170,25 +217,50 @@ func TestCIDRSubnets(t *testing.T) {
func TestCIDRSubnetSizes(t *testing.T) {
n := testNetNS()
- network := netip.MustParsePrefix("10.1.0.0/16")
- subnets, err := n.CIDRSubnetSizes(network)
- assert.Nil(t, subnets)
+ subnets, err := n.CIDRSubnetSizes(netip.MustParsePrefix("10.1.0.0/16"))
assert.Error(t, err)
-
- subnets, err = n.CIDRSubnetSizes(32, network)
assert.Nil(t, subnets)
+
+ subnets, err = n.CIDRSubnetSizes(32, netip.MustParsePrefix("10.1.0.0/16"))
assert.Error(t, err)
+ assert.Nil(t, subnets)
- subnets, err = n.CIDRSubnetSizes(-1, network)
+ subnets, err = n.CIDRSubnetSizes(127, netip.MustParsePrefix("ffff::/48"))
+ assert.Error(t, err)
assert.Nil(t, subnets)
+
+ subnets, err = n.CIDRSubnetSizes(-1, netip.MustParsePrefix("10.1.0.0/16"))
assert.Error(t, err)
+ assert.Nil(t, subnets)
+
+ network := netip.MustParsePrefix("8000::/1")
+ subnets, err = n.CIDRSubnetSizes(1, 2, 2, network)
+ require.NoError(t, err)
+ assert.Len(t, subnets, 3)
+ assert.Equal(t, "8000::/2", subnets[0].String())
+ assert.Equal(t, "c000::/3", subnets[1].String())
+ assert.Equal(t, "e000::/3", subnets[2].String())
+ network = netip.MustParsePrefix("10.1.0.0/16")
subnets, err = n.CIDRSubnetSizes(4, 4, 8, 4, network)
- assert.NoError(t, err)
+ require.NoError(t, err)
assert.Len(t, subnets, 4)
assert.Equal(t, "10.1.0.0/20", subnets[0].String())
assert.Equal(t, "10.1.16.0/20", subnets[1].String())
assert.Equal(t, "10.1.32.0/24", subnets[2].String())
assert.Equal(t, "10.1.48.0/20", subnets[3].String())
+
+ network = netip.MustParsePrefix("2016:1234:5678:9abc:ffff:ffff:ffff:cafe/64")
+ subnets, err = n.CIDRSubnetSizes(2, 2, 3, 3, 6, 6, 8, 10, network)
+ require.NoError(t, err)
+ assert.Len(t, subnets, 8)
+ assert.Equal(t, "2016:1234:5678:9abc::/66", subnets[0].String())
+ assert.Equal(t, "2016:1234:5678:9abc:4000::/66", subnets[1].String())
+ assert.Equal(t, "2016:1234:5678:9abc:8000::/67", subnets[2].String())
+ assert.Equal(t, "2016:1234:5678:9abc:a000::/67", subnets[3].String())
+ assert.Equal(t, "2016:1234:5678:9abc:c000::/70", subnets[4].String())
+ assert.Equal(t, "2016:1234:5678:9abc:c400::/70", subnets[5].String())
+ assert.Equal(t, "2016:1234:5678:9abc:c800::/72", subnets[6].String())
+ assert.Equal(t, "2016:1234:5678:9abc:c900::/74", subnets[7].String())
}