update... work pending
This commit is contained in:
310
tplCmd/funcs_tpl.go
Normal file
310
tplCmd/funcs_tpl.go
Normal file
@@ -0,0 +1,310 @@
|
||||
package tplCmd
|
||||
|
||||
import (
|
||||
`fmt`
|
||||
`net`
|
||||
`strconv`
|
||||
`strings`
|
||||
|
||||
`github.com/vishvananda/netlink`
|
||||
`go4.org/netipx`
|
||||
)
|
||||
|
||||
/*
|
||||
This file contains functions strictly for use in templates.
|
||||
*/
|
||||
|
||||
// Host functionality
|
||||
// TODO: How would I do this on non-Linux?
|
||||
|
||||
/*
|
||||
GetDefaultIface returns the interface name for the default route using netlink.
|
||||
IPv4 by default, IPv6 if ipv6 is true.
|
||||
If multiple routes match the default route for the inet family,
|
||||
the lowest metric route's interface will be returned.
|
||||
*/
|
||||
func GetDefaultIface(ipv6 bool) (iface string, err error) {
|
||||
|
||||
var inetFamily int
|
||||
var defNet *net.IPNet
|
||||
var routes []netlink.Route
|
||||
var defRt *netlink.Route
|
||||
var defIface *net.Interface
|
||||
var curPrio int = -1
|
||||
|
||||
// This can even be netlink.FAMILY_ALL, but that's silly.
|
||||
if !ipv6 {
|
||||
inetFamily = netlink.FAMILY_V4
|
||||
defNet = &net.IPNet{
|
||||
IP: net.ParseIP("0.0.0.0"),
|
||||
Mask: net.CIDRMask(0, 32),
|
||||
}
|
||||
} else {
|
||||
inetFamily = netlink.FAMILY_V6
|
||||
defNet = &net.IPNet{
|
||||
IP: net.ParseIP("::"),
|
||||
Mask: net.CIDRMask(0, 128),
|
||||
}
|
||||
}
|
||||
|
||||
if routes, err = netlink.RouteList(nil, inetFamily); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, route := range routes {
|
||||
if !(route.Dst != nil || route.Dst.String() == defNet.String()) {
|
||||
continue
|
||||
}
|
||||
if curPrio == -1 {
|
||||
curPrio = route.Priority
|
||||
defRt = &route
|
||||
} else {
|
||||
if route.Priority < curPrio {
|
||||
curPrio = route.Priority
|
||||
defRt = &route
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if defRt != nil {
|
||||
// There's also defRt.ILinkIndex, which is used for VLANs, tunnels, etc.
|
||||
if defIface, err = net.InterfaceByIndex(defRt.LinkIndex); err != nil {
|
||||
return
|
||||
}
|
||||
if defIface != nil {
|
||||
iface = defIface.Name
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func GetSITIface() () {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Conversions/assertions/coercions.
|
||||
|
||||
/*
|
||||
TplIsNil returns true if v is nil. This lets you determine if e.g. a map or slice is empty or nil.
|
||||
It currently only really works for a []interface{}, map[interface{}]interface{}, or map[string]interface{}.
|
||||
*/
|
||||
func TplIsNil(v interface{}) (isNil bool) {
|
||||
|
||||
switch t := v.(type) {
|
||||
case []interface{}:
|
||||
isNil = t == nil
|
||||
case map[interface{}]interface{}:
|
||||
isNil = t == nil
|
||||
case map[string]interface{}:
|
||||
isNil = t == nil
|
||||
case nil:
|
||||
isNil = true
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// TplToBool attempts to determine a boolean from v. Note that for numbers, b is true if v is *NOT* 0.
|
||||
func TplToBool(v interface{}) (b bool, err error) {
|
||||
|
||||
switch t := v.(type) {
|
||||
case bool:
|
||||
b = t
|
||||
case string:
|
||||
switch s := strings.ToLower(t); s {
|
||||
case "true", "y", "yes", "on", "1":
|
||||
b = true
|
||||
}
|
||||
case []byte:
|
||||
switch s := strings.ToLower(string(t)); s {
|
||||
case "true", "y", "yes", "on", "1":
|
||||
b = true
|
||||
}
|
||||
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64:
|
||||
b = t != 0
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
TplToFloat returns a float64 from v.
|
||||
Strings will be run through strconv.ParseFloat with 64 bitness.
|
||||
Mind overflows.
|
||||
*/
|
||||
func TplToFloat(v interface{}) (i float64, err error) {
|
||||
|
||||
switch t := v.(type) {
|
||||
case uint, uint8, uint16, uint32, uint64:
|
||||
i = float64(t.(uint64))
|
||||
case int, int8, int16, int32, int64:
|
||||
i = float64(t.(int64))
|
||||
case float64:
|
||||
i = t
|
||||
case float32:
|
||||
i = float64(t)
|
||||
case string:
|
||||
if i, err = strconv.ParseFloat(t, 64); err != nil {
|
||||
return
|
||||
}
|
||||
case []byte:
|
||||
if i, err = strconv.ParseFloat(string(t), 64); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
TplToInt returns a signed 64-bit integer from primitives.
|
||||
Strings will be run through strconv.ParseInt with base 10 and 64 bitness.
|
||||
Mind overflows.
|
||||
*/
|
||||
func TplToInt(v interface{}) (i int64, err error) {
|
||||
|
||||
switch t := v.(type) {
|
||||
case uint, uint8, uint16, uint32, uint64:
|
||||
i = int64(t.(uint64)) // If an overflow happens anywhere, it's either here or the string/[]bytes.
|
||||
case int64:
|
||||
i = t
|
||||
case int, int8, int16, int32:
|
||||
i = t.(int64)
|
||||
case float32, float64:
|
||||
i = int64(t.(float64))
|
||||
case string:
|
||||
if i, err = strconv.ParseInt(t, 10, 64); err != nil {
|
||||
return
|
||||
}
|
||||
case []byte:
|
||||
if i, err = strconv.ParseInt(string(t), 10, 64); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
TplToMap attempts to return a map[string]interface{} from v.
|
||||
Values can then be used with other TplTo* functions further.
|
||||
m will be nil if it can't be asserted.
|
||||
*/
|
||||
func TplToMap(v interface{}) (m map[string]interface{}, err error) {
|
||||
|
||||
switch t := v.(type) {
|
||||
case map[string]interface{}:
|
||||
m = t
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// TplToString returns a string representation of primitives.
|
||||
func TplToString(v interface{}) (s string, err error) {
|
||||
|
||||
switch t := v.(type) {
|
||||
case string:
|
||||
s = t
|
||||
case []byte:
|
||||
s = string(t)
|
||||
default:
|
||||
s = fmt.Sprintf("%v", v)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
TplToUint returns an unsigned 64-bit integer from primitives.
|
||||
Strings will be run through strconv.ParseUint with base 10 and 64 bitness.
|
||||
Mind overflows.
|
||||
*/
|
||||
func TplToUint(v interface{}) (i uint64, err error) {
|
||||
|
||||
switch t := v.(type) {
|
||||
case uint64:
|
||||
i = t
|
||||
case uint, uint8, uint16, uint32:
|
||||
i = t.(uint64)
|
||||
case int, int8, int16, int32, int64:
|
||||
i = uint64(t.(int64))
|
||||
case float32, float64:
|
||||
i = uint64(t.(float64))
|
||||
case string:
|
||||
if i, err = strconv.ParseUint(t, 10, 64); err != nil {
|
||||
return
|
||||
}
|
||||
case []byte:
|
||||
if i, err = strconv.ParseUint(string(t), 10, 64); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Wrappers
|
||||
|
||||
// TplGetIPSetBuilder returns a netipx.IPSetBuilder.
|
||||
func TplGetIPSetBuilder() (ipsb *netipx.IPSetBuilder) {
|
||||
|
||||
ipsb = new(netipx.IPSetBuilder)
|
||||
*ipsb = netipx.IPSetBuilder{}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// TplGetResolver returns a net.Resolver from the given options.
|
||||
func TplGetResolver(useGo, strictErr bool) (resolver *net.Resolver) {
|
||||
|
||||
resolver = &net.Resolver{
|
||||
PreferGo: useGo,
|
||||
StrictErrors: strictErr,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// TplSplitHostPortHost wraps net.SplitHostPort and returns the host.
|
||||
func TplSplitHostPortHost(s string) (host string, err error) {
|
||||
|
||||
if host, _, err = net.SplitHostPort(s); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// TplSplitHostPortPort wraps net.SplitHostPort and returns the port.
|
||||
func TplSplitHostPortPort(s string) (port string, err error) {
|
||||
|
||||
if _, port, err = net.SplitHostPort(s); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// TplToCidrHost wraps net.ParseCIDR and returns the host net.IP and any error.
|
||||
func TplToCidrHost(s string) (host net.IP, err error) {
|
||||
|
||||
if host, _, err = net.ParseCIDR(s); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// TplToCidrNet wraps net.ParseCIDR and returns the network *net.IPNet and any error.
|
||||
func TplToCidrNet(s string) (netwk *net.IPNet, err error) {
|
||||
|
||||
if _, netwk, err = net.ParseCIDR(s); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user