diff options
| author | Dave Henderson <dhenderson@gmail.com> | 2017-06-13 11:26:45 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-06-13 11:26:45 -0400 |
| commit | bc52886c7cf83bcbd4e4ae96ab4b0e2a84d527e7 (patch) | |
| tree | 278bfef3e032c8713b8ca864021df1f12d1832d5 | |
| parent | c40d861bc6b49d646ef7aff618ae8ff826bc1619 (diff) | |
| parent | a0cbffc2972202b05c48d5ecda7773578c7026a2 (diff) | |
Merge pull request #158 from hairyhenderson/add-net-lookup-funcs
Adding net.Lookup* functions
| -rw-r--r-- | docs/content/functions/net.md | 200 | ||||
| -rw-r--r-- | funcs.go | 1 | ||||
| -rw-r--r-- | funcs/net.go | 57 | ||||
| -rw-r--r-- | funcs/net_test.go | 12 | ||||
| -rw-r--r-- | net/net.go | 62 | ||||
| -rw-r--r-- | net/net_test.go | 32 | ||||
| -rw-r--r-- | test/integration/net.bats | 19 |
7 files changed, 383 insertions, 0 deletions
diff --git a/docs/content/functions/net.md b/docs/content/functions/net.md new file mode 100644 index 00000000..08e4c137 --- /dev/null +++ b/docs/content/functions/net.md @@ -0,0 +1,200 @@ +--- +title: net functions +menu: + main: + parent: functions +--- + +## `net.LookupIP` + +Resolve an IPv4 address for a given host name. When multiple IP addresses +are resolved, the first one is returned. + +**Note:** Unresolvable hostnames will result in an error, and `gomplate` will panic. + +### Usage + +```go +net.LookupIP name +``` + +### Arguments + +| name | description | +|--------|-------| +| `name` | The hostname to look up. This can be a simple hostname, or a fully-qualified domain name. | + +### Examples + +```console +$ gomplate -i '{{ net.LookupIP "example.com" }}' +93.184.216.34 +``` + +## `net.LookupIPs` + +Resolve all IPv4 addresses for a given host name. Returns an array of strings. + +**Note:** Unresolvable hostnames will result in an error, and `gomplate` will panic. + +### Usage + +```go +net.LookupIPs name +``` + +### Arguments + +| name | description | +|--------|-------| +| `name` | The hostname to look up. This can be a simple hostname, or a fully-qualified domain name. | + +### Examples + +```console +$ gomplate -i '{{ join (net.LookupIPs "twitter.com") "," }}' +104.244.42.65,104.244.42.193 +``` + +## `net.LookupCNAME` + +Resolve the canonical name for a given host name. This does a DNS lookup for the +`CNAME` record type. If no `CNAME` is present, a canonical form of the given name +is returned -- e.g. `net.LookupCNAME "localhost"` will return `"localhost."`. + +**Note:** Unresolvable hostnames will result in an error, and `gomplate` will panic. + +### Usage + +```go +net.LookupCNAME name +``` + +### Arguments + +| name | description | +|--------|-------| +| `name` | The hostname to look up. This can be a simple hostname, or a fully-qualified domain name. | + +### Examples + +```console +$ gomplate -i '{{ net.LookupCNAME "www.amazon.com" }}' +d3ag4hukkh62yn.cloudfront.net. +``` + +## `net.LookupSRV` + +Resolve a DNS [`SRV` service record](https://en.wikipedia.org/wiki/SRV_record). +This implementation supports the canonical [RFC2782](https://tools.ietf.org/html/rfc2782) +form (i.e. `_Service._Proto.Name`), but other forms are also supported, such as +those served by [Consul's DNS interface](https://www.consul.io/docs/agent/dns.html#standard-lookup). + +When multiple records are returned, this function returns the first. + +A [`net.SRV`](https://golang.org/pkg/net/#SRV) data structure is returned. The +following properties are available: +- `Target` - _(string)_ the hostname where the service can be reached +- `Port` - _(uint16)_ the service's port +- `Priority`, `Weight` - see [RFC2782](https://tools.ietf.org/html/rfc2782) for details + +**Note:** Unresolvable hostnames will result in an error, and `gomplate` will panic. + +### Usage + +```go +net.LookupSRV name +``` + +### Arguments + +| name | description | +|--------|-------| +| `name` | The service name to look up | + +### Examples + +```console +$ gomplate -i '{{ net.LookupSRV "_sip._udp.sip.voice.google.com" | toJSONPretty " " }} +' +{ + "Port": 5060, + "Priority": 10, + "Target": "sip-anycast-1.voice.google.com.", + "Weight": 1 +} +``` + +## `net.LookupSRVs` + +Resolve a DNS [`SRV` service record](https://en.wikipedia.org/wiki/SRV_record). +This implementation supports the canonical [RFC2782](https://tools.ietf.org/html/rfc2782) +form (i.e. `_Service._Proto.Name`), but other forms are also supported, such as +those served by [Consul's DNS interface](https://www.consul.io/docs/agent/dns.html#standard-lookup). + +This function returns all available SRV records. + +An array of [`net.SRV`](https://golang.org/pkg/net/#SRV) data structures is +returned. For each element, the following properties are available: +- `Target` - _(string)_ the hostname where the service can be reached +- `Port` - _(uint16)_ the service's port +- `Priority`, `Weight` - see [RFC2782](https://tools.ietf.org/html/rfc2782) for details + +**Note:** Unresolvable hostnames will result in an error, and `gomplate` will panic. + +### Usage + +```go +net.LookupSRVs name +``` + +### Arguments + +| name | description | +|--------|-------| +| `name` | The service name to look up | + +### Examples + +_input.tmpl:_ +``` +{{ range (net.LookupSRVs "_sip._udp.sip.voice.google.com") -}} +priority={{.Priority}}/port={{.Port}} +{{- end }} +``` + +```console +$ gomplate -f input.tmpl +priority=10/port=5060 +priority=20/port=5060 +``` + +## `net.LookupTXT` + +Resolve a DNS [`TXT` record](https://en.wikipedia.org/wiki/SRV_record). + +This function returns all available TXT records as an array of strings. + +**Note:** Unresolvable hostnames will result in an error, and `gomplate` will panic. + +### Usage + +```go +net.LookupTXT name +``` + +### Arguments + +| name | description | +|--------|-------| +| `name` | The host name to look up | + +### Examples + +```console +$ gomplate -i '{{net.LookupTXT "example.com" | toJSONPretty "\t" }}' +[ + "$Id: example.com 4415 2015-08-24 20:12:23Z davids $", + "v=spf1 -all" +] +``` @@ -53,5 +53,6 @@ func initFuncs(data *Data) template.FuncMap { } funcs.AWSFuncs(f) funcs.AddBase64Funcs(f) + funcs.AddNetFuncs(f) return f } diff --git a/funcs/net.go b/funcs/net.go new file mode 100644 index 00000000..75a47498 --- /dev/null +++ b/funcs/net.go @@ -0,0 +1,57 @@ +package funcs + +import ( + stdnet "net" + "sync" + + "github.com/hairyhenderson/gomplate/net" +) + +var ( + netNS *NetFuncs + netNSInit sync.Once +) + +// NetNS - the net namespace +func NetNS() *NetFuncs { + netNSInit.Do(func() { netNS = &NetFuncs{} }) + return netNS +} + +// AddNetFuncs - +func AddNetFuncs(f map[string]interface{}) { + f["net"] = NetNS +} + +// NetFuncs - +type NetFuncs struct{} + +// LookupIP - +func (f *NetFuncs) LookupIP(name string) string { + return net.LookupIP(name) +} + +// LookupIPs - +func (f *NetFuncs) LookupIPs(name string) []string { + return net.LookupIPs(name) +} + +// LookupCNAME - +func (f *NetFuncs) LookupCNAME(name string) string { + return net.LookupCNAME(name) +} + +// LookupSRV - +func (f *NetFuncs) LookupSRV(name string) *stdnet.SRV { + return net.LookupSRV(name) +} + +// LookupSRVs - +func (f *NetFuncs) LookupSRVs(name string) []*stdnet.SRV { + return net.LookupSRVs(name) +} + +// LookupTXT - +func (f *NetFuncs) LookupTXT(name string) []string { + return net.LookupTXT(name) +} diff --git a/funcs/net_test.go b/funcs/net_test.go new file mode 100644 index 00000000..18412954 --- /dev/null +++ b/funcs/net_test.go @@ -0,0 +1,12 @@ +package funcs + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestNetLookupIP(t *testing.T) { + n := &NetFuncs{} + assert.Equal(t, "127.0.0.1", n.LookupIP("localhost")) +} diff --git a/net/net.go b/net/net.go new file mode 100644 index 00000000..c0bfe594 --- /dev/null +++ b/net/net.go @@ -0,0 +1,62 @@ +package net + +import ( + "log" + "net" +) + +// LookupIP - +func LookupIP(name string) string { + i := LookupIPs(name) + if len(i) == 0 { + return "" + } + return i[0] +} + +// LookupIPs - +func LookupIPs(name string) []string { + srcIPs, err := net.LookupIP(name) + if err != nil { + log.Fatal(err) + } + var ips []string + for _, v := range srcIPs { + if v.To4() != nil { + ips = append(ips, v.String()) + } + } + return ips +} + +// LookupCNAME - +func LookupCNAME(name string) string { + cname, err := net.LookupCNAME(name) + if err != nil { + log.Fatal(err) + } + return cname +} + +// LookupTXT - +func LookupTXT(name string) []string { + records, err := net.LookupTXT(name) + if err != nil { + log.Fatal(err) + } + return records +} + +// LookupSRV - +func LookupSRV(name string) *net.SRV { + return LookupSRVs(name)[0] +} + +// LookupSRVs - +func LookupSRVs(name string) []*net.SRV { + _, addrs, err := net.LookupSRV("", "", name) + if err != nil { + log.Fatal(err) + } + return addrs +} diff --git a/net/net_test.go b/net/net_test.go new file mode 100644 index 00000000..ff4ffd37 --- /dev/null +++ b/net/net_test.go @@ -0,0 +1,32 @@ +package net + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestLookupIP(t *testing.T) { + assert.Equal(t, "127.0.0.1", LookupIP("localhost")) + assert.Equal(t, "169.254.255.254", LookupIP("hostlocal.io")) + assert.Equal(t, "93.184.216.34", LookupIP("example.com")) + +} + +func TestLookupIPs(t *testing.T) { + assert.Equal(t, []string{"127.0.0.1"}, LookupIPs("localhost")) + assert.Equal(t, []string{"169.254.255.254"}, LookupIPs("hostlocal.io")) + assert.Equal(t, []string{"93.184.216.34"}, LookupIPs("example.com")) +} + +func TestLookupTXT(t *testing.T) { + assert.NotEmpty(t, LookupTXT("example.com")) +} + +func TestLookupCNAME(t *testing.T) { + assert.Equal(t, "hairyhenderson.ca.", LookupCNAME("www.hairyhenderson.ca.")) +} + +func TestLookupSRV(t *testing.T) { + assert.Equal(t, uint16(5060), LookupSRV("_sip._udp.sip.voice.google.com").Port) +} diff --git a/test/integration/net.bats b/test/integration/net.bats new file mode 100644 index 00000000..d63eaf1b --- /dev/null +++ b/test/integration/net.bats @@ -0,0 +1,19 @@ +#!/usr/bin/env bats + +load helper + +tmpdir=$(mktemp -u) + +function setup () { + mkdir -p $tmpdir +} + +function teardown () { + rm -rf $tmpdir || true +} + +@test "'net.LookupIP'" { + gomplate -i '{{ net.LookupIP "localhost" }}' + [ "$status" -eq 0 ] + [[ "${output}" == "127.0.0.1" ]] +} |
