-
Notifications
You must be signed in to change notification settings - Fork 53
/
template.go
125 lines (103 loc) · 4.04 KB
/
template.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package template
import (
"bytes"
"fmt"
"text/template"
"github.com/hashicorp/errwrap"
sockaddr "github.com/hashicorp/go-sockaddr"
)
var (
// SourceFuncs is a map of all top-level functions that generate
// sockaddr data types.
SourceFuncs template.FuncMap
// SortFuncs is a map of all functions used in sorting
SortFuncs template.FuncMap
// FilterFuncs is a map of all functions used in sorting
FilterFuncs template.FuncMap
// HelperFuncs is a map of all functions used in sorting
HelperFuncs template.FuncMap
)
func init() {
SourceFuncs = template.FuncMap{
// GetAllInterfaces - Returns an exhaustive set of IfAddr
// structs available on the host. `GetAllInterfaces` is the
// initial input and accessible as the initial "dot" in the
// pipeline.
"GetAllInterfaces": sockaddr.GetAllInterfaces,
// GetDefaultInterfaces - Returns one IfAddr for every IP that
// is on the interface containing the default route for the
// host.
"GetDefaultInterfaces": sockaddr.GetDefaultInterfaces,
// GetPrivateInterfaces - Returns one IfAddr for every IP that
// matches RFC 6890, are attached to the interface with the
// default route, and are forwardable IP addresses. NOTE: RFC
// 6890 is a more exhaustive version of RFC1918 because it spans
// IPv4 and IPv6, however it doespermit the inclusion of likely
// undesired addresses such as multicast, therefore our
// definition of a "private" address also excludes
// non-forwardable IP addresses (as defined by the IETF).
"GetPrivateInterfaces": sockaddr.GetPrivateInterfaces,
// GetPublicInterfaces - Returns a list of IfAddr that do not
// match RFC 6890, are attached to the default route, and are
// forwardable.
"GetPublicInterfaces": sockaddr.GetPublicInterfaces,
}
SortFuncs = template.FuncMap{
"sort": sockaddr.SortIfBy,
}
FilterFuncs = template.FuncMap{
"exclude": sockaddr.ExcludeIfs,
"include": sockaddr.IncludeIfs,
}
HelperFuncs = template.FuncMap{
// Misc functions that operate on IfAddrs inputs
"attr": sockaddr.IfAttr,
"join": sockaddr.JoinIfAddrs,
"limit": sockaddr.LimitIfAddrs,
"offset": sockaddr.OffsetIfAddrs,
"unique": sockaddr.UniqueIfAddrsBy,
// Return a Private RFC 6890 IP address string that is attached
// to the default route and a forwardable address.
"GetPrivateIP": sockaddr.GetPrivateIP,
// Return a Public RFC 6890 IP address string that is attached
// to the default route and a forwardable address.
"GetPublicIP": sockaddr.GetPublicIP,
// Return the first IP address of the named interface, sorted by
// the largest network size.
"GetInterfaceIP": sockaddr.GetInterfaceIP,
}
}
// Parse parses input as template input using the addresses available on the
// host, then returns the string output if there are no errors.
func Parse(input string) (string, error) {
addrs, err := sockaddr.GetAllInterfaces()
if err != nil {
return "", errwrap.Wrapf("unable to query interface addresses: {{err}}", err)
}
return ParseIfAddrs(input, addrs)
}
// ParseIfAddrs parses input as template input using the IfAddrs inputs, then
// returns the string output if there are no errors.
func ParseIfAddrs(input string, ifAddrs sockaddr.IfAddrs) (string, error) {
return ParseIfAddrsTemplate(input, ifAddrs, template.New("sockaddr.Parse"))
}
// ParseIfAddrsTemplate parses input as template input using the IfAddrs inputs,
// then returns the string output if there are no errors.
func ParseIfAddrsTemplate(input string, ifAddrs sockaddr.IfAddrs, tmplIn *template.Template) (string, error) {
// Create a template, add the function map, and parse the text.
tmpl, err := tmplIn.Option("missingkey=error").
Funcs(SourceFuncs).
Funcs(SortFuncs).
Funcs(FilterFuncs).
Funcs(HelperFuncs).
Parse(input)
if err != nil {
return "", errwrap.Wrapf(fmt.Sprintf("unable to parse template %+q: {{err}}", input), err)
}
var outWriter bytes.Buffer
err = tmpl.Execute(&outWriter, ifAddrs)
if err != nil {
return "", errwrap.Wrapf(fmt.Sprintf("unable to execute sockaddr input %+q: {{err}}", input), err)
}
return outWriter.String(), nil
}