Merge pull request #2722 from hashicorp/update-deps

Updates memberlist and Serf (and adds new dependencies).
This commit is contained in:
James Phillips 2017-02-08 14:13:37 -08:00 committed by GitHub
commit 2ccfa63f9a
21 changed files with 423 additions and 182 deletions

63
vendor/github.com/hashicorp/go-sockaddr/Makefile generated vendored Normal file
View File

@ -0,0 +1,63 @@
TOOLS= golang.org/x/tools/cover
GOCOVER_TMPFILE?= $(GOCOVER_FILE).tmp
GOCOVER_FILE?= .cover.out
GOCOVERHTML?= coverage.html
test:: $(GOCOVER_FILE)
@$(MAKE) -C cmd/sockaddr test
cover:: coverage_report
$(GOCOVER_FILE)::
@find . -type d ! -path '*cmd*' ! -path '*.git*' -print0 | xargs -0 -I % sh -ec "cd % && rm -f $(GOCOVER_TMPFILE) && go test -coverprofile=$(GOCOVER_TMPFILE)"
@echo 'mode: set' > $(GOCOVER_FILE)
@find . -type f ! -path '*cmd*' ! -path '*.git*' -name "$(GOCOVER_TMPFILE)" -print0 | xargs -0 -n1 cat $(GOCOVER_TMPFILE) | grep -v '^mode: ' >> ${PWD}/$(GOCOVER_FILE)
$(GOCOVERHTML): $(GOCOVER_FILE)
go tool cover -html=$(GOCOVER_FILE) -o $(GOCOVERHTML)
coverage_report:: $(GOCOVER_FILE)
go tool cover -html=$(GOCOVER_FILE)
audit_tools::
@go get -u github.com/golang/lint/golint && echo "Installed golint:"
@go get -u github.com/fzipp/gocyclo && echo "Installed gocyclo:"
@go get -u github.com/remyoudompheng/go-misc/deadcode && echo "Installed deadcode:"
@go get -u github.com/client9/misspell/cmd/misspell && echo "Installed misspell:"
@go get -u github.com/gordonklaus/ineffassign && echo "Installed ineffassign:"
audit::
deadcode
go tool vet -all *.go
go tool vet -shadow=true *.go
golint *.go
ineffassign .
gocyclo -over 65 *.go
misspell *.go
clean::
rm -f $(GOCOVER_FILE) $(GOCOVERHTML)
dev::
@go build
@make -B -C cmd/sockaddr sockaddr
install::
@go install
@make -C cmd/sockaddr install
doc::
echo Visit: http://127.0.0.1:6060/pkg/github.com/hashicorp/go-sockaddr/
godoc -http=:6060 -goroot $GOROOT
world::
@set -e; \
for os in solaris darwin freebsd linux windows; do \
for arch in amd64; do \
printf "Building on %s-%s\n" "$${os}" "$${arch}" ; \
env GOOS="$${os}" GOARCH="$${arch}" go build -o /dev/null; \
done; \
done
make -C cmd/sockaddr world

118
vendor/github.com/hashicorp/go-sockaddr/README.md generated vendored Normal file
View File

