-
Notifications
You must be signed in to change notification settings - Fork 123
/
packet_discover.go
147 lines (122 loc) · 3.68 KB
/
packet_discover.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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package packet
import (
"fmt"
"log"
"os"
"strings"
"github.com/packethost/packngo"
)
const baseURL = "https://api.packet.net/"
// Provider struct
type Provider struct {
userAgent string
}
// SetUserAgent setter
func (p *Provider) SetUserAgent(s string) {
p.userAgent = s
}
// Help function
func (p *Provider) Help() string {
return `Packet:
provider: "packet"
project: UUID of packet project. Required
auth_token: Packet authentication token. Required
url: Packet REST URL. Optional
address_type: "private_v4", "public_v4" or "public_v6". Defaults to "private_v4". Optional
facility: Filter for specific facility (Examples: "ewr1,ams1")
tag: Filter by tag (Examples: "tag1,tag2")
Variables can also be provided by environmental variables:
export PACKET_PROJECT for project
export PACKET_URL for url
export PACKET_AUTH_TOKEN for auth_token
`
}
// Addrs function
func (p *Provider) Addrs(args map[string]string, l *log.Logger) ([]string, error) {
authToken := argsOrEnv(args, "auth_token", "PACKET_AUTH_TOKEN")
projectID := argsOrEnv(args, "project", "PACKET_PROJECT")
packetURL := argsOrEnv(args, "url", "PACKET_URL")
addressType := args["address_type"]
packetFacilities := args["facility"]
packetTags := args["tag"]
if addressType != "private_v4" && addressType != "public_v4" && addressType != "public_v6" {
l.Printf("[INFO] discover-packet: Address type %s is not supported. Valid values are {private_v4,public_v4,public_v6}. Falling back to 'private_v4'", addressType)
addressType = "private_v4"
}
includeFacilities := includeArgs(packetFacilities)
includeTags := includeArgs(packetTags)
c, err := client(p.userAgent, packetURL, authToken)
if err != nil {
return nil, fmt.Errorf("discover-packet: Initializing Packet client failed: %s", err)
}
var devices []packngo.Device
if projectID == "" {
return nil, fmt.Errorf("discover-packet: 'project' parameter must be provider")
}
devices, _, err = c.Devices.List(projectID, nil)
if err != nil {
return nil, fmt.Errorf("discover-packet: Fetching Packet devices failed: %s", err)
}
var addrs []string
for _, d := range devices {
if len(includeFacilities) > 0 && !Include(includeFacilities, d.Facility.Code) {
continue
}
if len(includeTags) > 0 && !Any(d.Tags, func(v string) bool { return Include(includeTags, v) }) {
continue
}
addressFamily := 4
if addressType == "public_v6" {
addressFamily = 6
}
for _, n := range d.Network {
if (n.Public == (addressType == "public_v4" || addressType == "public_v6")) && n.AddressFamily == addressFamily {
addrs = append(addrs, n.Address)
}
}
}
return addrs, nil
}
func client(useragent, url, token string) (*packngo.Client, error) {
if url == "" {
url = baseURL
}
return packngo.NewClientWithBaseURL(useragent, token, nil, url)
}
func argsOrEnv(args map[string]string, key, env string) string {
if value := args[key]; value != "" {
return value
}
return os.Getenv(env)
}
func includeArgs(s string) []string {
var include []string
for _, localstring := range strings.Split(s, ",") {
if len(localstring) > 0 {
include = append(include, localstring)
}
}
return include
}
// Index returns the first index of the target string t, or -1 if no match is found.
func Index(vs []string, t string) int {
for i, v := range vs {
if v == t {
return i
}
}
return -1
}
// Include returns true if the target string t is in the slice.
func Include(vs []string, t string) bool {
return Index(vs, t) >= 0
}
//Any returns true if one of the strings in the slice satisfies the predicate f.
func Any(vs []string, f func(string) bool) bool {
for _, v := range vs {
if f(v) {
return true
}
}
return false
}