run 'go get -u; make revendor'
Signed-off-by: Stephan Renatus <srenatus@chef.io>
This commit is contained in:
51
vendor/github.com/coreos/etcd/pkg/tlsutil/cipher_suites.go
generated
vendored
Normal file
51
vendor/github.com/coreos/etcd/pkg/tlsutil/cipher_suites.go
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright 2018 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tlsutil
|
||||
|
||||
import "crypto/tls"
|
||||
|
||||
// cipher suites implemented by Go
|
||||
// https://github.com/golang/go/blob/dev.boringcrypto.go1.10/src/crypto/tls/cipher_suites.go
|
||||
var cipherSuites = map[string]uint16{
|
||||
"TLS_RSA_WITH_RC4_128_SHA": tls.TLS_RSA_WITH_RC4_128_SHA,
|
||||
"TLS_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA": tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||
"TLS_RSA_WITH_AES_256_CBC_SHA": tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
|
||||
"TLS_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||
"TLS_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||
"TLS_ECDHE_RSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
||||
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
||||
}
|
||||
|
||||
// GetCipherSuite returns the corresponding cipher suite,
|
||||
// and boolean value if it is supported.
|
||||
func GetCipherSuite(s string) (uint16, bool) {
|
||||
v, ok := cipherSuites[s]
|
||||
return v, ok
|
||||
}
|
2
vendor/github.com/coreos/etcd/pkg/transport/keepalive_listener.go
generated
vendored
2
vendor/github.com/coreos/etcd/pkg/transport/keepalive_listener.go
generated
vendored
@@ -79,7 +79,7 @@ func (l *tlsKeepaliveListener) Accept() (c net.Conn, err error) {
|
||||
kac.SetKeepAlive(true)
|
||||
kac.SetKeepAlivePeriod(30 * time.Second)
|
||||
c = tls.Server(c, l.config)
|
||||
return
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// NewListener creates a Listener which accepts connections from an inner
|
||||
|
51
vendor/github.com/coreos/etcd/pkg/transport/listener.go
generated
vendored
51
vendor/github.com/coreos/etcd/pkg/transport/listener.go
generated
vendored
@@ -22,6 +22,7 @@ import (
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net"
|
||||
@@ -52,15 +53,17 @@ func wrapTLS(addr, scheme string, tlsinfo *TLSInfo, l net.Listener) (net.Listene
|
||||
if scheme != "https" && scheme != "unixs" {
|
||||
return l, nil
|
||||
}
|
||||
return newTLSListener(l, tlsinfo)
|
||||
return newTLSListener(l, tlsinfo, checkSAN)
|
||||
}
|
||||
|
||||
type TLSInfo struct {
|
||||
CertFile string
|
||||
KeyFile string
|
||||
CAFile string
|
||||
TrustedCAFile string
|
||||
ClientCertAuth bool
|
||||
CertFile string
|
||||
KeyFile string
|
||||
CAFile string // TODO: deprecate this in v4
|
||||
TrustedCAFile string
|
||||
ClientCertAuth bool
|
||||
CRLFile string
|
||||
InsecureSkipVerify bool
|
||||
|
||||
// ServerName ensures the cert matches the given host in case of discovery / virtual hosting
|
||||
ServerName string
|
||||
@@ -69,15 +72,23 @@ type TLSInfo struct {
|
||||
// connection will be closed immediately afterwards.
|
||||
HandshakeFailure func(*tls.Conn, error)
|
||||
|
||||
// CipherSuites is a list of supported cipher suites.
|
||||
// If empty, Go auto-populates it by default.
|
||||
// Note that cipher suites are prioritized in the given order.
|
||||
CipherSuites []uint16
|
||||
|
||||
selfCert bool
|
||||
|
||||
// parseFunc exists to simplify testing. Typically, parseFunc
|
||||
// should be left nil. In that case, tls.X509KeyPair will be used.
|
||||
parseFunc func([]byte, []byte) (tls.Certificate, error)
|
||||
|
||||
// AllowedCN is a CN which must be provided by a client.
|
||||
AllowedCN string
|
||||
}
|
||||
|
||||
func (info TLSInfo) String() string {
|
||||
return fmt.Sprintf("cert = %s, key = %s, ca = %s, trusted-ca = %s, client-cert-auth = %v", info.CertFile, info.KeyFile, info.CAFile, info.TrustedCAFile, info.ClientCertAuth)
|
||||
return fmt.Sprintf("cert = %s, key = %s, ca = %s, trusted-ca = %s, client-cert-auth = %v, crl-file = %s", info.CertFile, info.KeyFile, info.CAFile, info.TrustedCAFile, info.ClientCertAuth, info.CRLFile)
|
||||
}
|
||||
|
||||
func (info TLSInfo) Empty() bool {
|
||||
@@ -162,16 +173,33 @@ func (info TLSInfo) baseConfig() (*tls.Config, error) {
|
||||
return nil, fmt.Errorf("KeyFile and CertFile must both be present[key: %v, cert: %v]", info.KeyFile, info.CertFile)
|
||||
}
|
||||
|
||||
tlsCert, err := tlsutil.NewCert(info.CertFile, info.KeyFile, info.parseFunc)
|
||||
_, err := tlsutil.NewCert(info.CertFile, info.KeyFile, info.parseFunc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cfg := &tls.Config{
|
||||
Certificates: []tls.Certificate{*tlsCert},
|
||||
MinVersion: tls.VersionTLS12,
|
||||
ServerName: info.ServerName,
|
||||
MinVersion: tls.VersionTLS12,
|
||||
ServerName: info.ServerName,
|
||||
}
|
||||
|
||||
if len(info.CipherSuites) > 0 {
|
||||
cfg.CipherSuites = info.CipherSuites
|
||||
}
|
||||
|
||||
if info.AllowedCN != "" {
|
||||
cfg.VerifyPeerCertificate = func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
|
||||
for _, chains := range verifiedChains {
|
||||
if len(chains) != 0 {
|
||||
if info.AllowedCN == chains[0].Subject.CommonName {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return errors.New("CommonName authentication failed")
|
||||
}
|
||||
}
|
||||
|
||||
// this only reloads certs when there's a client request
|
||||
// TODO: support server-side refresh (e.g. inotify, SIGHUP), caching
|
||||
cfg.GetCertificate = func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
||||
@@ -235,6 +263,7 @@ func (info TLSInfo) ClientConfig() (*tls.Config, error) {
|
||||
} else {
|
||||
cfg = &tls.Config{ServerName: info.ServerName}
|
||||
}
|
||||
cfg.InsecureSkipVerify = info.InsecureSkipVerify
|
||||
|
||||
CAFiles := info.cafiles()
|
||||
if len(CAFiles) > 0 {
|
||||
|
81
vendor/github.com/coreos/etcd/pkg/transport/listener_tls.go
generated
vendored
81
vendor/github.com/coreos/etcd/pkg/transport/listener_tls.go
generated
vendored
@@ -19,22 +19,33 @@ import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// tlsListener overrides a TLS listener so it will reject client
|
||||
// certificates with insufficient SAN credentials.
|
||||
// certificates with insufficient SAN credentials or CRL revoked
|
||||
// certificates.
|
||||
type tlsListener struct {
|
||||
net.Listener
|
||||
connc chan net.Conn
|
||||
donec chan struct{}
|
||||
err error
|
||||
handshakeFailure func(*tls.Conn, error)
|
||||
check tlsCheckFunc
|
||||
}
|
||||
|
||||
func newTLSListener(l net.Listener, tlsinfo *TLSInfo) (net.Listener, error) {
|
||||
type tlsCheckFunc func(context.Context, *tls.Conn) error
|
||||
|
||||
// NewTLSListener handshakes TLS connections and performs optional CRL checking.
|
||||
func NewTLSListener(l net.Listener, tlsinfo *TLSInfo) (net.Listener, error) {
|
||||
check := func(context.Context, *tls.Conn) error { return nil }
|
||||
return newTLSListener(l, tlsinfo, check)
|
||||
}
|
||||
|
||||
func newTLSListener(l net.Listener, tlsinfo *TLSInfo, check tlsCheckFunc) (net.Listener, error) {
|
||||
if tlsinfo == nil || tlsinfo.Empty() {
|
||||
l.Close()
|
||||
return nil, fmt.Errorf("cannot listen on TLS for %s: KeyFile and CertFile are not presented", l.Addr().String())
|
||||
@@ -48,11 +59,27 @@ func newTLSListener(l net.Listener, tlsinfo *TLSInfo) (net.Listener, error) {
|
||||
if hf == nil {
|
||||
hf = func(*tls.Conn, error) {}
|
||||
}
|
||||
|
||||
if len(tlsinfo.CRLFile) > 0 {
|
||||
prevCheck := check
|
||||
check = func(ctx context.Context, tlsConn *tls.Conn) error {
|
||||
if err := prevCheck(ctx, tlsConn); err != nil {
|
||||
return err
|
||||
}
|
||||
st := tlsConn.ConnectionState()
|
||||
if certs := st.PeerCertificates; len(certs) > 0 {
|
||||
return checkCRL(tlsinfo.CRLFile, certs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
tlsl := &tlsListener{
|
||||
Listener: tls.NewListener(l, tlscfg),
|
||||
connc: make(chan net.Conn),
|
||||
donec: make(chan struct{}),
|
||||
handshakeFailure: hf,
|
||||
check: check,
|
||||
}
|
||||
go tlsl.acceptLoop()
|
||||
return tlsl, nil
|
||||
@@ -67,6 +94,15 @@ func (l *tlsListener) Accept() (net.Conn, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func checkSAN(ctx context.Context, tlsConn *tls.Conn) error {
|
||||
st := tlsConn.ConnectionState()
|
||||
if certs := st.PeerCertificates; len(certs) > 0 {
|
||||
addr := tlsConn.RemoteAddr().String()
|
||||
return checkCertSAN(ctx, certs[0], addr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// acceptLoop launches each TLS handshake in a separate goroutine
|
||||
// to prevent a hanging TLS connection from blocking other connections.
|
||||
func (l *tlsListener) acceptLoop() {
|
||||
@@ -111,20 +147,16 @@ func (l *tlsListener) acceptLoop() {
|
||||
pendingMu.Lock()
|
||||
delete(pending, conn)
|
||||
pendingMu.Unlock()
|
||||
|
||||
if herr != nil {
|
||||
l.handshakeFailure(tlsConn, herr)
|
||||
return
|
||||
}
|
||||
|
||||
st := tlsConn.ConnectionState()
|
||||
if len(st.PeerCertificates) > 0 {
|
||||
cert := st.PeerCertificates[0]
|
||||
addr := tlsConn.RemoteAddr().String()
|
||||
if cerr := checkCert(ctx, cert, addr); cerr != nil {
|
||||
l.handshakeFailure(tlsConn, cerr)
|
||||
return
|
||||
}
|
||||
if err := l.check(ctx, tlsConn); err != nil {
|
||||
l.handshakeFailure(tlsConn, err)
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
case l.connc <- tlsConn:
|
||||
conn = nil
|
||||
@@ -134,11 +166,34 @@ func (l *tlsListener) acceptLoop() {
|
||||
}
|
||||
}
|
||||
|
||||
func checkCert(ctx context.Context, cert *x509.Certificate, remoteAddr string) error {
|
||||
h, _, herr := net.SplitHostPort(remoteAddr)
|
||||
func checkCRL(crlPath string, cert []*x509.Certificate) error {
|
||||
// TODO: cache
|
||||
crlBytes, err := ioutil.ReadFile(crlPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
certList, err := x509.ParseCRL(crlBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
revokedSerials := make(map[string]struct{})
|
||||
for _, rc := range certList.TBSCertList.RevokedCertificates {
|
||||
revokedSerials[string(rc.SerialNumber.Bytes())] = struct{}{}
|
||||
}
|
||||
for _, c := range cert {
|
||||
serial := string(c.SerialNumber.Bytes())
|
||||
if _, ok := revokedSerials[serial]; ok {
|
||||
return fmt.Errorf("transport: certificate serial %x revoked", serial)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkCertSAN(ctx context.Context, cert *x509.Certificate, remoteAddr string) error {
|
||||
if len(cert.IPAddresses) == 0 && len(cert.DNSNames) == 0 {
|
||||
return nil
|
||||
}
|
||||
h, _, herr := net.SplitHostPort(remoteAddr)
|
||||
if herr != nil {
|
||||
return herr
|
||||
}
|
||||
|
17
vendor/github.com/coreos/etcd/pkg/types/doc.go
generated
vendored
Normal file
17
vendor/github.com/coreos/etcd/pkg/types/doc.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package types declares various data types and implements type-checking
|
||||
// functions.
|
||||
package types
|
41
vendor/github.com/coreos/etcd/pkg/types/id.go
generated
vendored
Normal file
41
vendor/github.com/coreos/etcd/pkg/types/id.go
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// ID represents a generic identifier which is canonically
|
||||
// stored as a uint64 but is typically represented as a
|
||||
// base-16 string for input/output
|
||||
type ID uint64
|
||||
|
||||
func (i ID) String() string {
|
||||
return strconv.FormatUint(uint64(i), 16)
|
||||
}
|
||||
|
||||
// IDFromString attempts to create an ID from a base-16 string.
|
||||
func IDFromString(s string) (ID, error) {
|
||||
i, err := strconv.ParseUint(s, 16, 64)
|
||||
return ID(i), err
|
||||
}
|
||||
|
||||
// IDSlice implements the sort interface
|
||||
type IDSlice []ID
|
||||
|
||||
func (p IDSlice) Len() int { return len(p) }
|
||||
func (p IDSlice) Less(i, j int) bool { return uint64(p[i]) < uint64(p[j]) }
|
||||
func (p IDSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
178
vendor/github.com/coreos/etcd/pkg/types/set.go
generated
vendored
Normal file
178
vendor/github.com/coreos/etcd/pkg/types/set.go
generated
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Set interface {
|
||||
Add(string)
|
||||
Remove(string)
|
||||
Contains(string) bool
|
||||
Equals(Set) bool
|
||||
Length() int
|
||||
Values() []string
|
||||
Copy() Set
|
||||
Sub(Set) Set
|
||||
}
|
||||
|
||||
func NewUnsafeSet(values ...string) *unsafeSet {
|
||||
set := &unsafeSet{make(map[string]struct{})}
|
||||
for _, v := range values {
|
||||
set.Add(v)
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
func NewThreadsafeSet(values ...string) *tsafeSet {
|
||||
us := NewUnsafeSet(values...)
|
||||
return &tsafeSet{us, sync.RWMutex{}}
|
||||
}
|
||||
|
||||
type unsafeSet struct {
|
||||
d map[string]struct{}
|
||||
}
|
||||
|
||||
// Add adds a new value to the set (no-op if the value is already present)
|
||||
func (us *unsafeSet) Add(value string) {
|
||||
us.d[value] = struct{}{}
|
||||
}
|
||||
|
||||
// Remove removes the given value from the set
|
||||
func (us *unsafeSet) Remove(value string) {
|
||||
delete(us.d, value)
|
||||
}
|
||||
|
||||
// Contains returns whether the set contains the given value
|
||||
func (us *unsafeSet) Contains(value string) (exists bool) {
|
||||
_, exists = us.d[value]
|
||||
return exists
|
||||
}
|
||||
|
||||
// ContainsAll returns whether the set contains all given values
|
||||
func (us *unsafeSet) ContainsAll(values []string) bool {
|
||||
for _, s := range values {
|
||||
if !us.Contains(s) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Equals returns whether the contents of two sets are identical
|
||||
func (us *unsafeSet) Equals(other Set) bool {
|
||||
v1 := sort.StringSlice(us.Values())
|
||||
v2 := sort.StringSlice(other.Values())
|
||||
v1.Sort()
|
||||
v2.Sort()
|
||||
return reflect.DeepEqual(v1, v2)
|
||||
}
|
||||
|
||||
// Length returns the number of elements in the set
|
||||
func (us *unsafeSet) Length() int {
|
||||
return len(us.d)
|
||||
}
|
||||
|
||||
// Values returns the values of the Set in an unspecified order.
|
||||
func (us *unsafeSet) Values() (values []string) {
|
||||
values = make([]string, 0)
|
||||
for val := range us.d {
|
||||
values = append(values, val)
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
// Copy creates a new Set containing the values of the first
|
||||
func (us *unsafeSet) Copy() Set {
|
||||
cp := NewUnsafeSet()
|
||||
for val := range us.d {
|
||||
cp.Add(val)
|
||||
}
|
||||
|
||||
return cp
|
||||
}
|
||||
|
||||
// Sub removes all elements in other from the set
|
||||
func (us *unsafeSet) Sub(other Set) Set {
|
||||
oValues := other.Values()
|
||||
result := us.Copy().(*unsafeSet)
|
||||
|
||||
for _, val := range oValues {
|
||||
if _, ok := result.d[val]; !ok {
|
||||
continue
|
||||
}
|
||||
delete(result.d, val)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
type tsafeSet struct {
|
||||
us *unsafeSet
|
||||
m sync.RWMutex
|
||||
}
|
||||
|
||||
func (ts *tsafeSet) Add(value string) {
|
||||
ts.m.Lock()
|
||||
defer ts.m.Unlock()
|
||||
ts.us.Add(value)
|
||||
}
|
||||
|
||||
func (ts *tsafeSet) Remove(value string) {
|
||||
ts.m.Lock()
|
||||
defer ts.m.Unlock()
|
||||
ts.us.Remove(value)
|
||||
}
|
||||
|
||||
func (ts *tsafeSet) Contains(value string) (exists bool) {
|
||||
ts.m.RLock()
|
||||
defer ts.m.RUnlock()
|
||||
return ts.us.Contains(value)
|
||||
}
|
||||
|
||||
func (ts *tsafeSet) Equals(other Set) bool {
|
||||
ts.m.RLock()
|
||||
defer ts.m.RUnlock()
|
||||
return ts.us.Equals(other)
|
||||
}
|
||||
|
||||
func (ts *tsafeSet) Length() int {
|
||||
ts.m.RLock()
|
||||
defer ts.m.RUnlock()
|
||||
return ts.us.Length()
|
||||
}
|
||||
|
||||
func (ts *tsafeSet) Values() (values []string) {
|
||||
ts.m.RLock()
|
||||
defer ts.m.RUnlock()
|
||||
return ts.us.Values()
|
||||
}
|
||||
|
||||
func (ts *tsafeSet) Copy() Set {
|
||||
ts.m.RLock()
|
||||
defer ts.m.RUnlock()
|
||||
usResult := ts.us.Copy().(*unsafeSet)
|
||||
return &tsafeSet{usResult, sync.RWMutex{}}
|
||||
}
|
||||
|
||||
func (ts *tsafeSet) Sub(other Set) Set {
|
||||
ts.m.RLock()
|
||||
defer ts.m.RUnlock()
|
||||
usResult := ts.us.Sub(other).(*unsafeSet)
|
||||
return &tsafeSet{usResult, sync.RWMutex{}}
|
||||
}
|
22
vendor/github.com/coreos/etcd/pkg/types/slice.go
generated
vendored
Normal file
22
vendor/github.com/coreos/etcd/pkg/types/slice.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package types
|
||||
|
||||
// Uint64Slice implements sort interface
|
||||
type Uint64Slice []uint64
|
||||
|
||||
func (p Uint64Slice) Len() int { return len(p) }
|
||||
func (p Uint64Slice) Less(i, j int) bool { return p[i] < p[j] }
|
||||
func (p Uint64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
82
vendor/github.com/coreos/etcd/pkg/types/urls.go
generated
vendored
Normal file
82
vendor/github.com/coreos/etcd/pkg/types/urls.go
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type URLs []url.URL
|
||||
|
||||
func NewURLs(strs []string) (URLs, error) {
|
||||
all := make([]url.URL, len(strs))
|
||||
if len(all) == 0 {
|
||||
return nil, errors.New("no valid URLs given")
|
||||
}
|
||||
for i, in := range strs {
|
||||
in = strings.TrimSpace(in)
|
||||
u, err := url.Parse(in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if u.Scheme != "http" && u.Scheme != "https" && u.Scheme != "unix" && u.Scheme != "unixs" {
|
||||
return nil, fmt.Errorf("URL scheme must be http, https, unix, or unixs: %s", in)
|
||||
}
|
||||
if _, _, err := net.SplitHostPort(u.Host); err != nil {
|
||||
return nil, fmt.Errorf(`URL address does not have the form "host:port": %s`, in)
|
||||
}
|
||||
if u.Path != "" {
|
||||
return nil, fmt.Errorf("URL must not contain a path: %s", in)
|
||||
}
|
||||
all[i] = *u
|
||||
}
|
||||
us := URLs(all)
|
||||
us.Sort()
|
||||
|
||||
return us, nil
|
||||
}
|
||||
|
||||
func MustNewURLs(strs []string) URLs {
|
||||
urls, err := NewURLs(strs)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return urls
|
||||
}
|
||||
|
||||
func (us URLs) String() string {
|
||||
return strings.Join(us.StringSlice(), ",")
|
||||
}
|
||||
|
||||
func (us *URLs) Sort() {
|
||||
sort.Sort(us)
|
||||
}
|
||||
func (us URLs) Len() int { return len(us) }
|
||||
func (us URLs) Less(i, j int) bool { return us[i].String() < us[j].String() }
|
||||
func (us URLs) Swap(i, j int) { us[i], us[j] = us[j], us[i] }
|
||||
|
||||
func (us URLs) StringSlice() []string {
|
||||
out := make([]string, len(us))
|
||||
for i := range us {
|
||||
out[i] = us[i].String()
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
107
vendor/github.com/coreos/etcd/pkg/types/urlsmap.go
generated
vendored
Normal file
107
vendor/github.com/coreos/etcd/pkg/types/urlsmap.go
generated
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// URLsMap is a map from a name to its URLs.
|
||||
type URLsMap map[string]URLs
|
||||
|
||||
// NewURLsMap returns a URLsMap instantiated from the given string,
|
||||
// which consists of discovery-formatted names-to-URLs, like:
|
||||
// mach0=http://1.1.1.1:2380,mach0=http://2.2.2.2::2380,mach1=http://3.3.3.3:2380,mach2=http://4.4.4.4:2380
|
||||
func NewURLsMap(s string) (URLsMap, error) {
|
||||
m := parse(s)
|
||||
|
||||
cl := URLsMap{}
|
||||
for name, urls := range m {
|
||||
us, err := NewURLs(urls)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cl[name] = us
|
||||
}
|
||||
return cl, nil
|
||||
}
|
||||
|
||||
// NewURLsMapFromStringMap takes a map of strings and returns a URLsMap. The
|
||||
// string values in the map can be multiple values separated by the sep string.
|
||||
func NewURLsMapFromStringMap(m map[string]string, sep string) (URLsMap, error) {
|
||||
var err error
|
||||
um := URLsMap{}
|
||||
for k, v := range m {
|
||||
um[k], err = NewURLs(strings.Split(v, sep))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return um, nil
|
||||
}
|
||||
|
||||
// String turns URLsMap into discovery-formatted name-to-URLs sorted by name.
|
||||
func (c URLsMap) String() string {
|
||||
var pairs []string
|
||||
for name, urls := range c {
|
||||
for _, url := range urls {
|
||||
pairs = append(pairs, fmt.Sprintf("%s=%s", name, url.String()))
|
||||
}
|
||||
}
|
||||
sort.Strings(pairs)
|
||||
return strings.Join(pairs, ",")
|
||||
}
|
||||
|
||||
// URLs returns a list of all URLs.
|
||||
// The returned list is sorted in ascending lexicographical order.
|
||||
func (c URLsMap) URLs() []string {
|
||||
var urls []string
|
||||
for _, us := range c {
|
||||
for _, u := range us {
|
||||
urls = append(urls, u.String())
|
||||
}
|
||||
}
|
||||
sort.Strings(urls)
|
||||
return urls
|
||||
}
|
||||
|
||||
// Len returns the size of URLsMap.
|
||||
func (c URLsMap) Len() int {
|
||||
return len(c)
|
||||
}
|
||||
|
||||
// parse parses the given string and returns a map listing the values specified for each key.
|
||||
func parse(s string) map[string][]string {
|
||||
m := make(map[string][]string)
|
||||
for s != "" {
|
||||
key := s
|
||||
if i := strings.IndexAny(key, ","); i >= 0 {
|
||||
key, s = key[:i], key[i+1:]
|
||||
} else {
|
||||
s = ""
|
||||
}
|
||||
if key == "" {
|
||||
continue
|
||||
}
|
||||
value := ""
|
||||
if i := strings.Index(key, "="); i >= 0 {
|
||||
key, value = key[:i], key[i+1:]
|
||||
}
|
||||
m[key] = append(m[key], value)
|
||||
}
|
||||
return m
|
||||
}
|
Reference in New Issue
Block a user