You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
boundary/internal/libs/endpoint/option.go

107 lines
2.5 KiB

package endpoint
import (
"fmt"
"net"
"strings"
)
// getOpts iterates the inbound Options and returns a struct
func getOpts(opt ...Option) (options, error) {
opts := getDefaultOptions()
for _, o := range opt {
if o == nil {
continue
}
if err := o(&opts); err != nil {
return options{}, err
}
}
return opts, nil
}
// Option - how Options are passed as arguments
type Option func(*options) error
// options = how options are represented
type options struct {
withIpAddrs []string
withDnsNames []string
withMatchers []matcher
}
func getDefaultOptions() options {
return options{}
}
// WithIpAddrs contains IP addresses to add into the endpoint possibilities.
// If an IP cannot be parsed, this function will error.
func WithIpAddrs(with []string) Option {
return func(o *options) error {
for _, addr := range with {
ip := net.ParseIP(addr)
if ip == nil {
return fmt.Errorf("input '%s' is not parseable as an ip address", addr)
}
o.withIpAddrs = append(o.withIpAddrs, addr)
}
return nil
}
}
// WithDnsNames contains DNS names to add into the endpoint possibilities
func WithDnsNames(with []string) Option {
return func(o *options) error {
o.withDnsNames = with
return nil
}
}
// WithPreferenceOrder contains the preference order specification. If one of
// the preferences cannot be parsed, this function will error. Internally it
// builds up a set of matchers.
func WithPreferenceOrder(with []string) Option {
return func(o *options) error {
for _, input := range with {
var m matcher
switch {
case strings.HasPrefix(input, "cidr:"):
// Make sure ParseCIDR won't choke on a bare address
cidr := strings.TrimPrefix(input, "cidr:")
if !strings.Contains(cidr, "/") {
// See if it seems like an IPv6 address vs. IPv4; colons are
// a good way to check this
if strings.Contains(cidr, ":") {
cidr = fmt.Sprintf("%s/128", cidr)
} else {
cidr = fmt.Sprintf("%s/32", cidr)
}
}
_, ipNet, err := net.ParseCIDR(cidr)
if err != nil {
return fmt.Errorf("error parsing cidr %s: %w", cidr, err)
}
m = cidrMatcher{
ipNet: ipNet,
}
case strings.HasPrefix(input, "dns:"):
pattern := strings.TrimPrefix(input, "dns:")
if pattern == "" {
return fmt.Errorf("empty dns pattern provided")
}
m = dnsMatcher{
pattern: pattern,
}
default:
return fmt.Errorf("preference string %q is not supported", input)
}
if m != nil {
o.withMatchers = append(o.withMatchers, m)
}
}
return nil
}
}