summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/hashicorp/go-sockaddr/template/template.go
blob: bbed513617f27ddc12ae093c242e0cd2371868c2 (plain)
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
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":   Attr,
		"join":   sockaddr.JoinIfAddrs,
		"limit":  sockaddr.LimitIfAddrs,
		"offset": sockaddr.OffsetIfAddrs,
		"unique": sockaddr.UniqueIfAddrsBy,

		// Misc math functions that operate on a single IfAddr input
		"math": sockaddr.IfAddrsMath,

		// Return a Private RFC 6890 IP address string that is attached
		// to the default route and a forwardable address.
		"GetPrivateIP": sockaddr.GetPrivateIP,

		// Return all Private RFC 6890 IP addresses as a space-delimited string of
		// IP addresses.  Addresses returned do not have to be on the interface with
		// a default route.
		"GetPrivateIPs": sockaddr.GetPrivateIPs,

		// Return a Public RFC 6890 IP address string that is attached
		// to the default route and a forwardable address.
		"GetPublicIP": sockaddr.GetPublicIP,

		// Return allPublic RFC 6890 IP addresses as a space-delimited string of IP
		// addresses.  Addresses returned do not have to be on the interface with a
		// default route.
		"GetPublicIPs": sockaddr.GetPublicIPs,

		// Return the first IP address of the named interface, sorted by
		// the largest network size.
		"GetInterfaceIP": sockaddr.GetInterfaceIP,

		// Return all IP addresses on the named interface, sorted by the largest
		// network size.
		"GetInterfaceIPs": sockaddr.GetInterfaceIPs,
	}
}

// Attr returns the attribute from the ifAddrRaw argument.  If the argument is
// an IfAddrs, only the first element will be evaluated for resolution.
func Attr(selectorName string, ifAddrsRaw interface{}) (string, error) {
	switch v := ifAddrsRaw.(type) {
	case sockaddr.IfAddr:
		return sockaddr.IfAttr(selectorName, v)
	case sockaddr.IfAddrs:
		return sockaddr.IfAttrs(selectorName, v)
	default:
		return "", fmt.Errorf("unable to obtain attribute %s from type %T (%v)", selectorName, ifAddrsRaw, ifAddrsRaw)
	}
}

// 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
}