File: discover.go

package info (click to toggle)
golang-github-hashicorp-go-discover 0.0+git20190905.34a6505-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, sid
  • size: 476 kB
  • sloc: makefile: 9
file content (170 lines) | stat: -rw-r--r-- 4,475 bytes parent folder | download
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// Package discover provides functions to get metadata for different
// cloud environments.
package discover

import (
	"fmt"
	"log"
	"sort"
	"strings"
	"sync"

	"github.com/hashicorp/go-discover/provider/aliyun"
	"github.com/hashicorp/go-discover/provider/aws"
	"github.com/hashicorp/go-discover/provider/gce"
	"github.com/hashicorp/go-discover/provider/mdns"
	"github.com/hashicorp/go-discover/provider/os"
	"github.com/hashicorp/go-discover/provider/packet"
)

// Provider has lookup functions for meta data in a
// cloud environment.
type Provider interface {
	// Addrs looks up addresses in the cloud environment according to the
	// configuration provided in args.
	Addrs(args map[string]string, l *log.Logger) ([]string, error)

	// Help provides the configuration help for the command line client.
	Help() string
}

// ProviderWithUserAgent is a provider that declares it's user agent. Not all
// providers support this.
type ProviderWithUserAgent interface {
	// SetUserAgent sets the user agent on the provider to the provided string.
	SetUserAgent(s string)
}

// Providers contains all available providers.
var Providers = map[string]Provider{
	"aliyun":       &aliyun.Provider{},
	"aws":          &aws.Provider{},
	"gce":          &gce.Provider{},
	"mdns":         &mdns.Provider{},
	"os":           &os.Provider{},
	"packet":       &packet.Provider{},
}

// Discover looks up metadata in different cloud environments.
type Discover struct {
	// Providers is the list of address lookup providers.
	// If nil, the default list of providers is used.
	Providers map[string]Provider

	// userAgent is the string to use for requests, when supported.
	userAgent string

	// once is used to initialize the actual list of providers.
	once sync.Once
}

// Option is used as an initialization option/
type Option func(*Discover) error

// New creates a new discover client with the given options.
func New(opts ...Option) (*Discover, error) {
	d := new(Discover)

	for _, opt := range opts {
		if err := opt(d); err != nil {
			return nil, err
		}
	}

	d.once.Do(d.initProviders)

	return d, nil
}

// WithUserAgent allows specifying a custom user agent option to send with
// requests when the underlying client library supports it.
func WithUserAgent(agent string) Option {
	return func(d *Discover) error {
		d.userAgent = agent
		return nil
	}
}

// WithProviders allows specifying your own set of providers.
func WithProviders(m map[string]Provider) Option {
	return func(d *Discover) error {
		d.Providers = m
		return nil
	}
}

// initProviders sets the list of providers to the
// default list of providers if none are configured.
func (d *Discover) initProviders() {
	if d.Providers == nil {
		d.Providers = Providers
	}
}

// Names returns the names of the configured providers.
func (d *Discover) Names() []string {
	d.once.Do(d.initProviders)

	var names []string
	for n := range d.Providers {
		names = append(names, n)
	}
	sort.Strings(names)
	return names
}

var globalHelp = `The options for discovering ip addresses are provided as a
  single string value in "key=value key=value ..." format where
  the values are URL encoded.

    provider=aws region=eu-west-1 ...

  The options are provider specific and are listed below.
`

// Help describes the format of the configuration string for address discovery
// and the various provider specific options.
func (d *Discover) Help() string {
	d.once.Do(d.initProviders)

	h := []string{globalHelp}
	for _, name := range d.Names() {
		h = append(h, d.Providers[name].Help())
	}
	return strings.Join(h, "\n")
}

// Addrs discovers ip addresses of nodes that match the given filter criteria.
// The config string must have the format 'provider=xxx key=val key=val ...'
// where the keys and values are provider specific. The values are URL encoded.
func (d *Discover) Addrs(cfg string, l *log.Logger) ([]string, error) {
	d.once.Do(d.initProviders)

	args, err := Parse(cfg)
	if err != nil {
		return nil, fmt.Errorf("discover: %s", err)
	}

	name := args["provider"]
	if name == "" {
		return nil, fmt.Errorf("discover: no provider")
	}

	providers := d.Providers
	if providers == nil {
		providers = Providers
	}

	p := providers[name]
	if p == nil {
		return nil, fmt.Errorf("discover: unknown provider " + name)
	}
	l.Printf("[DEBUG] discover: Using provider %q", name)

	if typ, ok := p.(ProviderWithUserAgent); ok {
		typ.SetUserAgent(d.userAgent)
		return p.Addrs(args, l)
	}

	return p.Addrs(args, l)
}