summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Henderson <dhenderson@gmail.com>2017-06-13 11:26:45 -0400
committerGitHub <noreply@github.com>2017-06-13 11:26:45 -0400
commitbc52886c7cf83bcbd4e4ae96ab4b0e2a84d527e7 (patch)
tree278bfef3e032c8713b8ca864021df1f12d1832d5
parentc40d861bc6b49d646ef7aff618ae8ff826bc1619 (diff)
parenta0cbffc2972202b05c48d5ecda7773578c7026a2 (diff)
Merge pull request #158 from hairyhenderson/add-net-lookup-funcs
Adding net.Lookup* functions
-rw-r--r--docs/content/functions/net.md200
-rw-r--r--funcs.go1
-rw-r--r--funcs/net.go57
-rw-r--r--funcs/net_test.go12
-rw-r--r--net/net.go62
-rw-r--r--net/net_test.go32
-rw-r--r--test/integration/net.bats19
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"
+]
+```
diff --git a/funcs.go b/funcs.go
index bd1367f4..6a1504de 100644
--- a/funcs.go
+++ b/funcs.go
@@ -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" ]]
+}