@ -0,0 +1,118 @@
# go-sockaddr
## `sockaddr` Library
Socket address convenience functions for Go. `go-sockaddr` is a convenience
library that makes doing the right thing with IP addresses easy. `go-sockaddr`
is loosely modeled after the UNIX `sockaddr_t` and creates a union of the family
of `sockaddr_t` types (see below for an ascii diagram). Library documentation
is available
at
[https://godoc.org/github.com/hashicorp/go-sockaddr](https://godoc.org/github.com/hashicorp/go-sockaddr).
The primary intent of the library was to make it possible to define heuristics
for selecting the correct IP addresses when a configuration is evaluated at
runtime. See
the
[docs](https://godoc.org/github.com/hashicorp/go-sockaddr),
[`template` package](https://godoc.org/github.com/hashicorp/go-sockaddr/template),
tests,
and
[CLI utility](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr)
for details and hints as to how to use this library.
For example, with this library it is possible to find an IP address that:
* is attached to a default route
([`GetDefaultInterfaces()`](https://godoc.org/github.com/hashicorp/go-sockaddr#GetDefaultInterfaces))
* is contained within a CIDR block (['IfByNetwork()'](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByNetwork))
* is an RFC1918 address
([`IfByRFC("1918")`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByRFC))
* is ordered
([`OrderedIfAddrBy(args)`](https://godoc.org/github.com/hashicorp/go-sockaddr#OrderedIfAddrBy) where
`args` includes, but is not limited
to,
[`AscIfType`](https://godoc.org/github.com/hashicorp/go-sockaddr#AscIfType),
[`AscNetworkSize`](https://godoc.org/github.com/hashicorp/go-sockaddr#AscNetworkSize))
* excludes all IPv6 addresses
([`IfByType("^(IPv4)$")`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByType))
* is larger than a `/32`
([`IfByMaskSize(32)`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByMaskSize))
* is not on a `down` interface
([`ExcludeIfs("flags", "down")`](https://godoc.org/github.com/hashicorp/go-sockaddr#ExcludeIfs))
* preferences an IPv6 address over an IPv4 address
([`SortIfByType()`](https://godoc.org/github.com/hashicorp/go-sockaddr#SortIfByType) +
[`ReverseIfAddrs()`](https://godoc.org/github.com/hashicorp/go-sockaddr#ReverseIfAddrs)); and
* excludes any IP in RFC6890 address
([`IfByRFC("6890")`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByRFC))
Or any combination or variation therein.
There are also a few simple helper functions such as `GetPublicIP` and
`GetPrivateIP` which both return strings and select the first public or private
IP address on the default interface, respectively. Similarly, there is also a
helper function called `GetInterfaceIP` which returns the first usable IP
address on the named interface.
## `sockaddr` CLI
Given the possible complexity of the `sockaddr` library, there is a CLI utility
that accompanies the library, also
called
[`sockaddr`](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr).
The
[`sockaddr`](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr)
utility exposes nearly all of the functionality of the library and can be used
either as an administrative tool or testing tool. To install
the
[`sockaddr`](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr),
run:
```text
$ go get -u github.com/hashicorp/go-sockaddr/cmd/sockaddr
```
If you're familiar with UNIX's `sockaddr` struct's, the following diagram
mapping the C `sockaddr` (top) to `go-sockaddr` structs (bottom) and
interfaces will be helpful:
```
+-------------------------------------------------------+
| |
| sockaddr |
| SockAddr |
| |
| +--------------+ +----------------------------------+ |
| | sockaddr_un | | | |
| | SockAddrUnix | | sockaddr_in{,6} | |
| +--------------+ | IPAddr | |
| | | |
| | +-------------+ +--------------+ | |
| | | sockaddr_in | | sockaddr_in6 | | |
| | | IPv4Addr | | IPv6Addr | | |
| | +-------------+ +--------------+ | |
| | | |
| +----------------------------------+ |
| |
+-------------------------------------------------------+
```
## Inspiration and Design
There were many subtle inspirations that led to this design, but the most direct
inspiration for the filtering syntax was
OpenBSD's
[`pf.conf(5)`](https://www.freebsd.org/cgi/man.cgi?query=pf.conf&apropos=0&sektion=0&arch=default&format=html#PARAMETERS) firewall
syntax that lets you select the first IP address on a given named interface.
The original problem stemmed from:
* needing to create immutable images using [Packer](https://www.packer.io) that
ran the [Consul](https://www.consul.io) process (Consul can only use one IP
address at a time);
* images that may or may not have multiple interfaces or IP addresses at
runtime; and
* we didn't want to rely on configuration management to render out the correct
IP address if the VM image was being used in an auto-scaling group.
Instead we needed some way to codify a heuristic that would correctly select the
right IP address but the input parameters were not known when the image was
created.

5
vendor/github.com/hashicorp/go-sockaddr/doc.go generated vendored Normal file
View File

@ -0,0 +1,5 @@
/*
Package sockaddr is a Go implementation of the UNIX socket family data types and
related helper functions.
*/
package sockaddr

View File

@ -11,7 +11,7 @@ func init() {
// GetPrivateIP returns a string with a single IP address that is part of RFC
// 6890 and has a default route. If the system can't determine its IP address
// or find an RFC 6890 IP address, an empty string will be returned instead.
// This function is the `eval` equivilant of:
// This function is the `eval` equivalent of:
//
// ```
// $ sockaddr eval -r '{{GetPrivateInterfaces | attr "address"}}'
@ -33,7 +33,7 @@ func GetPrivateIP() (string, error) {
// GetPublicIP returns a string with a single IP address that is NOT part of RFC
// 6890 and has a default route. If the system can't determine its IP address
// or find a non RFC 6890 IP address, an empty string will be returned instead.
// This function is the `eval` equivilant of:
// This function is the `eval` equivalent of:
//
// ```
// $ sockaddr eval -r '{{GetPublicInterfaces | attr "address"}}'
@ -53,7 +53,7 @@ func GetPublicIP() (string, error) {
// GetInterfaceIP returns a string with a single IP address sorted by the size
// of the network (i.e. IP addresses with a smaller netmask, larger network
// size, are sorted first). This function is the `eval` equivilant of:
// size, are sorted first). This function is the `eval` equivalent of:
//
// ```
// $ sockaddr eval -r '{{GetAllInterfaces | include "name" <<ARG>> | sort "type,size" | include "flag" "forwardable" | attr "address" }}'

View File

@ -240,7 +240,7 @@ func GetDefaultInterfaces() (IfAddrs, error) {
// GetPrivateInterfaces returns an IfAddrs that are part of RFC 6890 and have a
// default route. If the system can't determine its IP address or find an RFC
// 6890 IP address, an empty IfAddrs will be returned instead. This function is
// the `eval` equivilant of:
// the `eval` equivalent of:
//
// ```
// $ sockaddr eval -r '{{GetDefaultInterfaces | include "type" "ip" | include "flags" "forwardable|up" | sort "type,size" | include "RFC" "6890" }}'
@ -282,7 +282,7 @@ func GetPrivateInterfaces() (IfAddrs, error) {
// GetPublicInterfaces returns an IfAddrs that are NOT part of RFC 6890 and has a
// default route. If the system can't determine its IP address or find a non
// RFC 6890 IP address, an empty IfAddrs will be returned instead. This
// function is the `eval` equivilant of:
// function is the `eval` equivalent of:
//
// ```
// $ sockaddr eval -r '{{GetDefaultInterfaces | include "type" "ip" | include "flags" "forwardable|up" | sort "type,size" | exclude "RFC" "6890" }}'

View File

@ -20,7 +20,7 @@ func NewRouteInfo() (routeInfo, error) {
}, nil
}
// GetDefaultInterfaceName returns the interace name attached to the default
// GetDefaultInterfaceName returns the interface name attached to the default
// route on the default interface.
func (ri routeInfo) GetDefaultInterfaceName() (string, error) {
out, err := exec.Command(cmds["route"][0], cmds["route"][1:]...).Output()

View File

@ -21,7 +21,7 @@ func NewRouteInfo() (routeInfo, error) {
}, nil
}
// GetDefaultInterfaceName returns the interace name attached to the default
// GetDefaultInterfaceName returns the interface name attached to the default
// route on the default interface.
func (ri routeInfo) GetDefaultInterfaceName() (string, error) {
out, err := exec.Command(cmds["ip"][0], cmds["ip"][1:]...).Output()

View File

@ -21,7 +21,7 @@ func NewRouteInfo() (routeInfo, error) {
}, nil
}
// GetDefaultInterfaceName returns the interace name attached to the default
// GetDefaultInterfaceName returns the interface name attached to the default
// route on the default interface.
func (ri routeInfo) GetDefaultInterfaceName() (string, error) {
out, err := exec.Command(cmds["route"][0], cmds["route"][1:]...).Output()

View File

@ -19,7 +19,7 @@ func NewRouteInfo() (routeInfo, error) {
}, nil
}
// GetDefaultInterfaceName returns the interace name attached to the default
// GetDefaultInterfaceName returns the interface name attached to the default
// route on the default interface.
func (ri routeInfo) GetDefaultInterfaceName() (string, error) {
ifNameOut, err := exec.Command(cmds["netstat"][0], cmds["netstat"][1:]...).Output()

View File

@ -188,6 +188,12 @@ type Config struct {
// size of this determines the size of the queue which Memberlist will keep
// while UDP messages are handled.
HandoffQueueDepth int
// Maximum number of bytes that memberlist expects UDP messages to be. A safe
// value for this is typically 1400 bytes (which is the default.) However,
// depending on your network's MTU (Maximum Transmission Unit) you may be able
// to increase this.
UDPBufferSize int
}
// DefaultLANConfig returns a sane set of configurations for Memberlist.
@ -228,6 +234,7 @@ func DefaultLANConfig() *Config {
DNSConfigPath: "/etc/resolv.conf",
HandoffQueueDepth: 1024,
UDPBufferSize: 1400,
}
}

View File

@ -25,6 +25,7 @@ import (
"time"
"github.com/hashicorp/go-multierror"
sockaddr "github.com/hashicorp/go-sockaddr"
"github.com/miekg/dns"
)
@ -326,7 +327,7 @@ func (m *Memberlist) resolveAddr(hostStr string) ([]ipPort, error) {
// as if we received an alive notification our own network channel for
// ourself.
func (m *Memberlist) setAlive() error {
var advertiseAddr []byte
var advertiseAddr net.IP
var advertisePort int
if m.config.AdvertiseAddr != "" {
// If AdvertiseAddr is not empty, then advertise
@ -345,42 +346,21 @@ func (m *Memberlist) setAlive() error {
advertisePort = m.config.AdvertisePort
} else {
if m.config.BindAddr == "0.0.0.0" {
// Otherwise, if we're not bound to a specific IP,
//let's list the interfaces on this machine and use
// the first private IP we find.
addresses, err := net.InterfaceAddrs()
// Otherwise, if we're not bound to a specific IP, let's use a suitable
// private IP address.
var err error
m.config.AdvertiseAddr, err = sockaddr.GetPrivateIP()
if err != nil {
return fmt.Errorf("Failed to get interface addresses! Err: %v", err)
return fmt.Errorf("Failed to get interface addresses: %v", err)
}
// Find private IPv4 address
for _, rawAddr := range addresses {
var ip net.IP
switch addr := rawAddr.(type) {
case *net.IPAddr:
ip = addr.IP
case *net.IPNet:
ip = addr.IP
default:
continue
}
if ip.To4() == nil {
continue
}
if !IsPrivateIP(ip.String()) {
continue
}
advertiseAddr = ip
break
}
// Failed to find private IP, error
if advertiseAddr == nil {
if m.config.AdvertiseAddr == "" {
return fmt.Errorf("No private IP address found, and explicit IP not provided")
}
advertiseAddr = net.ParseIP(m.config.AdvertiseAddr)
if advertiseAddr == nil {
return fmt.Errorf("Failed to parse advertise address: %q", m.config.AdvertiseAddr)
}
} else {
// Use the IP that we're bound to.
addr := m.tcpListener.Addr().(*net.TCPAddr)
@ -392,8 +372,19 @@ func (m *Memberlist) setAlive() error {
}
// Check if this is a public address without encryption
addrStr := net.IP(advertiseAddr).String()
if !IsPrivateIP(addrStr) && !isLoopbackIP(addrStr) && !m.config.EncryptionEnabled() {
ipAddr, err := sockaddr.NewIPAddr(advertiseAddr.String())
if err != nil {
return fmt.Errorf("Failed to parse interface addresses: %v", err)
}
ifAddrs := []sockaddr.IfAddr{
sockaddr.IfAddr{
SockAddr: ipAddr,
},
}
_, publicIfs, err := sockaddr.IfByRFC("6890", ifAddrs)
if len(publicIfs) > 0 && !m.config.EncryptionEnabled() {
m.logger.Printf("[WARN] memberlist: Binding to public address without encryption!")
}

View File

@ -70,7 +70,6 @@ const (
compoundOverhead = 2 // Assumed overhead per entry in compoundHeader
udpBufSize = 65536
udpRecvBuf = 2 * 1024 * 1024
udpSendBuf = 1400
userMsgOverhead = 1
blockingWarning = 10 * time.Millisecond // Warn if a UDP packet takes this long to process
maxPushStateBytes = 10 * 1024 * 1024
@ -605,7 +604,7 @@ func (m *Memberlist) encodeAndSendMsg(to net.Addr, msgType messageType, msg inte
// create a compoundMsg and piggy back other broadcasts
func (m *Memberlist) sendMsg(to net.Addr, msg []byte) error {
// Check if we can piggy back any messages
bytesAvail := udpSendBuf - len(msg) - compoundHeaderOverhead
bytesAvail := m.config.UDPBufferSize - len(msg) - compoundHeaderOverhead
if m.config.EncryptionEnabled() {
bytesAvail -= encryptOverhead(m.encryptionVersion())
}

View File

@ -439,8 +439,8 @@ func (m *Memberlist) resetNodes() {
m.nodeLock.Lock()
defer m.nodeLock.Unlock()
// Move the dead nodes
deadIdx := moveDeadNodes(m.nodes)
// Move dead nodes, but respect gossip to the dead interval
deadIdx := moveDeadNodes(m.nodes, m.config.GossipToTheDeadTime)
// Deregister the dead nodes
for i := deadIdx; i < len(m.nodes); i++ {
@ -484,7 +484,7 @@ func (m *Memberlist) gossip() {
m.nodeLock.RUnlock()
// Compute the bytes available
bytesAvail := udpSendBuf - compoundHeaderOverhead
bytesAvail := m.config.UDPBufferSize - compoundHeaderOverhead
if m.config.EncryptionEnabled() {
bytesAvail -= encryptOverhead(m.encryptionVersion())
}
@ -496,13 +496,19 @@ func (m *Memberlist) gossip() {
return
}
// Create a compound message
compound := makeCompoundMessage(msgs)
// Send the compound message
destAddr := &net.UDPAddr{IP: node.Addr, Port: int(node.Port)}
if err := m.rawSendMsgUDP(destAddr, &node.Node, compound.Bytes()); err != nil {
m.logger.Printf("[ERR] memberlist: Failed to send gossip to %s: %s", destAddr, err)
if len(msgs) == 1 {
// Send single message as is
if err := m.rawSendMsgUDP(destAddr, &node.Node, msgs[0]); err != nil {
m.logger.Printf("[ERR] memberlist: Failed to send gossip to %s: %s", destAddr, err)
}
} else {
// Otherwise create and send a compound message
compound := makeCompoundMessage(msgs)
if err := m.rawSendMsgUDP(destAddr, &node.Node, compound.Bytes()); err != nil {
m.logger.Printf("[ERR] memberlist: Failed to send gossip to %s: %s", destAddr, err)
}
}
}
}

View File

@ -8,11 +8,11 @@ import (
"io"
"math"
"math/rand"
"net"
"strings"
"time"
"github.com/hashicorp/go-msgpack/codec"
"github.com/sean-/seed"
)
// pushPullScale is the minimum number of nodes
@ -22,72 +22,13 @@ import (
// while the 65th will triple it.
const pushPullScaleThreshold = 32
/*
* Contains an entry for each private block:
* 10.0.0.0/8
* 100.64.0.0/10
* 127.0.0.0/8
* 169.254.0.0/16
* 172.16.0.0/12
* 192.168.0.0/16
*/
var privateBlocks []*net.IPNet
var loopbackBlock *net.IPNet
const (
// Constant litWidth 2-8
lzwLitWidth = 8
)
func init() {
// Seed the random number generator
rand.Seed(time.Now().UnixNano())
// Add each private block
privateBlocks = make([]*net.IPNet, 6)
_, block, err := net.ParseCIDR("10.0.0.0/8")
if err != nil {
panic(fmt.Sprintf("Bad cidr. Got %v", err))
}
privateBlocks[0] = block
_, block, err = net.ParseCIDR("100.64.0.0/10")
if err != nil {
panic(fmt.Sprintf("Bad cidr. Got %v", err))
}
privateBlocks[1] = block
_, block, err = net.ParseCIDR("127.0.0.0/8")
if err != nil {
panic(fmt.Sprintf("Bad cidr. Got %v", err))
}
privateBlocks[2] = block
_, block, err = net.ParseCIDR("169.254.0.0/16")
if err != nil {
panic(fmt.Sprintf("Bad cidr. Got %v", err))
}
privateBlocks[3] = block
_, block, err = net.ParseCIDR("172.16.0.0/12")
if err != nil {
panic(fmt.Sprintf("Bad cidr. Got %v", err))
}
privateBlocks[4] = block
_, block, err = net.ParseCIDR("192.168.0.0/16")
if err != nil {
panic(fmt.Sprintf("Bad cidr. Got %v", err))
}
privateBlocks[5] = block
_, block, err = net.ParseCIDR("127.0.0.0/8")
if err != nil {
panic(fmt.Sprintf("Bad cidr. Got %v", err))
}
loopbackBlock = block
seed.Init()
}
// Decode reverses the encode operation on a byte slice input
@ -108,42 +49,6 @@ func encode(msgType messageType, in interface{}) (*bytes.Buffer, error) {
return buf, err
}
// GetPrivateIP returns the first private IP address found in a list of
// addresses.
func GetPrivateIP(addresses []net.Addr) (net.IP, error) {
var candidates []net.IP
// Find private IPv4 address
for _, rawAddr := range addresses {
var ip net.IP
switch addr := rawAddr.(type) {
case *net.IPAddr:
ip = addr.IP
case *net.IPNet:
ip = addr.IP
default:
continue
}
if ip.To4() == nil {
continue
}
if !IsPrivateIP(ip.String()) {
continue
}
candidates = append(candidates, ip)
}
numIps := len(candidates)
switch numIps {
case 0:
return nil, fmt.Errorf("No private IP address found")
case 1:
return candidates[0], nil
default:
return nil, fmt.Errorf("Multiple private IPs found. Please configure one.")
}
}
// Returns a random offset between 0 and n
func randomOffset(n int) int {
if n == 0 {
@ -190,9 +95,9 @@ func pushPullScale(interval time.Duration, n int) time.Duration {
return time.Duration(multiplier) * interval
}
// moveDeadNodes moves all the nodes in the dead state
// to the end of the slice and returns the index of the first dead node.
func moveDeadNodes(nodes []*nodeState) int {
// moveDeadNodes moves nodes that are dead and beyond the gossip to the dead interval
// to the end of the slice and returns the index of the first moved node.
func moveDeadNodes(nodes []*nodeState, gossipToTheDeadTime time.Duration) int {
numDead := 0
n := len(nodes)
for i := 0; i < n-numDead; i++ {
@ -200,6 +105,11 @@ func moveDeadNodes(nodes []*nodeState) int {
continue
}
// Respect the gossip to the dead interval
if time.Since(nodes[i].StateChange) <= gossipToTheDeadTime {
continue
}
// Move this node to the end
nodes[i], nodes[n-numDead-1] = nodes[n-numDead-1], nodes[i]
numDead++
@ -305,23 +215,6 @@ func decodeCompoundMessage(buf []byte) (trunc int, parts [][]byte, err error) {
return
}
// Returns if the given IP is in a private block
func IsPrivateIP(ip_str string) bool {
ip := net.ParseIP(ip_str)
for _, priv := range privateBlocks {
if priv.Contains(ip) {
return true
}
}
return false
}
// Returns if the given IP is in a loopback block
func isLoopbackIP(ip_str string) bool {
ip := net.ParseIP(ip_str)
return loopbackBlock.Contains(ip)
}
// Given a string of the form "host", "host:port",
// "ipv6::addr" or "[ipv6::address]:port",
// return true if the string includes a port.

View File

@ -2,6 +2,7 @@ package serf
import (
"io"
"log"
"os"
"time"
@ -183,6 +184,12 @@ type Config struct {
// logs will go to stderr.
LogOutput io.Writer
// Logger is a custom logger which you provide. If Logger is set, it will use
// this for the internal logger. If Logger is not set, it will fall back to the
// behavior for using LogOutput. You cannot specify both LogOutput and Logger
// at the same time.
Logger *log.Logger
// SnapshotPath if provided is used to snapshot live nodes as well
// as lamport clock values. When Serf is started with a snapshot,
// it will attempt to join all the previously known nodes until one

View File

@ -10,6 +10,7 @@ import (
"log"
"math/rand"
"net"
"os"
"strconv"
"sync"
"time"
@ -240,9 +241,23 @@ func Create(conf *Config) (*Serf, error) {
conf.ProtocolVersion, ProtocolVersionMin, ProtocolVersionMax)
}
if conf.LogOutput != nil && conf.Logger != nil {
return nil, fmt.Errorf("Cannot specify both LogOutput and Logger. Please choose a single log configuration setting.")
}
logDest := conf.LogOutput
if logDest == nil {
logDest = os.Stderr
}
logger := conf.Logger
if logger == nil {
logger = log.New(logDest, "", log.LstdFlags)
}
serf := &Serf{
config: conf,
logger: log.New(conf.LogOutput, "", log.LstdFlags),
logger: logger,
members: make(map[string]*memberState),
queryResponse: make(map[LamportTime]*QueryResponse),
shutdownCh: make(chan struct{}),

View File

@ -84,7 +84,7 @@ func NewSnapshotter(path string,
inCh := make(chan Event, 1024)
// Try to open the file
fh, err := os.OpenFile(path, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0755)
fh, err := os.OpenFile(path, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0644)
if err != nil {
return nil, nil, fmt.Errorf("failed to open snapshot: %v", err)
}

22
vendor/github.com/sean-/seed/LICENSE generated vendored Normal file
View File

@ -0,0 +1,22 @@
MIT License
Copyright (c) 2017 Sean Chittenden
Copyright (c) 2016 Alex Dadgar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

44
vendor/github.com/sean-/seed/README.md generated vendored Normal file
View File

@ -0,0 +1,44 @@
# `seed` - Quickly Seed Go's Random Number Generator
Boiler-plate to securely [seed](https://en.wikipedia.org/wiki/Random_seed) Go's
random number generator (if possible). This library isn't anything fancy, it's
just a canonical way of seeding Go's random number generator. Cribbed from
[`Nomad`](https://github.com/hashicorp/nomad/commit/f89a993ec6b91636a3384dd568898245fbc273a1)
before it was moved into
[`Consul`](https://github.com/hashicorp/consul/commit/d695bcaae6e31ee307c11fdf55bb0bf46ea9fcf4)
and made into a helper function, and now further modularized to be a super
lightweight and reusable library.
Time is better than
[Go's default seed of `1`](https://golang.org/pkg/math/rand/#Seed), but friends
don't let friends use time as a seed to a random number generator. Use
`seed.MustInit()` instead.
`seed.Init()` is an idempotent and reentrant call that will return an error if
it can't seed the value the first time it is called. `Init()` is reentrant.
`seed.MustInit()` is idempotent and reentrant call that will `panic()` if it
can't seed the value the first time it is called. `MustInit()` is reentrant.
## Usage
```
package mypackage
import (
"github.com/sean-/seed"
)
// MustInit will panic() if it is unable to set a high-entropy random seed:
func init() {
seed.MustInit()
}
// Or if you want to not panic() and can actually handle this error:
func init() {
if ok, err := !seed.Init(); !ok {
// Handle the error
//panic(fmt.Sprintf("Unable to securely seed Go's RNG: %v", err))
}
}
```

65
vendor/github.com/sean-/seed/init.go generated vendored Normal file
View File

@ -0,0 +1,65 @@
package seed
import (
crand "crypto/rand"
"fmt"
"math"
"math/big"
"math/rand"
"sync"
"time"
)
var (
once sync.Once
secure bool
seeded bool
)
// Init provides best-effort seeding (which is better than running with Go's
// default seed of 1). If `/dev/urandom` is available, Init() will seed Go's
// runtime with entropy from `/dev/urandom` and return true because the runtime
// was securely seeded. If Init() has already initialized the random number or
// it had failed to securely initialize the random number generation, Init()
// will return false. See MustInit().
func Init() (bool, error) {
var err error
once.Do(func() {
var n *big.Int
n, err = crand.Int(crand.Reader, big.NewInt(math.MaxInt64))
if err != nil {
rand.Seed(time.Now().UTC().UnixNano())
return
}
rand.Seed(n.Int64())
secure = true
seeded = true
})
return seeded && secure, err
}
// MustInit provides guaranteed seeding. If `/dev/urandom` is not available,
// MustInit will panic() with an error indicating why reading from
// `/dev/urandom` failed. See Init()
func MustInit() {
once.Do(func() {
n, err := crand.Int(crand.Reader, big.NewInt(math.MaxInt64))
if err != nil {
panic(fmt.Sprintf("Unable to seed the random number generator: %v", err))
}
rand.Seed(n.Int64())
secure = true
seeded = true
})
}
// Secure returns true if a cryptographically secure seed was used to
// initialize rand.
func Secure() bool {
return secure
}
// Seeded returns true if Init has seeded the random number generator.
func Seeded() bool {
return seeded
}

24
vendor/vendor.json vendored
View File

@ -474,10 +474,10 @@
"revisionTime": "2016-09-30T03:51:02Z"
},
{
"checksumSHA1": "L9iVjsIjeU9Ia1VZUY417ZHBAtc=",
"checksumSHA1": "BGODc7juQbdG3vNXHZG07kt+lKI=",
"path": "github.com/hashicorp/go-sockaddr",
"revision": "945b922c7db81f071a1f176e747e9857b76ed7c3",
"revisionTime": "2017-01-17T20:27:00Z"
"revision": "f910dd83c2052566cad78352c33af714358d1372",
"revisionTime": "2017-02-08T07:30:35Z"
},
{
"checksumSHA1": "lPzwetgfMBtpHqdTPolgejMctVQ=",
@ -582,10 +582,10 @@
"revisionTime": "2015-06-09T07:04:31Z"
},
{
"checksumSHA1": "hSoH77pX3FyU6kkYqOOYmf3r55Y=",
"checksumSHA1": "1zk7IeGClUqBo+Phsx89p7fQ/rQ=",
"path": "github.com/hashicorp/memberlist",
"revision": "9800c50ab79c002353852a9b1095e9591b161513",
"revisionTime": "2016-12-13T23:44:46Z"
"revision": "23ad4b7d7b38496cd64c241dfd4c60b7794c254a",
"revisionTime": "2017-02-08T21:15:06Z"
},
{
"checksumSHA1": "qnlqWJYV81ENr61SZk9c65R1mDo=",
@ -625,11 +625,11 @@
"revisionTime": "2016-08-09T01:42:04Z"
},
{
"checksumSHA1": "E63/tz2qjNJ6+hyGi9AoYb0sH9s=",
"checksumSHA1": "AZ4RoXStVz6qx38ZMZAyC6Gw3Q4=",
"comment": "v0.7.0-66-g6c4672d",
"path": "github.com/hashicorp/serf/serf",
"revision": "f85661e5323286a0406cabeb0ad515962c1780b7",
"revisionTime": "2017-02-06T16:55:42Z"
"revision": "c5e26c3704ca774760df65ee8cbb039d9d9ec560",
"revisionTime": "2017-02-08T21:49:39Z"
},
{
"checksumSHA1": "ZhK6IO2XN81Y+3RAjTcVm1Ic7oU=",
@ -692,6 +692,12 @@
"revision": "9b3edd62028f107d7cabb19353292afd29311a4e",
"revisionTime": "2016-07-12T16:32:29Z"
},
{
"checksumSHA1": "A/YUMbGg1LHIeK2+NLZBt+MIAao=",
"path": "github.com/sean-/seed",
"revision": "3c72d44db0c567f7c901f9c5da5fe68392227750",
"revisionTime": "2017-02-08T16:47:21Z"
},
{
"checksumSHA1": "9rCHOi3ELajBtQUPWxxmEo/Nalk=",
"path": "github.com/shirou/gopsutil",