Просмотр исходного кода

Vendor swarmkit @27fbaef4ceed6

Adds a new task runtime to support network attachmemt for plain old
docker containers so that they can participate multi-host networks and
get access to services.

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
Jana Radhakrishnan 8 лет назад
Родитель
Сommit
39143ef15d
59 измененных файлов с 3164 добавлено и 1273 удалено
  1. 5 5
      hack/vendor.sh
  2. 4 0
      vendor/src/github.com/cloudflare/cfssl/certdb/README.md
  3. 113 17
      vendor/src/github.com/cloudflare/cfssl/config/config.go
  4. 4 0
      vendor/src/github.com/cloudflare/cfssl/errors/error.go
  5. 39 0
      vendor/src/github.com/cloudflare/cfssl/helpers/helpers.go
  6. 10 9
      vendor/src/github.com/cloudflare/cfssl/initca/initca.go
  7. 0 8
      vendor/src/github.com/cloudflare/cfssl/log/log.go
  8. 11 11
      vendor/src/github.com/cloudflare/cfssl/signer/local/local.go
  9. 9 7
      vendor/src/github.com/cloudflare/cfssl/signer/signer.go
  10. 23 0
      vendor/src/github.com/coreos/etcd/pkg/fileutil/fileutil.go
  11. 2 2
      vendor/src/github.com/coreos/etcd/raft/log.go
  12. 12 0
      vendor/src/github.com/coreos/etcd/raft/node.go
  13. 7 5
      vendor/src/github.com/coreos/etcd/raft/raft.go
  14. 3 0
      vendor/src/github.com/coreos/etcd/raft/storage.go
  15. 1 1
      vendor/src/github.com/coreos/etcd/raft/util.go
  16. 13 17
      vendor/src/github.com/coreos/etcd/wal/wal.go
  17. 38 0
      vendor/src/github.com/coreos/etcd/wal/wal_unix.go
  18. 41 0
      vendor/src/github.com/coreos/etcd/wal/wal_windows.go
  19. 1 1
      vendor/src/github.com/docker/go-connections/sockets/tcp_socket.go
  20. 41 21
      vendor/src/github.com/docker/go-events/broadcast.go
  21. 19 5
      vendor/src/github.com/docker/go-events/channel.go
  22. 1 1
      vendor/src/github.com/docker/go-events/filter.go
  23. 1 1
      vendor/src/github.com/docker/go-events/queue.go
  24. 16 5
      vendor/src/github.com/docker/go-events/retry.go
  25. 2 2
      vendor/src/github.com/docker/swarmkit/agent/config.go
  26. 33 28
      vendor/src/github.com/docker/swarmkit/agent/node.go
  27. 14 9
      vendor/src/github.com/docker/swarmkit/agent/reporter.go
  28. 69 0
      vendor/src/github.com/docker/swarmkit/agent/resource.go
  29. 2 2
      vendor/src/github.com/docker/swarmkit/agent/session.go
  30. 1 3
      vendor/src/github.com/docker/swarmkit/agent/worker.go
  31. 1 1
      vendor/src/github.com/docker/swarmkit/api/gen.go
  32. 1105 0
      vendor/src/github.com/docker/swarmkit/api/resource.pb.go
  33. 34 0
      vendor/src/github.com/docker/swarmkit/api/resource.proto
  34. 394 262
      vendor/src/github.com/docker/swarmkit/api/specs.pb.go
  35. 24 13
      vendor/src/github.com/docker/swarmkit/api/specs.proto
  36. 531 236
      vendor/src/github.com/docker/swarmkit/api/types.pb.go
  37. 17 0
      vendor/src/github.com/docker/swarmkit/api/types.proto
  38. 33 27
      vendor/src/github.com/docker/swarmkit/ca/certificates.go
  39. 6 6
      vendor/src/github.com/docker/swarmkit/ca/config.go
  40. 23 11
      vendor/src/github.com/docker/swarmkit/manager/allocator/network.go
  41. 13 3
      vendor/src/github.com/docker/swarmkit/manager/allocator/networkallocator/networkallocator.go
  42. 6 1
      vendor/src/github.com/docker/swarmkit/manager/controlapi/network.go
  43. 14 2
      vendor/src/github.com/docker/swarmkit/manager/controlapi/service.go
  44. 4 4
      vendor/src/github.com/docker/swarmkit/manager/dispatcher/dispatcher.go
  45. 1 1
      vendor/src/github.com/docker/swarmkit/manager/dispatcher/nodes.go
  46. 37 26
      vendor/src/github.com/docker/swarmkit/manager/manager.go
  47. 17 26
      vendor/src/github.com/docker/swarmkit/manager/orchestrator/updater.go
  48. 124 0
      vendor/src/github.com/docker/swarmkit/manager/resourceapi/allocator.go
  49. 78 15
      vendor/src/github.com/docker/swarmkit/manager/state/raft/membership/cluster.go
  50. 56 31
      vendor/src/github.com/docker/swarmkit/manager/state/raft/raft.go
  51. 7 1
      vendor/src/github.com/docker/swarmkit/manager/state/raft/storage.go
  52. 4 4
      vendor/src/github.com/docker/swarmkit/manager/state/raft/util.go
  53. 1 135
      vendor/src/github.com/docker/swarmkit/remotes/remotes.go
  54. 43 13
      vendor/src/github.com/google/certificate-transparency/go/client/logclient.go
  55. 56 5
      vendor/src/github.com/google/certificate-transparency/go/serialization.go
  56. 0 1
      vendor/src/github.com/mreiferson/go-httpclient/.gitignore
  57. 0 11
      vendor/src/github.com/mreiferson/go-httpclient/.travis.yml
  58. 0 41
      vendor/src/github.com/mreiferson/go-httpclient/README.md
  59. 0 237
      vendor/src/github.com/mreiferson/go-httpclient/httpclient.go

+ 5 - 5
hack/vendor.sh

@@ -72,7 +72,7 @@ clone git github.com/imdario/mergo 0.2.1
 
 
 #get libnetwork packages
 #get libnetwork packages
 clone git github.com/docker/libnetwork 82fb373e3eaa4e9bbb5b5ac148b0a3a71f80fca6
 clone git github.com/docker/libnetwork 82fb373e3eaa4e9bbb5b5ac148b0a3a71f80fca6
-clone git github.com/docker/go-events afb2b9f2c23f33ada1a22b03651775fdc65a5089
+clone git github.com/docker/go-events 18b43f1bc85d9cdd42c05a6cd2d444c7a200a894
 clone git github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
 clone git github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
 clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
 clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
 clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
 clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
@@ -85,7 +85,7 @@ clone git github.com/vishvananda/netlink e73bad418fd727ed3a02830b1af1ad0283a1de6
 clone git github.com/BurntSushi/toml f706d00e3de6abe700c994cdd545a1a4915af060
 clone git github.com/BurntSushi/toml f706d00e3de6abe700c994cdd545a1a4915af060
 clone git github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374
 clone git github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374
 clone git github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d
 clone git github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d
-clone git github.com/coreos/etcd 06e2338108fdc694349aed923f4a7e45cf0cec1f
+clone git github.com/coreos/etcd 3a49cbb769ebd8d1dd25abb1e83386e9883a5707
 clone git github.com/ugorji/go f1f1a805ed361a0e078bb537e4ea78cd37dcf065
 clone git github.com/ugorji/go f1f1a805ed361a0e078bb537e4ea78cd37dcf065
 clone git github.com/hashicorp/consul v0.5.2
 clone git github.com/hashicorp/consul v0.5.2
 clone git github.com/boltdb/bolt v1.2.1
 clone git github.com/boltdb/bolt v1.2.1
@@ -144,11 +144,11 @@ clone git github.com/docker/docker-credential-helpers v0.3.0
 clone git github.com/docker/containerd 8508d2bec90b96403143a1104cdcbd56f6aeb361
 clone git github.com/docker/containerd 8508d2bec90b96403143a1104cdcbd56f6aeb361
 
 
 # cluster
 # cluster
-clone git github.com/docker/swarmkit 8a761950fb4d9251c335dc6149a8a02756cb3b10
+clone git github.com/docker/swarmkit 27fbaef4ceed648bb575969ccc9083a6e104a719
 clone git github.com/golang/mock bd3c8e81be01eef76d4b503f5e687d2d1354d2d9
 clone git github.com/golang/mock bd3c8e81be01eef76d4b503f5e687d2d1354d2d9
 clone git github.com/gogo/protobuf 43a2e0b1c32252bfbbdf81f7faa7a88fb3fa4028
 clone git github.com/gogo/protobuf 43a2e0b1c32252bfbbdf81f7faa7a88fb3fa4028
-clone git github.com/cloudflare/cfssl b895b0549c0ff676f92cf09ba971ae02bb41367b
-clone git github.com/google/certificate-transparency 025a5cab06f6a819c455d9fdc9e2a1b6d0982284
+clone git github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a
+clone git github.com/google/certificate-transparency 0f6e3d1d1ba4d03fdaab7cd716f36255c2e48341
 clone git golang.org/x/crypto 3fbbcd23f1cb824e69491a5930cfeff09b12f4d2 https://github.com/golang/crypto.git
 clone git golang.org/x/crypto 3fbbcd23f1cb824e69491a5930cfeff09b12f4d2 https://github.com/golang/crypto.git
 clone git golang.org/x/time a4bde12657593d5e90d0533a3e4fd95e635124cb https://github.com/golang/time.git
 clone git golang.org/x/time a4bde12657593d5e90d0533a3e4fd95e635124cb https://github.com/golang/time.git
 clone git github.com/mreiferson/go-httpclient 63fe23f7434723dc904c901043af07931f293c47
 clone git github.com/mreiferson/go-httpclient 63fe23f7434723dc904c901043af07931f293c47

+ 4 - 0
vendor/src/github.com/cloudflare/cfssl/certdb/README.md

@@ -69,3 +69,7 @@ JSON dictionary:
 or
 or
 
 
     {"driver":"postgres","data_source":"postgres://user:password@host/db"}
     {"driver":"postgres","data_source":"postgres://user:password@host/db"}
+ 
+or
+
+    {"driver":"mysql","data_source":"user:password@tcp(hostname:3306)/db?parseTime=true"}

+ 113 - 17
vendor/src/github.com/cloudflare/cfssl/config/config.go

@@ -2,6 +2,7 @@
 package config
 package config
 
 
 import (
 import (
+	"crypto/tls"
 	"crypto/x509"
 	"crypto/x509"
 	"encoding/asn1"
 	"encoding/asn1"
 	"encoding/json"
 	"encoding/json"
@@ -59,26 +60,35 @@ type AuthRemote struct {
 	AuthKeyName string `json:"auth_key"`
 	AuthKeyName string `json:"auth_key"`
 }
 }
 
 
+// CAConstraint specifies various CA constraints on the signed certificate.
+// CAConstraint would verify against (and override) the CA
+// extensions in the given CSR.
+type CAConstraint struct {
+	IsCA           bool `json:"is_ca"`
+	MaxPathLen     int  `json:"max_path_len"`
+	MaxPathLenZero bool `json:"max_path_len_zero"`
+}
+
 // A SigningProfile stores information that the CA needs to store
 // A SigningProfile stores information that the CA needs to store
 // signature policy.
 // signature policy.
 type SigningProfile struct {
 type SigningProfile struct {
-	Usage               []string   `json:"usages"`
-	IssuerURL           []string   `json:"issuer_urls"`
-	OCSP                string     `json:"ocsp_url"`
-	CRL                 string     `json:"crl_url"`
-	CA                  bool       `json:"is_ca"`
-	OCSPNoCheck         bool       `json:"ocsp_no_check"`
-	ExpiryString        string     `json:"expiry"`
-	BackdateString      string     `json:"backdate"`
-	AuthKeyName         string     `json:"auth_key"`
-	RemoteName          string     `json:"remote"`
-	NotBefore           time.Time  `json:"not_before"`
-	NotAfter            time.Time  `json:"not_after"`
-	NameWhitelistString string     `json:"name_whitelist"`
-	AuthRemote          AuthRemote `json:"auth_remote"`
-	CTLogServers        []string   `json:"ct_log_servers"`
-	AllowedExtensions   []OID      `json:"allowed_extensions"`
-	CertStore           string     `json:"cert_store"`
+	Usage               []string     `json:"usages"`
+	IssuerURL           []string     `json:"issuer_urls"`
+	OCSP                string       `json:"ocsp_url"`
+	CRL                 string       `json:"crl_url"`
+	CAConstraint        CAConstraint `json:"ca_constraint"`
+	OCSPNoCheck         bool         `json:"ocsp_no_check"`
+	ExpiryString        string       `json:"expiry"`
+	BackdateString      string       `json:"backdate"`
+	AuthKeyName         string       `json:"auth_key"`
+	RemoteName          string       `json:"remote"`
+	NotBefore           time.Time    `json:"not_before"`
+	NotAfter            time.Time    `json:"not_after"`
+	NameWhitelistString string       `json:"name_whitelist"`
+	AuthRemote          AuthRemote   `json:"auth_remote"`
+	CTLogServers        []string     `json:"ct_log_servers"`
+	AllowedExtensions   []OID        `json:"allowed_extensions"`
+	CertStore           string       `json:"cert_store"`
 
 
 	Policies                    []CertificatePolicy
 	Policies                    []CertificatePolicy
 	Expiry                      time.Duration
 	Expiry                      time.Duration
@@ -86,6 +96,8 @@ type SigningProfile struct {
 	Provider                    auth.Provider
 	Provider                    auth.Provider
 	RemoteProvider              auth.Provider
 	RemoteProvider              auth.Provider
 	RemoteServer                string
 	RemoteServer                string
+	RemoteCAs                   *x509.CertPool
+	ClientCert                  *tls.Certificate
 	CSRWhitelist                *CSRWhitelist
 	CSRWhitelist                *CSRWhitelist
 	NameWhitelist               *regexp.Regexp
 	NameWhitelist               *regexp.Regexp
 	ExtensionWhitelist          map[string]bool
 	ExtensionWhitelist          map[string]bool
@@ -303,6 +315,44 @@ func (p *Signing) OverrideRemotes(remote string) error {
 	return nil
 	return nil
 }
 }
 
 
+// SetClientCertKeyPairFromFile updates the properties to set client certificates for mutual
+// authenticated TLS remote requests
+func (p *Signing) SetClientCertKeyPairFromFile(certFile string, keyFile string) error {
+	if certFile != "" && keyFile != "" {
+		cert, err := helpers.LoadClientCertificate(certFile, keyFile)
+		if err != nil {
+			return err
+		}
+		for _, profile := range p.Profiles {
+			profile.ClientCert = cert
+		}
+		p.Default.ClientCert = cert
+	}
+	return nil
+}
+
+// SetRemoteCAsFromFile reads root CAs from file and updates the properties to set remote CAs for TLS
+// remote requests
+func (p *Signing) SetRemoteCAsFromFile(caFile string) error {
+	if caFile != "" {
+		remoteCAs, err := helpers.LoadPEMCertPool(caFile)
+		if err != nil {
+			return err
+		}
+		p.SetRemoteCAs(remoteCAs)
+	}
+	return nil
+}
+
+// SetRemoteCAs updates the properties to set remote CAs for TLS
+// remote requests
+func (p *Signing) SetRemoteCAs(remoteCAs *x509.CertPool) {
+	for _, profile := range p.Profiles {
+		profile.RemoteCAs = remoteCAs
+	}
+	p.Default.RemoteCAs = remoteCAs
+}
+
 // NeedsRemoteSigner returns true if one of the profiles has a remote set
 // NeedsRemoteSigner returns true if one of the profiles has a remote set
 func (p *Signing) NeedsRemoteSigner() bool {
 func (p *Signing) NeedsRemoteSigner() bool {
 	for _, profile := range p.Profiles {
 	for _, profile := range p.Profiles {
@@ -360,6 +410,11 @@ func (p *SigningProfile) validProfile(isDefault bool) bool {
 		return false
 		return false
 	}
 	}
 
 
+	if p.AuthRemote.RemoteName == "" && p.AuthRemote.AuthKeyName != "" {
+		log.Debugf("invalid auth remote profile: no remote signer specified")
+		return false
+	}
+
 	if p.RemoteName != "" {
 	if p.RemoteName != "" {
 		log.Debugf("validate remote profile")
 		log.Debugf("validate remote profile")
 
 
@@ -375,6 +430,7 @@ func (p *SigningProfile) validProfile(isDefault bool) bool {
 
 
 		if p.AuthRemote.RemoteName != "" {
 		if p.AuthRemote.RemoteName != "" {
 			log.Debugf("invalid remote profile: auth remote is also specified")
 			log.Debugf("invalid remote profile: auth remote is also specified")
+			return false
 		}
 		}
 	} else if p.AuthRemote.RemoteName != "" {
 	} else if p.AuthRemote.RemoteName != "" {
 		log.Debugf("validate auth remote profile")
 		log.Debugf("validate auth remote profile")
@@ -409,6 +465,43 @@ func (p *SigningProfile) validProfile(isDefault bool) bool {
 	return true
 	return true
 }
 }
 
 
+// This checks if the SigningProfile object contains configurations that are only effective with a local signer
+// which has access to CA private key.
+func (p *SigningProfile) hasLocalConfig() bool {
+	if p.Usage != nil ||
+		p.IssuerURL != nil ||
+		p.OCSP != "" ||
+		p.ExpiryString != "" ||
+		p.BackdateString != "" ||
+		p.CAConstraint.IsCA != false ||
+		!p.NotBefore.IsZero() ||
+		!p.NotAfter.IsZero() ||
+		p.NameWhitelistString != "" ||
+		len(p.CTLogServers) != 0 {
+		return true
+	}
+	return false
+}
+
+// warnSkippedSettings prints a log warning message about skipped settings
+// in a SigningProfile, usually due to remote signer.
+func (p *Signing) warnSkippedSettings() {
+	const warningMessage = `The configuration value by "usages", "issuer_urls", "ocsp_url", "crl_url", "ca_constraint", "expiry", "backdate", "not_before", "not_after", "cert_store" and "ct_log_servers" are skipped`
+	if p == nil {
+		return
+	}
+
+	if (p.Default.RemoteName != "" || p.Default.AuthRemote.RemoteName != "") && p.Default.hasLocalConfig() {
+		log.Warning("default profile points to a remote signer: ", warningMessage)
+	}
+
+	for name, profile := range p.Profiles {
+		if (profile.RemoteName != "" || profile.AuthRemote.RemoteName != "") && profile.hasLocalConfig() {
+			log.Warningf("Profiles[%s] points to a remote signer: %s", name, warningMessage)
+		}
+	}
+}
+
 // Signing codifies the signature configuration policy for a CA.
 // Signing codifies the signature configuration policy for a CA.
 type Signing struct {
 type Signing struct {
 	Profiles map[string]*SigningProfile `json:"profiles"`
 	Profiles map[string]*SigningProfile `json:"profiles"`
@@ -450,6 +543,9 @@ func (p *Signing) Valid() bool {
 			return false
 			return false
 		}
 		}
 	}
 	}
+
+	p.warnSkippedSettings()
+
 	return true
 	return true
 }
 }
 
 

+ 4 - 0
vendor/src/github.com/cloudflare/cfssl/errors/error.go

@@ -149,6 +149,8 @@ const (
 
 
 	// UnknownProfile indicates that the profile does not exist.
 	// UnknownProfile indicates that the profile does not exist.
 	UnknownProfile // 54XX
 	UnknownProfile // 54XX
+
+	UnmatchedWhitelist // 55xx
 )
 )
 
 
 // The following are API client related errors, and should be
 // The following are API client related errors, and should be
@@ -313,6 +315,8 @@ func New(category Category, reason Reason) *Error {
 			msg = "Policy violation request"
 			msg = "Policy violation request"
 		case UnknownProfile:
 		case UnknownProfile:
 			msg = "Unknown policy profile"
 			msg = "Unknown policy profile"
+		case UnmatchedWhitelist:
+			msg = "Request does not match policy whitelist"
 		default:
 		default:
 			panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category PolicyError.",
 			panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category PolicyError.",
 				reason))
 				reason))

+ 39 - 0
vendor/src/github.com/cloudflare/cfssl/helpers/helpers.go

@@ -8,6 +8,7 @@ import (
 	"crypto/ecdsa"
 	"crypto/ecdsa"
 	"crypto/elliptic"
 	"crypto/elliptic"
 	"crypto/rsa"
 	"crypto/rsa"
+	"crypto/tls"
 	"crypto/x509"
 	"crypto/x509"
 	"encoding/asn1"
 	"encoding/asn1"
 	"encoding/pem"
 	"encoding/pem"
@@ -311,11 +312,23 @@ func ParseOneCertificateFromPEM(certsPEM []byte) ([]*x509.Certificate, []byte, e
 
 
 // LoadPEMCertPool loads a pool of PEM certificates from file.
 // LoadPEMCertPool loads a pool of PEM certificates from file.
 func LoadPEMCertPool(certsFile string) (*x509.CertPool, error) {
 func LoadPEMCertPool(certsFile string) (*x509.CertPool, error) {
+	if certsFile == "" {
+		return nil, nil
+	}
 	pemCerts, err := ioutil.ReadFile(certsFile)
 	pemCerts, err := ioutil.ReadFile(certsFile)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 
 
+	return PEMToCertPool(pemCerts)
+}
+
+// PEMToCertPool concerts PEM certificates to a CertPool.
+func PEMToCertPool(pemCerts []byte) (*x509.CertPool, error) {
+	if len(pemCerts) == 0 {
+		return nil, nil
+	}
+
 	certPool := x509.NewCertPool()
 	certPool := x509.NewCertPool()
 	if !certPool.AppendCertsFromPEM(pemCerts) {
 	if !certPool.AppendCertsFromPEM(pemCerts) {
 		return nil, errors.New("failed to load cert pool")
 		return nil, errors.New("failed to load cert pool")
@@ -477,3 +490,29 @@ func SignerAlgo(priv crypto.Signer) x509.SignatureAlgorithm {
 		return x509.UnknownSignatureAlgorithm
 		return x509.UnknownSignatureAlgorithm
 	}
 	}
 }
 }
+
+// LoadClientCertificate load key/certificate from pem files
+func LoadClientCertificate(certFile string, keyFile string) (*tls.Certificate, error) {
+	if certFile != "" && keyFile != "" {
+		cert, err := tls.LoadX509KeyPair(certFile, keyFile)
+		if err != nil {
+			log.Critical("Unable to read client certificate from file: %s or key from file: %s", certFile, keyFile)
+			return nil, err
+		}
+		log.Debug("Client certificate loaded ")
+		return &cert, nil
+	}
+	return nil, nil
+}
+
+// CreateTLSConfig creates a tls.Config object from certs and roots
+func CreateTLSConfig(remoteCAs *x509.CertPool, cert *tls.Certificate) *tls.Config {
+	var certs []tls.Certificate
+	if cert != nil {
+		certs = []tls.Certificate{*cert}
+	}
+	return &tls.Config{
+		Certificates: certs,
+		RootCAs:      remoteCAs,
+	}
+}

+ 10 - 9
vendor/src/github.com/cloudflare/cfssl/initca/initca.go

@@ -48,13 +48,16 @@ func New(req *csr.CertificateRequest) (cert, csrPEM, key []byte, err error) {
 		if req.CA.Expiry != "" {
 		if req.CA.Expiry != "" {
 			policy.Default.ExpiryString = req.CA.Expiry
 			policy.Default.ExpiryString = req.CA.Expiry
 			policy.Default.Expiry, err = time.ParseDuration(req.CA.Expiry)
 			policy.Default.Expiry, err = time.ParseDuration(req.CA.Expiry)
+			if err != nil {
+				return
+			}
 		}
 		}
 
 
-		signer.MaxPathLen = req.CA.PathLength
+		policy.Default.CAConstraint.MaxPathLen = req.CA.PathLength
 		if req.CA.PathLength != 0 && req.CA.PathLenZero == true {
 		if req.CA.PathLength != 0 && req.CA.PathLenZero == true {
 			log.Infof("ignore invalid 'pathlenzero' value")
 			log.Infof("ignore invalid 'pathlenzero' value")
 		} else {
 		} else {
-			signer.MaxPathLenZero = req.CA.PathLenZero
+			policy.Default.CAConstraint.MaxPathLenZero = req.CA.PathLenZero
 		}
 		}
 	}
 	}
 
 
@@ -72,12 +75,11 @@ func New(req *csr.CertificateRequest) (cert, csrPEM, key []byte, err error) {
 		return
 		return
 	}
 	}
 
 
-	s, err := local.NewSigner(priv, nil, signer.DefaultSigAlgo(priv), nil)
+	s, err := local.NewSigner(priv, nil, signer.DefaultSigAlgo(priv), policy)
 	if err != nil {
 	if err != nil {
 		log.Errorf("failed to create signer: %v", err)
 		log.Errorf("failed to create signer: %v", err)
 		return
 		return
 	}
 	}
-	s.SetPolicy(policy)
 
 
 	signReq := signer.SignRequest{Hosts: req.Hosts, Request: string(csrPEM)}
 	signReq := signer.SignRequest{Hosts: req.Hosts, Request: string(csrPEM)}
 	cert, err = s.Sign(signReq)
 	cert, err = s.Sign(signReq)
@@ -143,11 +145,11 @@ func NewFromSigner(req *csr.CertificateRequest, priv crypto.Signer) (cert, csrPE
 			}
 			}
 		}
 		}
 
 
-		signer.MaxPathLen = req.CA.PathLength
+		policy.Default.CAConstraint.MaxPathLen = req.CA.PathLength
 		if req.CA.PathLength != 0 && req.CA.PathLenZero == true {
 		if req.CA.PathLength != 0 && req.CA.PathLenZero == true {
 			log.Infof("ignore invalid 'pathlenzero' value")
 			log.Infof("ignore invalid 'pathlenzero' value")
 		} else {
 		} else {
-			signer.MaxPathLenZero = req.CA.PathLenZero
+			policy.Default.CAConstraint.MaxPathLenZero = req.CA.PathLenZero
 		}
 		}
 	}
 	}
 
 
@@ -156,12 +158,11 @@ func NewFromSigner(req *csr.CertificateRequest, priv crypto.Signer) (cert, csrPE
 		return nil, nil, err
 		return nil, nil, err
 	}
 	}
 
 
-	s, err := local.NewSigner(priv, nil, signer.DefaultSigAlgo(priv), nil)
+	s, err := local.NewSigner(priv, nil, signer.DefaultSigAlgo(priv), policy)
 	if err != nil {
 	if err != nil {
 		log.Errorf("failed to create signer: %v", err)
 		log.Errorf("failed to create signer: %v", err)
 		return
 		return
 	}
 	}
-	s.SetPolicy(policy)
 
 
 	signReq := signer.SignRequest{Request: string(csrPEM)}
 	signReq := signer.SignRequest{Request: string(csrPEM)}
 	cert, err = s.Sign(signReq)
 	cert, err = s.Sign(signReq)
@@ -217,7 +218,7 @@ var CAPolicy = func() *config.Signing {
 			Usage:        []string{"cert sign", "crl sign"},
 			Usage:        []string{"cert sign", "crl sign"},
 			ExpiryString: "43800h",
 			ExpiryString: "43800h",
 			Expiry:       5 * helpers.OneYear,
 			Expiry:       5 * helpers.OneYear,
-			CA:           true,
+			CAConstraint: config.CAConstraint{IsCA: true},
 		},
 		},
 	}
 	}
 }
 }

+ 0 - 8
vendor/src/github.com/cloudflare/cfssl/log/log.go

@@ -6,7 +6,6 @@
 package log
 package log
 
 
 import (
 import (
-	"flag"
 	"fmt"
 	"fmt"
 	"log"
 	"log"
 	"os"
 	"os"
@@ -63,13 +62,6 @@ func SetLogger(logger SyslogWriter) {
 	syslogWriter = logger
 	syslogWriter = logger
 }
 }
 
 
-func init() {
-	// Only define loglevel flag once.
-	if flag.Lookup("loglevel") == nil {
-		flag.IntVar(&Level, "loglevel", LevelInfo, "Log level (0 = DEBUG, 5 = FATAL)")
-	}
-}
-
 func print(l int, msg string) {
 func print(l int, msg string) {
 	if l >= Level {
 	if l >= Level {
 		if syslogWriter != nil {
 		if syslogWriter != nil {

+ 11 - 11
vendor/src/github.com/cloudflare/cfssl/signer/local/local.go

@@ -115,9 +115,6 @@ func (s *Signer) sign(template *x509.Certificate, profile *config.SigningProfile
 		template.EmailAddresses = nil
 		template.EmailAddresses = nil
 		s.ca = template
 		s.ca = template
 		initRoot = true
 		initRoot = true
-	} else if template.IsCA {
-		template.DNSNames = nil
-		template.EmailAddresses = nil
 	}
 	}
 
 
 	derBytes, err := x509.CreateCertificate(rand.Reader, template, s.ca, template.PublicKey, s.priv)
 	derBytes, err := x509.CreateCertificate(rand.Reader, template, s.ca, template.PublicKey, s.priv)
@@ -250,18 +247,21 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
 	}
 	}
 
 
 	if safeTemplate.IsCA {
 	if safeTemplate.IsCA {
-		if !profile.CA {
-			return nil, cferr.New(cferr.CertificateError, cferr.InvalidRequest)
+		if !profile.CAConstraint.IsCA {
+			log.Error("local signer policy disallows issuing CA certificate")
+			return nil, cferr.New(cferr.PolicyError, cferr.InvalidRequest)
 		}
 		}
 
 
 		if s.ca != nil && s.ca.MaxPathLen > 0 {
 		if s.ca != nil && s.ca.MaxPathLen > 0 {
 			if safeTemplate.MaxPathLen >= s.ca.MaxPathLen {
 			if safeTemplate.MaxPathLen >= s.ca.MaxPathLen {
+				log.Error("local signer certificate disallows CA MaxPathLen extending")
 				// do not sign a cert with pathlen > current
 				// do not sign a cert with pathlen > current
-				return nil, cferr.New(cferr.CertificateError, cferr.InvalidRequest)
+				return nil, cferr.New(cferr.PolicyError, cferr.InvalidRequest)
 			}
 			}
 		} else if s.ca != nil && s.ca.MaxPathLen == 0 && s.ca.MaxPathLenZero {
 		} else if s.ca != nil && s.ca.MaxPathLen == 0 && s.ca.MaxPathLenZero {
+			log.Error("local signer certificate disallows issuing CA certificate")
 			// signer has pathlen of 0, do not sign more intermediate CAs
 			// signer has pathlen of 0, do not sign more intermediate CAs
-			return nil, cferr.New(cferr.CertificateError, cferr.InvalidRequest)
+			return nil, cferr.New(cferr.PolicyError, cferr.InvalidRequest)
 		}
 		}
 	}
 	}
 
 
@@ -272,17 +272,17 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
 	if profile.NameWhitelist != nil {
 	if profile.NameWhitelist != nil {
 		if safeTemplate.Subject.CommonName != "" {
 		if safeTemplate.Subject.CommonName != "" {
 			if profile.NameWhitelist.Find([]byte(safeTemplate.Subject.CommonName)) == nil {
 			if profile.NameWhitelist.Find([]byte(safeTemplate.Subject.CommonName)) == nil {
-				return nil, cferr.New(cferr.PolicyError, cferr.InvalidPolicy)
+				return nil, cferr.New(cferr.PolicyError, cferr.UnmatchedWhitelist)
 			}
 			}
 		}
 		}
 		for _, name := range safeTemplate.DNSNames {
 		for _, name := range safeTemplate.DNSNames {
 			if profile.NameWhitelist.Find([]byte(name)) == nil {
 			if profile.NameWhitelist.Find([]byte(name)) == nil {
-				return nil, cferr.New(cferr.PolicyError, cferr.InvalidPolicy)
+				return nil, cferr.New(cferr.PolicyError, cferr.UnmatchedWhitelist)
 			}
 			}
 		}
 		}
 		for _, name := range safeTemplate.EmailAddresses {
 		for _, name := range safeTemplate.EmailAddresses {
 			if profile.NameWhitelist.Find([]byte(name)) == nil {
 			if profile.NameWhitelist.Find([]byte(name)) == nil {
-				return nil, cferr.New(cferr.PolicyError, cferr.InvalidPolicy)
+				return nil, cferr.New(cferr.PolicyError, cferr.UnmatchedWhitelist)
 			}
 			}
 		}
 		}
 	}
 	}
@@ -352,7 +352,7 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
 
 
 		for _, server := range profile.CTLogServers {
 		for _, server := range profile.CTLogServers {
 			log.Infof("submitting poisoned precertificate to %s", server)
 			log.Infof("submitting poisoned precertificate to %s", server)
-			var ctclient = client.New(server)
+			var ctclient = client.New(server, nil)
 			var resp *ct.SignedCertificateTimestamp
 			var resp *ct.SignedCertificateTimestamp
 			resp, err = ctclient.AddPreChain(prechain)
 			resp, err = ctclient.AddPreChain(prechain)
 			if err != nil {
 			if err != nil {

+ 9 - 7
vendor/src/github.com/cloudflare/cfssl/signer/signer.go

@@ -23,12 +23,6 @@ import (
 	"github.com/cloudflare/cfssl/info"
 	"github.com/cloudflare/cfssl/info"
 )
 )
 
 
-// MaxPathLen is the default path length for a new CA certificate.
-var MaxPathLen = 2
-
-// MaxPathLenZero indicates whether a new CA certificate has pathlen=0
-var MaxPathLenZero = false
-
 // Subject contains the information that should be used to override the
 // Subject contains the information that should be used to override the
 // subject information when signing a certificate.
 // subject information when signing a certificate.
 type Subject struct {
 type Subject struct {
@@ -294,7 +288,15 @@ func FillTemplate(template *x509.Certificate, defaultProfile, profile *config.Si
 	template.KeyUsage = ku
 	template.KeyUsage = ku
 	template.ExtKeyUsage = eku
 	template.ExtKeyUsage = eku
 	template.BasicConstraintsValid = true
 	template.BasicConstraintsValid = true
-	template.IsCA = profile.CA
+	template.IsCA = profile.CAConstraint.IsCA
+	if template.IsCA {
+		template.MaxPathLen = profile.CAConstraint.MaxPathLen
+		if template.MaxPathLen == 0 {
+			template.MaxPathLenZero = profile.CAConstraint.MaxPathLenZero
+		}
+		template.DNSNames = nil
+		template.EmailAddresses = nil
+	}
 	template.SubjectKeyId = ski
 	template.SubjectKeyId = ski
 
 
 	if ocspURL != "" {
 	if ocspURL != "" {

+ 23 - 0
vendor/src/github.com/coreos/etcd/pkg/fileutil/fileutil.go

@@ -96,3 +96,26 @@ func Exist(name string) bool {
 	_, err := os.Stat(name)
 	_, err := os.Stat(name)
 	return err == nil
 	return err == nil
 }
 }
+
+// ZeroToEnd zeros a file starting from SEEK_CUR to its SEEK_END. May temporarily
+// shorten the length of the file.
+func ZeroToEnd(f *os.File) error {
+	// TODO: support FALLOC_FL_ZERO_RANGE
+	off, err := f.Seek(0, os.SEEK_CUR)
+	if err != nil {
+		return err
+	}
+	lenf, lerr := f.Seek(0, os.SEEK_END)
+	if lerr != nil {
+		return lerr
+	}
+	if err = f.Truncate(off); err != nil {
+		return err
+	}
+	// make sure blocks remain allocated
+	if err = Preallocate(f, lenf, true); err != nil {
+		return err
+	}
+	_, err = f.Seek(off, os.SEEK_SET)
+	return err
+}

+ 2 - 2
vendor/src/github.com/coreos/etcd/raft/log.go

@@ -232,7 +232,7 @@ func (l *raftLog) term(i uint64) (uint64, error) {
 	if err == nil {
 	if err == nil {
 		return t, nil
 		return t, nil
 	}
 	}
-	if err == ErrCompacted {
+	if err == ErrCompacted || err == ErrUnavailable {
 		return 0, err
 		return 0, err
 	}
 	}
 	panic(err) // TODO(bdarnell)
 	panic(err) // TODO(bdarnell)
@@ -339,7 +339,7 @@ func (l *raftLog) mustCheckOutOfBounds(lo, hi uint64) error {
 		return ErrCompacted
 		return ErrCompacted
 	}
 	}
 
 
-	length := l.lastIndex() - fi + 1
+	length := l.lastIndex() + 1 - fi
 	if lo < fi || hi > fi+length {
 	if lo < fi || hi > fi+length {
 		l.logger.Panicf("slice[%d,%d) out of bound [%d,%d]", lo, hi, fi, l.lastIndex())
 		l.logger.Panicf("slice[%d,%d) out of bound [%d,%d]", lo, hi, fi, l.lastIndex())
 	}
 	}

+ 12 - 0
vendor/src/github.com/coreos/etcd/raft/node.go

@@ -144,6 +144,9 @@ type Node interface {
 	// to match MemoryStorage.Compact.
 	// to match MemoryStorage.Compact.
 	ApplyConfChange(cc pb.ConfChange) *pb.ConfState
 	ApplyConfChange(cc pb.ConfChange) *pb.ConfState
 
 
+	// TransferLeadership attempts to transfer leadership to the given transferee.
+	TransferLeadership(ctx context.Context, lead, transferee uint64)
+
 	// ReadIndex request a read state. The read state will be set in the ready.
 	// ReadIndex request a read state. The read state will be set in the ready.
 	// Read state has a read index. Once the application advances further than the read
 	// Read state has a read index. Once the application advances further than the read
 	// index, any linearizable read requests issued before the read request can be
 	// index, any linearizable read requests issued before the read request can be
@@ -485,6 +488,15 @@ func (n *node) ReportSnapshot(id uint64, status SnapshotStatus) {
 	}
 	}
 }
 }
 
 
+func (n *node) TransferLeadership(ctx context.Context, lead, transferee uint64) {
+	select {
+	// manually set 'from' and 'to', so that leader can voluntarily transfers its leadership
+	case n.recvc <- pb.Message{Type: pb.MsgTransferLeader, From: transferee, To: lead}:
+	case <-n.done:
+	case <-ctx.Done():
+	}
+}
+
 func (n *node) ReadIndex(ctx context.Context, rctx []byte) error {
 func (n *node) ReadIndex(ctx context.Context, rctx []byte) error {
 	return n.step(ctx, pb.Message{Type: pb.MsgReadIndex, Entries: []pb.Entry{{Data: rctx}}})
 	return n.step(ctx, pb.Message{Type: pb.MsgReadIndex, Entries: []pb.Entry{{Data: rctx}}})
 }
 }

+ 7 - 5
vendor/src/github.com/coreos/etcd/raft/raft.go

@@ -590,11 +590,6 @@ func (r *raft) Step(m pb.Message) error {
 		}
 		}
 		return nil
 		return nil
 	}
 	}
-	if m.Type == pb.MsgTransferLeader {
-		if r.state != StateLeader {
-			r.logger.Debugf("%x [term %d state %v] ignoring MsgTransferLeader to %x", r.id, r.Term, r.state, m.From)
-		}
-	}
 
 
 	switch {
 	switch {
 	case m.Term == 0:
 	case m.Term == 0:
@@ -874,6 +869,13 @@ func stepFollower(r *raft, m pb.Message) {
 				r.id, r.raftLog.lastTerm(), r.raftLog.lastIndex(), r.Vote, m.From, m.LogTerm, m.Index, r.Term)
 				r.id, r.raftLog.lastTerm(), r.raftLog.lastIndex(), r.Vote, m.From, m.LogTerm, m.Index, r.Term)
 			r.send(pb.Message{To: m.From, Type: pb.MsgVoteResp, Reject: true})
 			r.send(pb.Message{To: m.From, Type: pb.MsgVoteResp, Reject: true})
 		}
 		}
+	case pb.MsgTransferLeader:
+		if r.lead == None {
+			r.logger.Infof("%x no leader at term %d; dropping leader transfer msg", r.id, r.Term)
+			return
+		}
+		m.To = r.lead
+		r.send(m)
 	case pb.MsgTimeoutNow:
 	case pb.MsgTimeoutNow:
 		r.logger.Infof("%x [term %d] received MsgTimeoutNow from %x and starts an election to get leadership.", r.id, r.Term, m.From)
 		r.logger.Infof("%x [term %d] received MsgTimeoutNow from %x and starts an election to get leadership.", r.id, r.Term, m.From)
 		r.campaign(campaignTransfer)
 		r.campaign(campaignTransfer)

+ 3 - 0
vendor/src/github.com/coreos/etcd/raft/storage.go

@@ -130,6 +130,9 @@ func (ms *MemoryStorage) Term(i uint64) (uint64, error) {
 	if i < offset {
 	if i < offset {
 		return 0, ErrCompacted
 		return 0, ErrCompacted
 	}
 	}
+	if int(i-offset) >= len(ms.ents) {
+		return 0, ErrUnavailable
+	}
 	return ms.ents[i-offset].Term, nil
 	return ms.ents[i-offset].Term, nil
 }
 }
 
 

+ 1 - 1
vendor/src/github.com/coreos/etcd/raft/util.go

@@ -48,7 +48,7 @@ func max(a, b uint64) uint64 {
 
 
 func IsLocalMsg(msgt pb.MessageType) bool {
 func IsLocalMsg(msgt pb.MessageType) bool {
 	return msgt == pb.MsgHup || msgt == pb.MsgBeat || msgt == pb.MsgUnreachable ||
 	return msgt == pb.MsgHup || msgt == pb.MsgBeat || msgt == pb.MsgUnreachable ||
-		msgt == pb.MsgSnapStatus || msgt == pb.MsgCheckQuorum || msgt == pb.MsgTransferLeader
+		msgt == pb.MsgSnapStatus || msgt == pb.MsgCheckQuorum
 }
 }
 
 
 func IsResponseMsg(msgt pb.MessageType) bool {
 func IsResponseMsg(msgt pb.MessageType) bool {

+ 13 - 17
vendor/src/github.com/coreos/etcd/wal/wal.go

@@ -131,22 +131,7 @@ func Create(dirpath string, metadata []byte) (*WAL, error) {
 		return nil, err
 		return nil, err
 	}
 	}
 
 
-	// rename of directory with locked files doesn't work on windows; close
-	// the WAL to release the locks so the directory can be renamed
-	w.Close()
-	if err := os.Rename(tmpdirpath, dirpath); err != nil {
-		return nil, err
-	}
-	// reopen and relock
-	newWAL, oerr := Open(dirpath, walpb.Snapshot{})
-	if oerr != nil {
-		return nil, oerr
-	}
-	if _, _, _, err := newWAL.ReadAll(); err != nil {
-		newWAL.Close()
-		return nil, err
-	}
-	return newWAL, nil
+	return w.renameWal(tmpdirpath)
 }
 }
 
 
 // Open opens the WAL at the given snap.
 // Open opens the WAL at the given snap.
@@ -301,6 +286,18 @@ func (w *WAL) ReadAll() (metadata []byte, state raftpb.HardState, ents []raftpb.
 			state.Reset()
 			state.Reset()
 			return nil, state, nil, err
 			return nil, state, nil, err
 		}
 		}
+		// decodeRecord() will return io.EOF if it detects a zero record,
+		// but this zero record may be followed by non-zero records from
+		// a torn write. Overwriting some of these non-zero records, but
+		// not all, will cause CRC errors on WAL open. Since the records
+		// were never fully synced to disk in the first place, it's safe
+		// to zero them out to avoid any CRC errors from new writes.
+		if _, err = w.tail().Seek(w.decoder.lastOffset(), os.SEEK_SET); err != nil {
+			return nil, state, nil, err
+		}
+		if err = fileutil.ZeroToEnd(w.tail().File); err != nil {
+			return nil, state, nil, err
+		}
 	}
 	}
 
 
 	err = nil
 	err = nil
@@ -319,7 +316,6 @@ func (w *WAL) ReadAll() (metadata []byte, state raftpb.HardState, ents []raftpb.
 
 
 	if w.tail() != nil {
 	if w.tail() != nil {
 		// create encoder (chain crc with the decoder), enable appending
 		// create encoder (chain crc with the decoder), enable appending
-		_, err = w.tail().Seek(w.decoder.lastOffset(), os.SEEK_SET)
 		w.encoder = newEncoder(w.tail(), w.decoder.lastCRC())
 		w.encoder = newEncoder(w.tail(), w.decoder.lastCRC())
 	}
 	}
 	w.decoder = nil
 	w.decoder = nil

+ 38 - 0
vendor/src/github.com/coreos/etcd/wal/wal_unix.go

@@ -0,0 +1,38 @@
+// Copyright 2016 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.
+
+// +build !windows
+
+package wal
+
+import "os"
+
+func (w *WAL) renameWal(tmpdirpath string) (*WAL, error) {
+	// On non-Windows platforms, hold the lock while renaming. Releasing
+	// the lock and trying to reacquire it quickly can be flaky because
+	// it's possible the process will fork to spawn a process while this is
+	// happening. The fds are set up as close-on-exec by the Go runtime,
+	// but there is a window between the fork and the exec where another
+	// process holds the lock.
+
+	if err := os.RemoveAll(w.dir); err != nil {
+		return nil, err
+	}
+	if err := os.Rename(tmpdirpath, w.dir); err != nil {
+		return nil, err
+	}
+
+	w.fp = newFilePipeline(w.dir, SegmentSizeBytes)
+	return w, nil
+}

+ 41 - 0
vendor/src/github.com/coreos/etcd/wal/wal_windows.go

@@ -0,0 +1,41 @@
+// Copyright 2016 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 wal
+
+import (
+	"os"
+
+	"github.com/coreos/etcd/wal/walpb"
+)
+
+func (w *WAL) renameWal(tmpdirpath string) (*WAL, error) {
+	// rename of directory with locked files doesn't work on
+	// windows; close the WAL to release the locks so the directory
+	// can be renamed
+	w.Close()
+	if err := os.Rename(tmpdirpath, w.dir); err != nil {
+		return nil, err
+	}
+	// reopen and relock
+	newWAL, oerr := Open(w.dir, walpb.Snapshot{})
+	if oerr != nil {
+		return nil, oerr
+	}
+	if _, _, _, err := newWAL.ReadAll(); err != nil {
+		newWAL.Close()
+		return nil, err
+	}
+	return newWAL, nil
+}

+ 1 - 1
vendor/src/github.com/docker/go-connections/sockets/tcp_socket.go

@@ -7,7 +7,7 @@ import (
 )
 )
 
 
 // NewTCPSocket creates a TCP socket listener with the specified address and
 // NewTCPSocket creates a TCP socket listener with the specified address and
-// the specified tls configuration. If TLSConfig is set, will encapsulate the
+// and the specified tls configuration. If TLSConfig is set, will encapsulate the
 // TCP listener inside a TLS one.
 // TCP listener inside a TLS one.
 func NewTCPSocket(addr string, tlsConfig *tls.Config) (net.Listener, error) {
 func NewTCPSocket(addr string, tlsConfig *tls.Config) (net.Listener, error) {
 	l, err := net.Listen("tcp", addr)
 	l, err := net.Listen("tcp", addr)

+ 41 - 21
vendor/src/github.com/docker/go-events/broadcast.go

@@ -1,6 +1,11 @@
 package events
 package events
 
 
-import "github.com/Sirupsen/logrus"
+import (
+	"fmt"
+	"sync"
+
+	"github.com/Sirupsen/logrus"
+)
 
 
 // Broadcaster sends events to multiple, reliable Sinks. The goal of this
 // Broadcaster sends events to multiple, reliable Sinks. The goal of this
 // component is to dispatch events to configured endpoints. Reliability can be
 // component is to dispatch events to configured endpoints. Reliability can be
@@ -10,7 +15,10 @@ type Broadcaster struct {
 	events  chan Event
 	events  chan Event
 	adds    chan configureRequest
 	adds    chan configureRequest
 	removes chan configureRequest
 	removes chan configureRequest
-	closed  chan chan struct{}
+
+	shutdown chan struct{}
+	closed   chan struct{}
+	once     sync.Once
 }
 }
 
 
 // NewBroadcaster appends one or more sinks to the list of sinks. The
 // NewBroadcaster appends one or more sinks to the list of sinks. The
@@ -19,11 +27,12 @@ type Broadcaster struct {
 // its own. Use of EventQueue and RetryingSink should be used here.
 // its own. Use of EventQueue and RetryingSink should be used here.
 func NewBroadcaster(sinks ...Sink) *Broadcaster {
 func NewBroadcaster(sinks ...Sink) *Broadcaster {
 	b := Broadcaster{
 	b := Broadcaster{
-		sinks:   sinks,
-		events:  make(chan Event),
-		adds:    make(chan configureRequest),
-		removes: make(chan configureRequest),
-		closed:  make(chan chan struct{}),
+		sinks:    sinks,
+		events:   make(chan Event),
+		adds:     make(chan configureRequest),
+		removes:  make(chan configureRequest),
+		shutdown: make(chan struct{}),
+		closed:   make(chan struct{}),
 	}
 	}
 
 
 	// Start the broadcaster
 	// Start the broadcaster
@@ -82,24 +91,19 @@ func (b *Broadcaster) configure(ch chan configureRequest, sink Sink) error {
 // Close the broadcaster, ensuring that all messages are flushed to the
 // Close the broadcaster, ensuring that all messages are flushed to the
 // underlying sink before returning.
 // underlying sink before returning.
 func (b *Broadcaster) Close() error {
 func (b *Broadcaster) Close() error {
-	select {
-	case <-b.closed:
-		// already closed
-		return ErrSinkClosed
-	default:
-		// do a little chan handoff dance to synchronize closing
-		closed := make(chan struct{})
-		b.closed <- closed
-		close(b.closed)
-		<-closed
-		return nil
-	}
+	b.once.Do(func() {
+		close(b.shutdown)
+	})
+
+	<-b.closed
+	return nil
 }
 }
 
 
 // run is the main broadcast loop, started when the broadcaster is created.
 // run is the main broadcast loop, started when the broadcaster is created.
 // Under normal conditions, it waits for events on the event channel. After
 // Under normal conditions, it waits for events on the event channel. After
 // Close is called, this goroutine will exit.
 // Close is called, this goroutine will exit.
 func (b *Broadcaster) run() {
 func (b *Broadcaster) run() {
+	defer close(b.closed)
 	remove := func(target Sink) {
 	remove := func(target Sink) {
 		for i, sink := range b.sinks {
 		for i, sink := range b.sinks {
 			if sink == target {
 			if sink == target {
@@ -143,7 +147,7 @@ func (b *Broadcaster) run() {
 		case request := <-b.removes:
 		case request := <-b.removes:
 			remove(request.sink)
 			remove(request.sink)
 			request.response <- nil
 			request.response <- nil
-		case closing := <-b.closed:
+		case <-b.shutdown:
 			// close all the underlying sinks
 			// close all the underlying sinks
 			for _, sink := range b.sinks {
 			for _, sink := range b.sinks {
 				if err := sink.Close(); err != nil && err != ErrSinkClosed {
 				if err := sink.Close(); err != nil && err != ErrSinkClosed {
@@ -151,8 +155,24 @@ func (b *Broadcaster) run() {
 						Errorf("broadcaster: closing sink failed")
 						Errorf("broadcaster: closing sink failed")
 				}
 				}
 			}
 			}
-			closing <- struct{}{}
 			return
 			return
 		}
 		}
 	}
 	}
 }
 }
+
+func (b Broadcaster) String() string {
+	// Serialize copy of this broadcaster without the sync.Once, to avoid
+	// a data race.
+
+	b2 := map[string]interface{}{
+		"sinks":   b.sinks,
+		"events":  b.events,
+		"adds":    b.adds,
+		"removes": b.removes,
+
+		"shutdown": b.shutdown,
+		"closed":   b.closed,
+	}
+
+	return fmt.Sprint(b2)
+}

+ 19 - 5
vendor/src/github.com/docker/go-events/channel.go

@@ -1,5 +1,10 @@
 package events
 package events
 
 
+import (
+	"fmt"
+	"sync"
+)
+
 // Channel provides a sink that can be listened on. The writer and channel
 // Channel provides a sink that can be listened on. The writer and channel
 // listener must operate in separate goroutines.
 // listener must operate in separate goroutines.
 //
 //
@@ -8,6 +13,7 @@ type Channel struct {
 	C chan Event
 	C chan Event
 
 
 	closed chan struct{}
 	closed chan struct{}
+	once   sync.Once
 }
 }
 
 
 // NewChannel returns a channel. If buffer is zero, the channel is
 // NewChannel returns a channel. If buffer is zero, the channel is
@@ -37,11 +43,19 @@ func (ch *Channel) Write(event Event) error {
 
 
 // Close the channel sink.
 // Close the channel sink.
 func (ch *Channel) Close() error {
 func (ch *Channel) Close() error {
-	select {
-	case <-ch.closed:
-		return ErrSinkClosed
-	default:
+	ch.once.Do(func() {
 		close(ch.closed)
 		close(ch.closed)
-		return nil
+	})
+
+	return nil
+}
+
+func (ch Channel) String() string {
+	// Serialize a copy of the Channel that doesn't contain the sync.Once,
+	// to avoid a data race.
+	ch2 := map[string]interface{}{
+		"C":      ch.C,
+		"closed": ch.closed,
 	}
 	}
+	return fmt.Sprint(ch2)
 }
 }

+ 1 - 1
vendor/src/github.com/docker/go-events/filter.go

@@ -44,7 +44,7 @@ func (f *Filter) Write(event Event) error {
 func (f *Filter) Close() error {
 func (f *Filter) Close() error {
 	// TODO(stevvooe): Not all sinks should have Close.
 	// TODO(stevvooe): Not all sinks should have Close.
 	if f.closed {
 	if f.closed {
-		return ErrSinkClosed
+		return nil
 	}
 	}
 
 
 	f.closed = true
 	f.closed = true

+ 1 - 1
vendor/src/github.com/docker/go-events/queue.go

@@ -52,7 +52,7 @@ func (eq *Queue) Close() error {
 	defer eq.mu.Unlock()
 	defer eq.mu.Unlock()
 
 
 	if eq.closed {
 	if eq.closed {
-		return ErrSinkClosed
+		return nil
 	}
 	}
 
 
 	// set closed flag
 	// set closed flag

+ 16 - 5
vendor/src/github.com/docker/go-events/retry.go

@@ -1,6 +1,7 @@
 package events
 package events
 
 
 import (
 import (
+	"fmt"
 	"math/rand"
 	"math/rand"
 	"sync"
 	"sync"
 	"sync/atomic"
 	"sync/atomic"
@@ -18,6 +19,7 @@ type RetryingSink struct {
 	sink     Sink
 	sink     Sink
 	strategy RetryStrategy
 	strategy RetryStrategy
 	closed   chan struct{}
 	closed   chan struct{}
+	once     sync.Once
 }
 }
 
 
 // NewRetryingSink returns a sink that will retry writes to a sink, backing
 // NewRetryingSink returns a sink that will retry writes to a sink, backing
@@ -81,13 +83,22 @@ retry:
 
 
 // Close closes the sink and the underlying sink.
 // Close closes the sink and the underlying sink.
 func (rs *RetryingSink) Close() error {
 func (rs *RetryingSink) Close() error {
-	select {
-	case <-rs.closed:
-		return ErrSinkClosed
-	default:
+	rs.once.Do(func() {
 		close(rs.closed)
 		close(rs.closed)
-		return rs.sink.Close()
+	})
+
+	return nil
+}
+
+func (rs RetryingSink) String() string {
+	// Serialize a copy of the RetryingSink without the sync.Once, to avoid
+	// a data race.
+	rs2 := map[string]interface{}{
+		"sink":     rs.sink,
+		"strategy": rs.strategy,
+		"closed":   rs.closed,
 	}
 	}
+	return fmt.Sprint(rs2)
 }
 }
 
 
 // RetryStrategy defines a strategy for retrying event sink writes.
 // RetryStrategy defines a strategy for retrying event sink writes.

+ 2 - 2
vendor/src/github.com/docker/swarmkit/agent/config.go

@@ -6,7 +6,7 @@ import (
 	"github.com/boltdb/bolt"
 	"github.com/boltdb/bolt"
 	"github.com/docker/swarmkit/agent/exec"
 	"github.com/docker/swarmkit/agent/exec"
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/api"
-	"github.com/docker/swarmkit/picker"
+	"github.com/docker/swarmkit/remotes"
 	"google.golang.org/grpc/credentials"
 	"google.golang.org/grpc/credentials"
 )
 )
 
 
@@ -17,7 +17,7 @@ type Config struct {
 
 
 	// Managers provides the manager backend used by the agent. It will be
 	// Managers provides the manager backend used by the agent. It will be
 	// updated with managers weights as observed by the agent.
 	// updated with managers weights as observed by the agent.
-	Managers picker.Remotes
+	Managers remotes.Remotes
 
 
 	// Executor specifies the executor to use for the agent.
 	// Executor specifies the executor to use for the agent.
 	Executor exec.Executor
 	Executor exec.Executor

+ 33 - 28
vendor/src/github.com/docker/swarmkit/agent/node.go

@@ -21,7 +21,7 @@ import (
 	"github.com/docker/swarmkit/ioutils"
 	"github.com/docker/swarmkit/ioutils"
 	"github.com/docker/swarmkit/log"
 	"github.com/docker/swarmkit/log"
 	"github.com/docker/swarmkit/manager"
 	"github.com/docker/swarmkit/manager"
-	"github.com/docker/swarmkit/picker"
+	"github.com/docker/swarmkit/remotes"
 	"golang.org/x/net/context"
 	"golang.org/x/net/context"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/credentials"
 	"google.golang.org/grpc/credentials"
@@ -178,7 +178,7 @@ func (n *Node) run(ctx context.Context) (err error) {
 	if n.config.JoinAddr != "" || n.config.ForceNewCluster {
 	if n.config.JoinAddr != "" || n.config.ForceNewCluster {
 		n.remotes = newPersistentRemotes(filepath.Join(n.config.StateDir, stateFilename))
 		n.remotes = newPersistentRemotes(filepath.Join(n.config.StateDir, stateFilename))
 		if n.config.JoinAddr != "" {
 		if n.config.JoinAddr != "" {
-			n.remotes.Observe(api.Peer{Addr: n.config.JoinAddr}, picker.DefaultObservationWeight)
+			n.remotes.Observe(api.Peer{Addr: n.config.JoinAddr}, remotes.DefaultObservationWeight)
 		}
 		}
 	}
 	}
 
 
@@ -204,7 +204,7 @@ func (n *Node) run(ctx context.Context) (err error) {
 	}()
 	}()
 
 
 	certDir := filepath.Join(n.config.StateDir, "certificates")
 	certDir := filepath.Join(n.config.StateDir, "certificates")
-	securityConfig, err := ca.LoadOrCreateSecurityConfig(ctx, certDir, n.config.JoinToken, ca.ManagerRole, picker.NewPicker(n.remotes), issueResponseChan)
+	securityConfig, err := ca.LoadOrCreateSecurityConfig(ctx, certDir, n.config.JoinToken, ca.ManagerRole, n.remotes, issueResponseChan)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
@@ -256,7 +256,7 @@ func (n *Node) run(ctx context.Context) (err error) {
 		}
 		}
 	}()
 	}()
 
 
-	updates := ca.RenewTLSConfig(ctx, securityConfig, certDir, picker.NewPicker(n.remotes), forceCertRenewal)
+	updates := ca.RenewTLSConfig(ctx, securityConfig, certDir, n.remotes, forceCertRenewal)
 	go func() {
 	go func() {
 		for {
 		for {
 			select {
 			select {
@@ -533,31 +533,29 @@ func (n *Node) initManagerConnection(ctx context.Context, ready chan<- struct{})
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
-	state := grpc.Idle
+	client := api.NewHealthClient(conn)
 	for {
 	for {
-		s, err := conn.WaitForStateChange(ctx, state)
+		resp, err := client.Check(ctx, &api.HealthCheckRequest{Service: "ControlAPI"})
 		if err != nil {
 		if err != nil {
-			n.setControlSocket(nil)
 			return err
 			return err
 		}
 		}
-		if s == grpc.Ready {
-			n.setControlSocket(conn)
-			if ready != nil {
-				close(ready)
-				ready = nil
-			}
-		} else if state == grpc.Shutdown {
-			n.setControlSocket(nil)
+		if resp.Status == api.HealthCheckResponse_SERVING {
+			break
 		}
 		}
-		state = s
+		time.Sleep(500 * time.Millisecond)
+	}
+	n.setControlSocket(conn)
+	if ready != nil {
+		close(ready)
 	}
 	}
+	return nil
 }
 }
 
 
-func (n *Node) waitRole(ctx context.Context, role string) {
+func (n *Node) waitRole(ctx context.Context, role string) error {
 	n.roleCond.L.Lock()
 	n.roleCond.L.Lock()
 	if role == n.role {
 	if role == n.role {
 		n.roleCond.L.Unlock()
 		n.roleCond.L.Unlock()
-		return
+		return nil
 	}
 	}
 	finishCh := make(chan struct{})
 	finishCh := make(chan struct{})
 	defer close(finishCh)
 	defer close(finishCh)
@@ -572,18 +570,24 @@ func (n *Node) waitRole(ctx context.Context, role string) {
 	defer n.roleCond.L.Unlock()
 	defer n.roleCond.L.Unlock()
 	for role != n.role {
 	for role != n.role {
 		n.roleCond.Wait()
 		n.roleCond.Wait()
-		if ctx.Err() != nil {
-			return
+		select {
+		case <-ctx.Done():
+			if ctx.Err() != nil {
+				return ctx.Err()
+			}
+		default:
 		}
 		}
 	}
 	}
+
+	return nil
 }
 }
 
 
 func (n *Node) runManager(ctx context.Context, securityConfig *ca.SecurityConfig, ready chan struct{}) error {
 func (n *Node) runManager(ctx context.Context, securityConfig *ca.SecurityConfig, ready chan struct{}) error {
 	for {
 	for {
-		n.waitRole(ctx, ca.ManagerRole)
-		if ctx.Err() != nil {
-			return ctx.Err()
+		if err := n.waitRole(ctx, ca.ManagerRole); err != nil {
+			return err
 		}
 		}
+
 		remoteAddr, _ := n.remotes.Select(n.nodeID)
 		remoteAddr, _ := n.remotes.Select(n.nodeID)
 		m, err := manager.New(&manager.Config{
 		m, err := manager.New(&manager.Config{
 			ForceNewCluster: n.config.ForceNewCluster,
 			ForceNewCluster: n.config.ForceNewCluster,
@@ -620,14 +624,14 @@ func (n *Node) runManager(ctx context.Context, securityConfig *ca.SecurityConfig
 			go func(ready chan struct{}) {
 			go func(ready chan struct{}) {
 				select {
 				select {
 				case <-ready:
 				case <-ready:
-					n.remotes.Observe(api.Peer{NodeID: n.nodeID, Addr: n.config.ListenRemoteAPI}, picker.DefaultObservationWeight)
+					n.remotes.Observe(api.Peer{NodeID: n.nodeID, Addr: n.config.ListenRemoteAPI}, remotes.DefaultObservationWeight)
 				case <-connCtx.Done():
 				case <-connCtx.Done():
 				}
 				}
 			}(ready)
 			}(ready)
 			ready = nil
 			ready = nil
 		}
 		}
 
 
-		n.waitRole(ctx, ca.AgentRole)
+		err = n.waitRole(ctx, ca.AgentRole)
 
 
 		n.Lock()
 		n.Lock()
 		n.manager = nil
 		n.manager = nil
@@ -641,6 +645,7 @@ func (n *Node) runManager(ctx context.Context, securityConfig *ca.SecurityConfig
 			<-done
 			<-done
 		}
 		}
 		connCancel()
 		connCancel()
+		n.setControlSocket(nil)
 
 
 		if err != nil {
 		if err != nil {
 			return err
 			return err
@@ -651,15 +656,15 @@ func (n *Node) runManager(ctx context.Context, securityConfig *ca.SecurityConfig
 type persistentRemotes struct {
 type persistentRemotes struct {
 	sync.RWMutex
 	sync.RWMutex
 	c *sync.Cond
 	c *sync.Cond
-	picker.Remotes
+	remotes.Remotes
 	storePath      string
 	storePath      string
 	lastSavedState []api.Peer
 	lastSavedState []api.Peer
 }
 }
 
 
-func newPersistentRemotes(f string, remotes ...api.Peer) *persistentRemotes {
+func newPersistentRemotes(f string, peers ...api.Peer) *persistentRemotes {
 	pr := &persistentRemotes{
 	pr := &persistentRemotes{
 		storePath: f,
 		storePath: f,
-		Remotes:   picker.NewRemotes(remotes...),
+		Remotes:   remotes.NewRemotes(peers...),
 	}
 	}
 	pr.c = sync.NewCond(pr.RLocker())
 	pr.c = sync.NewCond(pr.RLocker())
 	return pr
 	return pr

+ 14 - 9
vendor/src/github.com/docker/swarmkit/agent/reporter.go

@@ -79,6 +79,9 @@ func (sr *statusReporter) run(ctx context.Context) {
 	done := make(chan struct{})
 	done := make(chan struct{})
 	defer close(done)
 	defer close(done)
 
 
+	sr.mu.Lock() // released during wait, below.
+	defer sr.mu.Unlock()
+
 	go func() {
 	go func() {
 		select {
 		select {
 		case <-ctx.Done():
 		case <-ctx.Done():
@@ -88,27 +91,29 @@ func (sr *statusReporter) run(ctx context.Context) {
 		}
 		}
 	}()
 	}()
 
 
-	sr.mu.Lock() // released during wait, below.
-	defer sr.mu.Unlock()
-
 	for {
 	for {
 		if len(sr.statuses) == 0 {
 		if len(sr.statuses) == 0 {
 			sr.cond.Wait()
 			sr.cond.Wait()
 		}
 		}
 
 
-		for taskID, status := range sr.statuses {
-			if sr.closed {
-				// TODO(stevvooe): Add support here for waiting until all
-				// statuses are flushed before shutting down.
-				return
-			}
+		if sr.closed {
+			// TODO(stevvooe): Add support here for waiting until all
+			// statuses are flushed before shutting down.
+			return
+		}
 
 
+		for taskID, status := range sr.statuses {
 			delete(sr.statuses, taskID) // delete the entry, while trying to send.
 			delete(sr.statuses, taskID) // delete the entry, while trying to send.
 
 
 			sr.mu.Unlock()
 			sr.mu.Unlock()
 			err := sr.reporter.UpdateTaskStatus(ctx, taskID, status)
 			err := sr.reporter.UpdateTaskStatus(ctx, taskID, status)
 			sr.mu.Lock()
 			sr.mu.Lock()
 
 
+			// reporter might be closed during UpdateTaskStatus call
+			if sr.closed {
+				return
+			}
+
 			if err != nil {
 			if err != nil {
 				log.G(ctx).WithError(err).Error("failed reporting status to agent")
 				log.G(ctx).WithError(err).Error("failed reporting status to agent")
 
 

+ 69 - 0
vendor/src/github.com/docker/swarmkit/agent/resource.go

@@ -0,0 +1,69 @@
+package agent
+
+import (
+	"github.com/docker/swarmkit/api"
+	"golang.org/x/net/context"
+)
+
+type resourceAllocator struct {
+	agent *Agent
+}
+
+// ResourceAllocator is an interface to allocate resource such as
+// network attachments from a worker node.
+type ResourceAllocator interface {
+	// AttachNetwork creates a network attachment in the manager
+	// given a target network and a unique ID representing the
+	// connecting entity and optionally a list of ipv4/ipv6
+	// addresses to be assigned to the attachment. AttachNetwork
+	// returns a unique ID for the attachment if successfull or an
+	// error in case of failure.
+	AttachNetwork(ctx context.Context, id, target string, addresses []string) (string, error)
+
+	// DetachNetworks deletes a network attachment for the passed
+	// attachment ID. The attachment ID is obtained from a
+	// previous AttachNetwork call.
+	DetachNetwork(ctx context.Context, aID string) error
+}
+
+// AttachNetwork creates a network attachment.
+func (r *resourceAllocator) AttachNetwork(ctx context.Context, id, target string, addresses []string) (string, error) {
+	var taskID string
+	if err := r.agent.withSession(ctx, func(session *session) error {
+		client := api.NewResourceAllocatorClient(session.conn)
+		r, err := client.AttachNetwork(ctx, &api.AttachNetworkRequest{
+			Config: &api.NetworkAttachmentConfig{
+				Target:    target,
+				Addresses: addresses,
+			},
+			ContainerID: id,
+		})
+		if err != nil {
+			return err
+		}
+		taskID = r.AttachmentID
+		return nil
+	}); err != nil {
+		return "", err
+	}
+
+	return taskID, nil
+}
+
+// DetachNetwork deletes a network attachment.
+func (r *resourceAllocator) DetachNetwork(ctx context.Context, aID string) error {
+	return r.agent.withSession(ctx, func(session *session) error {
+		client := api.NewResourceAllocatorClient(session.conn)
+		_, err := client.DetachNetwork(ctx, &api.DetachNetworkRequest{
+			AttachmentID: aID,
+		})
+
+		return err
+	})
+}
+
+// ResourceAllocator provides an interface to access resource
+// allocation methods such as AttachNetwork and DetachNetwork.
+func (a *Agent) ResourceAllocator() ResourceAllocator {
+	return &resourceAllocator{agent: a}
+}

+ 2 - 2
vendor/src/github.com/docker/swarmkit/agent/session.go

@@ -6,8 +6,8 @@ import (
 
 
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/log"
 	"github.com/docker/swarmkit/log"
-	"github.com/docker/swarmkit/picker"
 	"github.com/docker/swarmkit/protobuf/ptypes"
 	"github.com/docker/swarmkit/protobuf/ptypes"
+	"github.com/docker/swarmkit/remotes"
 	"golang.org/x/net/context"
 	"golang.org/x/net/context"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/codes"
@@ -307,7 +307,7 @@ func (s *session) close() error {
 		return errSessionClosed
 		return errSessionClosed
 	default:
 	default:
 		if s.conn != nil {
 		if s.conn != nil {
-			s.agent.config.Managers.ObserveIfExists(api.Peer{Addr: s.addr}, -picker.DefaultObservationWeight)
+			s.agent.config.Managers.ObserveIfExists(api.Peer{Addr: s.addr}, -remotes.DefaultObservationWeight)
 			s.conn.Close()
 			s.conn.Close()
 		}
 		}
 		close(s.closed)
 		close(s.closed)

+ 1 - 3
vendor/src/github.com/docker/swarmkit/agent/worker.go

@@ -134,8 +134,6 @@ func (w *worker) Assign(ctx context.Context, tasks []*api.Task) error {
 				if err := PutTaskStatus(tx, task.ID, &task.Status); err != nil {
 				if err := PutTaskStatus(tx, task.ID, &task.Status); err != nil {
 					return err
 					return err
 				}
 				}
-
-				status = &task.Status
 			} else {
 			} else {
 				task.Status = *status // overwrite the stale manager status with ours.
 				task.Status = *status // overwrite the stale manager status with ours.
 			}
 			}
@@ -181,7 +179,7 @@ func (w *worker) Listen(ctx context.Context, reporter StatusReporter) {
 	go func() {
 	go func() {
 		<-ctx.Done()
 		<-ctx.Done()
 		w.mu.Lock()
 		w.mu.Lock()
-		defer w.mu.Lock()
+		defer w.mu.Unlock()
 		delete(w.listeners, key) // remove the listener if the context is closed.
 		delete(w.listeners, key) // remove the listener if the context is closed.
 	}()
 	}()
 
 

+ 1 - 1
vendor/src/github.com/docker/swarmkit/api/gen.go

@@ -1,3 +1,3 @@
 package api
 package api
 
 
-//go:generate protoc -I.:../protobuf:../vendor:../vendor/github.com/gogo/protobuf --gogoswarm_out=plugins=grpc+deepcopy+raftproxy+authenticatedwrapper,import_path=github.com/docker/swarmkit/api,Mgogoproto/gogo.proto=github.com/gogo/protobuf/gogoproto,Mtimestamp/timestamp.proto=github.com/docker/swarmkit/api/timestamp,Mduration/duration.proto=github.com/docker/swarmkit/api/duration,Mgoogle/protobuf/descriptor.proto=github.com/gogo/protobuf/protoc-gen-gogo/descriptor,Mplugin/plugin.proto=github.com/docker/swarmkit/protobuf/plugin:. types.proto specs.proto objects.proto control.proto dispatcher.proto ca.proto snapshot.proto raft.proto health.proto
+//go:generate protoc -I.:../protobuf:../vendor:../vendor/github.com/gogo/protobuf --gogoswarm_out=plugins=grpc+deepcopy+raftproxy+authenticatedwrapper,import_path=github.com/docker/swarmkit/api,Mgogoproto/gogo.proto=github.com/gogo/protobuf/gogoproto,Mtimestamp/timestamp.proto=github.com/docker/swarmkit/api/timestamp,Mduration/duration.proto=github.com/docker/swarmkit/api/duration,Mgoogle/protobuf/descriptor.proto=github.com/gogo/protobuf/protoc-gen-gogo/descriptor,Mplugin/plugin.proto=github.com/docker/swarmkit/protobuf/plugin:. types.proto specs.proto objects.proto control.proto dispatcher.proto ca.proto snapshot.proto raft.proto health.proto resource.proto

+ 1105 - 0
vendor/src/github.com/docker/swarmkit/api/resource.pb.go

@@ -0,0 +1,1105 @@
+// Code generated by protoc-gen-gogo.
+// source: resource.proto
+// DO NOT EDIT!
+
+package api
+
+import proto "github.com/gogo/protobuf/proto"
+import fmt "fmt"
+import math "math"
+import _ "github.com/gogo/protobuf/gogoproto"
+import _ "github.com/docker/swarmkit/protobuf/plugin"
+
+import strings "strings"
+import github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto"
+import sort "sort"
+import strconv "strconv"
+import reflect "reflect"
+
+import (
+	context "golang.org/x/net/context"
+	grpc "google.golang.org/grpc"
+)
+
+import raftpicker "github.com/docker/swarmkit/manager/raftpicker"
+import codes "google.golang.org/grpc/codes"
+import metadata "google.golang.org/grpc/metadata"
+import transport "google.golang.org/grpc/transport"
+
+import io "io"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+type AttachNetworkRequest struct {
+	Config      *NetworkAttachmentConfig `protobuf:"bytes,1,opt,name=config" json:"config,omitempty"`
+	ContainerID string                   `protobuf:"bytes,2,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"`
+}
+
+func (m *AttachNetworkRequest) Reset()                    { *m = AttachNetworkRequest{} }
+func (*AttachNetworkRequest) ProtoMessage()               {}
+func (*AttachNetworkRequest) Descriptor() ([]byte, []int) { return fileDescriptorResource, []int{0} }
+
+type AttachNetworkResponse struct {
+	AttachmentID string `protobuf:"bytes,1,opt,name=attachment_id,json=attachmentId,proto3" json:"attachment_id,omitempty"`
+}
+
+func (m *AttachNetworkResponse) Reset()                    { *m = AttachNetworkResponse{} }
+func (*AttachNetworkResponse) ProtoMessage()               {}
+func (*AttachNetworkResponse) Descriptor() ([]byte, []int) { return fileDescriptorResource, []int{1} }
+
+type DetachNetworkRequest struct {
+	AttachmentID string `protobuf:"bytes,1,opt,name=attachment_id,json=attachmentId,proto3" json:"attachment_id,omitempty"`
+}
+
+func (m *DetachNetworkRequest) Reset()                    { *m = DetachNetworkRequest{} }
+func (*DetachNetworkRequest) ProtoMessage()               {}
+func (*DetachNetworkRequest) Descriptor() ([]byte, []int) { return fileDescriptorResource, []int{2} }
+
+type DetachNetworkResponse struct {
+}
+
+func (m *DetachNetworkResponse) Reset()                    { *m = DetachNetworkResponse{} }
+func (*DetachNetworkResponse) ProtoMessage()               {}
+func (*DetachNetworkResponse) Descriptor() ([]byte, []int) { return fileDescriptorResource, []int{3} }
+
+func init() {
+	proto.RegisterType((*AttachNetworkRequest)(nil), "docker.swarmkit.v1.AttachNetworkRequest")
+	proto.RegisterType((*AttachNetworkResponse)(nil), "docker.swarmkit.v1.AttachNetworkResponse")
+	proto.RegisterType((*DetachNetworkRequest)(nil), "docker.swarmkit.v1.DetachNetworkRequest")
+	proto.RegisterType((*DetachNetworkResponse)(nil), "docker.swarmkit.v1.DetachNetworkResponse")
+}
+
+type authenticatedWrapperResourceAllocatorServer struct {
+	local     ResourceAllocatorServer
+	authorize func(context.Context, []string) error
+}
+
+func NewAuthenticatedWrapperResourceAllocatorServer(local ResourceAllocatorServer, authorize func(context.Context, []string) error) ResourceAllocatorServer {
+	return &authenticatedWrapperResourceAllocatorServer{
+		local:     local,
+		authorize: authorize,
+	}
+}
+
+func (p *authenticatedWrapperResourceAllocatorServer) AttachNetwork(ctx context.Context, r *AttachNetworkRequest) (*AttachNetworkResponse, error) {
+
+	if err := p.authorize(ctx, []string{"swarm-worker", "swarm-manager"}); err != nil {
+		return nil, err
+	}
+	return p.local.AttachNetwork(ctx, r)
+}
+
+func (p *authenticatedWrapperResourceAllocatorServer) DetachNetwork(ctx context.Context, r *DetachNetworkRequest) (*DetachNetworkResponse, error) {
+
+	if err := p.authorize(ctx, []string{"swarm-worker", "swarm-manager"}); err != nil {
+		return nil, err
+	}
+	return p.local.DetachNetwork(ctx, r)
+}
+
+func (m *AttachNetworkRequest) Copy() *AttachNetworkRequest {
+	if m == nil {
+		return nil
+	}
+
+	o := &AttachNetworkRequest{
+		Config:      m.Config.Copy(),
+		ContainerID: m.ContainerID,
+	}
+
+	return o
+}
+
+func (m *AttachNetworkResponse) Copy() *AttachNetworkResponse {
+	if m == nil {
+		return nil
+	}
+
+	o := &AttachNetworkResponse{
+		AttachmentID: m.AttachmentID,
+	}
+
+	return o
+}
+
+func (m *DetachNetworkRequest) Copy() *DetachNetworkRequest {
+	if m == nil {
+		return nil
+	}
+
+	o := &DetachNetworkRequest{
+		AttachmentID: m.AttachmentID,
+	}
+
+	return o
+}
+
+func (m *DetachNetworkResponse) Copy() *DetachNetworkResponse {
+	if m == nil {
+		return nil
+	}
+
+	o := &DetachNetworkResponse{}
+
+	return o
+}
+
+func (this *AttachNetworkRequest) GoString() string {
+	if this == nil {
+		return "nil"
+	}
+	s := make([]string, 0, 6)
+	s = append(s, "&api.AttachNetworkRequest{")
+	if this.Config != nil {
+		s = append(s, "Config: "+fmt.Sprintf("%#v", this.Config)+",\n")
+	}
+	s = append(s, "ContainerID: "+fmt.Sprintf("%#v", this.ContainerID)+",\n")
+	s = append(s, "}")
+	return strings.Join(s, "")
+}
+func (this *AttachNetworkResponse) GoString() string {
+	if this == nil {
+		return "nil"
+	}
+	s := make([]string, 0, 5)
+	s = append(s, "&api.AttachNetworkResponse{")
+	s = append(s, "AttachmentID: "+fmt.Sprintf("%#v", this.AttachmentID)+",\n")
+	s = append(s, "}")
+	return strings.Join(s, "")
+}
+func (this *DetachNetworkRequest) GoString() string {
+	if this == nil {
+		return "nil"
+	}
+	s := make([]string, 0, 5)
+	s = append(s, "&api.DetachNetworkRequest{")
+	s = append(s, "AttachmentID: "+fmt.Sprintf("%#v", this.AttachmentID)+",\n")
+	s = append(s, "}")
+	return strings.Join(s, "")
+}
+func (this *DetachNetworkResponse) GoString() string {
+	if this == nil {
+		return "nil"
+	}
+	s := make([]string, 0, 4)
+	s = append(s, "&api.DetachNetworkResponse{")
+	s = append(s, "}")
+	return strings.Join(s, "")
+}
+func valueToGoStringResource(v interface{}, typ string) string {
+	rv := reflect.ValueOf(v)
+	if rv.IsNil() {
+		return "nil"
+	}
+	pv := reflect.Indirect(rv).Interface()
+	return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
+}
+func extensionToGoStringResource(e map[int32]github_com_gogo_protobuf_proto.Extension) string {
+	if e == nil {
+		return "nil"
+	}
+	s := "map[int32]proto.Extension{"
+	keys := make([]int, 0, len(e))
+	for k := range e {
+		keys = append(keys, int(k))
+	}
+	sort.Ints(keys)
+	ss := []string{}
+	for _, k := range keys {
+		ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString())
+	}
+	s += strings.Join(ss, ",") + "}"
+	return s
+}
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConn
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+const _ = grpc.SupportPackageIsVersion2
+
+// Client API for ResourceAllocator service
+
+type ResourceAllocatorClient interface {
+	AttachNetwork(ctx context.Context, in *AttachNetworkRequest, opts ...grpc.CallOption) (*AttachNetworkResponse, error)
+	DetachNetwork(ctx context.Context, in *DetachNetworkRequest, opts ...grpc.CallOption) (*DetachNetworkResponse, error)
+}
+
+type resourceAllocatorClient struct {
+	cc *grpc.ClientConn
+}
+
+func NewResourceAllocatorClient(cc *grpc.ClientConn) ResourceAllocatorClient {
+	return &resourceAllocatorClient{cc}
+}
+
+func (c *resourceAllocatorClient) AttachNetwork(ctx context.Context, in *AttachNetworkRequest, opts ...grpc.CallOption) (*AttachNetworkResponse, error) {
+	out := new(AttachNetworkResponse)
+	err := grpc.Invoke(ctx, "/docker.swarmkit.v1.ResourceAllocator/AttachNetwork", in, out, c.cc, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *resourceAllocatorClient) DetachNetwork(ctx context.Context, in *DetachNetworkRequest, opts ...grpc.CallOption) (*DetachNetworkResponse, error) {
+	out := new(DetachNetworkResponse)
+	err := grpc.Invoke(ctx, "/docker.swarmkit.v1.ResourceAllocator/DetachNetwork", in, out, c.cc, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// Server API for ResourceAllocator service
+
+type ResourceAllocatorServer interface {
+	AttachNetwork(context.Context, *AttachNetworkRequest) (*AttachNetworkResponse, error)
+	DetachNetwork(context.Context, *DetachNetworkRequest) (*DetachNetworkResponse, error)
+}
+
+func RegisterResourceAllocatorServer(s *grpc.Server, srv ResourceAllocatorServer) {
+	s.RegisterService(&_ResourceAllocator_serviceDesc, srv)
+}
+
+func _ResourceAllocator_AttachNetwork_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(AttachNetworkRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(ResourceAllocatorServer).AttachNetwork(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/docker.swarmkit.v1.ResourceAllocator/AttachNetwork",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(ResourceAllocatorServer).AttachNetwork(ctx, req.(*AttachNetworkRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _ResourceAllocator_DetachNetwork_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(DetachNetworkRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(ResourceAllocatorServer).DetachNetwork(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/docker.swarmkit.v1.ResourceAllocator/DetachNetwork",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(ResourceAllocatorServer).DetachNetwork(ctx, req.(*DetachNetworkRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+var _ResourceAllocator_serviceDesc = grpc.ServiceDesc{
+	ServiceName: "docker.swarmkit.v1.ResourceAllocator",
+	HandlerType: (*ResourceAllocatorServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "AttachNetwork",
+			Handler:    _ResourceAllocator_AttachNetwork_Handler,
+		},
+		{
+			MethodName: "DetachNetwork",
+			Handler:    _ResourceAllocator_DetachNetwork_Handler,
+		},
+	},
+	Streams: []grpc.StreamDesc{},
+}
+
+func (m *AttachNetworkRequest) Marshal() (data []byte, err error) {
+	size := m.Size()
+	data = make([]byte, size)
+	n, err := m.MarshalTo(data)
+	if err != nil {
+		return nil, err
+	}
+	return data[:n], nil
+}
+
+func (m *AttachNetworkRequest) MarshalTo(data []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	if m.Config != nil {
+		data[i] = 0xa
+		i++
+		i = encodeVarintResource(data, i, uint64(m.Config.Size()))
+		n1, err := m.Config.MarshalTo(data[i:])
+		if err != nil {
+			return 0, err
+		}
+		i += n1
+	}
+	if len(m.ContainerID) > 0 {
+		data[i] = 0x12
+		i++
+		i = encodeVarintResource(data, i, uint64(len(m.ContainerID)))
+		i += copy(data[i:], m.ContainerID)
+	}
+	return i, nil
+}
+
+func (m *AttachNetworkResponse) Marshal() (data []byte, err error) {
+	size := m.Size()
+	data = make([]byte, size)
+	n, err := m.MarshalTo(data)
+	if err != nil {
+		return nil, err
+	}
+	return data[:n], nil
+}
+
+func (m *AttachNetworkResponse) MarshalTo(data []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	if len(m.AttachmentID) > 0 {
+		data[i] = 0xa
+		i++
+		i = encodeVarintResource(data, i, uint64(len(m.AttachmentID)))
+		i += copy(data[i:], m.AttachmentID)
+	}
+	return i, nil
+}
+
+func (m *DetachNetworkRequest) Marshal() (data []byte, err error) {
+	size := m.Size()
+	data = make([]byte, size)
+	n, err := m.MarshalTo(data)
+	if err != nil {
+		return nil, err
+	}
+	return data[:n], nil
+}
+
+func (m *DetachNetworkRequest) MarshalTo(data []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	if len(m.AttachmentID) > 0 {
+		data[i] = 0xa
+		i++
+		i = encodeVarintResource(data, i, uint64(len(m.AttachmentID)))
+		i += copy(data[i:], m.AttachmentID)
+	}
+	return i, nil
+}
+
+func (m *DetachNetworkResponse) Marshal() (data []byte, err error) {
+	size := m.Size()
+	data = make([]byte, size)
+	n, err := m.MarshalTo(data)
+	if err != nil {
+		return nil, err
+	}
+	return data[:n], nil
+}
+
+func (m *DetachNetworkResponse) MarshalTo(data []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	return i, nil
+}
+
+func encodeFixed64Resource(data []byte, offset int, v uint64) int {
+	data[offset] = uint8(v)
+	data[offset+1] = uint8(v >> 8)
+	data[offset+2] = uint8(v >> 16)
+	data[offset+3] = uint8(v >> 24)
+	data[offset+4] = uint8(v >> 32)
+	data[offset+5] = uint8(v >> 40)
+	data[offset+6] = uint8(v >> 48)
+	data[offset+7] = uint8(v >> 56)
+	return offset + 8
+}
+func encodeFixed32Resource(data []byte, offset int, v uint32) int {
+	data[offset] = uint8(v)
+	data[offset+1] = uint8(v >> 8)
+	data[offset+2] = uint8(v >> 16)
+	data[offset+3] = uint8(v >> 24)
+	return offset + 4
+}
+func encodeVarintResource(data []byte, offset int, v uint64) int {
+	for v >= 1<<7 {
+		data[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	data[offset] = uint8(v)
+	return offset + 1
+}
+
+type raftProxyResourceAllocatorServer struct {
+	local        ResourceAllocatorServer
+	connSelector raftpicker.Interface
+	cluster      raftpicker.RaftCluster
+	ctxMods      []func(context.Context) (context.Context, error)
+}
+
+func NewRaftProxyResourceAllocatorServer(local ResourceAllocatorServer, connSelector raftpicker.Interface, cluster raftpicker.RaftCluster, ctxMod func(context.Context) (context.Context, error)) ResourceAllocatorServer {
+	redirectChecker := func(ctx context.Context) (context.Context, error) {
+		s, ok := transport.StreamFromContext(ctx)
+		if !ok {
+			return ctx, grpc.Errorf(codes.InvalidArgument, "remote addr is not found in context")
+		}
+		addr := s.ServerTransport().RemoteAddr().String()
+		md, ok := metadata.FromContext(ctx)
+		if ok && len(md["redirect"]) != 0 {
+			return ctx, grpc.Errorf(codes.ResourceExhausted, "more than one redirect to leader from: %s", md["redirect"])
+		}
+		if !ok {
+			md = metadata.New(map[string]string{})
+		}
+		md["redirect"] = append(md["redirect"], addr)
+		return metadata.NewContext(ctx, md), nil
+	}
+	mods := []func(context.Context) (context.Context, error){redirectChecker}
+	mods = append(mods, ctxMod)
+
+	return &raftProxyResourceAllocatorServer{
+		local:        local,
+		cluster:      cluster,
+		connSelector: connSelector,
+		ctxMods:      mods,
+	}
+}
+func (p *raftProxyResourceAllocatorServer) runCtxMods(ctx context.Context) (context.Context, error) {
+	var err error
+	for _, mod := range p.ctxMods {
+		ctx, err = mod(ctx)
+		if err != nil {
+			return ctx, err
+		}
+	}
+	return ctx, nil
+}
+
+func (p *raftProxyResourceAllocatorServer) AttachNetwork(ctx context.Context, r *AttachNetworkRequest) (*AttachNetworkResponse, error) {
+
+	if p.cluster.IsLeader() {
+		return p.local.AttachNetwork(ctx, r)
+	}
+	ctx, err := p.runCtxMods(ctx)
+	if err != nil {
+		return nil, err
+	}
+	conn, err := p.connSelector.Conn()
+	if err != nil {
+		return nil, err
+	}
+
+	defer func() {
+		if err != nil {
+			errStr := err.Error()
+			if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) ||
+				strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) ||
+				strings.Contains(errStr, "connection error") ||
+				grpc.Code(err) == codes.Internal {
+				p.connSelector.Reset()
+			}
+		}
+	}()
+
+	return NewResourceAllocatorClient(conn).AttachNetwork(ctx, r)
+}
+
+func (p *raftProxyResourceAllocatorServer) DetachNetwork(ctx context.Context, r *DetachNetworkRequest) (*DetachNetworkResponse, error) {
+
+	if p.cluster.IsLeader() {
+		return p.local.DetachNetwork(ctx, r)
+	}
+	ctx, err := p.runCtxMods(ctx)
+	if err != nil {
+		return nil, err
+	}
+	conn, err := p.connSelector.Conn()
+	if err != nil {
+		return nil, err
+	}
+
+	defer func() {
+		if err != nil {
+			errStr := err.Error()
+			if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) ||
+				strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) ||
+				strings.Contains(errStr, "connection error") ||
+				grpc.Code(err) == codes.Internal {
+				p.connSelector.Reset()
+			}
+		}
+	}()
+
+	return NewResourceAllocatorClient(conn).DetachNetwork(ctx, r)
+}
+
+func (m *AttachNetworkRequest) Size() (n int) {
+	var l int
+	_ = l
+	if m.Config != nil {
+		l = m.Config.Size()
+		n += 1 + l + sovResource(uint64(l))
+	}
+	l = len(m.ContainerID)
+	if l > 0 {
+		n += 1 + l + sovResource(uint64(l))
+	}
+	return n
+}
+
+func (m *AttachNetworkResponse) Size() (n int) {
+	var l int
+	_ = l
+	l = len(m.AttachmentID)
+	if l > 0 {
+		n += 1 + l + sovResource(uint64(l))
+	}
+	return n
+}
+
+func (m *DetachNetworkRequest) Size() (n int) {
+	var l int
+	_ = l
+	l = len(m.AttachmentID)
+	if l > 0 {
+		n += 1 + l + sovResource(uint64(l))
+	}
+	return n
+}
+
+func (m *DetachNetworkResponse) Size() (n int) {
+	var l int
+	_ = l
+	return n
+}
+
+func sovResource(x uint64) (n int) {
+	for {
+		n++
+		x >>= 7
+		if x == 0 {
+			break
+		}
+	}
+	return n
+}
+func sozResource(x uint64) (n int) {
+	return sovResource(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (this *AttachNetworkRequest) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&AttachNetworkRequest{`,
+		`Config:` + strings.Replace(fmt.Sprintf("%v", this.Config), "NetworkAttachmentConfig", "NetworkAttachmentConfig", 1) + `,`,
+		`ContainerID:` + fmt.Sprintf("%v", this.ContainerID) + `,`,
+		`}`,
+	}, "")
+	return s
+}
+func (this *AttachNetworkResponse) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&AttachNetworkResponse{`,
+		`AttachmentID:` + fmt.Sprintf("%v", this.AttachmentID) + `,`,
+		`}`,
+	}, "")
+	return s
+}
+func (this *DetachNetworkRequest) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&DetachNetworkRequest{`,
+		`AttachmentID:` + fmt.Sprintf("%v", this.AttachmentID) + `,`,
+		`}`,
+	}, "")
+	return s
+}
+func (this *DetachNetworkResponse) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&DetachNetworkResponse{`,
+		`}`,
+	}, "")
+	return s
+}
+func valueToStringResource(v interface{}) string {
+	rv := reflect.ValueOf(v)
+	if rv.IsNil() {
+		return "nil"
+	}
+	pv := reflect.Indirect(rv).Interface()
+	return fmt.Sprintf("*%v", pv)
+}
+func (m *AttachNetworkRequest) Unmarshal(data []byte) error {
+	l := len(data)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowResource
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := data[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: AttachNetworkRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: AttachNetworkRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Config", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowResource
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := data[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthResource
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Config == nil {
+				m.Config = &NetworkAttachmentConfig{}
+			}
+			if err := m.Config.Unmarshal(data[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ContainerID", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowResource
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := data[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthResource
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.ContainerID = string(data[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipResource(data[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthResource
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *AttachNetworkResponse) Unmarshal(data []byte) error {
+	l := len(data)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowResource
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := data[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: AttachNetworkResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: AttachNetworkResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field AttachmentID", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowResource
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := data[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthResource
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.AttachmentID = string(data[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipResource(data[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthResource
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *DetachNetworkRequest) Unmarshal(data []byte) error {
+	l := len(data)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowResource
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := data[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: DetachNetworkRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: DetachNetworkRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field AttachmentID", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowResource
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := data[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthResource
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.AttachmentID = string(data[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipResource(data[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthResource
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *DetachNetworkResponse) Unmarshal(data []byte) error {
+	l := len(data)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowResource
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := data[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: DetachNetworkResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: DetachNetworkResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		default:
+			iNdEx = preIndex
+			skippy, err := skipResource(data[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthResource
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipResource(data []byte) (n int, err error) {
+	l := len(data)
+	iNdEx := 0
+	for iNdEx < l {
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return 0, ErrIntOverflowResource
+			}
+			if iNdEx >= l {
+				return 0, io.ErrUnexpectedEOF
+			}
+			b := data[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		wireType := int(wire & 0x7)
+		switch wireType {
+		case 0:
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowResource
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				iNdEx++
+				if data[iNdEx-1] < 0x80 {
+					break
+				}
+			}
+			return iNdEx, nil
+		case 1:
+			iNdEx += 8
+			return iNdEx, nil
+		case 2:
+			var length int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowResource
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				b := data[iNdEx]
+				iNdEx++
+				length |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			iNdEx += length
+			if length < 0 {
+				return 0, ErrInvalidLengthResource
+			}
+			return iNdEx, nil
+		case 3:
+			for {
+				var innerWire uint64
+				var start int = iNdEx
+				for shift := uint(0); ; shift += 7 {
+					if shift >= 64 {
+						return 0, ErrIntOverflowResource
+					}
+					if iNdEx >= l {
+						return 0, io.ErrUnexpectedEOF
+					}
+					b := data[iNdEx]
+					iNdEx++
+					innerWire |= (uint64(b) & 0x7F) << shift
+					if b < 0x80 {
+						break
+					}
+				}
+				innerWireType := int(innerWire & 0x7)
+				if innerWireType == 4 {
+					break
+				}
+				next, err := skipResource(data[start:])
+				if err != nil {
+					return 0, err
+				}
+				iNdEx = start + next
+			}
+			return iNdEx, nil
+		case 4:
+			return iNdEx, nil
+		case 5:
+			iNdEx += 4
+			return iNdEx, nil
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+	}
+	panic("unreachable")
+}
+
+var (
+	ErrInvalidLengthResource = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowResource   = fmt.Errorf("proto: integer overflow")
+)
+
+var fileDescriptorResource = []byte{
+	// 373 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x2b, 0x4a, 0x2d, 0xce,
+	0x2f, 0x2d, 0x4a, 0x4e, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x4a, 0xc9, 0x4f, 0xce,
+	0x4e, 0x2d, 0xd2, 0x2b, 0x2e, 0x4f, 0x2c, 0xca, 0xcd, 0xce, 0x2c, 0xd1, 0x2b, 0x33, 0x94, 0xe2,
+	0x2e, 0xa9, 0x2c, 0x48, 0x2d, 0x86, 0x28, 0x90, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0x33, 0xf5,
+	0x41, 0x2c, 0xa8, 0xa8, 0x70, 0x41, 0x4e, 0x69, 0x7a, 0x66, 0x9e, 0x3e, 0x84, 0x82, 0x08, 0x2a,
+	0xf5, 0x33, 0x72, 0x89, 0x38, 0x96, 0x94, 0x24, 0x26, 0x67, 0xf8, 0xa5, 0x96, 0x94, 0xe7, 0x17,
+	0x65, 0x07, 0xa5, 0x16, 0x96, 0xa6, 0x16, 0x97, 0x08, 0x39, 0x73, 0xb1, 0x25, 0xe7, 0xe7, 0xa5,
+	0x65, 0xa6, 0x4b, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x1b, 0x69, 0xeb, 0x61, 0xda, 0xaa, 0x07, 0xd5,
+	0x03, 0x31, 0x20, 0x37, 0x35, 0xaf, 0xc4, 0x19, 0xac, 0x25, 0x08, 0xaa, 0x55, 0xc8, 0x88, 0x8b,
+	0x27, 0x39, 0x3f, 0xaf, 0x24, 0x31, 0x33, 0x2f, 0xb5, 0x28, 0x3e, 0x33, 0x45, 0x82, 0x49, 0x81,
+	0x51, 0x83, 0xd3, 0x89, 0xff, 0xd1, 0x3d, 0x79, 0x6e, 0x67, 0x98, 0xb8, 0xa7, 0x4b, 0x10, 0x37,
+	0x5c, 0x91, 0x67, 0x8a, 0x92, 0x1f, 0x97, 0x28, 0x9a, 0x83, 0x8a, 0x0b, 0xf2, 0xf3, 0x8a, 0x53,
+	0x85, 0x4c, 0xb9, 0x78, 0x13, 0xe1, 0x16, 0x81, 0x4c, 0x63, 0x04, 0x9b, 0x26, 0xf0, 0xe8, 0x9e,
+	0x3c, 0x0f, 0xc2, 0x05, 0x9e, 0x2e, 0x41, 0x3c, 0x08, 0x65, 0x9e, 0x29, 0x4a, 0xbe, 0x5c, 0x22,
+	0x2e, 0xa9, 0x58, 0x3c, 0x48, 0xa6, 0x71, 0xe2, 0x5c, 0xa2, 0x68, 0xc6, 0x41, 0x9c, 0x67, 0xb4,
+	0x9a, 0x89, 0x4b, 0x30, 0x08, 0x1a, 0x51, 0x8e, 0x39, 0x39, 0xf9, 0xc9, 0x89, 0x25, 0xf9, 0x45,
+	0x42, 0x9d, 0x8c, 0x5c, 0xbc, 0x28, 0xde, 0x11, 0xd2, 0xc0, 0x16, 0x90, 0xd8, 0xa2, 0x40, 0x4a,
+	0x93, 0x08, 0x95, 0x10, 0xcb, 0x95, 0x94, 0x4f, 0xad, 0x7b, 0x37, 0x83, 0x49, 0x96, 0x8b, 0x07,
+	0xac, 0x54, 0x17, 0x24, 0x97, 0x5a, 0xc4, 0xc5, 0x0b, 0xe1, 0xe5, 0x26, 0xe6, 0x25, 0xa6, 0xa7,
+	0x42, 0xdc, 0x82, 0xe2, 0x76, 0xec, 0x6e, 0xc1, 0x16, 0x5a, 0xd8, 0xdd, 0x82, 0x35, 0x20, 0x88,
+	0x72, 0x8b, 0x93, 0xcc, 0x89, 0x87, 0x72, 0x0c, 0x37, 0x1e, 0xca, 0x31, 0x7c, 0x78, 0x28, 0xc7,
+	0xd8, 0xf0, 0x48, 0x8e, 0xf1, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92,
+	0x63, 0x4c, 0x62, 0x03, 0x27, 0x4e, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xef, 0x94, 0x58,
+	0xde, 0xfa, 0x02, 0x00, 0x00,
+}

+ 34 - 0
vendor/src/github.com/docker/swarmkit/api/resource.proto

@@ -0,0 +1,34 @@
+syntax = "proto3";
+
+package docker.swarmkit.v1;
+
+import "types.proto";
+import "gogoproto/gogo.proto";
+import "plugin/plugin.proto";
+
+// Allocator is the API provided by a manager group for agents to control the allocation of certain entities.
+//
+// API methods on this service are used only by agent nodes.
+service ResourceAllocator {
+	rpc AttachNetwork(AttachNetworkRequest) returns (AttachNetworkResponse) {
+		option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-worker" roles: "swarm-manager" };
+	};
+	rpc DetachNetwork(DetachNetworkRequest) returns (DetachNetworkResponse) {
+		option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-worker" roles: "swarm-manager" };
+	};
+}
+
+message AttachNetworkRequest {
+	NetworkAttachmentConfig config = 1;
+	string container_id = 2 [(gogoproto.customname) = "ContainerID"];
+}
+
+message AttachNetworkResponse {
+	string attachment_id = 1 [(gogoproto.customname) = "AttachmentID"];
+}
+
+message DetachNetworkRequest {
+	string attachment_id = 1 [(gogoproto.customname) = "AttachmentID"];
+}
+
+message DetachNetworkResponse {}

Разница между файлами не показана из-за своего большого размера
+ 394 - 262
vendor/src/github.com/docker/swarmkit/api/specs.pb.go


+ 24 - 13
vendor/src/github.com/docker/swarmkit/api/specs.proto

@@ -72,19 +72,7 @@ message ServiceSpec {
 	// UpdateConfig controls the rate and policy of updates.
 	// UpdateConfig controls the rate and policy of updates.
 	UpdateConfig update = 6;
 	UpdateConfig update = 6;
 
 
-	// NetworkAttachmentConfig specifies how a service should be attached to a particular network.
-	//
-	// For now, this is a simple struct, but this can include future information
-	// instructing Swarm on how this service should work on the particular
-	// network.
-	message NetworkAttachmentConfig {
-		// Target specifies the target network for attachment. This value may be a
-		// network name or identifier. Only identifiers are supported at this time.
-		string target = 1;
-		// Aliases specifies a list of discoverable alternate names for the service on this Target.
-		repeated string aliases = 2;
-	}
-	repeated NetworkAttachmentConfig networks = 7;
+	repeated NetworkAttachmentConfig networks = 7 [deprecated=true];
 
 
 	// Service endpoint specifies the user provided configuration
 	// Service endpoint specifies the user provided configuration
 	// to properly discover and load balance a service.
 	// to properly discover and load balance a service.
@@ -103,6 +91,7 @@ message GlobalService {
 
 
 message TaskSpec {
 message TaskSpec {
 	oneof runtime {
 	oneof runtime {
+		NetworkAttachmentSpec attachment = 8;
 		ContainerSpec container = 1;
 		ContainerSpec container = 1;
 	}
 	}
 
 
@@ -118,6 +107,19 @@ message TaskSpec {
 	// LogDriver specifies the log driver to use for the task. Any runtime will
 	// LogDriver specifies the log driver to use for the task. Any runtime will
 	// direct logs into the specified driver for the duration of the task.
 	// direct logs into the specified driver for the duration of the task.
 	Driver log_driver = 6;
 	Driver log_driver = 6;
+
+	// Networks specifies the list of network attachment
+	// configurations (which specify the network and per-network
+	// aliases) that this task spec is bound to.
+	repeated NetworkAttachmentConfig networks = 7;
+}
+
+// NetworkAttachmentSpec specifies runtime parameters required to attach
+// a container to a network.
+message NetworkAttachmentSpec {
+	// ContainerID spcifies a unique ID of the container for which
+	// this attachment is for.
+	string container_id = 1 [(gogoproto.customname) = "ContainerID"];
 }
 }
 
 
 // Container specifies runtime parameters for a container.
 // Container specifies runtime parameters for a container.
@@ -234,6 +236,15 @@ message NetworkSpec {
 	bool internal = 4;
 	bool internal = 4;
 
 
 	IPAMOptions ipam = 5 [(gogoproto.customname) = "IPAM"];
 	IPAMOptions ipam = 5 [(gogoproto.customname) = "IPAM"];
+
+	// Attachable allows external(to swarm) entities to manually
+	// attach to this network. With this flag enabled, external
+	// entities such as containers running in an worker node in
+	// the cluster can manually attach to this network and access
+	// the services attached to this network. If this flag is not
+	// enabled(default case) no manual attachment to this network
+	// can happen.
+	bool attachable = 6;
 }
 }
 
 
 // ClusterSpec specifies global cluster settings.
 // ClusterSpec specifies global cluster settings.

+ 531 - 236
vendor/src/github.com/docker/swarmkit/api/types.pb.go

@@ -15,6 +15,7 @@
 		snapshot.proto
 		snapshot.proto
 		raft.proto
 		raft.proto
 		health.proto
 		health.proto
+		resource.proto
 
 
 	It has these top-level messages:
 	It has these top-level messages:
 		Version
 		Version
@@ -34,6 +35,7 @@
 		UpdateStatus
 		UpdateStatus
 		ContainerStatus
 		ContainerStatus
 		TaskStatus
 		TaskStatus
+		NetworkAttachmentConfig
 		IPAMConfig
 		IPAMConfig
 		PortConfig
 		PortConfig
 		Driver
 		Driver
@@ -59,6 +61,7 @@
 		ReplicatedService
 		ReplicatedService
 		GlobalService
 		GlobalService
 		TaskSpec
 		TaskSpec
+		NetworkAttachmentSpec
 		ContainerSpec
 		ContainerSpec
 		EndpointSpec
 		EndpointSpec
 		NetworkSpec
 		NetworkSpec
@@ -140,6 +143,10 @@
 		StoreAction
 		StoreAction
 		HealthCheckRequest
 		HealthCheckRequest
 		HealthCheckResponse
 		HealthCheckResponse
+		AttachNetworkRequest
+		AttachNetworkResponse
+		DetachNetworkRequest
+		DetachNetworkResponse
 */
 */
 package api
 package api
 
 
@@ -473,7 +480,7 @@ func (x IPAMConfig_AddressFamily) String() string {
 	return proto.EnumName(IPAMConfig_AddressFamily_name, int32(x))
 	return proto.EnumName(IPAMConfig_AddressFamily_name, int32(x))
 }
 }
 func (IPAMConfig_AddressFamily) EnumDescriptor() ([]byte, []int) {
 func (IPAMConfig_AddressFamily) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptorTypes, []int{17, 0}
+	return fileDescriptorTypes, []int{18, 0}
 }
 }
 
 
 type PortConfig_Protocol int32
 type PortConfig_Protocol int32
@@ -495,7 +502,7 @@ var PortConfig_Protocol_value = map[string]int32{
 func (x PortConfig_Protocol) String() string {
 func (x PortConfig_Protocol) String() string {
 	return proto.EnumName(PortConfig_Protocol_name, int32(x))
 	return proto.EnumName(PortConfig_Protocol_name, int32(x))
 }
 }
-func (PortConfig_Protocol) EnumDescriptor() ([]byte, []int) { return fileDescriptorTypes, []int{18, 0} }
+func (PortConfig_Protocol) EnumDescriptor() ([]byte, []int) { return fileDescriptorTypes, []int{19, 0} }
 
 
 type IssuanceStatus_State int32
 type IssuanceStatus_State int32
 
 
@@ -525,7 +532,7 @@ var IssuanceStatus_State_value = map[string]int32{
 func (x IssuanceStatus_State) String() string {
 func (x IssuanceStatus_State) String() string {
 	return proto.EnumName(IssuanceStatus_State_name, int32(x))
 	return proto.EnumName(IssuanceStatus_State_name, int32(x))
 }
 }
-func (IssuanceStatus_State) EnumDescriptor() ([]byte, []int) { return fileDescriptorTypes, []int{23, 0} }
+func (IssuanceStatus_State) EnumDescriptor() ([]byte, []int) { return fileDescriptorTypes, []int{24, 0} }
 
 
 type ExternalCA_CAProtocol int32
 type ExternalCA_CAProtocol int32
 
 
@@ -544,7 +551,7 @@ func (x ExternalCA_CAProtocol) String() string {
 	return proto.EnumName(ExternalCA_CAProtocol_name, int32(x))
 	return proto.EnumName(ExternalCA_CAProtocol_name, int32(x))
 }
 }
 func (ExternalCA_CAProtocol) EnumDescriptor() ([]byte, []int) {
 func (ExternalCA_CAProtocol) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptorTypes, []int{25, 0}
+	return fileDescriptorTypes, []int{26, 0}
 }
 }
 
 
 // Encryption algorithm that can implemented using this key
 // Encryption algorithm that can implemented using this key
@@ -565,7 +572,7 @@ func (x EncryptionKey_Algorithm) String() string {
 	return proto.EnumName(EncryptionKey_Algorithm_name, int32(x))
 	return proto.EnumName(EncryptionKey_Algorithm_name, int32(x))
 }
 }
 func (EncryptionKey_Algorithm) EnumDescriptor() ([]byte, []int) {
 func (EncryptionKey_Algorithm) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptorTypes, []int{35, 0}
+	return fileDescriptorTypes, []int{36, 0}
 }
 }
 
 
 // Version tracks the last time an object in the store was updated.
 // Version tracks the last time an object in the store was updated.
@@ -952,6 +959,27 @@ func _TaskStatus_OneofSizer(msg proto.Message) (n int) {
 	return n
 	return n
 }
 }
 
 
+// NetworkAttachmentConfig specifies how a service should be attached to a particular network.
+//
+// For now, this is a simple struct, but this can include future information
+// instructing Swarm on how this service should work on the particular
+// network.
+type NetworkAttachmentConfig struct {
+	// Target specifies the target network for attachment. This value may be a
+	// network name or identifier. Only identifiers are supported at this time.
+	Target string `protobuf:"bytes,1,opt,name=target,proto3" json:"target,omitempty"`
+	// Aliases specifies a list of discoverable alternate names for the service on this Target.
+	Aliases []string `protobuf:"bytes,2,rep,name=aliases" json:"aliases,omitempty"`
+	// Addresses specifies a list of ipv4 and ipv6 addresses
+	// preferred. If these addresses are not available then the
+	// attachment might fail.
+	Addresses []string `protobuf:"bytes,3,rep,name=addresses" json:"addresses,omitempty"`
+}
+
+func (m *NetworkAttachmentConfig) Reset()                    { *m = NetworkAttachmentConfig{} }
+func (*NetworkAttachmentConfig) ProtoMessage()               {}
+func (*NetworkAttachmentConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{17} }
+
 // IPAMConfig specifies parameters for IP Address Management.
 // IPAMConfig specifies parameters for IP Address Management.
 type IPAMConfig struct {
 type IPAMConfig struct {
 	Family IPAMConfig_AddressFamily `protobuf:"varint,1,opt,name=family,proto3,enum=docker.swarmkit.v1.IPAMConfig_AddressFamily" json:"family,omitempty"`
 	Family IPAMConfig_AddressFamily `protobuf:"varint,1,opt,name=family,proto3,enum=docker.swarmkit.v1.IPAMConfig_AddressFamily" json:"family,omitempty"`
@@ -971,7 +999,7 @@ type IPAMConfig struct {
 
 
 func (m *IPAMConfig) Reset()                    { *m = IPAMConfig{} }
 func (m *IPAMConfig) Reset()                    { *m = IPAMConfig{} }
 func (*IPAMConfig) ProtoMessage()               {}
 func (*IPAMConfig) ProtoMessage()               {}
-func (*IPAMConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{17} }
+func (*IPAMConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{18} }
 
 
 // PortConfig specifies an exposed port which can be
 // PortConfig specifies an exposed port which can be
 // addressed using the given name. This can be later queried
 // addressed using the given name. This can be later queried
@@ -996,7 +1024,7 @@ type PortConfig struct {
 
 
 func (m *PortConfig) Reset()                    { *m = PortConfig{} }
 func (m *PortConfig) Reset()                    { *m = PortConfig{} }
 func (*PortConfig) ProtoMessage()               {}
 func (*PortConfig) ProtoMessage()               {}
-func (*PortConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{18} }
+func (*PortConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{19} }
 
 
 // Driver is a generic driver type to be used throughout the API. For now, a
 // Driver is a generic driver type to be used throughout the API. For now, a
 // driver is simply a name and set of options. The field contents depend on the
 // driver is simply a name and set of options. The field contents depend on the
@@ -1009,7 +1037,7 @@ type Driver struct {
 
 
 func (m *Driver) Reset()                    { *m = Driver{} }
 func (m *Driver) Reset()                    { *m = Driver{} }
 func (*Driver) ProtoMessage()               {}
 func (*Driver) ProtoMessage()               {}
-func (*Driver) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{19} }
+func (*Driver) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{20} }
 
 
 type IPAMOptions struct {
 type IPAMOptions struct {
 	Driver  *Driver       `protobuf:"bytes,1,opt,name=driver" json:"driver,omitempty"`
 	Driver  *Driver       `protobuf:"bytes,1,opt,name=driver" json:"driver,omitempty"`
@@ -1018,7 +1046,7 @@ type IPAMOptions struct {
 
 
 func (m *IPAMOptions) Reset()                    { *m = IPAMOptions{} }
 func (m *IPAMOptions) Reset()                    { *m = IPAMOptions{} }
 func (*IPAMOptions) ProtoMessage()               {}
 func (*IPAMOptions) ProtoMessage()               {}
-func (*IPAMOptions) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{20} }
+func (*IPAMOptions) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{21} }
 
 
 // Peer should be used anywhere where we are describing a remote peer.
 // Peer should be used anywhere where we are describing a remote peer.
 type Peer struct {
 type Peer struct {
@@ -1028,7 +1056,7 @@ type Peer struct {
 
 
 func (m *Peer) Reset()                    { *m = Peer{} }
 func (m *Peer) Reset()                    { *m = Peer{} }
 func (*Peer) ProtoMessage()               {}
 func (*Peer) ProtoMessage()               {}
-func (*Peer) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{21} }
+func (*Peer) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{22} }
 
 
 // WeightedPeer should be used anywhere where we are describing a remote peer
 // WeightedPeer should be used anywhere where we are describing a remote peer
 // with a weight.
 // with a weight.
@@ -1039,7 +1067,7 @@ type WeightedPeer struct {
 
 
 func (m *WeightedPeer) Reset()                    { *m = WeightedPeer{} }
 func (m *WeightedPeer) Reset()                    { *m = WeightedPeer{} }
 func (*WeightedPeer) ProtoMessage()               {}
 func (*WeightedPeer) ProtoMessage()               {}
-func (*WeightedPeer) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{22} }
+func (*WeightedPeer) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{23} }
 
 
 type IssuanceStatus struct {
 type IssuanceStatus struct {
 	State IssuanceStatus_State `protobuf:"varint,1,opt,name=state,proto3,enum=docker.swarmkit.v1.IssuanceStatus_State" json:"state,omitempty"`
 	State IssuanceStatus_State `protobuf:"varint,1,opt,name=state,proto3,enum=docker.swarmkit.v1.IssuanceStatus_State" json:"state,omitempty"`
@@ -1051,7 +1079,7 @@ type IssuanceStatus struct {
 
 
 func (m *IssuanceStatus) Reset()                    { *m = IssuanceStatus{} }
 func (m *IssuanceStatus) Reset()                    { *m = IssuanceStatus{} }
 func (*IssuanceStatus) ProtoMessage()               {}
 func (*IssuanceStatus) ProtoMessage()               {}
-func (*IssuanceStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{23} }
+func (*IssuanceStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{24} }
 
 
 type AcceptancePolicy struct {
 type AcceptancePolicy struct {
 	Policies []*AcceptancePolicy_RoleAdmissionPolicy `protobuf:"bytes,1,rep,name=policies" json:"policies,omitempty"`
 	Policies []*AcceptancePolicy_RoleAdmissionPolicy `protobuf:"bytes,1,rep,name=policies" json:"policies,omitempty"`
@@ -1059,7 +1087,7 @@ type AcceptancePolicy struct {
 
 
 func (m *AcceptancePolicy) Reset()                    { *m = AcceptancePolicy{} }
 func (m *AcceptancePolicy) Reset()                    { *m = AcceptancePolicy{} }
 func (*AcceptancePolicy) ProtoMessage()               {}
 func (*AcceptancePolicy) ProtoMessage()               {}
-func (*AcceptancePolicy) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{24} }
+func (*AcceptancePolicy) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{25} }
 
 
 type AcceptancePolicy_RoleAdmissionPolicy struct {
 type AcceptancePolicy_RoleAdmissionPolicy struct {
 	Role NodeRole `protobuf:"varint,1,opt,name=role,proto3,enum=docker.swarmkit.v1.NodeRole" json:"role,omitempty"`
 	Role NodeRole `protobuf:"varint,1,opt,name=role,proto3,enum=docker.swarmkit.v1.NodeRole" json:"role,omitempty"`
@@ -1074,7 +1102,7 @@ type AcceptancePolicy_RoleAdmissionPolicy struct {
 func (m *AcceptancePolicy_RoleAdmissionPolicy) Reset()      { *m = AcceptancePolicy_RoleAdmissionPolicy{} }
 func (m *AcceptancePolicy_RoleAdmissionPolicy) Reset()      { *m = AcceptancePolicy_RoleAdmissionPolicy{} }
 func (*AcceptancePolicy_RoleAdmissionPolicy) ProtoMessage() {}
 func (*AcceptancePolicy_RoleAdmissionPolicy) ProtoMessage() {}
 func (*AcceptancePolicy_RoleAdmissionPolicy) Descriptor() ([]byte, []int) {
 func (*AcceptancePolicy_RoleAdmissionPolicy) Descriptor() ([]byte, []int) {
-	return fileDescriptorTypes, []int{24, 0}
+	return fileDescriptorTypes, []int{25, 0}
 }
 }
 
 
 type AcceptancePolicy_RoleAdmissionPolicy_Secret struct {
 type AcceptancePolicy_RoleAdmissionPolicy_Secret struct {
@@ -1089,7 +1117,7 @@ func (m *AcceptancePolicy_RoleAdmissionPolicy_Secret) Reset() {
 }
 }
 func (*AcceptancePolicy_RoleAdmissionPolicy_Secret) ProtoMessage() {}
 func (*AcceptancePolicy_RoleAdmissionPolicy_Secret) ProtoMessage() {}
 func (*AcceptancePolicy_RoleAdmissionPolicy_Secret) Descriptor() ([]byte, []int) {
 func (*AcceptancePolicy_RoleAdmissionPolicy_Secret) Descriptor() ([]byte, []int) {
-	return fileDescriptorTypes, []int{24, 0, 0}
+	return fileDescriptorTypes, []int{25, 0, 0}
 }
 }
 
 
 type ExternalCA struct {
 type ExternalCA struct {
@@ -1104,7 +1132,7 @@ type ExternalCA struct {
 
 
 func (m *ExternalCA) Reset()                    { *m = ExternalCA{} }
 func (m *ExternalCA) Reset()                    { *m = ExternalCA{} }
 func (*ExternalCA) ProtoMessage()               {}
 func (*ExternalCA) ProtoMessage()               {}
-func (*ExternalCA) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{25} }
+func (*ExternalCA) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{26} }
 
 
 type CAConfig struct {
 type CAConfig struct {
 	// NodeCertExpiry is the duration certificates should be issued for
 	// NodeCertExpiry is the duration certificates should be issued for
@@ -1116,7 +1144,7 @@ type CAConfig struct {
 
 
 func (m *CAConfig) Reset()                    { *m = CAConfig{} }
 func (m *CAConfig) Reset()                    { *m = CAConfig{} }
 func (*CAConfig) ProtoMessage()               {}
 func (*CAConfig) ProtoMessage()               {}
-func (*CAConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{26} }
+func (*CAConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{27} }
 
 
 // OrchestrationConfig defines cluster-level orchestration settings.
 // OrchestrationConfig defines cluster-level orchestration settings.
 type OrchestrationConfig struct {
 type OrchestrationConfig struct {
@@ -1127,7 +1155,7 @@ type OrchestrationConfig struct {
 
 
 func (m *OrchestrationConfig) Reset()                    { *m = OrchestrationConfig{} }
 func (m *OrchestrationConfig) Reset()                    { *m = OrchestrationConfig{} }
 func (*OrchestrationConfig) ProtoMessage()               {}
 func (*OrchestrationConfig) ProtoMessage()               {}
-func (*OrchestrationConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{27} }
+func (*OrchestrationConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{28} }
 
 
 // TaskDefaults specifies default values for task creation.
 // TaskDefaults specifies default values for task creation.
 type TaskDefaults struct {
 type TaskDefaults struct {
@@ -1141,7 +1169,7 @@ type TaskDefaults struct {
 
 
 func (m *TaskDefaults) Reset()                    { *m = TaskDefaults{} }
 func (m *TaskDefaults) Reset()                    { *m = TaskDefaults{} }
 func (*TaskDefaults) ProtoMessage()               {}
 func (*TaskDefaults) ProtoMessage()               {}
-func (*TaskDefaults) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{28} }
+func (*TaskDefaults) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{29} }
 
 
 // DispatcherConfig defines cluster-level dispatcher settings.
 // DispatcherConfig defines cluster-level dispatcher settings.
 type DispatcherConfig struct {
 type DispatcherConfig struct {
@@ -1152,7 +1180,7 @@ type DispatcherConfig struct {
 
 
 func (m *DispatcherConfig) Reset()                    { *m = DispatcherConfig{} }
 func (m *DispatcherConfig) Reset()                    { *m = DispatcherConfig{} }
 func (*DispatcherConfig) ProtoMessage()               {}
 func (*DispatcherConfig) ProtoMessage()               {}
-func (*DispatcherConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{29} }
+func (*DispatcherConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{30} }
 
 
 // RaftConfig defines raft settings for the cluster.
 // RaftConfig defines raft settings for the cluster.
 type RaftConfig struct {
 type RaftConfig struct {
@@ -1174,7 +1202,7 @@ type RaftConfig struct {
 
 
 func (m *RaftConfig) Reset()                    { *m = RaftConfig{} }
 func (m *RaftConfig) Reset()                    { *m = RaftConfig{} }
 func (*RaftConfig) ProtoMessage()               {}
 func (*RaftConfig) ProtoMessage()               {}
-func (*RaftConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{30} }
+func (*RaftConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{31} }
 
 
 // Placement specifies task distribution constraints.
 // Placement specifies task distribution constraints.
 type Placement struct {
 type Placement struct {
@@ -1184,7 +1212,7 @@ type Placement struct {
 
 
 func (m *Placement) Reset()                    { *m = Placement{} }
 func (m *Placement) Reset()                    { *m = Placement{} }
 func (*Placement) ProtoMessage()               {}
 func (*Placement) ProtoMessage()               {}
-func (*Placement) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{31} }
+func (*Placement) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{32} }
 
 
 // JoinToken contains the join tokens for workers and managers.
 // JoinToken contains the join tokens for workers and managers.
 type JoinTokens struct {
 type JoinTokens struct {
@@ -1196,7 +1224,7 @@ type JoinTokens struct {
 
 
 func (m *JoinTokens) Reset()                    { *m = JoinTokens{} }
 func (m *JoinTokens) Reset()                    { *m = JoinTokens{} }
 func (*JoinTokens) ProtoMessage()               {}
 func (*JoinTokens) ProtoMessage()               {}
-func (*JoinTokens) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{32} }
+func (*JoinTokens) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{33} }
 
 
 type RootCA struct {
 type RootCA struct {
 	// CAKey is the root CA private key.
 	// CAKey is the root CA private key.
@@ -1211,7 +1239,7 @@ type RootCA struct {
 
 
 func (m *RootCA) Reset()                    { *m = RootCA{} }
 func (m *RootCA) Reset()                    { *m = RootCA{} }
 func (*RootCA) ProtoMessage()               {}
 func (*RootCA) ProtoMessage()               {}
-func (*RootCA) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{33} }
+func (*RootCA) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{34} }
 
 
 type Certificate struct {
 type Certificate struct {
 	Role        NodeRole       `protobuf:"varint,1,opt,name=role,proto3,enum=docker.swarmkit.v1.NodeRole" json:"role,omitempty"`
 	Role        NodeRole       `protobuf:"varint,1,opt,name=role,proto3,enum=docker.swarmkit.v1.NodeRole" json:"role,omitempty"`
@@ -1224,7 +1252,7 @@ type Certificate struct {
 
 
 func (m *Certificate) Reset()                    { *m = Certificate{} }
 func (m *Certificate) Reset()                    { *m = Certificate{} }
 func (*Certificate) ProtoMessage()               {}
 func (*Certificate) ProtoMessage()               {}
-func (*Certificate) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{34} }
+func (*Certificate) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{35} }
 
 
 // Symmetric keys to encrypt inter-agent communication.
 // Symmetric keys to encrypt inter-agent communication.
 type EncryptionKey struct {
 type EncryptionKey struct {
@@ -1240,7 +1268,7 @@ type EncryptionKey struct {
 
 
 func (m *EncryptionKey) Reset()                    { *m = EncryptionKey{} }
 func (m *EncryptionKey) Reset()                    { *m = EncryptionKey{} }
 func (*EncryptionKey) ProtoMessage()               {}
 func (*EncryptionKey) ProtoMessage()               {}
-func (*EncryptionKey) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{35} }
+func (*EncryptionKey) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{36} }
 
 
 // ManagerStatus provides informations about the state of a manager in the cluster.
 // ManagerStatus provides informations about the state of a manager in the cluster.
 type ManagerStatus struct {
 type ManagerStatus struct {
@@ -1257,7 +1285,7 @@ type ManagerStatus struct {
 
 
 func (m *ManagerStatus) Reset()                    { *m = ManagerStatus{} }
 func (m *ManagerStatus) Reset()                    { *m = ManagerStatus{} }
 func (*ManagerStatus) ProtoMessage()               {}
 func (*ManagerStatus) ProtoMessage()               {}
-func (*ManagerStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{36} }
+func (*ManagerStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{37} }
 
 
 func init() {
 func init() {
 	proto.RegisterType((*Version)(nil), "docker.swarmkit.v1.Version")
 	proto.RegisterType((*Version)(nil), "docker.swarmkit.v1.Version")
@@ -1280,6 +1308,7 @@ func init() {
 	proto.RegisterType((*UpdateStatus)(nil), "docker.swarmkit.v1.UpdateStatus")
 	proto.RegisterType((*UpdateStatus)(nil), "docker.swarmkit.v1.UpdateStatus")
 	proto.RegisterType((*ContainerStatus)(nil), "docker.swarmkit.v1.ContainerStatus")
 	proto.RegisterType((*ContainerStatus)(nil), "docker.swarmkit.v1.ContainerStatus")
 	proto.RegisterType((*TaskStatus)(nil), "docker.swarmkit.v1.TaskStatus")
 	proto.RegisterType((*TaskStatus)(nil), "docker.swarmkit.v1.TaskStatus")
+	proto.RegisterType((*NetworkAttachmentConfig)(nil), "docker.swarmkit.v1.NetworkAttachmentConfig")
 	proto.RegisterType((*IPAMConfig)(nil), "docker.swarmkit.v1.IPAMConfig")
 	proto.RegisterType((*IPAMConfig)(nil), "docker.swarmkit.v1.IPAMConfig")
 	proto.RegisterType((*PortConfig)(nil), "docker.swarmkit.v1.PortConfig")
 	proto.RegisterType((*PortConfig)(nil), "docker.swarmkit.v1.PortConfig")
 	proto.RegisterType((*Driver)(nil), "docker.swarmkit.v1.Driver")
 	proto.RegisterType((*Driver)(nil), "docker.swarmkit.v1.Driver")
@@ -1626,6 +1655,32 @@ func (m *TaskStatus) Copy() *TaskStatus {
 	return o
 	return o
 }
 }
 
 
+func (m *NetworkAttachmentConfig) Copy() *NetworkAttachmentConfig {
+	if m == nil {
+		return nil
+	}
+
+	o := &NetworkAttachmentConfig{
+		Target: m.Target,
+	}
+
+	if m.Aliases != nil {
+		o.Aliases = make([]string, 0, len(m.Aliases))
+		for _, v := range m.Aliases {
+			o.Aliases = append(o.Aliases, v)
+		}
+	}
+
+	if m.Addresses != nil {
+		o.Addresses = make([]string, 0, len(m.Addresses))
+		for _, v := range m.Addresses {
+			o.Addresses = append(o.Addresses, v)
+		}
+	}
+
+	return o
+}
+
 func (m *IPAMConfig) Copy() *IPAMConfig {
 func (m *IPAMConfig) Copy() *IPAMConfig {
 	if m == nil {
 	if m == nil {
 		return nil
 		return nil
@@ -2278,6 +2333,18 @@ func (this *TaskStatus_Container) GoString() string {
 		`Container:` + fmt.Sprintf("%#v", this.Container) + `}`}, ", ")
 		`Container:` + fmt.Sprintf("%#v", this.Container) + `}`}, ", ")
 	return s
 	return s
 }
 }
+func (this *NetworkAttachmentConfig) GoString() string {
+	if this == nil {
+		return "nil"
+	}
+	s := make([]string, 0, 7)
+	s = append(s, "&api.NetworkAttachmentConfig{")
+	s = append(s, "Target: "+fmt.Sprintf("%#v", this.Target)+",\n")
+	s = append(s, "Aliases: "+fmt.Sprintf("%#v", this.Aliases)+",\n")
+	s = append(s, "Addresses: "+fmt.Sprintf("%#v", this.Addresses)+",\n")
+	s = append(s, "}")
+	return strings.Join(s, "")
+}
 func (this *IPAMConfig) GoString() string {
 func (this *IPAMConfig) GoString() string {
 	if this == nil {
 	if this == nil {
 		return "nil"
 		return "nil"
@@ -3416,6 +3483,60 @@ func (m *TaskStatus_Container) MarshalTo(data []byte) (int, error) {
 	}
 	}
 	return i, nil
 	return i, nil
 }
 }
+func (m *NetworkAttachmentConfig) Marshal() (data []byte, err error) {
+	size := m.Size()
+	data = make([]byte, size)
+	n, err := m.MarshalTo(data)
+	if err != nil {
+		return nil, err
+	}
+	return data[:n], nil
+}
+
+func (m *NetworkAttachmentConfig) MarshalTo(data []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	if len(m.Target) > 0 {
+		data[i] = 0xa
+		i++
+		i = encodeVarintTypes(data, i, uint64(len(m.Target)))
+		i += copy(data[i:], m.Target)
+	}
+	if len(m.Aliases) > 0 {
+		for _, s := range m.Aliases {
+			data[i] = 0x12
+			i++
+			l = len(s)
+			for l >= 1<<7 {
+				data[i] = uint8(uint64(l)&0x7f | 0x80)
+				l >>= 7
+				i++
+			}
+			data[i] = uint8(l)
+			i++
+			i += copy(data[i:], s)
+		}
+	}
+	if len(m.Addresses) > 0 {
+		for _, s := range m.Addresses {
+			data[i] = 0x1a
+			i++
+			l = len(s)
+			for l >= 1<<7 {
+				data[i] = uint8(uint64(l)&0x7f | 0x80)
+				l >>= 7
+				i++
+			}
+			data[i] = uint8(l)
+			i++
+			i += copy(data[i:], s)
+		}
+	}
+	return i, nil
+}
+
 func (m *IPAMConfig) Marshal() (data []byte, err error) {
 func (m *IPAMConfig) Marshal() (data []byte, err error) {
 	size := m.Size()
 	size := m.Size()
 	data = make([]byte, size)
 	data = make([]byte, size)
@@ -4609,6 +4730,28 @@ func (m *TaskStatus_Container) Size() (n int) {
 	}
 	}
 	return n
 	return n
 }
 }
+func (m *NetworkAttachmentConfig) Size() (n int) {
+	var l int
+	_ = l
+	l = len(m.Target)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	if len(m.Aliases) > 0 {
+		for _, s := range m.Aliases {
+			l = len(s)
+			n += 1 + l + sovTypes(uint64(l))
+		}
+	}
+	if len(m.Addresses) > 0 {
+		for _, s := range m.Addresses {
+			l = len(s)
+			n += 1 + l + sovTypes(uint64(l))
+		}
+	}
+	return n
+}
+
 func (m *IPAMConfig) Size() (n int) {
 func (m *IPAMConfig) Size() (n int) {
 	var l int
 	var l int
 	_ = l
 	_ = l
@@ -5257,6 +5400,18 @@ func (this *TaskStatus_Container) String() string {
 	}, "")
 	}, "")
 	return s
 	return s
 }
 }
+func (this *NetworkAttachmentConfig) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&NetworkAttachmentConfig{`,
+		`Target:` + fmt.Sprintf("%v", this.Target) + `,`,
+		`Aliases:` + fmt.Sprintf("%v", this.Aliases) + `,`,
+		`Addresses:` + fmt.Sprintf("%v", this.Addresses) + `,`,
+		`}`,
+	}, "")
+	return s
+}
 func (this *IPAMConfig) String() string {
 func (this *IPAMConfig) String() string {
 	if this == nil {
 	if this == nil {
 		return "nil"
 		return "nil"
@@ -8286,6 +8441,143 @@ func (m *TaskStatus) Unmarshal(data []byte) error {
 	}
 	}
 	return nil
 	return nil
 }
 }
+func (m *NetworkAttachmentConfig) Unmarshal(data []byte) error {
+	l := len(data)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := data[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: NetworkAttachmentConfig: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: NetworkAttachmentConfig: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Target", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := data[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Target = string(data[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Aliases", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := data[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Aliases = append(m.Aliases, string(data[iNdEx:postIndex]))
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := data[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Addresses = append(m.Addresses, string(data[iNdEx:postIndex]))
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(data[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
 func (m *IPAMConfig) Unmarshal(data []byte) error {
 func (m *IPAMConfig) Unmarshal(data []byte) error {
 	l := len(data)
 	l := len(data)
 	iNdEx := 0
 	iNdEx := 0
@@ -11256,218 +11548,221 @@ var (
 )
 )
 
 
 var fileDescriptorTypes = []byte{
 var fileDescriptorTypes = []byte{
-	// 3398 bytes of a gzipped FileDescriptorProto
+	// 3442 bytes of a gzipped FileDescriptorProto
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x59, 0x4d, 0x6c, 0x1b, 0x49,
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x59, 0x4d, 0x6c, 0x1b, 0x49,
 	0x76, 0x16, 0x7f, 0x45, 0x3e, 0x52, 0x72, 0xbb, 0xec, 0xf5, 0xc8, 0x1c, 0x8f, 0xc4, 0x69, 0x8f,
 	0x76, 0x16, 0x7f, 0x45, 0x3e, 0x52, 0x72, 0xbb, 0xec, 0xf5, 0xc8, 0x1c, 0x8f, 0xc4, 0x69, 0x8f,
 	0x77, 0xbc, 0xb3, 0x13, 0xce, 0x8c, 0x66, 0x13, 0x78, 0xc7, 0xc9, 0xce, 0xb4, 0x48, 0xca, 0xe6,
 	0x77, 0xbc, 0xb3, 0x13, 0xce, 0x8c, 0x66, 0x13, 0x78, 0xc7, 0xc9, 0xce, 0xb4, 0x48, 0xca, 0xe6,
-	0x5a, 0xa2, 0x88, 0xa2, 0x68, 0x63, 0x10, 0x20, 0x44, 0xa9, 0xbb, 0x44, 0xf5, 0xa8, 0xd9, 0xc5,
+	0x5a, 0xa2, 0x88, 0x22, 0x69, 0x63, 0x10, 0x20, 0x44, 0xa9, 0xbb, 0x44, 0xf6, 0xa8, 0xd9, 0xc5,
 	0x74, 0x17, 0x25, 0x33, 0x41, 0x00, 0x27, 0x97, 0x04, 0x3a, 0xe5, 0x1e, 0x08, 0x8b, 0x20, 0x41,
 	0x74, 0x17, 0x25, 0x33, 0x41, 0x00, 0x27, 0x97, 0x04, 0x3a, 0xe5, 0x1e, 0x08, 0x8b, 0x20, 0x41,
 	0x6e, 0x39, 0xe4, 0x14, 0x20, 0x27, 0x1f, 0xe7, 0xb8, 0x41, 0x80, 0x60, 0x91, 0x00, 0x42, 0x46,
 	0x6e, 0x39, 0xe4, 0x14, 0x20, 0x27, 0x1f, 0xe7, 0xb8, 0x41, 0x80, 0x60, 0x91, 0x00, 0x42, 0x46,
-	0x39, 0xe6, 0xb2, 0x40, 0x0e, 0x7b, 0x48, 0x0e, 0x41, 0xfd, 0x74, 0xb3, 0x49, 0xd3, 0x1a, 0x4f,
-	0x76, 0x4f, 0xec, 0x7a, 0xf5, 0xbd, 0x57, 0xef, 0x55, 0xbd, 0x7a, 0xf5, 0x55, 0x11, 0x4a, 0x7c,
-	0x32, 0xa2, 0x61, 0x6d, 0x14, 0x30, 0xce, 0x10, 0x72, 0x98, 0x7d, 0x4c, 0x83, 0x5a, 0x78, 0x4a,
-	0x82, 0xe1, 0xb1, 0xcb, 0x6b, 0x27, 0x9f, 0x54, 0x6e, 0x73, 0x77, 0x48, 0x43, 0x4e, 0x86, 0xa3,
-	0x8f, 0xe2, 0x2f, 0x05, 0xaf, 0xbc, 0xe5, 0x8c, 0x03, 0xc2, 0x5d, 0xe6, 0x7f, 0x14, 0x7d, 0xe8,
-	0x8e, 0x9b, 0x03, 0x36, 0x60, 0xf2, 0xf3, 0x23, 0xf1, 0xa5, 0xa4, 0xe6, 0x06, 0x2c, 0x3f, 0xa5,
-	0x41, 0xe8, 0x32, 0x1f, 0xdd, 0x84, 0x9c, 0xeb, 0x3b, 0xf4, 0xf9, 0x5a, 0xaa, 0x9a, 0xba, 0x9f,
-	0xc5, 0xaa, 0x61, 0xfe, 0x75, 0x0a, 0x4a, 0x96, 0xef, 0x33, 0x2e, 0x6d, 0x85, 0x08, 0x41, 0xd6,
-	0x27, 0x43, 0x2a, 0x41, 0x45, 0x2c, 0xbf, 0x51, 0x1d, 0xf2, 0x1e, 0x39, 0xa0, 0x5e, 0xb8, 0x96,
-	0xae, 0x66, 0xee, 0x97, 0x36, 0x7f, 0x58, 0x7b, 0xd5, 0xe7, 0x5a, 0xc2, 0x48, 0x6d, 0x47, 0xa2,
-	0x9b, 0x3e, 0x0f, 0x26, 0x58, 0xab, 0x56, 0x7e, 0x0c, 0xa5, 0x84, 0x18, 0x19, 0x90, 0x39, 0xa6,
-	0x13, 0x3d, 0x8c, 0xf8, 0x14, 0xfe, 0x9d, 0x10, 0x6f, 0x4c, 0xd7, 0xd2, 0x52, 0xa6, 0x1a, 0x9f,
-	0xa5, 0x1f, 0xa4, 0xcc, 0x2f, 0xa1, 0x88, 0x69, 0xc8, 0xc6, 0x81, 0x4d, 0x43, 0xf4, 0x03, 0x28,
-	0xfa, 0xc4, 0x67, 0x7d, 0x7b, 0x34, 0x0e, 0xa5, 0x7a, 0x66, 0xab, 0x7c, 0x79, 0xb1, 0x51, 0x68,
-	0x13, 0x9f, 0xd5, 0x3b, 0xbd, 0x10, 0x17, 0x44, 0x77, 0x7d, 0x34, 0x0e, 0xd1, 0xbb, 0x50, 0x1e,
-	0xd2, 0x21, 0x0b, 0x26, 0xfd, 0x83, 0x09, 0xa7, 0xa1, 0x34, 0x9c, 0xc1, 0x25, 0x25, 0xdb, 0x12,
-	0x22, 0xf3, 0x2f, 0x53, 0x70, 0x33, 0xb2, 0x8d, 0xe9, 0x1f, 0x8e, 0xdd, 0x80, 0x0e, 0xa9, 0xcf,
-	0x43, 0xf4, 0xdb, 0x90, 0xf7, 0xdc, 0xa1, 0xcb, 0xd5, 0x18, 0xa5, 0xcd, 0x77, 0x16, 0xc5, 0x1c,
-	0x7b, 0x85, 0x35, 0x18, 0x59, 0x50, 0x0e, 0x68, 0x48, 0x83, 0x13, 0x35, 0x13, 0x72, 0xc8, 0x6f,
-	0x55, 0x9e, 0x51, 0x31, 0xb7, 0xa1, 0xd0, 0xf1, 0x08, 0x3f, 0x64, 0xc1, 0x10, 0x99, 0x50, 0x26,
-	0x81, 0x7d, 0xe4, 0x72, 0x6a, 0xf3, 0x71, 0x10, 0xad, 0xca, 0x8c, 0x0c, 0xdd, 0x82, 0x34, 0x53,
-	0x03, 0x15, 0xb7, 0xf2, 0x97, 0x17, 0x1b, 0xe9, 0xbd, 0x2e, 0x4e, 0xb3, 0xd0, 0x7c, 0x08, 0xd7,
-	0x3b, 0xde, 0x78, 0xe0, 0xfa, 0x0d, 0x1a, 0xda, 0x81, 0x3b, 0x12, 0xd6, 0xc5, 0xf2, 0x8a, 0xe4,
-	0x8b, 0x96, 0x57, 0x7c, 0xc7, 0x4b, 0x9e, 0x9e, 0x2e, 0xb9, 0xf9, 0xe7, 0x69, 0xb8, 0xde, 0xf4,
-	0x07, 0xae, 0x4f, 0x93, 0xda, 0xf7, 0x60, 0x95, 0x4a, 0x61, 0xff, 0x44, 0x25, 0x95, 0xb6, 0xb3,
-	0xa2, 0xa4, 0x51, 0xa6, 0xb5, 0xe6, 0xf2, 0xe5, 0x93, 0x45, 0xe1, 0xbf, 0x62, 0x7d, 0x51, 0xd6,
-	0xa0, 0x26, 0x2c, 0x8f, 0x64, 0x10, 0xe1, 0x5a, 0x46, 0xda, 0xba, 0xb7, 0xc8, 0xd6, 0x2b, 0x71,
-	0x6e, 0x65, 0xbf, 0xbe, 0xd8, 0x58, 0xc2, 0x91, 0xee, 0xaf, 0x93, 0x7c, 0xff, 0x99, 0x82, 0x6b,
-	0x6d, 0xe6, 0xcc, 0xcc, 0x43, 0x05, 0x0a, 0x47, 0x2c, 0xe4, 0x89, 0x8d, 0x12, 0xb7, 0xd1, 0x03,
-	0x28, 0x8c, 0xf4, 0xf2, 0xe9, 0xd5, 0xbf, 0xb3, 0xd8, 0x65, 0x85, 0xc1, 0x31, 0x1a, 0x3d, 0x84,
-	0x62, 0x10, 0xe5, 0xc4, 0x5a, 0xe6, 0x4d, 0x12, 0x67, 0x8a, 0x47, 0xbf, 0x07, 0x79, 0xb5, 0x08,
-	0x6b, 0x59, 0xa9, 0x79, 0xef, 0x8d, 0xe6, 0x1c, 0x6b, 0x25, 0xf3, 0x17, 0x29, 0x30, 0x30, 0x39,
-	0xe4, 0xbb, 0x74, 0x78, 0x40, 0x83, 0x2e, 0x27, 0x7c, 0x1c, 0xa2, 0x5b, 0x90, 0xf7, 0x28, 0x71,
-	0x68, 0x20, 0x83, 0x2c, 0x60, 0xdd, 0x42, 0x3d, 0x91, 0xe4, 0xc4, 0x3e, 0x22, 0x07, 0xae, 0xe7,
-	0xf2, 0x89, 0x0c, 0x73, 0x75, 0xf1, 0x2a, 0xcf, 0xdb, 0xac, 0xe1, 0x84, 0x22, 0x9e, 0x31, 0x83,
-	0xd6, 0x60, 0x79, 0x48, 0xc3, 0x90, 0x0c, 0xa8, 0x8c, 0xbe, 0x88, 0xa3, 0xa6, 0xf9, 0x10, 0xca,
-	0x49, 0x3d, 0x54, 0x82, 0xe5, 0x5e, 0xfb, 0x49, 0x7b, 0xef, 0x59, 0xdb, 0x58, 0x42, 0xd7, 0xa0,
-	0xd4, 0x6b, 0xe3, 0xa6, 0x55, 0x7f, 0x6c, 0x6d, 0xed, 0x34, 0x8d, 0x14, 0x5a, 0x81, 0xe2, 0xb4,
-	0x99, 0x36, 0x7f, 0x96, 0x02, 0x10, 0x0b, 0xa8, 0x83, 0xfa, 0x0c, 0x72, 0x21, 0x27, 0x5c, 0x2d,
-	0xdc, 0xea, 0xe6, 0x7b, 0x8b, 0xbc, 0x9e, 0xc2, 0x6b, 0xe2, 0x87, 0x62, 0xa5, 0x92, 0xf4, 0x30,
-	0x3d, 0xef, 0x61, 0x4e, 0x22, 0x67, 0x5d, 0x2b, 0x40, 0xb6, 0x21, 0xbe, 0x52, 0xa8, 0x08, 0x39,
-	0xdc, 0xb4, 0x1a, 0x5f, 0x1a, 0x69, 0x64, 0x40, 0xb9, 0xd1, 0xea, 0xd6, 0xf7, 0xda, 0xed, 0x66,
-	0x7d, 0xbf, 0xd9, 0x30, 0x32, 0xe6, 0x3d, 0xc8, 0xb5, 0x86, 0x64, 0x40, 0xd1, 0x1d, 0x91, 0x01,
-	0x87, 0x34, 0xa0, 0xbe, 0x1d, 0x25, 0xd6, 0x54, 0x60, 0xfe, 0xbc, 0x08, 0xb9, 0x5d, 0x36, 0xf6,
-	0x39, 0xda, 0x4c, 0xec, 0xe2, 0xd5, 0xcd, 0xf5, 0x45, 0x21, 0x48, 0x60, 0x6d, 0x7f, 0x32, 0xa2,
-	0x7a, 0x97, 0xdf, 0x82, 0xbc, 0xca, 0x15, 0xed, 0xba, 0x6e, 0x09, 0x39, 0x27, 0xc1, 0x80, 0x72,
-	0x3d, 0xe9, 0xba, 0x85, 0xee, 0x43, 0x21, 0xa0, 0xc4, 0x61, 0xbe, 0x37, 0x91, 0x29, 0x55, 0x50,
-	0x65, 0x16, 0x53, 0xe2, 0xec, 0xf9, 0xde, 0x04, 0xc7, 0xbd, 0xe8, 0x31, 0x94, 0x0f, 0x5c, 0xdf,
-	0xe9, 0xb3, 0x91, 0xaa, 0x79, 0xb9, 0xd7, 0x27, 0xa0, 0xf2, 0x6a, 0xcb, 0xf5, 0x9d, 0x3d, 0x05,
-	0xc6, 0xa5, 0x83, 0x69, 0x03, 0xb5, 0x61, 0xf5, 0x84, 0x79, 0xe3, 0x21, 0x8d, 0x6d, 0xe5, 0xa5,
-	0xad, 0xf7, 0x5f, 0x6f, 0xeb, 0xa9, 0xc4, 0x47, 0xd6, 0x56, 0x4e, 0x92, 0x4d, 0xf4, 0x04, 0x56,
-	0xf8, 0x70, 0x74, 0x18, 0xc6, 0xe6, 0x96, 0xa5, 0xb9, 0xef, 0x5f, 0x31, 0x61, 0x02, 0x1e, 0x59,
-	0x2b, 0xf3, 0x44, 0xab, 0xf2, 0x67, 0x19, 0x28, 0x25, 0x3c, 0x47, 0x5d, 0x28, 0x8d, 0x02, 0x36,
-	0x22, 0x03, 0x59, 0xb7, 0xf5, 0x5a, 0x7c, 0xf2, 0x46, 0x51, 0xd7, 0x3a, 0x53, 0x45, 0x9c, 0xb4,
-	0x62, 0x9e, 0xa7, 0xa1, 0x94, 0xe8, 0x44, 0x1f, 0x40, 0x01, 0x77, 0x70, 0xeb, 0xa9, 0xb5, 0xdf,
-	0x34, 0x96, 0x2a, 0x77, 0xce, 0xce, 0xab, 0x6b, 0xd2, 0x5a, 0xd2, 0x40, 0x27, 0x70, 0x4f, 0x44,
-	0xea, 0xdd, 0x87, 0xe5, 0x08, 0x9a, 0xaa, 0xbc, 0x7d, 0x76, 0x5e, 0x7d, 0x6b, 0x1e, 0x9a, 0x40,
-	0xe2, 0xee, 0x63, 0x0b, 0x37, 0x1b, 0x46, 0x7a, 0x31, 0x12, 0x77, 0x8f, 0x48, 0x40, 0x1d, 0xf4,
-	0x7d, 0xc8, 0x6b, 0x60, 0xa6, 0x52, 0x39, 0x3b, 0xaf, 0xde, 0x9a, 0x07, 0x4e, 0x71, 0xb8, 0xbb,
-	0x63, 0x3d, 0x6d, 0x1a, 0xd9, 0xc5, 0x38, 0xdc, 0xf5, 0xc8, 0x09, 0x45, 0xef, 0x41, 0x4e, 0xc1,
-	0x72, 0x95, 0xdb, 0x67, 0xe7, 0xd5, 0xef, 0xbd, 0x62, 0x4e, 0xa0, 0x2a, 0x6b, 0x7f, 0xf1, 0x37,
-	0xeb, 0x4b, 0xff, 0xf4, 0xb7, 0xeb, 0xc6, 0x7c, 0x77, 0xe5, 0x7f, 0x53, 0xb0, 0x32, 0xb3, 0xe4,
-	0xc8, 0x84, 0xbc, 0xcf, 0x6c, 0x36, 0x52, 0xe5, 0xbc, 0xb0, 0x05, 0x97, 0x17, 0x1b, 0xf9, 0x36,
-	0xab, 0xb3, 0xd1, 0x04, 0xeb, 0x1e, 0xf4, 0x64, 0xee, 0x40, 0xfa, 0xf4, 0x0d, 0xf3, 0x69, 0xe1,
-	0x91, 0xf4, 0x39, 0xac, 0x38, 0x81, 0x7b, 0x42, 0x83, 0xbe, 0xcd, 0xfc, 0x43, 0x77, 0xa0, 0x4b,
-	0x75, 0x65, 0x91, 0xcd, 0x86, 0x04, 0xe2, 0xb2, 0x52, 0xa8, 0x4b, 0xfc, 0xaf, 0x71, 0x18, 0x55,
-	0x9e, 0x42, 0x39, 0x99, 0xa1, 0xe8, 0x1d, 0x80, 0xd0, 0xfd, 0x23, 0xaa, 0xf9, 0x8d, 0x64, 0x43,
-	0xb8, 0x28, 0x24, 0x92, 0xdd, 0xa0, 0xf7, 0x21, 0x3b, 0x64, 0x8e, 0xb2, 0x93, 0xdb, 0xba, 0x21,
-	0xce, 0xc4, 0x7f, 0xbb, 0xd8, 0x28, 0xb1, 0xb0, 0xb6, 0xed, 0x7a, 0x74, 0x97, 0x39, 0x14, 0x4b,
-	0x80, 0x79, 0x02, 0x59, 0x51, 0x2a, 0xd0, 0xdb, 0x90, 0xdd, 0x6a, 0xb5, 0x1b, 0xc6, 0x52, 0xe5,
-	0xfa, 0xd9, 0x79, 0x75, 0x45, 0x4e, 0x89, 0xe8, 0x10, 0xb9, 0x8b, 0x36, 0x20, 0xff, 0x74, 0x6f,
-	0xa7, 0xb7, 0x2b, 0xd2, 0xeb, 0xc6, 0xd9, 0x79, 0xf5, 0x5a, 0xdc, 0xad, 0x26, 0x0d, 0xbd, 0x03,
-	0xb9, 0xfd, 0xdd, 0xce, 0x76, 0xd7, 0x48, 0x57, 0xd0, 0xd9, 0x79, 0x75, 0x35, 0xee, 0x97, 0x3e,
-	0x57, 0xae, 0xeb, 0x55, 0x2d, 0xc6, 0x72, 0xf3, 0x7f, 0xd2, 0xb0, 0x82, 0x05, 0xbf, 0x0d, 0x78,
-	0x87, 0x79, 0xae, 0x3d, 0x41, 0x1d, 0x28, 0xda, 0xcc, 0x77, 0xdc, 0xc4, 0x9e, 0xda, 0x7c, 0xcd,
-	0x21, 0x38, 0xd5, 0x8a, 0x5a, 0xf5, 0x48, 0x13, 0x4f, 0x8d, 0xa0, 0x4d, 0xc8, 0x39, 0xd4, 0x23,
-	0x93, 0xab, 0x4e, 0xe3, 0x86, 0xe6, 0xd2, 0x58, 0x41, 0x25, 0x73, 0x24, 0xcf, 0xfb, 0x84, 0x73,
-	0x3a, 0x1c, 0x71, 0x75, 0x1a, 0x67, 0x71, 0x69, 0x48, 0x9e, 0x5b, 0x5a, 0x84, 0x7e, 0x04, 0xf9,
-	0x53, 0xd7, 0x77, 0xd8, 0xa9, 0x3e, 0x70, 0xaf, 0xb6, 0xab, 0xb1, 0xe6, 0x99, 0x38, 0x67, 0xe7,
-	0x9c, 0x15, 0xb3, 0xde, 0xde, 0x6b, 0x37, 0xa3, 0x59, 0xd7, 0xfd, 0x7b, 0x7e, 0x9b, 0xf9, 0x62,
-	0xc7, 0xc0, 0x5e, 0xbb, 0xbf, 0x6d, 0xb5, 0x76, 0x7a, 0x58, 0xcc, 0xfc, 0xcd, 0xb3, 0xf3, 0xaa,
-	0x11, 0x43, 0xb6, 0x89, 0xeb, 0x09, 0x12, 0x78, 0x1b, 0x32, 0x56, 0xfb, 0x4b, 0x23, 0x5d, 0x31,
-	0xce, 0xce, 0xab, 0xe5, 0xb8, 0xdb, 0xf2, 0x27, 0xd3, 0xcd, 0x34, 0x3f, 0xae, 0xf9, 0x5f, 0x29,
-	0x28, 0xf7, 0x46, 0x0e, 0xe1, 0x54, 0x65, 0x26, 0xaa, 0x42, 0x69, 0x44, 0x02, 0xe2, 0x79, 0xd4,
-	0x73, 0xc3, 0xa1, 0xbe, 0x28, 0x24, 0x45, 0xe8, 0xc1, 0x77, 0x98, 0x4c, 0x4d, 0xc2, 0xf4, 0x94,
-	0xf6, 0x60, 0xf5, 0x50, 0x39, 0xdb, 0x27, 0xb6, 0x5c, 0xdd, 0x8c, 0x5c, 0xdd, 0xda, 0x22, 0x13,
-	0x49, 0xaf, 0x6a, 0x3a, 0x46, 0x4b, 0x6a, 0xe1, 0x95, 0xc3, 0x64, 0xd3, 0xbc, 0x0f, 0x2b, 0x33,
-	0xfd, 0xe2, 0xa4, 0xed, 0x58, 0xbd, 0x6e, 0xd3, 0x58, 0x42, 0x65, 0x28, 0xd4, 0xf7, 0xda, 0xfb,
-	0xad, 0x76, 0xaf, 0x69, 0xa4, 0xcc, 0x7f, 0x48, 0x47, 0xd1, 0x6a, 0x26, 0xb0, 0x35, 0xcb, 0x04,
-	0x3e, 0x7c, 0xbd, 0x23, 0x9a, 0x0b, 0x4c, 0x1b, 0x31, 0x23, 0xf8, 0x5d, 0x00, 0x39, 0xa9, 0xd4,
-	0xe9, 0x13, 0x7e, 0x15, 0xdb, 0xdf, 0x8f, 0xee, 0x71, 0xb8, 0xa8, 0x15, 0x2c, 0x8e, 0xbe, 0x80,
-	0xb2, 0xcd, 0x86, 0x23, 0x8f, 0x6a, 0xfd, 0xcc, 0x9b, 0xe8, 0x97, 0x62, 0x15, 0x8b, 0x27, 0x19,
-	0x49, 0x76, 0x96, 0x91, 0xd4, 0xa1, 0x94, 0xf0, 0x77, 0x96, 0x97, 0x94, 0xa1, 0xd0, 0xeb, 0x34,
-	0xac, 0xfd, 0x56, 0xfb, 0x91, 0x91, 0x42, 0x00, 0x79, 0x39, 0x63, 0x0d, 0x23, 0x2d, 0xb8, 0x53,
-	0x7d, 0x6f, 0xb7, 0xb3, 0xd3, 0x54, 0xcc, 0xe4, 0x4f, 0xe0, 0x5a, 0x9d, 0xf9, 0x9c, 0xb8, 0x7e,
-	0x4c, 0x0a, 0x37, 0x85, 0xcf, 0x5a, 0xd4, 0x77, 0x1d, 0x55, 0xb7, 0xb6, 0xae, 0x5d, 0x5e, 0x6c,
-	0x94, 0x62, 0x68, 0xab, 0x21, 0xbc, 0x8c, 0x1a, 0x8e, 0xc8, 0xce, 0x91, 0xeb, 0xe8, 0x32, 0xb4,
-	0x7c, 0x79, 0xb1, 0x91, 0xe9, 0xb4, 0x1a, 0x58, 0xc8, 0xd0, 0xdb, 0x50, 0xa4, 0xcf, 0x5d, 0xde,
-	0xb7, 0x45, 0x9d, 0x12, 0xf1, 0xe7, 0x70, 0x41, 0x08, 0xea, 0xa2, 0x2c, 0xfd, 0x69, 0x1a, 0x60,
-	0x9f, 0x84, 0xc7, 0x7a, 0xe8, 0x87, 0x50, 0x8c, 0xaf, 0xc3, 0x57, 0x5d, 0xcb, 0x12, 0x73, 0x1d,
-	0xe3, 0xd1, 0xa7, 0xd1, 0x6a, 0x2b, 0xb6, 0xba, 0x58, 0x51, 0x8f, 0xb5, 0x88, 0xf0, 0xcd, 0x52,
-	0x52, 0x51, 0xb5, 0x69, 0x10, 0xe8, 0x49, 0x17, 0x9f, 0xa8, 0x2e, 0x2b, 0x97, 0x8a, 0x59, 0x73,
-	0xa0, 0xbb, 0x8b, 0x06, 0x99, 0x9b, 0xd0, 0xc7, 0x4b, 0x78, 0xaa, 0xb7, 0x65, 0xc0, 0x6a, 0x30,
-	0xf6, 0x85, 0xd7, 0xfd, 0x50, 0x76, 0x9b, 0xff, 0x92, 0x06, 0x68, 0x75, 0xac, 0x5d, 0xbd, 0x45,
-	0x1b, 0x90, 0x3f, 0x24, 0x43, 0xd7, 0x9b, 0x5c, 0x95, 0xb5, 0x53, 0x7c, 0xcd, 0x72, 0x9c, 0x80,
-	0x86, 0xe1, 0xb6, 0xd4, 0xc1, 0x5a, 0x57, 0x92, 0xc1, 0xf1, 0x81, 0x4f, 0x79, 0x4c, 0x06, 0x65,
-	0x4b, 0x9c, 0x3c, 0x01, 0xf1, 0xe3, 0x68, 0x55, 0x43, 0xcc, 0xc2, 0x80, 0x70, 0x7a, 0x4a, 0x26,
-	0x51, 0x92, 0xe9, 0x26, 0x7a, 0x2c, 0x48, 0xa2, 0xb8, 0xbb, 0x52, 0x67, 0x2d, 0x27, 0x8f, 0xd6,
-	0x6f, 0xf3, 0x07, 0x6b, 0xb8, 0x3a, 0x53, 0x63, 0xed, 0xca, 0x43, 0x79, 0x10, 0x4c, 0xbb, 0xbe,
-	0xd3, 0x1d, 0xed, 0x63, 0x58, 0x99, 0x89, 0xf3, 0x15, 0x16, 0xde, 0xea, 0x3c, 0xfd, 0x91, 0x91,
-	0xd5, 0x5f, 0xbf, 0x63, 0xe4, 0xcd, 0xff, 0x4e, 0x01, 0x74, 0x98, 0x2c, 0x86, 0x62, 0x56, 0x17,
-	0xbf, 0x7a, 0x14, 0xe4, 0x1b, 0x8a, 0xcd, 0x3c, 0x9d, 0x33, 0x0b, 0x69, 0xe8, 0xd4, 0x8a, 0x60,
-	0x75, 0x12, 0x8e, 0x63, 0x45, 0xb4, 0x01, 0x25, 0xc5, 0xa7, 0xfb, 0x23, 0x16, 0xa8, 0x0d, 0xbe,
-	0x82, 0x41, 0x89, 0x84, 0xa6, 0xb8, 0x52, 0x8f, 0xc6, 0x07, 0x9e, 0x1b, 0x1e, 0x51, 0x47, 0x61,
-	0xb2, 0x12, 0xb3, 0x12, 0x4b, 0x05, 0xcc, 0x6c, 0x40, 0x21, 0xb2, 0x8e, 0xd6, 0x20, 0xb3, 0x5f,
-	0xef, 0x18, 0x4b, 0x95, 0x6b, 0x67, 0xe7, 0xd5, 0x52, 0x24, 0xde, 0xaf, 0x77, 0x44, 0x4f, 0xaf,
-	0xd1, 0x31, 0x52, 0xb3, 0x3d, 0xbd, 0x46, 0xa7, 0x92, 0x15, 0x87, 0x80, 0xf9, 0x57, 0x29, 0xc8,
-	0x2b, 0x4a, 0xb2, 0x30, 0x62, 0x0b, 0x96, 0x23, 0xa2, 0xac, 0x78, 0xd2, 0xfb, 0xaf, 0xe7, 0x34,
-	0x35, 0x4d, 0x41, 0xd4, 0x3a, 0x46, 0x7a, 0x95, 0xcf, 0xa0, 0x9c, 0xec, 0xf8, 0x4e, 0xab, 0xf8,
-	0xc7, 0x50, 0x12, 0x89, 0x12, 0x71, 0x9b, 0x4d, 0xc8, 0x2b, 0xda, 0xa4, 0xb7, 0xfa, 0x55, 0x04,
-	0x4b, 0x23, 0xd1, 0x03, 0x58, 0x56, 0xa4, 0x2c, 0x7a, 0x2e, 0x58, 0xbf, 0x3a, 0x1d, 0x71, 0x04,
-	0x37, 0x3f, 0x87, 0x6c, 0x87, 0xd2, 0x00, 0xdd, 0x85, 0x65, 0x9f, 0x39, 0x74, 0x5a, 0xd9, 0x34,
-	0x9f, 0x74, 0x68, 0xab, 0x21, 0xf8, 0xa4, 0x43, 0x5b, 0x8e, 0x98, 0x3c, 0xe2, 0x38, 0x41, 0xf4,
-	0x62, 0x22, 0xbe, 0xcd, 0x7d, 0x28, 0x3f, 0xa3, 0xee, 0xe0, 0x88, 0x53, 0x47, 0x1a, 0xfa, 0x10,
-	0xb2, 0x23, 0x1a, 0x3b, 0xbf, 0xb6, 0x30, 0x75, 0x28, 0x0d, 0xb0, 0x44, 0x89, 0x0d, 0x79, 0x2a,
-	0xb5, 0xf5, 0x23, 0x95, 0x6e, 0x99, 0x7f, 0x9f, 0x86, 0xd5, 0x56, 0x18, 0x8e, 0x89, 0x6f, 0x47,
-	0xc7, 0xd6, 0x4f, 0x66, 0x8f, 0xad, 0xfb, 0x0b, 0x23, 0x9c, 0x51, 0x99, 0xbd, 0xc4, 0xea, 0xca,
-	0x95, 0x8e, 0x2b, 0x97, 0xf9, 0x75, 0x2a, 0xba, 0xbd, 0xde, 0x4b, 0xec, 0x9b, 0xca, 0xda, 0xd9,
-	0x79, 0xf5, 0x66, 0xd2, 0x12, 0xed, 0xf9, 0xc7, 0x3e, 0x3b, 0xf5, 0xd1, 0xbb, 0xe2, 0x36, 0xdb,
-	0x6e, 0x3e, 0x33, 0x52, 0x95, 0x5b, 0x67, 0xe7, 0x55, 0x34, 0x03, 0xc2, 0xd4, 0xa7, 0xa7, 0xc2,
-	0x52, 0xa7, 0xd9, 0x6e, 0x88, 0x13, 0x26, 0xbd, 0xc0, 0x52, 0x87, 0xfa, 0x8e, 0xeb, 0x0f, 0xd0,
-	0x5d, 0xc8, 0xb7, 0xba, 0xdd, 0x9e, 0xbc, 0x5f, 0xbc, 0x75, 0x76, 0x5e, 0xbd, 0x31, 0x83, 0x12,
-	0x0d, 0xea, 0x08, 0x90, 0xe0, 0x3f, 0xcd, 0x86, 0x91, 0x5d, 0x00, 0x12, 0xc7, 0x3f, 0x75, 0x74,
-	0x86, 0xff, 0x7b, 0x1a, 0x0c, 0xcb, 0xb6, 0xe9, 0x88, 0x8b, 0x7e, 0xcd, 0x29, 0xf7, 0xa1, 0x30,
-	0x12, 0x5f, 0xae, 0xe4, 0xc8, 0x22, 0x2d, 0x1e, 0x2c, 0x7c, 0xc1, 0x9c, 0xd3, 0xab, 0x61, 0xe6,
-	0x51, 0xcb, 0x19, 0xba, 0x61, 0x28, 0xee, 0x4e, 0x52, 0x86, 0x63, 0x4b, 0x95, 0x5f, 0xa6, 0xe0,
-	0xc6, 0x02, 0x04, 0xfa, 0x18, 0xb2, 0x01, 0xf3, 0xa2, 0xe5, 0xb9, 0xf3, 0xba, 0xf7, 0x05, 0xa1,
-	0x8a, 0x25, 0x12, 0xad, 0x03, 0x90, 0x31, 0x67, 0x44, 0x8e, 0x2f, 0x17, 0xa6, 0x80, 0x13, 0x12,
-	0xf4, 0x0c, 0xf2, 0x21, 0xb5, 0x03, 0x1a, 0x11, 0x84, 0xcf, 0xff, 0xbf, 0xde, 0xd7, 0xba, 0xd2,
-	0x0c, 0xd6, 0xe6, 0x2a, 0x35, 0xc8, 0x2b, 0x89, 0xc8, 0x68, 0x87, 0x70, 0x22, 0x9d, 0x2e, 0x63,
-	0xf9, 0x2d, 0x12, 0x85, 0x78, 0x83, 0x28, 0x51, 0x88, 0x37, 0x30, 0x7f, 0x96, 0x06, 0x68, 0x3e,
-	0xe7, 0x34, 0xf0, 0x89, 0x57, 0xb7, 0x50, 0x33, 0x51, 0x21, 0x55, 0xb4, 0x3f, 0x58, 0xf8, 0xea,
-	0x14, 0x6b, 0xd4, 0xea, 0xd6, 0x82, 0x1a, 0x79, 0x1b, 0x32, 0xe3, 0xc0, 0xd3, 0x2f, 0x98, 0x92,
-	0x1d, 0xf4, 0xf0, 0x0e, 0x16, 0x32, 0xd4, 0x9c, 0x56, 0xa4, 0xcc, 0xeb, 0x9f, 0x9e, 0x13, 0x03,
-	0xfc, 0xe6, 0xab, 0xd2, 0x87, 0x00, 0x53, 0xaf, 0xd1, 0x3a, 0xe4, 0xea, 0xdb, 0xdd, 0xee, 0x8e,
-	0xb1, 0xa4, 0xae, 0x40, 0xd3, 0x2e, 0x29, 0x36, 0xff, 0x2e, 0x05, 0x85, 0xba, 0xa5, 0x4f, 0x95,
-	0x6d, 0x30, 0x64, 0x2d, 0xb1, 0x69, 0xc0, 0xfb, 0xf4, 0xf9, 0xc8, 0x0d, 0x26, 0xba, 0x1c, 0x5c,
-	0x7d, 0x59, 0x58, 0x15, 0x5a, 0x75, 0x1a, 0xf0, 0xa6, 0xd4, 0x41, 0x18, 0xca, 0x54, 0x87, 0xd8,
-	0xb7, 0x49, 0x54, 0x9c, 0xd7, 0xaf, 0x9e, 0x0a, 0x45, 0xc9, 0xa6, 0xed, 0x10, 0x97, 0x22, 0x23,
-	0x75, 0x12, 0x9a, 0x4f, 0xe1, 0xc6, 0x5e, 0x60, 0x1f, 0xd1, 0x90, 0xab, 0x41, 0xb5, 0xcb, 0x9f,
-	0xc3, 0x1d, 0x4e, 0xc2, 0xe3, 0xfe, 0x91, 0x1b, 0x72, 0x16, 0x4c, 0xfa, 0x01, 0xe5, 0xd4, 0x17,
-	0xfd, 0x7d, 0xf9, 0xc0, 0xad, 0xaf, 0x98, 0xb7, 0x05, 0xe6, 0xb1, 0x82, 0xe0, 0x08, 0xb1, 0x23,
-	0x00, 0x66, 0x0b, 0xca, 0x82, 0x45, 0x35, 0xe8, 0x21, 0x19, 0x7b, 0x3c, 0x44, 0x3f, 0x06, 0xf0,
-	0xd8, 0xa0, 0xff, 0xc6, 0x95, 0xbc, 0xe8, 0xb1, 0x81, 0xfa, 0x34, 0x7f, 0x1f, 0x8c, 0x86, 0x1b,
-	0x8e, 0x08, 0xb7, 0x8f, 0xa2, 0xbb, 0x33, 0x7a, 0x04, 0xc6, 0x11, 0x25, 0x01, 0x3f, 0xa0, 0x84,
-	0xf7, 0x47, 0x34, 0x70, 0x99, 0xf3, 0x46, 0x53, 0x7a, 0x2d, 0xd6, 0xea, 0x48, 0x25, 0xf3, 0x57,
-	0x29, 0x00, 0x4c, 0x0e, 0x23, 0x02, 0xf0, 0x43, 0xb8, 0x1e, 0xfa, 0x64, 0x14, 0x1e, 0x31, 0xde,
-	0x77, 0x7d, 0x4e, 0x83, 0x13, 0xe2, 0xe9, 0xfb, 0x8f, 0x11, 0x75, 0xb4, 0xb4, 0x1c, 0x7d, 0x08,
-	0xe8, 0x98, 0xd2, 0x51, 0x9f, 0x79, 0x4e, 0x3f, 0xea, 0x54, 0x2f, 0xf0, 0x59, 0x6c, 0x88, 0x9e,
-	0x3d, 0xcf, 0xe9, 0x46, 0x72, 0xb4, 0x05, 0xeb, 0x62, 0x06, 0xa8, 0xcf, 0x03, 0x97, 0x86, 0xfd,
-	0x43, 0x16, 0xf4, 0x43, 0x8f, 0x9d, 0xf6, 0x0f, 0x99, 0xe7, 0xb1, 0x53, 0x1a, 0x44, 0xb7, 0xcb,
-	0x8a, 0xc7, 0x06, 0x4d, 0x05, 0xda, 0x66, 0x41, 0xd7, 0x63, 0xa7, 0xdb, 0x11, 0x42, 0xb0, 0x84,
-	0x69, 0xd8, 0xdc, 0xb5, 0x8f, 0x23, 0x96, 0x10, 0x4b, 0xf7, 0x5d, 0xfb, 0x18, 0xdd, 0x85, 0x15,
-	0xea, 0x51, 0x79, 0x0f, 0x52, 0xa8, 0x9c, 0x44, 0x95, 0x23, 0xa1, 0x00, 0x99, 0xbf, 0x05, 0xc5,
-	0x8e, 0x47, 0x6c, 0xf9, 0x3f, 0x87, 0xb8, 0xf1, 0xd9, 0xcc, 0x17, 0x49, 0xe0, 0xfa, 0x5c, 0x55,
-	0xc7, 0x22, 0x4e, 0x8a, 0xcc, 0x9f, 0x00, 0xfc, 0x94, 0xb9, 0xfe, 0x3e, 0x3b, 0xa6, 0xbe, 0x7c,
-	0x12, 0x3e, 0x65, 0xc1, 0xb1, 0x5e, 0xca, 0x22, 0xd6, 0x2d, 0x49, 0x94, 0x89, 0x4f, 0x06, 0x34,
-	0x88, 0x5f, 0x46, 0x55, 0x53, 0x1c, 0x2e, 0x79, 0xcc, 0x18, 0xaf, 0x5b, 0xa8, 0x0a, 0x79, 0x9b,
-	0xf4, 0xa3, 0x9d, 0x57, 0xde, 0x2a, 0x5e, 0x5e, 0x6c, 0xe4, 0xea, 0xd6, 0x13, 0x3a, 0xc1, 0x39,
-	0x9b, 0x3c, 0xa1, 0x13, 0x71, 0xfa, 0xda, 0x44, 0xee, 0x17, 0x69, 0xa6, 0xac, 0x4e, 0xdf, 0xba,
-	0x25, 0x36, 0x03, 0xce, 0xdb, 0x44, 0xfc, 0xa2, 0x8f, 0xa1, 0xac, 0x41, 0xfd, 0x23, 0x12, 0x1e,
-	0x29, 0xae, 0xba, 0xb5, 0x7a, 0x79, 0xb1, 0x01, 0x0a, 0xf9, 0x98, 0x84, 0x47, 0x18, 0x14, 0x5a,
-	0x7c, 0xa3, 0x26, 0x94, 0xbe, 0x62, 0xae, 0xdf, 0xe7, 0x32, 0x08, 0x7d, 0x61, 0x5f, 0xb8, 0x7f,
-	0xa6, 0xa1, 0xea, 0xdb, 0x2b, 0x7c, 0x15, 0x4b, 0xcc, 0x7f, 0x4d, 0x41, 0x49, 0xd8, 0x74, 0x0f,
-	0x5d, 0x5b, 0x9c, 0x96, 0xdf, 0xbd, 0xd2, 0xdf, 0x86, 0x8c, 0x1d, 0x06, 0x3a, 0x36, 0x59, 0xea,
-	0xea, 0x5d, 0x8c, 0x85, 0x0c, 0x7d, 0x01, 0x79, 0xc5, 0xf8, 0x75, 0x91, 0x37, 0xbf, 0xfd, 0x5c,
-	0xd7, 0x2e, 0x6a, 0x3d, 0xb9, 0x96, 0x53, 0xef, 0x64, 0x94, 0x65, 0x9c, 0x14, 0xa1, 0x5b, 0x90,
-	0xb6, 0x7d, 0x99, 0x14, 0xfa, 0xaf, 0xa2, 0x7a, 0x1b, 0xa7, 0x6d, 0xdf, 0xfc, 0xe7, 0x14, 0xac,
-	0x34, 0x7d, 0x3b, 0x98, 0xc8, 0x22, 0x29, 0x16, 0xe2, 0x0e, 0x14, 0xc3, 0xf1, 0x41, 0x38, 0x09,
-	0x39, 0x1d, 0x46, 0x2f, 0xd1, 0xb1, 0x00, 0xb5, 0xa0, 0x48, 0xbc, 0x01, 0x0b, 0x5c, 0x7e, 0x34,
-	0xd4, 0xdc, 0x78, 0x71, 0x61, 0x4e, 0xda, 0xac, 0x59, 0x91, 0x0a, 0x9e, 0x6a, 0x47, 0xa5, 0x38,
-	0x23, 0x9d, 0x95, 0xa5, 0xf8, 0x5d, 0x28, 0x7b, 0x64, 0x28, 0xa8, 0x70, 0x5f, 0xdc, 0x83, 0x64,
-	0x1c, 0x59, 0x5c, 0xd2, 0x32, 0x71, 0xb7, 0x33, 0x4d, 0x28, 0xc6, 0xc6, 0xd0, 0x35, 0x28, 0x59,
-	0xcd, 0x6e, 0xff, 0x93, 0xcd, 0x07, 0xfd, 0x47, 0xf5, 0x5d, 0x63, 0x49, 0x33, 0x81, 0x7f, 0x4c,
-	0xc1, 0xca, 0xae, 0xca, 0x41, 0x4d, 0x9c, 0xee, 0xc2, 0x72, 0x40, 0x0e, 0x79, 0x44, 0xed, 0xb2,
-	0x2a, 0xb9, 0x44, 0x11, 0x10, 0xd4, 0x4e, 0x74, 0x2d, 0xa6, 0x76, 0x89, 0xff, 0x41, 0x32, 0x57,
-	0xfe, 0x0f, 0x92, 0xfd, 0x8d, 0xfc, 0x0f, 0xf2, 0xc1, 0xaf, 0x32, 0x50, 0x8c, 0x6f, 0xa2, 0x22,
-	0x65, 0x04, 0xd3, 0x5a, 0x52, 0x2f, 0x3b, 0xb1, 0xbc, 0x2d, 0x39, 0x56, 0xd1, 0xda, 0xd9, 0xd9,
-	0xab, 0x5b, 0xe2, 0xb2, 0xfe, 0x85, 0xa2, 0x62, 0x31, 0xc0, 0xf2, 0x3c, 0x26, 0x16, 0xdd, 0x41,
-	0xe6, 0x94, 0x8a, 0xbd, 0xd0, 0xef, 0x47, 0x31, 0x2a, 0xe2, 0x61, 0xef, 0x41, 0xc1, 0xea, 0x76,
-	0x5b, 0x8f, 0xda, 0xcd, 0x86, 0xf1, 0x32, 0x55, 0xf9, 0xde, 0xd9, 0x79, 0xf5, 0xfa, 0xd4, 0x54,
-	0x18, 0xba, 0x03, 0x9f, 0x3a, 0x12, 0x55, 0xaf, 0x37, 0x3b, 0x62, 0xbc, 0x17, 0xe9, 0x79, 0x94,
-	0x24, 0x20, 0xf2, 0x2d, 0xb8, 0xd8, 0xc1, 0xcd, 0x8e, 0x85, 0xc5, 0x88, 0x2f, 0xd3, 0x73, 0x7e,
-	0x75, 0x02, 0x3a, 0x22, 0x81, 0x18, 0x73, 0x3d, 0xfa, 0x4f, 0xe4, 0x45, 0x46, 0xbd, 0x17, 0x4e,
-	0xaf, 0xdf, 0x94, 0x38, 0x13, 0x31, 0x5a, 0x77, 0xdf, 0xc2, 0xf2, 0x95, 0xe2, 0x65, 0x66, 0x6e,
-	0xb4, 0x2e, 0x27, 0x01, 0x17, 0x56, 0x4c, 0x58, 0xc6, 0xbd, 0x76, 0x5b, 0x46, 0x97, 0x9d, 0x8b,
-	0x0e, 0x8f, 0x7d, 0x5f, 0x60, 0xee, 0x41, 0x21, 0x7a, 0xd5, 0x30, 0x5e, 0x66, 0xe7, 0x1c, 0xaa,
-	0x47, 0xcf, 0x29, 0x72, 0xc0, 0xc7, 0xbd, 0x7d, 0xf9, 0x97, 0xcd, 0x8b, 0xdc, 0xfc, 0x80, 0x47,
-	0x63, 0xee, 0x08, 0xf2, 0x5b, 0x8d, 0xd9, 0xe8, 0xcb, 0x9c, 0x22, 0x01, 0x31, 0x46, 0x51, 0x51,
-	0x61, 0x07, 0x37, 0x7f, 0xaa, 0xfe, 0xdd, 0x79, 0x91, 0x9f, 0xb3, 0x83, 0xe9, 0x57, 0xd4, 0xe6,
-	0xd4, 0x99, 0x3e, 0x87, 0xc6, 0x5d, 0x1f, 0xfc, 0x01, 0x14, 0xa2, 0x82, 0x81, 0xd6, 0x21, 0xff,
-	0x6c, 0x0f, 0x3f, 0x69, 0x62, 0x63, 0x49, 0xcd, 0x4e, 0xd4, 0xf3, 0x4c, 0x55, 0xdc, 0x2a, 0x2c,
-	0xef, 0x5a, 0x6d, 0xeb, 0x51, 0x13, 0x47, 0xcf, 0xb1, 0x11, 0x40, 0x67, 0x7d, 0xc5, 0xd0, 0x03,
-	0xc4, 0x36, 0xb7, 0xee, 0x7c, 0xfd, 0xcd, 0xfa, 0xd2, 0x2f, 0xbe, 0x59, 0x5f, 0xfa, 0xe5, 0x37,
-	0xeb, 0xa9, 0x17, 0x97, 0xeb, 0xa9, 0xaf, 0x2f, 0xd7, 0x53, 0x3f, 0xbf, 0x5c, 0x4f, 0xfd, 0xc7,
-	0xe5, 0x7a, 0xea, 0x20, 0x2f, 0x19, 0xd9, 0xa7, 0xff, 0x17, 0x00, 0x00, 0xff, 0xff, 0x84, 0x8b,
-	0x50, 0xe8, 0x9f, 0x20, 0x00, 0x00,
+	0x39, 0xe6, 0xb2, 0x40, 0x0e, 0x7b, 0x48, 0x0e, 0x41, 0xfd, 0x74, 0xf3, 0xc7, 0xb4, 0xc6, 0x93,
+	0xdd, 0x13, 0xbb, 0x5e, 0x7d, 0xef, 0xd5, 0xab, 0xaa, 0x57, 0xaf, 0xbe, 0x57, 0x84, 0x02, 0x9f,
+	0x8c, 0x68, 0x58, 0x19, 0x05, 0x8c, 0x33, 0x84, 0x1c, 0x66, 0x1f, 0xd3, 0xa0, 0x12, 0x9e, 0x92,
+	0x60, 0x78, 0xec, 0xf2, 0xca, 0xc9, 0x27, 0xa5, 0xdb, 0xdc, 0x1d, 0xd2, 0x90, 0x93, 0xe1, 0xe8,
+	0xa3, 0xf8, 0x4b, 0xc1, 0x4b, 0x6f, 0x39, 0xe3, 0x80, 0x70, 0x97, 0xf9, 0x1f, 0x45, 0x1f, 0xba,
+	0xe3, 0x66, 0x9f, 0xf5, 0x99, 0xfc, 0xfc, 0x48, 0x7c, 0x29, 0xa9, 0xb9, 0x05, 0xab, 0x4f, 0x69,
+	0x10, 0xba, 0xcc, 0x47, 0x37, 0x21, 0xe3, 0xfa, 0x0e, 0x7d, 0xbe, 0x91, 0x28, 0x27, 0xee, 0xa7,
+	0xb1, 0x6a, 0x98, 0x7f, 0x9d, 0x80, 0x82, 0xe5, 0xfb, 0x8c, 0x4b, 0x5b, 0x21, 0x42, 0x90, 0xf6,
+	0xc9, 0x90, 0x4a, 0x50, 0x1e, 0xcb, 0x6f, 0x54, 0x85, 0xac, 0x47, 0x0e, 0xa9, 0x17, 0x6e, 0x24,
+	0xcb, 0xa9, 0xfb, 0x85, 0xed, 0x1f, 0x56, 0x5e, 0xf5, 0xb9, 0x32, 0x63, 0xa4, 0xb2, 0x27, 0xd1,
+	0x75, 0x9f, 0x07, 0x13, 0xac, 0x55, 0x4b, 0x3f, 0x86, 0xc2, 0x8c, 0x18, 0x19, 0x90, 0x3a, 0xa6,
+	0x13, 0x3d, 0x8c, 0xf8, 0x14, 0xfe, 0x9d, 0x10, 0x6f, 0x4c, 0x37, 0x92, 0x52, 0xa6, 0x1a, 0x9f,
+	0x25, 0x1f, 0x24, 0xcc, 0x2f, 0x21, 0x8f, 0x69, 0xc8, 0xc6, 0x81, 0x4d, 0x43, 0xf4, 0x03, 0xc8,
+	0xfb, 0xc4, 0x67, 0x3d, 0x7b, 0x34, 0x0e, 0xa5, 0x7a, 0x6a, 0xa7, 0x78, 0x79, 0xb1, 0x95, 0x6b,
+	0x12, 0x9f, 0x55, 0x5b, 0xdd, 0x10, 0xe7, 0x44, 0x77, 0x75, 0x34, 0x0e, 0xd1, 0xbb, 0x50, 0x1c,
+	0xd2, 0x21, 0x0b, 0x26, 0xbd, 0xc3, 0x09, 0xa7, 0xa1, 0x34, 0x9c, 0xc2, 0x05, 0x25, 0xdb, 0x11,
+	0x22, 0xf3, 0x2f, 0x13, 0x70, 0x33, 0xb2, 0x8d, 0xe9, 0x1f, 0x8e, 0xdd, 0x80, 0x0e, 0xa9, 0xcf,
+	0x43, 0xf4, 0xdb, 0x90, 0xf5, 0xdc, 0xa1, 0xcb, 0xd5, 0x18, 0x85, 0xed, 0x77, 0x96, 0xcd, 0x39,
+	0xf6, 0x0a, 0x6b, 0x30, 0xb2, 0xa0, 0x18, 0xd0, 0x90, 0x06, 0x27, 0x6a, 0x25, 0xe4, 0x90, 0xdf,
+	0xaa, 0x3c, 0xa7, 0x62, 0xee, 0x42, 0xae, 0xe5, 0x11, 0x7e, 0xc4, 0x82, 0x21, 0x32, 0xa1, 0x48,
+	0x02, 0x7b, 0xe0, 0x72, 0x6a, 0xf3, 0x71, 0x10, 0xed, 0xca, 0x9c, 0x0c, 0xdd, 0x82, 0x24, 0x53,
+	0x03, 0xe5, 0x77, 0xb2, 0x97, 0x17, 0x5b, 0xc9, 0x83, 0x36, 0x4e, 0xb2, 0xd0, 0x7c, 0x08, 0xd7,
+	0x5b, 0xde, 0xb8, 0xef, 0xfa, 0x35, 0x1a, 0xda, 0x81, 0x3b, 0x12, 0xd6, 0xc5, 0xf6, 0x8a, 0xe0,
+	0x8b, 0xb6, 0x57, 0x7c, 0xc7, 0x5b, 0x9e, 0x9c, 0x6e, 0xb9, 0xf9, 0xe7, 0x49, 0xb8, 0x5e, 0xf7,
+	0xfb, 0xae, 0x4f, 0x67, 0xb5, 0xef, 0xc1, 0x3a, 0x95, 0xc2, 0xde, 0x89, 0x0a, 0x2a, 0x6d, 0x67,
+	0x4d, 0x49, 0xa3, 0x48, 0x6b, 0x2c, 0xc4, 0xcb, 0x27, 0xcb, 0xa6, 0xff, 0x8a, 0xf5, 0x65, 0x51,
+	0x83, 0xea, 0xb0, 0x3a, 0x92, 0x93, 0x08, 0x37, 0x52, 0xd2, 0xd6, 0xbd, 0x65, 0xb6, 0x5e, 0x99,
+	0xe7, 0x4e, 0xfa, 0xeb, 0x8b, 0xad, 0x15, 0x1c, 0xe9, 0xfe, 0x3a, 0xc1, 0xf7, 0x9f, 0x09, 0xb8,
+	0xd6, 0x64, 0xce, 0xdc, 0x3a, 0x94, 0x20, 0x37, 0x60, 0x21, 0x9f, 0x39, 0x28, 0x71, 0x1b, 0x3d,
+	0x80, 0xdc, 0x48, 0x6f, 0x9f, 0xde, 0xfd, 0x3b, 0xcb, 0x5d, 0x56, 0x18, 0x1c, 0xa3, 0xd1, 0x43,
+	0xc8, 0x07, 0x51, 0x4c, 0x6c, 0xa4, 0xde, 0x24, 0x70, 0xa6, 0x78, 0xf4, 0x7b, 0x90, 0x55, 0x9b,
+	0xb0, 0x91, 0x96, 0x9a, 0xf7, 0xde, 0x68, 0xcd, 0xb1, 0x56, 0x32, 0x7f, 0x91, 0x00, 0x03, 0x93,
+	0x23, 0xbe, 0x4f, 0x87, 0x87, 0x34, 0x68, 0x73, 0xc2, 0xc7, 0x21, 0xba, 0x05, 0x59, 0x8f, 0x12,
+	0x87, 0x06, 0x72, 0x92, 0x39, 0xac, 0x5b, 0xa8, 0x2b, 0x82, 0x9c, 0xd8, 0x03, 0x72, 0xe8, 0x7a,
+	0x2e, 0x9f, 0xc8, 0x69, 0xae, 0x2f, 0xdf, 0xe5, 0x45, 0x9b, 0x15, 0x3c, 0xa3, 0x88, 0xe7, 0xcc,
+	0xa0, 0x0d, 0x58, 0x1d, 0xd2, 0x30, 0x24, 0x7d, 0x2a, 0x67, 0x9f, 0xc7, 0x51, 0xd3, 0x7c, 0x08,
+	0xc5, 0x59, 0x3d, 0x54, 0x80, 0xd5, 0x6e, 0xf3, 0x49, 0xf3, 0xe0, 0x59, 0xd3, 0x58, 0x41, 0xd7,
+	0xa0, 0xd0, 0x6d, 0xe2, 0xba, 0x55, 0x7d, 0x6c, 0xed, 0xec, 0xd5, 0x8d, 0x04, 0x5a, 0x83, 0xfc,
+	0xb4, 0x99, 0x34, 0x7f, 0x96, 0x00, 0x10, 0x1b, 0xa8, 0x27, 0xf5, 0x19, 0x64, 0x42, 0x4e, 0xb8,
+	0xda, 0xb8, 0xf5, 0xed, 0xf7, 0x96, 0x79, 0x3d, 0x85, 0x57, 0xc4, 0x0f, 0xc5, 0x4a, 0x65, 0xd6,
+	0xc3, 0xe4, 0xa2, 0x87, 0x19, 0x89, 0x9c, 0x77, 0x2d, 0x07, 0xe9, 0x9a, 0xf8, 0x4a, 0xa0, 0x3c,
+	0x64, 0x70, 0xdd, 0xaa, 0x7d, 0x69, 0x24, 0x91, 0x01, 0xc5, 0x5a, 0xa3, 0x5d, 0x3d, 0x68, 0x36,
+	0xeb, 0xd5, 0x4e, 0xbd, 0x66, 0xa4, 0xcc, 0x7b, 0x90, 0x69, 0x0c, 0x49, 0x9f, 0xa2, 0x3b, 0x22,
+	0x02, 0x8e, 0x68, 0x40, 0x7d, 0x3b, 0x0a, 0xac, 0xa9, 0xc0, 0xfc, 0x79, 0x1e, 0x32, 0xfb, 0x6c,
+	0xec, 0x73, 0xb4, 0x3d, 0x73, 0x8a, 0xd7, 0xb7, 0x37, 0x97, 0x4d, 0x41, 0x02, 0x2b, 0x9d, 0xc9,
+	0x88, 0xea, 0x53, 0x7e, 0x0b, 0xb2, 0x2a, 0x56, 0xb4, 0xeb, 0xba, 0x25, 0xe4, 0x9c, 0x04, 0x7d,
+	0xca, 0xf5, 0xa2, 0xeb, 0x16, 0xba, 0x0f, 0xb9, 0x80, 0x12, 0x87, 0xf9, 0xde, 0x44, 0x86, 0x54,
+	0x4e, 0xa5, 0x59, 0x4c, 0x89, 0x73, 0xe0, 0x7b, 0x13, 0x1c, 0xf7, 0xa2, 0xc7, 0x50, 0x3c, 0x74,
+	0x7d, 0xa7, 0xc7, 0x46, 0x2a, 0xe7, 0x65, 0x5e, 0x1f, 0x80, 0xca, 0xab, 0x1d, 0xd7, 0x77, 0x0e,
+	0x14, 0x18, 0x17, 0x0e, 0xa7, 0x0d, 0xd4, 0x84, 0xf5, 0x13, 0xe6, 0x8d, 0x87, 0x34, 0xb6, 0x95,
+	0x95, 0xb6, 0xde, 0x7f, 0xbd, 0xad, 0xa7, 0x12, 0x1f, 0x59, 0x5b, 0x3b, 0x99, 0x6d, 0xa2, 0x27,
+	0xb0, 0xc6, 0x87, 0xa3, 0xa3, 0x30, 0x36, 0xb7, 0x2a, 0xcd, 0x7d, 0xff, 0x8a, 0x05, 0x13, 0xf0,
+	0xc8, 0x5a, 0x91, 0xcf, 0xb4, 0x4a, 0x7f, 0x96, 0x82, 0xc2, 0x8c, 0xe7, 0xa8, 0x0d, 0x85, 0x51,
+	0xc0, 0x46, 0xa4, 0x2f, 0xf3, 0xb6, 0xde, 0x8b, 0x4f, 0xde, 0x68, 0xd6, 0x95, 0xd6, 0x54, 0x11,
+	0xcf, 0x5a, 0x31, 0xcf, 0x93, 0x50, 0x98, 0xe9, 0x44, 0x1f, 0x40, 0x0e, 0xb7, 0x70, 0xe3, 0xa9,
+	0xd5, 0xa9, 0x1b, 0x2b, 0xa5, 0x3b, 0x67, 0xe7, 0xe5, 0x0d, 0x69, 0x6d, 0xd6, 0x40, 0x2b, 0x70,
+	0x4f, 0x44, 0xe8, 0xdd, 0x87, 0xd5, 0x08, 0x9a, 0x28, 0xbd, 0x7d, 0x76, 0x5e, 0x7e, 0x6b, 0x11,
+	0x3a, 0x83, 0xc4, 0xed, 0xc7, 0x16, 0xae, 0xd7, 0x8c, 0xe4, 0x72, 0x24, 0x6e, 0x0f, 0x48, 0x40,
+	0x1d, 0xf4, 0x7d, 0xc8, 0x6a, 0x60, 0xaa, 0x54, 0x3a, 0x3b, 0x2f, 0xdf, 0x5a, 0x04, 0x4e, 0x71,
+	0xb8, 0xbd, 0x67, 0x3d, 0xad, 0x1b, 0xe9, 0xe5, 0x38, 0xdc, 0xf6, 0xc8, 0x09, 0x45, 0xef, 0x41,
+	0x46, 0xc1, 0x32, 0xa5, 0xdb, 0x67, 0xe7, 0xe5, 0xef, 0xbd, 0x62, 0x4e, 0xa0, 0x4a, 0x1b, 0x7f,
+	0xf1, 0x37, 0x9b, 0x2b, 0xff, 0xf4, 0xb7, 0x9b, 0xc6, 0x62, 0x77, 0xe9, 0x7f, 0x13, 0xb0, 0x36,
+	0xb7, 0xe5, 0xc8, 0x84, 0xac, 0xcf, 0x6c, 0x36, 0x52, 0xe9, 0x3c, 0xb7, 0x03, 0x97, 0x17, 0x5b,
+	0xd9, 0x26, 0xab, 0xb2, 0xd1, 0x04, 0xeb, 0x1e, 0xf4, 0x64, 0xe1, 0x42, 0xfa, 0xf4, 0x0d, 0xe3,
+	0x69, 0xe9, 0x95, 0xf4, 0x39, 0xac, 0x39, 0x81, 0x7b, 0x42, 0x83, 0x9e, 0xcd, 0xfc, 0x23, 0xb7,
+	0xaf, 0x53, 0x75, 0x69, 0x99, 0xcd, 0x9a, 0x04, 0xe2, 0xa2, 0x52, 0xa8, 0x4a, 0xfc, 0xaf, 0x71,
+	0x19, 0x95, 0x9e, 0x42, 0x71, 0x36, 0x42, 0xd1, 0x3b, 0x00, 0xa1, 0xfb, 0x47, 0x54, 0xf3, 0x1b,
+	0xc9, 0x86, 0x70, 0x5e, 0x48, 0x24, 0xbb, 0x41, 0xef, 0x43, 0x7a, 0xc8, 0x1c, 0x65, 0x27, 0xb3,
+	0x73, 0x43, 0xdc, 0x89, 0xff, 0x76, 0xb1, 0x55, 0x60, 0x61, 0x65, 0xd7, 0xf5, 0xe8, 0x3e, 0x73,
+	0x28, 0x96, 0x00, 0xf3, 0x04, 0xd2, 0x22, 0x55, 0xa0, 0xb7, 0x21, 0xbd, 0xd3, 0x68, 0xd6, 0x8c,
+	0x95, 0xd2, 0xf5, 0xb3, 0xf3, 0xf2, 0x9a, 0x5c, 0x12, 0xd1, 0x21, 0x62, 0x17, 0x6d, 0x41, 0xf6,
+	0xe9, 0xc1, 0x5e, 0x77, 0x5f, 0x84, 0xd7, 0x8d, 0xb3, 0xf3, 0xf2, 0xb5, 0xb8, 0x5b, 0x2d, 0x1a,
+	0x7a, 0x07, 0x32, 0x9d, 0xfd, 0xd6, 0x6e, 0xdb, 0x48, 0x96, 0xd0, 0xd9, 0x79, 0x79, 0x3d, 0xee,
+	0x97, 0x3e, 0x97, 0xae, 0xeb, 0x5d, 0xcd, 0xc7, 0x72, 0xf3, 0x7f, 0x92, 0xb0, 0x86, 0x05, 0xbf,
+	0x0d, 0x78, 0x8b, 0x79, 0xae, 0x3d, 0x41, 0x2d, 0xc8, 0xdb, 0xcc, 0x77, 0xdc, 0x99, 0x33, 0xb5,
+	0xfd, 0x9a, 0x4b, 0x70, 0xaa, 0x15, 0xb5, 0xaa, 0x91, 0x26, 0x9e, 0x1a, 0x41, 0xdb, 0x90, 0x71,
+	0xa8, 0x47, 0x26, 0x57, 0xdd, 0xc6, 0x35, 0xcd, 0xa5, 0xb1, 0x82, 0x4a, 0xe6, 0x48, 0x9e, 0xf7,
+	0x08, 0xe7, 0x74, 0x38, 0xe2, 0xea, 0x36, 0x4e, 0xe3, 0xc2, 0x90, 0x3c, 0xb7, 0xb4, 0x08, 0xfd,
+	0x08, 0xb2, 0xa7, 0xae, 0xef, 0xb0, 0x53, 0x7d, 0xe1, 0x5e, 0x6d, 0x57, 0x63, 0xcd, 0x33, 0x71,
+	0xcf, 0x2e, 0x38, 0x2b, 0x56, 0xbd, 0x79, 0xd0, 0xac, 0x47, 0xab, 0xae, 0xfb, 0x0f, 0xfc, 0x26,
+	0xf3, 0xc5, 0x89, 0x81, 0x83, 0x66, 0x6f, 0xd7, 0x6a, 0xec, 0x75, 0xb1, 0x58, 0xf9, 0x9b, 0x67,
+	0xe7, 0x65, 0x23, 0x86, 0xec, 0x12, 0xd7, 0x13, 0x24, 0xf0, 0x36, 0xa4, 0xac, 0xe6, 0x97, 0x46,
+	0xb2, 0x64, 0x9c, 0x9d, 0x97, 0x8b, 0x71, 0xb7, 0xe5, 0x4f, 0xa6, 0x87, 0x69, 0x71, 0x5c, 0xf3,
+	0xbf, 0x12, 0x50, 0xec, 0x8e, 0x1c, 0xc2, 0xa9, 0x8a, 0x4c, 0x54, 0x86, 0xc2, 0x88, 0x04, 0xc4,
+	0xf3, 0xa8, 0xe7, 0x86, 0x43, 0x5d, 0x28, 0xcc, 0x8a, 0xd0, 0x83, 0xef, 0xb0, 0x98, 0x9a, 0x84,
+	0xe9, 0x25, 0xed, 0xc2, 0xfa, 0x91, 0x72, 0xb6, 0x47, 0x6c, 0xb9, 0xbb, 0x29, 0xb9, 0xbb, 0x95,
+	0x65, 0x26, 0x66, 0xbd, 0xaa, 0xe8, 0x39, 0x5a, 0x52, 0x0b, 0xaf, 0x1d, 0xcd, 0x36, 0xcd, 0xfb,
+	0xb0, 0x36, 0xd7, 0x2f, 0x6e, 0xda, 0x96, 0xd5, 0x6d, 0xd7, 0x8d, 0x15, 0x54, 0x84, 0x5c, 0xf5,
+	0xa0, 0xd9, 0x69, 0x34, 0xbb, 0x75, 0x23, 0x61, 0xfe, 0x43, 0x32, 0x9a, 0xad, 0x66, 0x02, 0x3b,
+	0xf3, 0x4c, 0xe0, 0xc3, 0xd7, 0x3b, 0xa2, 0xb9, 0xc0, 0xb4, 0x11, 0x33, 0x82, 0xdf, 0x05, 0x90,
+	0x8b, 0x4a, 0x9d, 0x1e, 0xe1, 0x57, 0xb1, 0xfd, 0x4e, 0x54, 0xc7, 0xe1, 0xbc, 0x56, 0xb0, 0x38,
+	0xfa, 0x02, 0x8a, 0x36, 0x1b, 0x8e, 0x3c, 0xaa, 0xf5, 0x53, 0x6f, 0xa2, 0x5f, 0x88, 0x55, 0x2c,
+	0x3e, 0xcb, 0x48, 0xd2, 0xf3, 0x8c, 0xa4, 0x0a, 0x85, 0x19, 0x7f, 0xe7, 0x79, 0x49, 0x11, 0x72,
+	0xdd, 0x56, 0xcd, 0xea, 0x34, 0x9a, 0x8f, 0x8c, 0x04, 0x02, 0xc8, 0xca, 0x15, 0xab, 0x19, 0x49,
+	0xc1, 0x9d, 0xaa, 0x07, 0xfb, 0xad, 0xbd, 0xba, 0x62, 0x26, 0x7f, 0x02, 0xd7, 0xaa, 0xcc, 0xe7,
+	0xc4, 0xf5, 0x63, 0x52, 0xb8, 0x2d, 0x7c, 0xd6, 0xa2, 0x9e, 0xeb, 0xa8, 0xbc, 0xb5, 0x73, 0xed,
+	0xf2, 0x62, 0xab, 0x10, 0x43, 0x1b, 0x35, 0xe1, 0x65, 0xd4, 0x70, 0x44, 0x74, 0x8e, 0x5c, 0x47,
+	0xa7, 0xa1, 0xd5, 0xcb, 0x8b, 0xad, 0x54, 0xab, 0x51, 0xc3, 0x42, 0x86, 0xde, 0x86, 0x3c, 0x7d,
+	0xee, 0xf2, 0x9e, 0x2d, 0xf2, 0x94, 0x98, 0x7f, 0x06, 0xe7, 0x84, 0xa0, 0x2a, 0xd2, 0xd2, 0x9f,
+	0x26, 0x01, 0x3a, 0x24, 0x3c, 0xd6, 0x43, 0x3f, 0x84, 0x7c, 0x5c, 0x0e, 0x5f, 0x55, 0x96, 0xcd,
+	0xac, 0x75, 0x8c, 0x47, 0x9f, 0x46, 0xbb, 0xad, 0xd8, 0xea, 0x72, 0x45, 0x3d, 0xd6, 0x32, 0xc2,
+	0x37, 0x4f, 0x49, 0x45, 0xd6, 0xa6, 0x41, 0xa0, 0x17, 0x5d, 0x7c, 0xa2, 0xaa, 0xcc, 0x5c, 0x6a,
+	0xce, 0x9a, 0x03, 0xdd, 0x5d, 0x36, 0xc8, 0xc2, 0x82, 0x3e, 0x5e, 0xc1, 0x53, 0xbd, 0x1d, 0x03,
+	0xd6, 0x83, 0xb1, 0x2f, 0xbc, 0xee, 0x85, 0xb2, 0xdb, 0x74, 0xe1, 0xad, 0x26, 0xe5, 0xa7, 0x2c,
+	0x38, 0xb6, 0x38, 0x27, 0xf6, 0x40, 0x94, 0xa7, 0xfa, 0xb8, 0x4e, 0xa9, 0x5b, 0x62, 0x8e, 0xba,
+	0x6d, 0xc0, 0x2a, 0xf1, 0x5c, 0x12, 0x52, 0x75, 0xdf, 0xe5, 0x71, 0xd4, 0x14, 0x04, 0x93, 0x38,
+	0x4e, 0x40, 0xc3, 0x90, 0xaa, 0x82, 0x2a, 0x8f, 0xa7, 0x02, 0xf3, 0x5f, 0x92, 0x00, 0x8d, 0x96,
+	0xb5, 0xaf, 0xcd, 0xd7, 0x20, 0x7b, 0x44, 0x86, 0xae, 0x37, 0xb9, 0xea, 0x80, 0x4c, 0xf1, 0x15,
+	0x4b, 0x19, 0xda, 0x95, 0x3a, 0x58, 0xeb, 0x4a, 0xde, 0x39, 0x3e, 0xf4, 0x29, 0x8f, 0x79, 0xa7,
+	0x6c, 0x89, 0x4b, 0x2e, 0x20, 0x7e, 0xbc, 0xb0, 0xaa, 0x21, 0x5c, 0xef, 0x13, 0x4e, 0x4f, 0xc9,
+	0x24, 0x8a, 0x67, 0xdd, 0x44, 0x8f, 0x05, 0x1f, 0x15, 0x65, 0x32, 0x75, 0x36, 0x32, 0xf2, 0x16,
+	0xff, 0x36, 0x7f, 0xb0, 0x86, 0xab, 0xeb, 0x3b, 0xd6, 0x2e, 0x3d, 0x94, 0x77, 0xce, 0xb4, 0xeb,
+	0x3b, 0x95, 0x83, 0x1f, 0xc3, 0xda, 0xdc, 0x3c, 0x5f, 0x21, 0xfc, 0x8d, 0xd6, 0xd3, 0x1f, 0x19,
+	0x69, 0xfd, 0xf5, 0x3b, 0x46, 0xd6, 0xfc, 0xef, 0x04, 0x40, 0x8b, 0x05, 0xd1, 0xa6, 0x2d, 0x7f,
+	0x60, 0xc9, 0xc9, 0xe7, 0x1a, 0x9b, 0x79, 0x3a, 0x3c, 0x97, 0x32, 0xde, 0xa9, 0x15, 0x41, 0x20,
+	0x25, 0x1c, 0xc7, 0x8a, 0x68, 0x0b, 0x0a, 0x6a, 0xff, 0x7b, 0x23, 0x16, 0xa8, 0x5c, 0xb2, 0x86,
+	0x41, 0x89, 0x84, 0xa6, 0xa8, 0xde, 0x47, 0xe3, 0x43, 0xcf, 0x0d, 0x07, 0xd4, 0x51, 0x98, 0xb4,
+	0xc4, 0xac, 0xc5, 0x52, 0x01, 0x33, 0x6b, 0x90, 0x8b, 0xac, 0xa3, 0x0d, 0x48, 0x75, 0xaa, 0x2d,
+	0x63, 0xa5, 0x74, 0xed, 0xec, 0xbc, 0x5c, 0x88, 0xc4, 0x9d, 0x6a, 0x4b, 0xf4, 0x74, 0x6b, 0x2d,
+	0x23, 0x31, 0xdf, 0xd3, 0xad, 0xb5, 0x4a, 0x69, 0x71, 0xdf, 0x98, 0x7f, 0x95, 0x80, 0xac, 0x62,
+	0x3f, 0x4b, 0x67, 0x6c, 0xc1, 0x6a, 0xc4, 0xc9, 0x15, 0x25, 0x7b, 0xff, 0xf5, 0xf4, 0xa9, 0xa2,
+	0xd9, 0x8e, 0xda, 0xc7, 0x48, 0xaf, 0xf4, 0x19, 0x14, 0x67, 0x3b, 0xbe, 0xd3, 0x2e, 0xfe, 0x31,
+	0x14, 0x44, 0xa0, 0x44, 0x34, 0x6a, 0x1b, 0xb2, 0x8a, 0xa1, 0xe9, 0xac, 0x72, 0x15, 0x97, 0xd3,
+	0x48, 0xf4, 0x00, 0x56, 0x15, 0xff, 0x8b, 0x5e, 0x26, 0x36, 0xaf, 0x0e, 0x47, 0x1c, 0xc1, 0xcd,
+	0xcf, 0x21, 0xdd, 0xa2, 0x34, 0x40, 0x77, 0x61, 0xd5, 0x67, 0x0e, 0x9d, 0x26, 0x51, 0x4d, 0x5d,
+	0x1d, 0xda, 0xa8, 0x09, 0xea, 0xea, 0xd0, 0x86, 0x23, 0x16, 0x4f, 0x1c, 0xd0, 0xe8, 0x71, 0x46,
+	0x7c, 0x9b, 0x1d, 0x28, 0x3e, 0xa3, 0x6e, 0x7f, 0xc0, 0xa9, 0x23, 0x0d, 0x7d, 0x08, 0xe9, 0x11,
+	0x8d, 0x9d, 0xdf, 0x58, 0x1a, 0x3a, 0x94, 0x06, 0x58, 0xa2, 0xc4, 0x81, 0x3c, 0x95, 0xda, 0xfa,
+	0x3d, 0x4c, 0xb7, 0xcc, 0xbf, 0x4f, 0xc2, 0x7a, 0x23, 0x0c, 0xc7, 0xc4, 0xb7, 0xa3, 0x1b, 0xf2,
+	0x27, 0xf3, 0x37, 0xe4, 0xfd, 0xa5, 0x33, 0x9c, 0x53, 0x99, 0xaf, 0x97, 0x75, 0x92, 0x4c, 0xc6,
+	0x49, 0xd2, 0xfc, 0x3a, 0x11, 0x15, 0xca, 0xf7, 0x66, 0xce, 0x4d, 0x69, 0xe3, 0xec, 0xbc, 0x7c,
+	0x73, 0xd6, 0x12, 0xed, 0xfa, 0xc7, 0x3e, 0x3b, 0xf5, 0xd1, 0xbb, 0xa2, 0x70, 0x6e, 0xd6, 0x9f,
+	0x19, 0x89, 0xd2, 0xad, 0xb3, 0xf3, 0x32, 0x9a, 0x03, 0x61, 0xea, 0xd3, 0x53, 0x61, 0xa9, 0x55,
+	0x6f, 0xd6, 0xc4, 0x65, 0x96, 0x5c, 0x62, 0xa9, 0x45, 0x7d, 0xc7, 0xf5, 0xfb, 0xe8, 0x2e, 0x64,
+	0x1b, 0xed, 0x76, 0x57, 0x96, 0x32, 0x6f, 0x9d, 0x9d, 0x97, 0x6f, 0xcc, 0xa1, 0x44, 0x83, 0x3a,
+	0x02, 0x24, 0xa8, 0x56, 0xbd, 0x66, 0xa4, 0x97, 0x80, 0x04, 0xd3, 0xa0, 0x8e, 0x8e, 0xf0, 0x7f,
+	0x4f, 0x82, 0x61, 0xd9, 0x36, 0x1d, 0x71, 0xd1, 0xaf, 0xe9, 0x6b, 0x07, 0x72, 0x23, 0xf1, 0xe5,
+	0x4a, 0x3a, 0x2e, 0xc2, 0xe2, 0xc1, 0xd2, 0xc7, 0xd2, 0x05, 0xbd, 0x0a, 0x66, 0x1e, 0xb5, 0x9c,
+	0xa1, 0x1b, 0x86, 0xa2, 0x4c, 0x93, 0x32, 0x1c, 0x5b, 0x2a, 0xfd, 0x32, 0x01, 0x37, 0x96, 0x20,
+	0xd0, 0xc7, 0x90, 0x0e, 0x98, 0x17, 0x6d, 0xcf, 0x9d, 0xd7, 0x3d, 0x65, 0x08, 0x55, 0x2c, 0x91,
+	0x68, 0x13, 0x80, 0x8c, 0x39, 0x23, 0x72, 0x7c, 0xb9, 0x31, 0x39, 0x3c, 0x23, 0x41, 0xcf, 0x20,
+	0x1b, 0x52, 0x3b, 0xa0, 0x11, 0x17, 0xf9, 0xfc, 0xff, 0xeb, 0x7d, 0xa5, 0x2d, 0xcd, 0x60, 0x6d,
+	0xae, 0x54, 0x81, 0xac, 0x92, 0x88, 0x88, 0x76, 0x08, 0x27, 0xd2, 0xe9, 0x22, 0x96, 0xdf, 0x22,
+	0x50, 0x88, 0xd7, 0x8f, 0x02, 0x85, 0x78, 0x7d, 0xf3, 0x67, 0x49, 0x80, 0xfa, 0x73, 0x4e, 0x03,
+	0x9f, 0x78, 0x55, 0x0b, 0xd5, 0x67, 0x32, 0xa4, 0x9a, 0xed, 0x0f, 0x96, 0x3e, 0x70, 0xc5, 0x1a,
+	0x95, 0xaa, 0xb5, 0x24, 0x47, 0xde, 0x86, 0xd4, 0x38, 0xf0, 0xf4, 0x63, 0xa9, 0x24, 0x22, 0x5d,
+	0xbc, 0x87, 0x85, 0x0c, 0xd5, 0xa7, 0x19, 0x29, 0xf5, 0xfa, 0x57, 0xee, 0x99, 0x01, 0x7e, 0xf3,
+	0x59, 0xe9, 0x43, 0x80, 0xa9, 0xd7, 0x68, 0x13, 0x32, 0xd5, 0xdd, 0x76, 0x7b, 0xcf, 0x58, 0x51,
+	0xd5, 0xd6, 0xb4, 0x4b, 0x8a, 0xcd, 0xbf, 0x4b, 0x40, 0xae, 0x6a, 0xe9, 0x5b, 0x65, 0x17, 0x0c,
+	0x99, 0x4b, 0x6c, 0x1a, 0xf0, 0x1e, 0x7d, 0x3e, 0x72, 0x83, 0x89, 0x4e, 0x07, 0x57, 0xd7, 0x25,
+	0xeb, 0x42, 0xab, 0x4a, 0x03, 0x5e, 0x97, 0x3a, 0x08, 0x43, 0x91, 0xea, 0x29, 0xf6, 0x6c, 0x12,
+	0x25, 0xe7, 0xcd, 0xab, 0x97, 0x42, 0xb1, 0xbf, 0x69, 0x3b, 0xc4, 0x85, 0xc8, 0x48, 0x95, 0x84,
+	0xe6, 0x53, 0xb8, 0x71, 0x10, 0xd8, 0x03, 0x1a, 0x72, 0x35, 0xa8, 0x76, 0xf9, 0x73, 0xb8, 0xc3,
+	0x49, 0x78, 0xdc, 0x1b, 0xb8, 0x21, 0x67, 0xc1, 0xa4, 0x17, 0x50, 0x4e, 0x7d, 0xd1, 0xdf, 0x93,
+	0x6f, 0xe9, 0xba, 0x9a, 0xbd, 0x2d, 0x30, 0x8f, 0x15, 0x04, 0x47, 0x88, 0x3d, 0x01, 0x30, 0x1b,
+	0x50, 0x14, 0x84, 0xad, 0x46, 0x8f, 0xc8, 0xd8, 0xe3, 0x21, 0xfa, 0x31, 0x80, 0xc7, 0xfa, 0xbd,
+	0x37, 0xce, 0xe4, 0x79, 0x8f, 0xf5, 0xd5, 0xa7, 0xf9, 0xfb, 0x60, 0xd4, 0xdc, 0x70, 0x44, 0xb8,
+	0x3d, 0x88, 0xca, 0x74, 0xf4, 0x08, 0x8c, 0x01, 0x25, 0x01, 0x3f, 0xa4, 0x84, 0xf7, 0x46, 0x34,
+	0x70, 0x99, 0xf3, 0x46, 0x4b, 0x7a, 0x2d, 0xd6, 0x6a, 0x49, 0x25, 0xf3, 0x57, 0x09, 0x00, 0x4c,
+	0x8e, 0x22, 0x02, 0xf0, 0x43, 0xb8, 0x1e, 0xfa, 0x64, 0x14, 0x0e, 0x18, 0xef, 0xb9, 0x3e, 0xa7,
+	0xc1, 0x09, 0xf1, 0x74, 0xa9, 0x65, 0x44, 0x1d, 0x0d, 0x2d, 0x47, 0x1f, 0x02, 0x3a, 0xa6, 0x74,
+	0xd4, 0x63, 0x9e, 0xd3, 0x8b, 0x3a, 0xd5, 0x63, 0x7f, 0x1a, 0x1b, 0xa2, 0xe7, 0xc0, 0x73, 0xda,
+	0x91, 0x1c, 0xed, 0xc0, 0xa6, 0x58, 0x01, 0xea, 0xf3, 0xc0, 0xa5, 0x61, 0xef, 0x88, 0x05, 0xbd,
+	0xd0, 0x63, 0xa7, 0xbd, 0x23, 0xe6, 0x79, 0xec, 0x94, 0x06, 0x51, 0x21, 0x5b, 0xf2, 0x58, 0xbf,
+	0xae, 0x40, 0xbb, 0x2c, 0x68, 0x7b, 0xec, 0x74, 0x37, 0x42, 0x08, 0x96, 0x30, 0x9d, 0x36, 0x77,
+	0xed, 0xe3, 0x88, 0x25, 0xc4, 0xd2, 0x8e, 0x6b, 0x1f, 0xa3, 0xbb, 0xb0, 0x46, 0x3d, 0x2a, 0x4b,
+	0x2e, 0x85, 0xca, 0x48, 0x54, 0x31, 0x12, 0x0a, 0x90, 0xf9, 0x5b, 0x90, 0x6f, 0x79, 0xc4, 0x96,
+	0x7f, 0xa9, 0x88, 0xe2, 0xd2, 0x66, 0xbe, 0x08, 0x02, 0xd7, 0xe7, 0x2a, 0x3b, 0xe6, 0xf1, 0xac,
+	0xc8, 0xfc, 0x09, 0xc0, 0x4f, 0x99, 0xeb, 0x77, 0xd8, 0x31, 0xf5, 0xe5, 0xeb, 0xb3, 0x60, 0xbd,
+	0x7a, 0x2b, 0xf3, 0x58, 0xb7, 0x24, 0x27, 0x27, 0x3e, 0xe9, 0xd3, 0x20, 0x7e, 0x84, 0x55, 0x4d,
+	0x71, 0xb9, 0x64, 0x31, 0x63, 0xbc, 0x6a, 0xa1, 0x32, 0x64, 0x6d, 0xd2, 0x8b, 0x4e, 0x5e, 0x71,
+	0x27, 0x7f, 0x79, 0xb1, 0x95, 0xa9, 0x5a, 0x4f, 0xe8, 0x04, 0x67, 0x6c, 0xf2, 0x84, 0x4e, 0xc4,
+	0xed, 0x6b, 0x13, 0x79, 0x5e, 0xa4, 0x99, 0xa2, 0xba, 0x7d, 0xab, 0x96, 0x38, 0x0c, 0x38, 0x6b,
+	0x13, 0xf1, 0x8b, 0x3e, 0x86, 0xa2, 0x06, 0xf5, 0x06, 0x24, 0x1c, 0x28, 0xae, 0xba, 0xb3, 0x7e,
+	0x79, 0xb1, 0x05, 0x0a, 0xf9, 0x98, 0x84, 0x03, 0x0c, 0x0a, 0x2d, 0xbe, 0x51, 0x1d, 0x0a, 0x5f,
+	0x31, 0xd7, 0xef, 0x71, 0x39, 0x09, 0xfd, 0x36, 0xb0, 0xf4, 0xfc, 0x4c, 0xa7, 0xaa, 0x0b, 0x65,
+	0xf8, 0x2a, 0x96, 0x98, 0xff, 0x9a, 0x80, 0x82, 0xb0, 0xe9, 0x1e, 0xb9, 0xb6, 0xb8, 0x2d, 0xbf,
+	0x7b, 0xa6, 0xbf, 0x0d, 0x29, 0x3b, 0x0c, 0xf4, 0xdc, 0x64, 0xaa, 0xab, 0xb6, 0x31, 0x16, 0x32,
+	0xf4, 0x05, 0x64, 0x55, 0x71, 0xa1, 0x93, 0xbc, 0xf9, 0xed, 0xf7, 0xba, 0x76, 0x51, 0xeb, 0xc9,
+	0xbd, 0x9c, 0x7a, 0x27, 0x67, 0x59, 0xc4, 0xb3, 0x22, 0x74, 0x0b, 0x92, 0xb6, 0x2f, 0x83, 0x42,
+	0xff, 0x2b, 0x55, 0x6d, 0xe2, 0xa4, 0xed, 0x9b, 0xff, 0x9c, 0x80, 0xb5, 0xba, 0x6f, 0x07, 0x13,
+	0x99, 0x24, 0xc5, 0x46, 0xdc, 0x81, 0x7c, 0x38, 0x3e, 0x0c, 0x27, 0x21, 0xa7, 0xc3, 0xe8, 0xd1,
+	0x3b, 0x16, 0xa0, 0x06, 0xe4, 0x89, 0xd7, 0x67, 0x81, 0xcb, 0x07, 0x43, 0xcd, 0x8d, 0x97, 0x27,
+	0xe6, 0x59, 0x9b, 0x15, 0x2b, 0x52, 0xc1, 0x53, 0xed, 0x28, 0x15, 0xa7, 0xa4, 0xb3, 0x32, 0x15,
+	0xbf, 0x0b, 0x45, 0x8f, 0x0c, 0x05, 0x15, 0xee, 0x89, 0x92, 0x4b, 0xce, 0x23, 0x8d, 0x0b, 0x5a,
+	0x26, 0xca, 0x48, 0xd3, 0x84, 0x7c, 0x6c, 0x0c, 0x5d, 0x83, 0x82, 0x55, 0x6f, 0xf7, 0x3e, 0xd9,
+	0x7e, 0xd0, 0x7b, 0x54, 0xdd, 0x37, 0x56, 0x34, 0x13, 0xf8, 0xc7, 0x04, 0xac, 0xed, 0xab, 0x18,
+	0xd4, 0xc4, 0xe9, 0x2e, 0xac, 0x06, 0xe4, 0x88, 0x47, 0xd4, 0x2e, 0xad, 0x82, 0x4b, 0x24, 0x01,
+	0x41, 0xed, 0x44, 0xd7, 0x72, 0x6a, 0x37, 0xf3, 0x97, 0x4b, 0xea, 0xca, 0xbf, 0x5c, 0xd2, 0xbf,
+	0x91, 0xbf, 0x5c, 0x3e, 0xf8, 0x55, 0x0a, 0xf2, 0x71, 0xd1, 0x2b, 0x42, 0x46, 0x30, 0xad, 0x15,
+	0xf5, 0x88, 0x14, 0xcb, 0x9b, 0x92, 0x63, 0xe5, 0xad, 0xbd, 0xbd, 0x83, 0xaa, 0xd5, 0xa9, 0xd7,
+	0x8c, 0x2f, 0x14, 0x15, 0x8b, 0x01, 0x96, 0xe7, 0x31, 0xb1, 0xe9, 0x0e, 0x32, 0xa7, 0x54, 0xec,
+	0x85, 0x7e, 0xaa, 0x8a, 0x51, 0x11, 0x0f, 0x7b, 0x0f, 0x72, 0x56, 0xbb, 0xdd, 0x78, 0xd4, 0xac,
+	0xd7, 0x8c, 0x97, 0x89, 0xd2, 0xf7, 0xce, 0xce, 0xcb, 0xd7, 0xa7, 0xa6, 0xc2, 0xd0, 0xed, 0xfb,
+	0xd4, 0x91, 0xa8, 0x6a, 0xb5, 0xde, 0x12, 0xe3, 0xbd, 0x48, 0x2e, 0xa2, 0x24, 0x01, 0x91, 0xcf,
+	0xce, 0xf9, 0x16, 0xae, 0xb7, 0x2c, 0x2c, 0x46, 0x7c, 0x99, 0x5c, 0xf0, 0xab, 0x15, 0xd0, 0x11,
+	0x09, 0xc4, 0x98, 0x9b, 0xd1, 0xdf, 0x2f, 0x2f, 0x52, 0xea, 0x69, 0x72, 0x5a, 0xe9, 0x53, 0xe2,
+	0x4c, 0xc4, 0x68, 0xed, 0x8e, 0x85, 0xe5, 0x83, 0xc8, 0xcb, 0xd4, 0xc2, 0x68, 0x6d, 0x4e, 0x02,
+	0x2e, 0xac, 0x98, 0xb0, 0x8a, 0xbb, 0xcd, 0xa6, 0x9c, 0x5d, 0x7a, 0x61, 0x76, 0x78, 0xec, 0xfb,
+	0x02, 0x73, 0x0f, 0x72, 0xd1, 0x03, 0x8a, 0xf1, 0x32, 0xbd, 0xe0, 0x50, 0x35, 0x7a, 0xb9, 0x91,
+	0x03, 0x3e, 0xee, 0x76, 0xe4, 0xbf, 0x43, 0x2f, 0x32, 0x8b, 0x03, 0x0e, 0xc6, 0xdc, 0x11, 0xe4,
+	0xb7, 0x1c, 0xb3, 0xd1, 0x97, 0x19, 0x45, 0x02, 0x62, 0x8c, 0xa2, 0xa2, 0xc2, 0x0e, 0xae, 0xff,
+	0x54, 0xfd, 0x91, 0xf4, 0x22, 0xbb, 0x60, 0x07, 0xd3, 0xaf, 0xa8, 0xcd, 0xa9, 0x33, 0x7d, 0x79,
+	0x8d, 0xbb, 0x3e, 0xf8, 0x03, 0xc8, 0x45, 0x09, 0x03, 0x6d, 0x42, 0xf6, 0xd9, 0x01, 0x7e, 0x52,
+	0xc7, 0xc6, 0x8a, 0x5a, 0x9d, 0xa8, 0xe7, 0x99, 0xca, 0xb8, 0x65, 0x58, 0xdd, 0xb7, 0x9a, 0xd6,
+	0xa3, 0x3a, 0x8e, 0x5e, 0x7e, 0x23, 0x80, 0x8e, 0xfa, 0x92, 0xa1, 0x07, 0x88, 0x6d, 0xee, 0xdc,
+	0xf9, 0xfa, 0x9b, 0xcd, 0x95, 0x5f, 0x7c, 0xb3, 0xb9, 0xf2, 0xcb, 0x6f, 0x36, 0x13, 0x2f, 0x2e,
+	0x37, 0x13, 0x5f, 0x5f, 0x6e, 0x26, 0x7e, 0x7e, 0xb9, 0x99, 0xf8, 0x8f, 0xcb, 0xcd, 0xc4, 0x61,
+	0x56, 0x32, 0xb2, 0x4f, 0xff, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x7d, 0xe8, 0x50, 0x18, 0x0a, 0x21,
+	0x00, 0x00,
 }
 }

+ 17 - 0
vendor/src/github.com/docker/swarmkit/api/types.proto

@@ -407,6 +407,23 @@ message TaskStatus {
 	}
 	}
 }
 }
 
 
+// NetworkAttachmentConfig specifies how a service should be attached to a particular network.
+//
+// For now, this is a simple struct, but this can include future information
+// instructing Swarm on how this service should work on the particular
+// network.
+message NetworkAttachmentConfig {
+	// Target specifies the target network for attachment. This value may be a
+	// network name or identifier. Only identifiers are supported at this time.
+	string target = 1;
+	// Aliases specifies a list of discoverable alternate names for the service on this Target.
+	repeated string aliases = 2;
+	// Addresses specifies a list of ipv4 and ipv6 addresses
+	// preferred. If these addresses are not available then the
+	// attachment might fail.
+	repeated string addresses = 3;
+}
+
 // IPAMConfig specifies parameters for IP Address Management.
 // IPAMConfig specifies parameters for IP Address Management.
 message IPAMConfig {
 message IPAMConfig {
 	// TODO(stevvooe): It may make more sense to manage IPAM and network
 	// TODO(stevvooe): It may make more sense to manage IPAM and network

+ 33 - 27
vendor/src/github.com/docker/swarmkit/ca/certificates.go

@@ -28,7 +28,7 @@ import (
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/identity"
 	"github.com/docker/swarmkit/identity"
 	"github.com/docker/swarmkit/ioutils"
 	"github.com/docker/swarmkit/ioutils"
-	"github.com/docker/swarmkit/picker"
+	"github.com/docker/swarmkit/remotes"
 	"golang.org/x/net/context"
 	"golang.org/x/net/context"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/credentials"
 	"google.golang.org/grpc/credentials"
@@ -155,7 +155,7 @@ func (rca *RootCA) IssueAndSaveNewCertificates(paths CertPaths, cn, ou, org stri
 
 
 // RequestAndSaveNewCertificates gets new certificates issued, either by signing them locally if a signer is
 // RequestAndSaveNewCertificates gets new certificates issued, either by signing them locally if a signer is
 // available, or by requesting them from the remote server at remoteAddr.
 // available, or by requesting them from the remote server at remoteAddr.
-func (rca *RootCA) RequestAndSaveNewCertificates(ctx context.Context, paths CertPaths, token string, picker *picker.Picker, transport credentials.TransportAuthenticator, nodeInfo chan<- api.IssueNodeCertificateResponse) (*tls.Certificate, error) {
+func (rca *RootCA) RequestAndSaveNewCertificates(ctx context.Context, paths CertPaths, token string, remotes remotes.Remotes, transport credentials.TransportAuthenticator, nodeInfo chan<- api.IssueNodeCertificateResponse) (*tls.Certificate, error) {
 	// Create a new key/pair and CSR for the new manager
 	// Create a new key/pair and CSR for the new manager
 	// Write the new CSR and the new key to a temporary location so we can survive crashes on rotation
 	// Write the new CSR and the new key to a temporary location so we can survive crashes on rotation
 	tempPaths := genTempPaths(paths)
 	tempPaths := genTempPaths(paths)
@@ -170,7 +170,7 @@ func (rca *RootCA) RequestAndSaveNewCertificates(ctx context.Context, paths Cert
 	// responding properly (for example, it may have just been demoted).
 	// responding properly (for example, it may have just been demoted).
 	var signedCert []byte
 	var signedCert []byte
 	for i := 0; i != 5; i++ {
 	for i := 0; i != 5; i++ {
-		signedCert, err = GetRemoteSignedCertificate(ctx, csr, token, rca.Pool, picker, transport, nodeInfo)
+		signedCert, err = GetRemoteSignedCertificate(ctx, csr, token, rca.Pool, remotes, transport, nodeInfo)
 		if err == nil {
 		if err == nil {
 			break
 			break
 		}
 		}
@@ -423,33 +423,38 @@ func GetLocalRootCA(baseDir string) (RootCA, error) {
 }
 }
 
 
 // GetRemoteCA returns the remote endpoint's CA certificate
 // GetRemoteCA returns the remote endpoint's CA certificate
-func GetRemoteCA(ctx context.Context, d digest.Digest, picker *picker.Picker) (RootCA, error) {
-	// We need a valid picker to be able to Dial to a remote CA
-	if picker == nil {
-		return RootCA{}, fmt.Errorf("valid remote address picker required")
-	}
-
+func GetRemoteCA(ctx context.Context, d digest.Digest, r remotes.Remotes) (RootCA, error) {
 	// This TLS Config is intentionally using InsecureSkipVerify. Either we're
 	// This TLS Config is intentionally using InsecureSkipVerify. Either we're
 	// doing TOFU, in which case we don't validate the remote CA, or we're using
 	// doing TOFU, in which case we don't validate the remote CA, or we're using
 	// a user supplied hash to check the integrity of the CA certificate.
 	// a user supplied hash to check the integrity of the CA certificate.
 	insecureCreds := credentials.NewTLS(&tls.Config{InsecureSkipVerify: true})
 	insecureCreds := credentials.NewTLS(&tls.Config{InsecureSkipVerify: true})
 	opts := []grpc.DialOption{
 	opts := []grpc.DialOption{
 		grpc.WithTransportCredentials(insecureCreds),
 		grpc.WithTransportCredentials(insecureCreds),
-		grpc.WithBackoffMaxDelay(10 * time.Second),
-		grpc.WithPicker(picker)}
+		grpc.WithTimeout(5 * time.Second),
+		grpc.WithBackoffMaxDelay(5 * time.Second),
+	}
 
 
-	firstAddr, err := picker.PickAddr()
+	peer, err := r.Select()
 	if err != nil {
 	if err != nil {
 		return RootCA{}, err
 		return RootCA{}, err
 	}
 	}
 
 
-	conn, err := grpc.Dial(firstAddr, opts...)
+	conn, err := grpc.Dial(peer.Addr, opts...)
 	if err != nil {
 	if err != nil {
 		return RootCA{}, err
 		return RootCA{}, err
 	}
 	}
 	defer conn.Close()
 	defer conn.Close()
 
 
 	client := api.NewCAClient(conn)
 	client := api.NewCAClient(conn)
+	ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
+	defer cancel()
+	defer func() {
+		if err != nil {
+			r.Observe(peer, -remotes.DefaultObservationWeight)
+			return
+		}
+		r.Observe(peer, remotes.DefaultObservationWeight)
+	}()
 	response, err := client.GetRootCACertificate(ctx, &api.GetRootCACertificateRequest{})
 	response, err := client.GetRootCACertificate(ctx, &api.GetRootCACertificateRequest{})
 	if err != nil {
 	if err != nil {
 		return RootCA{}, err
 		return RootCA{}, err
@@ -596,16 +601,12 @@ func GenerateAndWriteNewKey(paths CertPaths) (csr, key []byte, err error) {
 	return
 	return
 }
 }
 
 
-// GetRemoteSignedCertificate submits a CSR to a remote CA server address
-// available through a picker, and that is part of a CA identified by a
-// specific certificate pool.
-func GetRemoteSignedCertificate(ctx context.Context, csr []byte, token string, rootCAPool *x509.CertPool, picker *picker.Picker, creds credentials.TransportAuthenticator, nodeInfo chan<- api.IssueNodeCertificateResponse) ([]byte, error) {
+// GetRemoteSignedCertificate submits a CSR to a remote CA server address,
+// and that is part of a CA identified by a specific certificate pool.
+func GetRemoteSignedCertificate(ctx context.Context, csr []byte, token string, rootCAPool *x509.CertPool, r remotes.Remotes, creds credentials.TransportAuthenticator, nodeInfo chan<- api.IssueNodeCertificateResponse) ([]byte, error) {
 	if rootCAPool == nil {
 	if rootCAPool == nil {
 		return nil, fmt.Errorf("valid root CA pool required")
 		return nil, fmt.Errorf("valid root CA pool required")
 	}
 	}
-	if picker == nil {
-		return nil, fmt.Errorf("valid remote address picker required")
-	}
 
 
 	if creds == nil {
 	if creds == nil {
 		// This is our only non-MTLS request, and it happens when we are boostraping our TLS certs
 		// This is our only non-MTLS request, and it happens when we are boostraping our TLS certs
@@ -613,17 +614,18 @@ func GetRemoteSignedCertificate(ctx context.Context, csr []byte, token string, r
 		creds = credentials.NewTLS(&tls.Config{ServerName: CARole, RootCAs: rootCAPool})
 		creds = credentials.NewTLS(&tls.Config{ServerName: CARole, RootCAs: rootCAPool})
 	}
 	}
 
 
-	opts := []grpc.DialOption{
-		grpc.WithTransportCredentials(creds),
-		grpc.WithBackoffMaxDelay(10 * time.Second),
-		grpc.WithPicker(picker)}
-
-	firstAddr, err := picker.PickAddr()
+	peer, err := r.Select()
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 
 
-	conn, err := grpc.Dial(firstAddr, opts...)
+	opts := []grpc.DialOption{
+		grpc.WithTransportCredentials(creds),
+		grpc.WithTimeout(5 * time.Second),
+		grpc.WithBackoffMaxDelay(5 * time.Second),
+	}
+
+	conn, err := grpc.Dial(peer.Addr, opts...)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -655,8 +657,11 @@ func GetRemoteSignedCertificate(ctx context.Context, csr []byte, token string, r
 	// Exponential backoff with Max of 30 seconds to wait for a new retry
 	// Exponential backoff with Max of 30 seconds to wait for a new retry
 	for {
 	for {
 		// Send the Request and retrieve the certificate
 		// Send the Request and retrieve the certificate
+		ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
+		defer cancel()
 		statusResponse, err := caClient.NodeCertificateStatus(ctx, statusRequest)
 		statusResponse, err := caClient.NodeCertificateStatus(ctx, statusRequest)
 		if err != nil {
 		if err != nil {
+			r.Observe(peer, -remotes.DefaultObservationWeight)
 			return nil, err
 			return nil, err
 		}
 		}
 
 
@@ -672,6 +677,7 @@ func GetRemoteSignedCertificate(ctx context.Context, csr []byte, token string, r
 			// retry until the certificate gets updated per our
 			// retry until the certificate gets updated per our
 			// current request.
 			// current request.
 			if bytes.Equal(statusResponse.Certificate.CSR, csr) {
 			if bytes.Equal(statusResponse.Certificate.CSR, csr) {
+				r.Observe(peer, remotes.DefaultObservationWeight)
 				return statusResponse.Certificate.Certificate, nil
 				return statusResponse.Certificate.Certificate, nil
 			}
 			}
 		}
 		}

+ 6 - 6
vendor/src/github.com/docker/swarmkit/ca/config.go

@@ -20,7 +20,7 @@ import (
 	"github.com/docker/distribution/digest"
 	"github.com/docker/distribution/digest"
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/identity"
 	"github.com/docker/swarmkit/identity"
-	"github.com/docker/swarmkit/picker"
+	"github.com/docker/swarmkit/remotes"
 
 
 	"golang.org/x/net/context"
 	"golang.org/x/net/context"
 )
 )
@@ -183,7 +183,7 @@ func getCAHashFromToken(token string) (digest.Digest, error) {
 // LoadOrCreateSecurityConfig encapsulates the security logic behind joining a cluster.
 // LoadOrCreateSecurityConfig encapsulates the security logic behind joining a cluster.
 // Every node requires at least a set of TLS certificates with which to join the cluster with.
 // Every node requires at least a set of TLS certificates with which to join the cluster with.
 // In the case of a manager, these certificates will be used both for client and server credentials.
 // In the case of a manager, these certificates will be used both for client and server credentials.
-func LoadOrCreateSecurityConfig(ctx context.Context, baseCertDir, token, proposedRole string, picker *picker.Picker, nodeInfo chan<- api.IssueNodeCertificateResponse) (*SecurityConfig, error) {
+func LoadOrCreateSecurityConfig(ctx context.Context, baseCertDir, token, proposedRole string, remotes remotes.Remotes, nodeInfo chan<- api.IssueNodeCertificateResponse) (*SecurityConfig, error) {
 	paths := NewConfigPaths(baseCertDir)
 	paths := NewConfigPaths(baseCertDir)
 
 
 	var (
 	var (
@@ -217,7 +217,7 @@ func LoadOrCreateSecurityConfig(ctx context.Context, baseCertDir, token, propose
 		// just been demoted, for example).
 		// just been demoted, for example).
 
 
 		for i := 0; i != 5; i++ {
 		for i := 0; i != 5; i++ {
-			rootCA, err = GetRemoteCA(ctx, d, picker)
+			rootCA, err = GetRemoteCA(ctx, d, remotes)
 			if err == nil {
 			if err == nil {
 				break
 				break
 			}
 			}
@@ -267,7 +267,7 @@ func LoadOrCreateSecurityConfig(ctx context.Context, baseCertDir, token, propose
 		} else {
 		} else {
 			// There was an error loading our Credentials, let's get a new certificate issued
 			// There was an error loading our Credentials, let's get a new certificate issued
 			// Last argument is nil because at this point we don't have any valid TLS creds
 			// Last argument is nil because at this point we don't have any valid TLS creds
-			tlsKeyPair, err = rootCA.RequestAndSaveNewCertificates(ctx, paths.Node, token, picker, nil, nodeInfo)
+			tlsKeyPair, err = rootCA.RequestAndSaveNewCertificates(ctx, paths.Node, token, remotes, nil, nodeInfo)
 			if err != nil {
 			if err != nil {
 				return nil, err
 				return nil, err
 			}
 			}
@@ -300,7 +300,7 @@ func LoadOrCreateSecurityConfig(ctx context.Context, baseCertDir, token, propose
 
 
 // RenewTLSConfig will continuously monitor for the necessity of renewing the local certificates, either by
 // RenewTLSConfig will continuously monitor for the necessity of renewing the local certificates, either by
 // issuing them locally if key-material is available, or requesting them from a remote CA.
 // issuing them locally if key-material is available, or requesting them from a remote CA.
-func RenewTLSConfig(ctx context.Context, s *SecurityConfig, baseCertDir string, picker *picker.Picker, renew <-chan struct{}) <-chan CertificateUpdate {
+func RenewTLSConfig(ctx context.Context, s *SecurityConfig, baseCertDir string, remotes remotes.Remotes, renew <-chan struct{}) <-chan CertificateUpdate {
 	paths := NewConfigPaths(baseCertDir)
 	paths := NewConfigPaths(baseCertDir)
 	updates := make(chan CertificateUpdate)
 	updates := make(chan CertificateUpdate)
 
 
@@ -344,7 +344,7 @@ func RenewTLSConfig(ctx context.Context, s *SecurityConfig, baseCertDir string,
 			tlsKeyPair, err := rootCA.RequestAndSaveNewCertificates(ctx,
 			tlsKeyPair, err := rootCA.RequestAndSaveNewCertificates(ctx,
 				paths.Node,
 				paths.Node,
 				"",
 				"",
-				picker,
+				remotes,
 				s.ClientTLSCreds,
 				s.ClientTLSCreds,
 				nil)
 				nil)
 			if err != nil {
 			if err != nil {

+ 23 - 11
vendor/src/github.com/docker/swarmkit/manager/allocator/network.go

@@ -165,7 +165,7 @@ func (a *Allocator) doNetworkInit(ctx context.Context) error {
 		nodes, err = store.FindNodes(tx, store.All)
 		nodes, err = store.FindNodes(tx, store.All)
 	})
 	})
 	if err != nil {
 	if err != nil {
-		return fmt.Errorf("error listing all services in store while trying to allocate during init: %v", err)
+		return fmt.Errorf("error listing all nodes in store while trying to allocate during init: %v", err)
 	}
 	}
 
 
 	for _, node := range nodes {
 	for _, node := range nodes {
@@ -420,9 +420,9 @@ func taskUpdateEndpoint(t *api.Task, endpoint *api.Endpoint) {
 }
 }
 
 
 func (a *Allocator) taskCreateNetworkAttachments(t *api.Task, s *api.Service) {
 func (a *Allocator) taskCreateNetworkAttachments(t *api.Task, s *api.Service) {
-	// If service is nil or if task network attachments have
-	// already been filled in no need to do anything else.
-	if s == nil || len(t.Networks) != 0 {
+	// If task network attachments have already been filled in no
+	// need to do anything else.
+	if len(t.Networks) != 0 {
 		return
 		return
 	}
 	}
 
 
@@ -431,19 +431,31 @@ func (a *Allocator) taskCreateNetworkAttachments(t *api.Task, s *api.Service) {
 	// The service to which this task belongs is trying to expose
 	// The service to which this task belongs is trying to expose
 	// ports to the external world. Automatically attach the task
 	// ports to the external world. Automatically attach the task
 	// to the ingress network.
 	// to the ingress network.
-	if s.Spec.Endpoint != nil && len(s.Spec.Endpoint.Ports) != 0 {
+	if s != nil && s.Spec.Endpoint != nil && len(s.Spec.Endpoint.Ports) != 0 {
 		networks = append(networks, &api.NetworkAttachment{Network: a.netCtx.ingressNetwork})
 		networks = append(networks, &api.NetworkAttachment{Network: a.netCtx.ingressNetwork})
 	}
 	}
 
 
 	a.store.View(func(tx store.ReadTx) {
 	a.store.View(func(tx store.ReadTx) {
-		for _, na := range s.Spec.Networks {
+		// Always prefer NetworkAttachmentConfig in the TaskSpec
+		specNetworks := t.Spec.Networks
+		if len(specNetworks) == 0 && s != nil && len(s.Spec.Networks) != 0 {
+			specNetworks = s.Spec.Networks
+		}
+
+		for _, na := range specNetworks {
 			n := store.GetNetwork(tx, na.Target)
 			n := store.GetNetwork(tx, na.Target)
 			if n != nil {
 			if n != nil {
 				var aliases []string
 				var aliases []string
+				var addresses []string
+
 				for _, a := range na.Aliases {
 				for _, a := range na.Aliases {
 					aliases = append(aliases, a)
 					aliases = append(aliases, a)
 				}
 				}
-				networks = append(networks, &api.NetworkAttachment{Network: n, Aliases: aliases})
+				for _, a := range na.Addresses {
+					addresses = append(addresses, a)
+				}
+
+				networks = append(networks, &api.NetworkAttachment{Network: n, Aliases: aliases, Addresses: addresses})
 			}
 			}
 		}
 		}
 	})
 	})
@@ -508,12 +520,12 @@ func (a *Allocator) doTaskAlloc(ctx context.Context, nc *networkContext, ev even
 				return
 				return
 			}
 			}
 		}
 		}
-
-		// Populate network attachments in the task
-		// based on service spec.
-		a.taskCreateNetworkAttachments(t, s)
 	}
 	}
 
 
+	// Populate network attachments in the task
+	// based on service spec.
+	a.taskCreateNetworkAttachments(t, s)
+
 	nc.unallocatedTasks[t.ID] = t
 	nc.unallocatedTasks[t.ID] = t
 }
 }
 
 

+ 13 - 3
vendor/src/github.com/docker/swarmkit/manager/allocator/networkallocator/networkallocator.go

@@ -197,8 +197,14 @@ func (na *NetworkAllocator) ServiceAllocate(s *api.Service) (err error) {
 		}
 		}
 	}
 	}
 
 
+	// Always prefer NetworkAttachmentConfig in the TaskSpec
+	specNetworks := s.Spec.Task.Networks
+	if len(specNetworks) == 0 && s != nil && len(s.Spec.Networks) != 0 {
+		specNetworks = s.Spec.Networks
+	}
+
 outer:
 outer:
-	for _, nAttach := range s.Spec.Networks {
+	for _, nAttach := range specNetworks {
 		for _, vip := range s.Endpoint.VirtualIPs {
 		for _, vip := range s.Endpoint.VirtualIPs {
 			if vip.NetworkID == nAttach.Target {
 			if vip.NetworkID == nAttach.Target {
 				continue outer
 				continue outer
@@ -286,7 +292,7 @@ func (na *NetworkAllocator) IsTaskAllocated(t *api.Task) bool {
 func (na *NetworkAllocator) IsServiceAllocated(s *api.Service) bool {
 func (na *NetworkAllocator) IsServiceAllocated(s *api.Service) bool {
 	// If endpoint mode is VIP and allocator does not have the
 	// If endpoint mode is VIP and allocator does not have the
 	// service in VIP allocated set then it is not allocated.
 	// service in VIP allocated set then it is not allocated.
-	if len(s.Spec.Networks) != 0 &&
+	if (len(s.Spec.Task.Networks) != 0 || len(s.Spec.Networks) != 0) &&
 		(s.Spec.Endpoint == nil ||
 		(s.Spec.Endpoint == nil ||
 			s.Spec.Endpoint.Mode == api.ResolutionModeVirtualIP) {
 			s.Spec.Endpoint.Mode == api.ResolutionModeVirtualIP) {
 		if _, ok := na.services[s.ID]; !ok {
 		if _, ok := na.services[s.ID]; !ok {
@@ -527,7 +533,11 @@ func (na *NetworkAllocator) allocateNetworkIPs(nAttach *api.NetworkAttachment) e
 			var err error
 			var err error
 			addr, _, err = net.ParseCIDR(rawAddr)
 			addr, _, err = net.ParseCIDR(rawAddr)
 			if err != nil {
 			if err != nil {
-				return err
+				addr = net.ParseIP(rawAddr)
+
+				if addr == nil {
+					return fmt.Errorf("could not parse address string %s: %v", rawAddr, err)
+				}
 			}
 			}
 		}
 		}
 
 

+ 6 - 1
vendor/src/github.com/docker/swarmkit/manager/controlapi/network.go

@@ -171,7 +171,12 @@ func (s *Server) RemoveNetwork(ctx context.Context, request *api.RemoveNetworkRe
 	}
 	}
 
 
 	for _, s := range services {
 	for _, s := range services {
-		for _, na := range s.Spec.Networks {
+		specNetworks := s.Spec.Task.Networks
+		if len(specNetworks) == 0 {
+			specNetworks = s.Spec.Networks
+		}
+
+		for _, na := range specNetworks {
 			if na.Target == request.NetworkID {
 			if na.Target == request.NetworkID {
 				return nil, grpc.Errorf(codes.FailedPrecondition, "network %s is in use", request.NetworkID)
 				return nil, grpc.Errorf(codes.FailedPrecondition, "network %s is in use", request.NetworkID)
 			}
 			}

+ 14 - 2
vendor/src/github.com/docker/swarmkit/manager/controlapi/service.go

@@ -327,8 +327,20 @@ func (s *Server) UpdateService(ctx context.Context, request *api.UpdateServiceRe
 			return nil
 			return nil
 		}
 		}
 		// temporary disable network update
 		// temporary disable network update
-		if request.Spec != nil && !reflect.DeepEqual(request.Spec.Networks, service.Spec.Networks) {
-			return errNetworkUpdateNotSupported
+		if request.Spec != nil {
+			requestSpecNetworks := request.Spec.Task.Networks
+			if len(requestSpecNetworks) == 0 {
+				requestSpecNetworks = request.Spec.Networks
+			}
+
+			specNetworks := service.Spec.Task.Networks
+			if len(specNetworks) == 0 {
+				specNetworks = service.Spec.Networks
+			}
+
+			if !reflect.DeepEqual(requestSpecNetworks, specNetworks) {
+				return errNetworkUpdateNotSupported
+			}
 		}
 		}
 
 
 		// orchestrator is designed to be stateless, so it should not deal
 		// orchestrator is designed to be stateless, so it should not deal

+ 4 - 4
vendor/src/github.com/docker/swarmkit/manager/dispatcher/dispatcher.go

@@ -19,8 +19,8 @@ import (
 	"github.com/docker/swarmkit/manager/state"
 	"github.com/docker/swarmkit/manager/state"
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/docker/swarmkit/manager/state/watch"
 	"github.com/docker/swarmkit/manager/state/watch"
-	"github.com/docker/swarmkit/picker"
 	"github.com/docker/swarmkit/protobuf/ptypes"
 	"github.com/docker/swarmkit/protobuf/ptypes"
+	"github.com/docker/swarmkit/remotes"
 	"golang.org/x/net/context"
 	"golang.org/x/net/context"
 )
 )
 
 
@@ -153,7 +153,7 @@ func getWeightedPeers(cluster Cluster) []*api.WeightedPeer {
 			// TODO(stevvooe): Calculate weight of manager selection based on
 			// TODO(stevvooe): Calculate weight of manager selection based on
 			// cluster-level observations, such as number of connections and
 			// cluster-level observations, such as number of connections and
 			// load.
 			// load.
-			Weight: picker.DefaultObservationWeight,
+			Weight: remotes.DefaultObservationWeight,
 		})
 		})
 	}
 	}
 	return mgrs
 	return mgrs
@@ -209,7 +209,7 @@ func (d *Dispatcher) Run(ctx context.Context) error {
 		for _, p := range peers {
 		for _, p := range peers {
 			mgrs = append(mgrs, &api.WeightedPeer{
 			mgrs = append(mgrs, &api.WeightedPeer{
 				Peer:   p,
 				Peer:   p,
-				Weight: picker.DefaultObservationWeight,
+				Weight: remotes.DefaultObservationWeight,
 			})
 			})
 		}
 		}
 		d.mu.Lock()
 		d.mu.Lock()
@@ -854,7 +854,7 @@ func (d *Dispatcher) Session(r *api.SessionRequest, stream api.Dispatcher_Sessio
 
 
 	for {
 	for {
 		// After each message send, we need to check the nodes sessionID hasn't
 		// After each message send, we need to check the nodes sessionID hasn't
-		// changed. If it has, we will the stream and make the node
+		// changed. If it has, we will shut down the stream and make the node
 		// re-register.
 		// re-register.
 		node, err := d.nodes.GetWithSession(nodeID, sessionID)
 		node, err := d.nodes.GetWithSession(nodeID, sessionID)
 		if err != nil {
 		if err != nil {

+ 1 - 1
vendor/src/github.com/docker/swarmkit/manager/dispatcher/nodes.go

@@ -86,7 +86,7 @@ func (s *nodeStore) AddUnknown(n *api.Node, expireFunc func()) error {
 	return nil
 	return nil
 }
 }
 
 
-// CheckRateLimit returs error if node with specified id is allowed to re-register
+// CheckRateLimit returns error if node with specified id is allowed to re-register
 // again.
 // again.
 func (s *nodeStore) CheckRateLimit(id string) error {
 func (s *nodeStore) CheckRateLimit(id string) error {
 	s.mu.Lock()
 	s.mu.Lock()

+ 37 - 26
vendor/src/github.com/docker/swarmkit/manager/manager.go

@@ -24,6 +24,7 @@ import (
 	"github.com/docker/swarmkit/manager/keymanager"
 	"github.com/docker/swarmkit/manager/keymanager"
 	"github.com/docker/swarmkit/manager/orchestrator"
 	"github.com/docker/swarmkit/manager/orchestrator"
 	"github.com/docker/swarmkit/manager/raftpicker"
 	"github.com/docker/swarmkit/manager/raftpicker"
+	"github.com/docker/swarmkit/manager/resourceapi"
 	"github.com/docker/swarmkit/manager/scheduler"
 	"github.com/docker/swarmkit/manager/scheduler"
 	"github.com/docker/swarmkit/manager/state/raft"
 	"github.com/docker/swarmkit/manager/state/raft"
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/docker/swarmkit/manager/state/store"
@@ -275,9 +276,12 @@ func (m *Manager) Run(parent context.Context) error {
 	}
 	}
 
 
 	baseControlAPI := controlapi.NewServer(m.RaftNode.MemoryStore(), m.RaftNode, m.config.SecurityConfig.RootCA())
 	baseControlAPI := controlapi.NewServer(m.RaftNode.MemoryStore(), m.RaftNode, m.config.SecurityConfig.RootCA())
+	baseResourceAPI := resourceapi.New(m.RaftNode.MemoryStore())
 	healthServer := health.NewHealthServer()
 	healthServer := health.NewHealthServer()
+	localHealthServer := health.NewHealthServer()
 
 
 	authenticatedControlAPI := api.NewAuthenticatedWrapperControlServer(baseControlAPI, authorize)
 	authenticatedControlAPI := api.NewAuthenticatedWrapperControlServer(baseControlAPI, authorize)
+	authenticatedResourceAPI := api.NewAuthenticatedWrapperResourceAllocatorServer(baseResourceAPI, authorize)
 	authenticatedDispatcherAPI := api.NewAuthenticatedWrapperDispatcherServer(m.Dispatcher, authorize)
 	authenticatedDispatcherAPI := api.NewAuthenticatedWrapperDispatcherServer(m.Dispatcher, authorize)
 	authenticatedCAAPI := api.NewAuthenticatedWrapperCAServer(m.caserver, authorize)
 	authenticatedCAAPI := api.NewAuthenticatedWrapperCAServer(m.caserver, authorize)
 	authenticatedNodeCAAPI := api.NewAuthenticatedWrapperNodeCAServer(m.caserver, authorize)
 	authenticatedNodeCAAPI := api.NewAuthenticatedWrapperNodeCAServer(m.caserver, authorize)
@@ -289,6 +293,7 @@ func (m *Manager) Run(parent context.Context) error {
 	proxyCAAPI := api.NewRaftProxyCAServer(authenticatedCAAPI, cs, m.RaftNode, ca.WithMetadataForwardTLSInfo)
 	proxyCAAPI := api.NewRaftProxyCAServer(authenticatedCAAPI, cs, m.RaftNode, ca.WithMetadataForwardTLSInfo)
 	proxyNodeCAAPI := api.NewRaftProxyNodeCAServer(authenticatedNodeCAAPI, cs, m.RaftNode, ca.WithMetadataForwardTLSInfo)
 	proxyNodeCAAPI := api.NewRaftProxyNodeCAServer(authenticatedNodeCAAPI, cs, m.RaftNode, ca.WithMetadataForwardTLSInfo)
 	proxyRaftMembershipAPI := api.NewRaftProxyRaftMembershipServer(authenticatedRaftMembershipAPI, cs, m.RaftNode, ca.WithMetadataForwardTLSInfo)
 	proxyRaftMembershipAPI := api.NewRaftProxyRaftMembershipServer(authenticatedRaftMembershipAPI, cs, m.RaftNode, ca.WithMetadataForwardTLSInfo)
+	proxyResourceAPI := api.NewRaftProxyResourceAllocatorServer(authenticatedResourceAPI, cs, m.RaftNode, ca.WithMetadataForwardTLSInfo)
 
 
 	// localProxyControlAPI is a special kind of proxy. It is only wired up
 	// localProxyControlAPI is a special kind of proxy. It is only wired up
 	// to receive requests from a trusted local socket, and these requests
 	// to receive requests from a trusted local socket, and these requests
@@ -306,10 +311,13 @@ func (m *Manager) Run(parent context.Context) error {
 	api.RegisterRaftServer(m.server, authenticatedRaftAPI)
 	api.RegisterRaftServer(m.server, authenticatedRaftAPI)
 	api.RegisterHealthServer(m.server, authenticatedHealthAPI)
 	api.RegisterHealthServer(m.server, authenticatedHealthAPI)
 	api.RegisterRaftMembershipServer(m.server, proxyRaftMembershipAPI)
 	api.RegisterRaftMembershipServer(m.server, proxyRaftMembershipAPI)
-	api.RegisterControlServer(m.localserver, localProxyControlAPI)
 	api.RegisterControlServer(m.server, authenticatedControlAPI)
 	api.RegisterControlServer(m.server, authenticatedControlAPI)
+	api.RegisterResourceAllocatorServer(m.server, proxyResourceAPI)
 	api.RegisterDispatcherServer(m.server, proxyDispatcherAPI)
 	api.RegisterDispatcherServer(m.server, proxyDispatcherAPI)
 
 
+	api.RegisterControlServer(m.localserver, localProxyControlAPI)
+	api.RegisterHealthServer(m.localserver, localHealthServer)
+
 	errServe := make(chan error, 2)
 	errServe := make(chan error, 2)
 	for proto, l := range m.listeners {
 	for proto, l := range m.listeners {
 		go m.serveListener(ctx, errServe, proto, l)
 		go m.serveListener(ctx, errServe, proto, l)
@@ -317,11 +325,14 @@ func (m *Manager) Run(parent context.Context) error {
 
 
 	// Set the raft server as serving for the health server
 	// Set the raft server as serving for the health server
 	healthServer.SetServingStatus("Raft", api.HealthCheckResponse_SERVING)
 	healthServer.SetServingStatus("Raft", api.HealthCheckResponse_SERVING)
+	localHealthServer.SetServingStatus("ControlAPI", api.HealthCheckResponse_SERVING)
+
+	defer func() {
+		m.server.Stop()
+		m.localserver.Stop()
+	}()
 
 
 	if err := m.RaftNode.JoinAndStart(); err != nil {
 	if err := m.RaftNode.JoinAndStart(); err != nil {
-		for _, lis := range m.listeners {
-			lis.Close()
-		}
 		return fmt.Errorf("can't initialize raft node: %v", err)
 		return fmt.Errorf("can't initialize raft node: %v", err)
 	}
 	}
 
 
@@ -336,13 +347,11 @@ func (m *Manager) Run(parent context.Context) error {
 	}()
 	}()
 
 
 	if err := raft.WaitForLeader(ctx, m.RaftNode); err != nil {
 	if err := raft.WaitForLeader(ctx, m.RaftNode); err != nil {
-		m.server.Stop()
 		return err
 		return err
 	}
 	}
 
 
 	c, err := raft.WaitForCluster(ctx, m.RaftNode)
 	c, err := raft.WaitForCluster(ctx, m.RaftNode)
 	if err != nil {
 	if err != nil {
-		m.server.Stop()
 		return err
 		return err
 	}
 	}
 	raftConfig := c.Spec.Raft
 	raftConfig := c.Spec.Raft
@@ -527,29 +536,31 @@ func (m *Manager) rotateRootCAKEK(ctx context.Context, clusterID string) error {
 
 
 }
 }
 
 
-// handleLeadershipEvents reads out and discards all of the messages when the manager is stopped,
-// otherwise it handles the is leader event or is follower event.
+// handleLeadershipEvents handles the is leader event or is follower event.
 func (m *Manager) handleLeadershipEvents(ctx context.Context, leadershipCh chan events.Event) {
 func (m *Manager) handleLeadershipEvents(ctx context.Context, leadershipCh chan events.Event) {
-	for leadershipEvent := range leadershipCh {
-		// read out and discard all of the messages when we've stopped
-		// don't acquire the mutex yet. if stopped is closed, we don't need
-		// this stops this loop from starving Run()'s attempt to Lock
+	for {
 		select {
 		select {
-		case <-m.stopped:
-			continue
-		default:
-			// do nothing, we're not stopped
-		}
-		// we're not stopping so NOW acquire the mutex
-		m.mu.Lock()
-		newState := leadershipEvent.(raft.LeadershipState)
+		case leadershipEvent := <-leadershipCh:
+			m.mu.Lock()
+			select {
+			case <-m.stopped:
+				m.mu.Unlock()
+				return
+			default:
+			}
+			newState := leadershipEvent.(raft.LeadershipState)
 
 
-		if newState == raft.IsLeader {
-			m.becomeLeader(ctx)
-		} else if newState == raft.IsFollower {
-			m.becomeFollower()
+			if newState == raft.IsLeader {
+				m.becomeLeader(ctx)
+			} else if newState == raft.IsFollower {
+				m.becomeFollower()
+			}
+			m.mu.Unlock()
+		case <-m.stopped:
+			return
+		case <-ctx.Done():
+			return
 		}
 		}
-		m.mu.Unlock()
 	}
 	}
 }
 }
 
 
@@ -609,7 +620,7 @@ func (m *Manager) becomeLeader(ctx context.Context) {
 	m.globalOrchestrator = orchestrator.NewGlobalOrchestrator(s)
 	m.globalOrchestrator = orchestrator.NewGlobalOrchestrator(s)
 	m.taskReaper = orchestrator.NewTaskReaper(s)
 	m.taskReaper = orchestrator.NewTaskReaper(s)
 	m.scheduler = scheduler.New(s)
 	m.scheduler = scheduler.New(s)
-	m.keyManager = keymanager.New(m.RaftNode.MemoryStore(), keymanager.DefaultConfig())
+	m.keyManager = keymanager.New(s, keymanager.DefaultConfig())
 
 
 	// TODO(stevvooe): Allocate a context that can be used to
 	// TODO(stevvooe): Allocate a context that can be used to
 	// shutdown underlying manager processes when leadership is
 	// shutdown underlying manager processes when leadership is

+ 17 - 26
vendor/src/github.com/docker/swarmkit/manager/orchestrator/updater.go

@@ -288,16 +288,8 @@ func (u *Updater) updateTask(ctx context.Context, slot slot, updated *api.Task)
 			return err
 			return err
 		}
 		}
 
 
-		u.removeOldTasks(ctx, batch, slot)
-
-		for _, t := range slot {
-			if t.DesiredState == api.TaskStateRunning {
-				// Wait for the old task to stop or time out, and then set the new one
-				// to RUNNING.
-				delayStartCh = u.restarts.DelayStart(ctx, nil, t, updated.ID, 0, true)
-				break
-			}
-		}
+		oldTask := u.removeOldTasks(ctx, batch, slot)
+		delayStartCh = u.restarts.DelayStart(ctx, nil, oldTask, updated.ID, 0, true)
 
 
 		return nil
 		return nil
 
 
@@ -333,34 +325,29 @@ func (u *Updater) useExistingTask(ctx context.Context, slot slot, existing *api.
 		}
 		}
 	}
 	}
 	if len(removeTasks) != 0 || existing.DesiredState != api.TaskStateRunning {
 	if len(removeTasks) != 0 || existing.DesiredState != api.TaskStateRunning {
+		var delayStartCh <-chan struct{}
 		_, err := u.store.Batch(func(batch *store.Batch) error {
 		_, err := u.store.Batch(func(batch *store.Batch) error {
-			u.removeOldTasks(ctx, batch, removeTasks)
+			oldTask := u.removeOldTasks(ctx, batch, removeTasks)
 
 
 			if existing.DesiredState != api.TaskStateRunning {
 			if existing.DesiredState != api.TaskStateRunning {
-				err := batch.Update(func(tx store.Tx) error {
-					t := store.GetTask(tx, existing.ID)
-					if t == nil {
-						return fmt.Errorf("task %s not found while trying to start it", existing.ID)
-					}
-					if t.DesiredState >= api.TaskStateRunning {
-						return fmt.Errorf("task %s was already started when reached by updater", existing.ID)
-					}
-					t.DesiredState = api.TaskStateRunning
-					return store.UpdateTask(tx, t)
-				})
-				if err != nil {
-					log.G(ctx).WithError(err).Errorf("starting task %s failed", existing.ID)
-				}
+				delayStartCh = u.restarts.DelayStart(ctx, nil, oldTask, existing.ID, 0, true)
 			}
 			}
 			return nil
 			return nil
 		})
 		})
 		if err != nil {
 		if err != nil {
 			log.G(ctx).WithError(err).Error("updater batch transaction failed")
 			log.G(ctx).WithError(err).Error("updater batch transaction failed")
 		}
 		}
+
+		if delayStartCh != nil {
+			<-delayStartCh
+		}
 	}
 	}
 }
 }
 
 
-func (u *Updater) removeOldTasks(ctx context.Context, batch *store.Batch, removeTasks []*api.Task) {
+// removeOldTasks shuts down the given tasks and returns one of the tasks that
+// was shut down, or nil.
+func (u *Updater) removeOldTasks(ctx context.Context, batch *store.Batch, removeTasks []*api.Task) *api.Task {
+	var removedTask *api.Task
 	for _, original := range removeTasks {
 	for _, original := range removeTasks {
 		err := batch.Update(func(tx store.Tx) error {
 		err := batch.Update(func(tx store.Tx) error {
 			t := store.GetTask(tx, original.ID)
 			t := store.GetTask(tx, original.ID)
@@ -375,8 +362,12 @@ func (u *Updater) removeOldTasks(ctx context.Context, batch *store.Batch, remove
 		})
 		})
 		if err != nil {
 		if err != nil {
 			log.G(ctx).WithError(err).Errorf("shutting down stale task %s failed", original.ID)
 			log.G(ctx).WithError(err).Errorf("shutting down stale task %s failed", original.ID)
+		} else {
+			removedTask = original
 		}
 		}
 	}
 	}
+
+	return removedTask
 }
 }
 
 
 func (u *Updater) isTaskDirty(t *api.Task) bool {
 func (u *Updater) isTaskDirty(t *api.Task) bool {

+ 124 - 0
vendor/src/github.com/docker/swarmkit/manager/resourceapi/allocator.go

@@ -0,0 +1,124 @@
+package resourceapi
+
+import (
+	"errors"
+	"time"
+
+	"github.com/docker/swarmkit/api"
+	"github.com/docker/swarmkit/ca"
+	"github.com/docker/swarmkit/identity"
+	"github.com/docker/swarmkit/manager/state/store"
+	"github.com/docker/swarmkit/protobuf/ptypes"
+	"golang.org/x/net/context"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/codes"
+)
+
+var (
+	errInvalidArgument = errors.New("invalid argument")
+)
+
+// ResourceAllocator handles resource allocation of cluster entities.
+type ResourceAllocator struct {
+	store *store.MemoryStore
+}
+
+// New returns an instance of the allocator
+func New(store *store.MemoryStore) *ResourceAllocator {
+	return &ResourceAllocator{store: store}
+}
+
+// AttachNetwork allows the node to request the resources
+// allocation needed for a network attachment on the specific node.
+// - Returns `InvalidArgument` if the Spec is malformed.
+// - Returns `NotFound` if the Network is not found.
+// - Returns `PermissionDenied` if the Network is not manually attachable.
+// - Returns an error if the creation fails.
+func (ra *ResourceAllocator) AttachNetwork(ctx context.Context, request *api.AttachNetworkRequest) (*api.AttachNetworkResponse, error) {
+	nodeInfo, err := ca.RemoteNode(ctx)
+	if err != nil {
+		return nil, err
+	}
+
+	var network *api.Network
+	ra.store.View(func(tx store.ReadTx) {
+		network = store.GetNetwork(tx, request.Config.Target)
+		if network == nil {
+			if networks, err := store.FindNetworks(tx, store.ByName(request.Config.Target)); err == nil && len(networks) == 1 {
+				network = networks[0]
+			}
+		}
+	})
+	if network == nil {
+		return nil, grpc.Errorf(codes.NotFound, "network %s not found", request.Config.Target)
+	}
+
+	if !network.Spec.Attachable {
+		return nil, grpc.Errorf(codes.PermissionDenied, "network %s not manually attachable", request.Config.Target)
+	}
+
+	t := &api.Task{
+		ID:     identity.NewID(),
+		NodeID: nodeInfo.NodeID,
+		Spec: api.TaskSpec{
+			Runtime: &api.TaskSpec_Attachment{
+				Attachment: &api.NetworkAttachmentSpec{
+					ContainerID: request.ContainerID,
+				},
+			},
+			Networks: []*api.NetworkAttachmentConfig{
+				{
+					Target:    network.ID,
+					Addresses: request.Config.Addresses,
+				},
+			},
+		},
+		Status: api.TaskStatus{
+			State:     api.TaskStateNew,
+			Timestamp: ptypes.MustTimestampProto(time.Now()),
+			Message:   "created",
+		},
+		DesiredState: api.TaskStateRunning,
+		// TODO: Add Network attachment.
+	}
+
+	if err := ra.store.Update(func(tx store.Tx) error {
+		return store.CreateTask(tx, t)
+	}); err != nil {
+		return nil, err
+	}
+
+	return &api.AttachNetworkResponse{AttachmentID: t.ID}, nil
+}
+
+// DetachNetwork allows the node to request the release of
+// the resources associated to the network attachment.
+// - Returns `InvalidArgument` if attachment ID is not provided.
+// - Returns `NotFound` if the attachment is not found.
+// - Returns an error if the deletion fails.
+func (ra *ResourceAllocator) DetachNetwork(ctx context.Context, request *api.DetachNetworkRequest) (*api.DetachNetworkResponse, error) {
+	if request.AttachmentID == "" {
+		return nil, grpc.Errorf(codes.InvalidArgument, errInvalidArgument.Error())
+	}
+
+	nodeInfo, err := ca.RemoteNode(ctx)
+	if err != nil {
+		return nil, err
+	}
+
+	if err := ra.store.Update(func(tx store.Tx) error {
+		t := store.GetTask(tx, request.AttachmentID)
+		if t == nil {
+			return grpc.Errorf(codes.NotFound, "attachment %s not found", request.AttachmentID)
+		}
+		if t.NodeID != nodeInfo.NodeID {
+			return grpc.Errorf(codes.PermissionDenied, "attachment %s doesn't belong to this node", request.AttachmentID)
+		}
+
+		return store.DeleteTask(tx, request.AttachmentID)
+	}); err != nil {
+		return nil, err
+	}
+
+	return &api.DetachNetworkResponse{}, nil
+}

+ 78 - 15
vendor/src/github.com/docker/swarmkit/manager/state/raft/membership/cluster.go

@@ -33,7 +33,8 @@ type Cluster struct {
 
 
 	// removed contains the list of removed Members,
 	// removed contains the list of removed Members,
 	// those ids cannot be reused
 	// those ids cannot be reused
-	removed map[uint64]bool
+	removed        map[uint64]bool
+	heartbeatTicks int
 
 
 	PeersBroadcast *watch.Queue
 	PeersBroadcast *watch.Queue
 }
 }
@@ -43,21 +44,40 @@ type Member struct {
 	*api.RaftMember
 	*api.RaftMember
 
 
 	api.RaftClient
 	api.RaftClient
-	Conn *grpc.ClientConn
+	Conn   *grpc.ClientConn
+	tick   int
+	active bool
 }
 }
 
 
-// NewCluster creates a new Cluster neighbors
-// list for a raft Member
-func NewCluster() *Cluster {
+// NewCluster creates a new Cluster neighbors list for a raft Member.
+// Member marked as inactive if there was no call ReportActive for heartbeatInterval.
+func NewCluster(heartbeatTicks int) *Cluster {
 	// TODO(abronan): generate Cluster ID for federation
 	// TODO(abronan): generate Cluster ID for federation
 
 
 	return &Cluster{
 	return &Cluster{
 		members:        make(map[uint64]*Member),
 		members:        make(map[uint64]*Member),
 		removed:        make(map[uint64]bool),
 		removed:        make(map[uint64]bool),
+		heartbeatTicks: heartbeatTicks,
 		PeersBroadcast: watch.NewQueue(),
 		PeersBroadcast: watch.NewQueue(),
 	}
 	}
 }
 }
 
 
+// Tick increases ticks for all members. After heartbeatTicks node marked as
+// inactive.
+func (c *Cluster) Tick() {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	for _, m := range c.members {
+		if !m.active {
+			continue
+		}
+		m.tick++
+		if m.tick > c.heartbeatTicks {
+			m.active = false
+		}
+	}
+}
+
 // Members returns the list of raft Members in the Cluster.
 // Members returns the list of raft Members in the Cluster.
 func (c *Cluster) Members() map[uint64]*Member {
 func (c *Cluster) Members() map[uint64]*Member {
 	members := make(map[uint64]*Member)
 	members := make(map[uint64]*Member)
@@ -106,26 +126,42 @@ func (c *Cluster) AddMember(member *Member) error {
 	if c.removed[member.RaftID] {
 	if c.removed[member.RaftID] {
 		return ErrIDRemoved
 		return ErrIDRemoved
 	}
 	}
+	member.active = true
+	member.tick = 0
 
 
 	c.members[member.RaftID] = member
 	c.members[member.RaftID] = member
+
 	c.broadcastUpdate()
 	c.broadcastUpdate()
 	return nil
 	return nil
 }
 }
 
 
-// RemoveMember removes a node from the Cluster Memberlist.
+// RemoveMember removes a node from the Cluster Memberlist, and adds it to
+// the removed list.
 func (c *Cluster) RemoveMember(id uint64) error {
 func (c *Cluster) RemoveMember(id uint64) error {
 	c.mu.Lock()
 	c.mu.Lock()
 	defer c.mu.Unlock()
 	defer c.mu.Unlock()
+	c.removed[id] = true
+
+	return c.clearMember(id)
+}
 
 
-	if c.members[id] != nil {
-		conn := c.members[id].Conn
-		if conn != nil {
-			_ = conn.Close()
+// ClearMember removes a node from the Cluster Memberlist, but does NOT add it
+// to the removed list.
+func (c *Cluster) ClearMember(id uint64) error {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+
+	return c.clearMember(id)
+}
+
+func (c *Cluster) clearMember(id uint64) error {
+	m, ok := c.members[id]
+	if ok {
+		if m.Conn != nil {
+			m.Conn.Close()
 		}
 		}
 		delete(c.members, id)
 		delete(c.members, id)
 	}
 	}
-
-	c.removed[id] = true
 	c.broadcastUpdate()
 	c.broadcastUpdate()
 	return nil
 	return nil
 }
 }
@@ -152,7 +188,6 @@ func (c *Cluster) ReplaceMemberConnection(id uint64, oldConn *Member, newConn *M
 	newMember := *oldMember
 	newMember := *oldMember
 	newMember.Conn = newConn.Conn
 	newMember.Conn = newConn.Conn
 	newMember.RaftClient = newConn.RaftClient
 	newMember.RaftClient = newConn.RaftClient
-
 	c.members[id] = &newMember
 	c.members[id] = &newMember
 
 
 	return nil
 	return nil
@@ -168,11 +203,40 @@ func (c *Cluster) IsIDRemoved(id uint64) bool {
 // Clear resets the list of active Members and removed Members.
 // Clear resets the list of active Members and removed Members.
 func (c *Cluster) Clear() {
 func (c *Cluster) Clear() {
 	c.mu.Lock()
 	c.mu.Lock()
+	for _, member := range c.members {
+		if member.Conn != nil {
+			member.Conn.Close()
+		}
+	}
+
 	c.members = make(map[uint64]*Member)
 	c.members = make(map[uint64]*Member)
 	c.removed = make(map[uint64]bool)
 	c.removed = make(map[uint64]bool)
 	c.mu.Unlock()
 	c.mu.Unlock()
 }
 }
 
 
+// ReportActive reports that member is acive (called ProcessRaftMessage),
+func (c *Cluster) ReportActive(id uint64) {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	m, ok := c.members[id]
+	if !ok {
+		return
+	}
+	m.tick = 0
+	m.active = true
+}
+
+// Active returns true if node is active.
+func (c *Cluster) Active(id uint64) bool {
+	c.mu.RLock()
+	defer c.mu.RUnlock()
+	m, ok := c.members[id]
+	if !ok {
+		return false
+	}
+	return m.active
+}
+
 // ValidateConfigurationChange takes a proposed ConfChange and
 // ValidateConfigurationChange takes a proposed ConfChange and
 // ensures that it is valid.
 // ensures that it is valid.
 func (c *Cluster) ValidateConfigurationChange(cc raftpb.ConfChange) error {
 func (c *Cluster) ValidateConfigurationChange(cc raftpb.ConfChange) error {
@@ -223,8 +287,7 @@ func (c *Cluster) CanRemoveMember(from uint64, id uint64) bool {
 			continue
 			continue
 		}
 		}
 
 
-		connState, err := m.Conn.State()
-		if err == nil && connState == grpc.Ready {
+		if c.Active(m.RaftID) {
 			nreachable++
 			nreachable++
 		}
 		}
 	}
 	}

+ 56 - 31
vendor/src/github.com/docker/swarmkit/manager/state/raft/raft.go

@@ -86,7 +86,6 @@ type Node struct {
 
 
 	Address  string
 	Address  string
 	StateDir string
 	StateDir string
-	Error    error
 
 
 	raftStore           *raft.MemoryStorage
 	raftStore           *raft.MemoryStorage
 	memoryStore         *store.MemoryStore
 	memoryStore         *store.MemoryStore
@@ -119,6 +118,7 @@ type Node struct {
 	leadershipBroadcast *watch.Queue
 	leadershipBroadcast *watch.Queue
 
 
 	// used to coordinate shutdown
 	// used to coordinate shutdown
+	// Lock should be used only in stop(), all other functions should use RLock.
 	stopMu sync.RWMutex
 	stopMu sync.RWMutex
 	// used for membership management checks
 	// used for membership management checks
 	membershipLock sync.Mutex
 	membershipLock sync.Mutex
@@ -176,7 +176,7 @@ func NewNode(ctx context.Context, opts NewNodeOptions) *Node {
 	n := &Node{
 	n := &Node{
 		Ctx:            ctx,
 		Ctx:            ctx,
 		cancel:         cancel,
 		cancel:         cancel,
-		cluster:        membership.NewCluster(),
+		cluster:        membership.NewCluster(cfg.ElectionTick),
 		tlsCredentials: opts.TLSCredentials,
 		tlsCredentials: opts.TLSCredentials,
 		raftStore:      raftStore,
 		raftStore:      raftStore,
 		Address:        opts.Addr,
 		Address:        opts.Addr,
@@ -224,10 +224,15 @@ func NewNode(ctx context.Context, opts NewNodeOptions) *Node {
 }
 }
 
 
 // JoinAndStart joins and starts the raft server
 // JoinAndStart joins and starts the raft server
-func (n *Node) JoinAndStart() error {
+func (n *Node) JoinAndStart() (err error) {
+	defer func() {
+		if err != nil {
+			n.done()
+		}
+	}()
+
 	loadAndStartErr := n.loadAndStart(n.Ctx, n.opts.ForceNewCluster)
 	loadAndStartErr := n.loadAndStart(n.Ctx, n.opts.ForceNewCluster)
 	if loadAndStartErr != nil && loadAndStartErr != errNoWAL {
 	if loadAndStartErr != nil && loadAndStartErr != errNoWAL {
-		n.ticker.Stop()
 		return loadAndStartErr
 		return loadAndStartErr
 	}
 	}
 
 
@@ -270,6 +275,9 @@ func (n *Node) JoinAndStart() error {
 			n.Node = raft.StartNode(n.Config, []raft.Peer{})
 			n.Node = raft.StartNode(n.Config, []raft.Peer{})
 
 
 			if err := n.registerNodes(resp.Members); err != nil {
 			if err := n.registerNodes(resp.Members); err != nil {
+				if walErr := n.wal.Close(); err != nil {
+					n.Config.Logger.Errorf("raft: error closing WAL: %v", walErr)
+				}
 				return err
 				return err
 			}
 			}
 		} else {
 		} else {
@@ -281,6 +289,9 @@ func (n *Node) JoinAndStart() error {
 			}
 			}
 			n.Node = raft.StartNode(n.Config, []raft.Peer{peer})
 			n.Node = raft.StartNode(n.Config, []raft.Peer{peer})
 			if err := n.Campaign(n.Ctx); err != nil {
 			if err := n.Campaign(n.Ctx); err != nil {
+				if walErr := n.wal.Close(); err != nil {
+					n.Config.Logger.Errorf("raft: error closing WAL: %v", walErr)
+				}
 				return err
 				return err
 			}
 			}
 		}
 		}
@@ -324,15 +335,24 @@ func (n *Node) MemoryStore() *store.MemoryStore {
 	return n.memoryStore
 	return n.memoryStore
 }
 }
 
 
+func (n *Node) done() {
+	n.cluster.Clear()
+
+	n.ticker.Stop()
+	n.leadershipBroadcast.Close()
+	n.cluster.PeersBroadcast.Close()
+	n.memoryStore.Close()
+
+	close(n.doneCh)
+}
+
 // Run is the main loop for a Raft node, it goes along the state machine,
 // Run is the main loop for a Raft node, it goes along the state machine,
 // acting on the messages received from other Raft nodes in the cluster.
 // acting on the messages received from other Raft nodes in the cluster.
 //
 //
 // Before running the main loop, it first starts the raft node based on saved
 // Before running the main loop, it first starts the raft node based on saved
 // cluster state. If no saved state exists, it starts a single-node cluster.
 // cluster state. If no saved state exists, it starts a single-node cluster.
 func (n *Node) Run(ctx context.Context) error {
 func (n *Node) Run(ctx context.Context) error {
-	defer func() {
-		close(n.doneCh)
-	}()
+	defer n.done()
 
 
 	wasLeader := false
 	wasLeader := false
 
 
@@ -340,7 +360,7 @@ func (n *Node) Run(ctx context.Context) error {
 		select {
 		select {
 		case <-n.ticker.C():
 		case <-n.ticker.C():
 			n.Tick()
 			n.Tick()
-
+			n.cluster.Tick()
 		case rd := <-n.Ready():
 		case rd := <-n.Ready():
 			raftConfig := DefaultRaftConfig()
 			raftConfig := DefaultRaftConfig()
 			n.memoryStore.View(func(readTx store.ReadTx) {
 			n.memoryStore.View(func(readTx store.ReadTx) {
@@ -453,9 +473,6 @@ func (n *Node) Run(ctx context.Context) error {
 			return ErrMemberRemoved
 			return ErrMemberRemoved
 		case <-n.stopCh:
 		case <-n.stopCh:
 			n.stop()
 			n.stop()
-			n.leadershipBroadcast.Close()
-			n.cluster.PeersBroadcast.Close()
-			n.memoryStore.Close()
 			return nil
 			return nil
 		}
 		}
 	}
 	}
@@ -481,13 +498,6 @@ func (n *Node) stop() {
 	n.waitProp.Wait()
 	n.waitProp.Wait()
 	n.asyncTasks.Wait()
 	n.asyncTasks.Wait()
 
 
-	members := n.cluster.Members()
-	for _, member := range members {
-		if member.Conn != nil {
-			_ = member.Conn.Close()
-		}
-	}
-
 	n.Stop()
 	n.Stop()
 	n.ticker.Stop()
 	n.ticker.Stop()
 	if err := n.wal.Close(); err != nil {
 	if err := n.wal.Close(); err != nil {
@@ -517,20 +527,26 @@ func (n *Node) IsLeader() bool {
 	return n.isLeader()
 	return n.isLeader()
 }
 }
 
 
-// leader returns the id of the leader, without the protection of lock
+// leader returns the id of the leader, without the protection of lock and
+// membership check, so it's caller task.
 func (n *Node) leader() uint64 {
 func (n *Node) leader() uint64 {
-	if !n.IsMember() {
-		return 0
-	}
 	return n.Node.Status().Lead
 	return n.Node.Status().Lead
 }
 }
 
 
 // Leader returns the id of the leader, with the protection of lock
 // Leader returns the id of the leader, with the protection of lock
-func (n *Node) Leader() uint64 {
+func (n *Node) Leader() (uint64, error) {
 	n.stopMu.RLock()
 	n.stopMu.RLock()
 	defer n.stopMu.RUnlock()
 	defer n.stopMu.RUnlock()
 
 
-	return n.leader()
+	if !n.IsMember() {
+		return 0, ErrNoRaftMember
+	}
+	leader := n.leader()
+	if leader == 0 {
+		return 0, ErrNoClusterLeader
+	}
+
+	return leader, nil
 }
 }
 
 
 // ReadyForProposals returns true if the node has broadcasted a message
 // ReadyForProposals returns true if the node has broadcasted a message
@@ -760,6 +776,8 @@ func (n *Node) ProcessRaftMessage(ctx context.Context, msg *api.ProcessRaftMessa
 		return nil, ErrMemberRemoved
 		return nil, ErrMemberRemoved
 	}
 	}
 
 
+	n.cluster.ReportActive(msg.Message.From)
+
 	if msg.Message.Type == raftpb.MsgProp {
 	if msg.Message.Type == raftpb.MsgProp {
 		// We don't accepted forwarded proposals. Our
 		// We don't accepted forwarded proposals. Our
 		// current architecture depends on only the leader
 		// current architecture depends on only the leader
@@ -923,15 +941,17 @@ func (n *Node) SubscribePeers() (q chan events.Event, cancel func()) {
 func (n *Node) GetMemberlist() map[uint64]*api.RaftMember {
 func (n *Node) GetMemberlist() map[uint64]*api.RaftMember {
 	memberlist := make(map[uint64]*api.RaftMember)
 	memberlist := make(map[uint64]*api.RaftMember)
 	members := n.cluster.Members()
 	members := n.cluster.Members()
-	leaderID := n.Leader()
+	leaderID, err := n.Leader()
+	if err != nil {
+		leaderID = 0
+	}
 
 
 	for id, member := range members {
 	for id, member := range members {
 		reachability := api.RaftMemberStatus_REACHABLE
 		reachability := api.RaftMemberStatus_REACHABLE
 		leader := false
 		leader := false
 
 
 		if member.RaftID != n.Config.ID {
 		if member.RaftID != n.Config.ID {
-			connState, err := member.Conn.State()
-			if err != nil || connState != grpc.Ready {
+			if !n.cluster.Active(member.RaftID) {
 				reachability = api.RaftMemberStatus_UNREACHABLE
 				reachability = api.RaftMemberStatus_UNREACHABLE
 			}
 			}
 		}
 		}
@@ -1111,7 +1131,10 @@ func (n *Node) sendToMember(members map[uint64]*membership.Member, m raftpb.Mess
 		if err != nil {
 		if err != nil {
 			n.Config.Logger.Errorf("could connect to member ID %x at %s: %v", m.To, conn.Addr, err)
 			n.Config.Logger.Errorf("could connect to member ID %x at %s: %v", m.To, conn.Addr, err)
 		} else {
 		} else {
-			n.cluster.ReplaceMemberConnection(m.To, conn, newConn)
+			err = n.cluster.ReplaceMemberConnection(m.To, conn, newConn)
+			if err != nil {
+				newConn.Conn.Close()
+			}
 		}
 		}
 	} else if m.Type == raftpb.MsgSnap {
 	} else if m.Type == raftpb.MsgSnap {
 		n.ReportSnapshot(m.To, raft.SnapshotFinish)
 		n.ReportSnapshot(m.To, raft.SnapshotFinish)
@@ -1129,12 +1152,14 @@ type applyResult struct {
 // an error or until the raft node finalizes all the proposals on node
 // an error or until the raft node finalizes all the proposals on node
 // shutdown.
 // shutdown.
 func (n *Node) processInternalRaftRequest(ctx context.Context, r *api.InternalRaftRequest, cb func()) (proto.Message, error) {
 func (n *Node) processInternalRaftRequest(ctx context.Context, r *api.InternalRaftRequest, cb func()) (proto.Message, error) {
-	n.waitProp.Add(1)
-	defer n.waitProp.Done()
-
+	n.stopMu.RLock()
 	if !n.canSubmitProposal() {
 	if !n.canSubmitProposal() {
+		n.stopMu.RUnlock()
 		return nil, ErrStopped
 		return nil, ErrStopped
 	}
 	}
+	n.waitProp.Add(1)
+	defer n.waitProp.Done()
+	n.stopMu.RUnlock()
 
 
 	r.ID = n.reqIDGen.Next()
 	r.ID = n.reqIDGen.Next()
 
 

+ 7 - 1
vendor/src/github.com/docker/swarmkit/manager/state/raft/storage.go

@@ -445,18 +445,24 @@ func (n *Node) restoreFromSnapshot(data []byte, forceNewCluster bool) error {
 		return err
 		return err
 	}
 	}
 
 
-	n.cluster.Clear()
+	oldMembers := n.cluster.Members()
 
 
 	if !forceNewCluster {
 	if !forceNewCluster {
 		for _, member := range snapshot.Membership.Members {
 		for _, member := range snapshot.Membership.Members {
 			if err := n.registerNode(&api.RaftMember{RaftID: member.RaftID, NodeID: member.NodeID, Addr: member.Addr}); err != nil {
 			if err := n.registerNode(&api.RaftMember{RaftID: member.RaftID, NodeID: member.NodeID, Addr: member.Addr}); err != nil {
 				return err
 				return err
 			}
 			}
+			delete(oldMembers, member.RaftID)
 		}
 		}
 	}
 	}
 
 
 	for _, removedMember := range snapshot.Membership.Removed {
 	for _, removedMember := range snapshot.Membership.Removed {
 		n.cluster.RemoveMember(removedMember)
 		n.cluster.RemoveMember(removedMember)
+		delete(oldMembers, removedMember)
+	}
+
+	for member := range oldMembers {
+		n.cluster.ClearMember(member)
 	}
 	}
 
 
 	return nil
 	return nil

+ 4 - 4
vendor/src/github.com/docker/swarmkit/manager/state/raft/util.go

@@ -35,19 +35,19 @@ func Register(server *grpc.Server, node *Node) {
 // WaitForLeader waits until node observe some leader in cluster. It returns
 // WaitForLeader waits until node observe some leader in cluster. It returns
 // error if ctx was cancelled before leader appeared.
 // error if ctx was cancelled before leader appeared.
 func WaitForLeader(ctx context.Context, n *Node) error {
 func WaitForLeader(ctx context.Context, n *Node) error {
-	l := n.Leader()
-	if l != 0 {
+	_, err := n.Leader()
+	if err == nil {
 		return nil
 		return nil
 	}
 	}
 	ticker := time.NewTicker(50 * time.Millisecond)
 	ticker := time.NewTicker(50 * time.Millisecond)
 	defer ticker.Stop()
 	defer ticker.Stop()
-	for l == 0 {
+	for err != nil {
 		select {
 		select {
 		case <-ticker.C:
 		case <-ticker.C:
 		case <-ctx.Done():
 		case <-ctx.Done():
 			return ctx.Err()
 			return ctx.Err()
 		}
 		}
-		l = n.Leader()
+		_, err = n.Leader()
 	}
 	}
 	return nil
 	return nil
 }
 }

+ 1 - 135
vendor/src/github.com/docker/swarmkit/picker/picker.go → vendor/src/github.com/docker/swarmkit/remotes/remotes.go

@@ -1,4 +1,4 @@
-package picker
+package remotes
 
 
 import (
 import (
 	"fmt"
 	"fmt"
@@ -8,9 +8,6 @@ import (
 	"sync"
 	"sync"
 
 
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/api"
-	"golang.org/x/net/context"
-	"google.golang.org/grpc"
-	"google.golang.org/grpc/transport"
 )
 )
 
 
 var errRemotesUnavailable = fmt.Errorf("no remote hosts provided")
 var errRemotesUnavailable = fmt.Errorf("no remote hosts provided")
@@ -204,134 +201,3 @@ func (mwr *remotesWeightedRandom) observe(peer api.Peer, weight float64) {
 
 
 	mwr.remotes[peer] = int(math.Ceil(wn))
 	mwr.remotes[peer] = int(math.Ceil(wn))
 }
 }
-
-// Picker implements a grpc Picker
-type Picker struct {
-	r    Remotes
-	peer api.Peer // currently selected remote peer
-	conn *grpc.Conn
-	mu   sync.Mutex
-}
-
-var _ grpc.Picker = &Picker{}
-
-// NewPicker returns a Picker
-func NewPicker(r Remotes, initial ...string) *Picker {
-	var peer api.Peer
-	if len(initial) == 0 {
-		peer, _ = r.Select() // empty in case of error
-	} else {
-		peer = api.Peer{Addr: initial[0]}
-	}
-	return &Picker{r: r, peer: peer}
-}
-
-// Init does initial processing for the Picker, e.g., initiate some connections.
-func (p *Picker) Init(cc *grpc.ClientConn) error {
-	p.mu.Lock()
-	peer := p.peer
-	p.mu.Unlock()
-
-	p.r.ObserveIfExists(peer, DefaultObservationWeight)
-	c, err := grpc.NewConn(cc)
-	if err != nil {
-		return err
-	}
-
-	p.mu.Lock()
-	p.conn = c
-	p.mu.Unlock()
-	return nil
-}
-
-// Pick blocks until either a transport.ClientTransport is ready for the upcoming RPC
-// or some error happens.
-func (p *Picker) Pick(ctx context.Context) (transport.ClientTransport, error) {
-	p.mu.Lock()
-	peer := p.peer
-	p.mu.Unlock()
-	transport, err := p.conn.Wait(ctx)
-	if err != nil {
-		p.r.ObserveIfExists(peer, -DefaultObservationWeight)
-	}
-
-	return transport, err
-}
-
-// PickAddr picks a peer address for connecting. This will be called repeated for
-// connecting/reconnecting.
-func (p *Picker) PickAddr() (string, error) {
-	p.mu.Lock()
-	peer := p.peer
-	p.mu.Unlock()
-
-	p.r.ObserveIfExists(peer, -DefaultObservationWeight) // downweight the current addr
-
-	var err error
-	peer, err = p.r.Select()
-	if err != nil {
-		return "", err
-	}
-
-	p.mu.Lock()
-	p.peer = peer
-	p.mu.Unlock()
-	return peer.Addr, err
-}
-
-// State returns the connectivity state of the underlying connections.
-func (p *Picker) State() (grpc.ConnectivityState, error) {
-	return p.conn.State(), nil
-}
-
-// WaitForStateChange blocks until the state changes to something other than
-// the sourceState. It returns the new state or error.
-func (p *Picker) WaitForStateChange(ctx context.Context, sourceState grpc.ConnectivityState) (grpc.ConnectivityState, error) {
-	p.mu.Lock()
-	conn := p.conn
-	peer := p.peer
-	p.mu.Unlock()
-
-	state, err := conn.WaitForStateChange(ctx, sourceState)
-	if err != nil {
-		return state, err
-	}
-
-	// TODO(stevvooe): We may want to actually score the transition by checking
-	// sourceState.
-
-	// TODO(stevvooe): This is questionable, but we'll see how it works.
-	switch state {
-	case grpc.Idle:
-		p.r.ObserveIfExists(peer, DefaultObservationWeight)
-	case grpc.Connecting:
-		p.r.ObserveIfExists(peer, DefaultObservationWeight)
-	case grpc.Ready:
-		p.r.ObserveIfExists(peer, DefaultObservationWeight)
-	case grpc.TransientFailure:
-		p.r.ObserveIfExists(peer, -DefaultObservationWeight)
-	case grpc.Shutdown:
-		p.r.ObserveIfExists(peer, -DefaultObservationWeight)
-	}
-
-	return state, err
-}
-
-// Reset the current connection and force a reconnect to another address.
-func (p *Picker) Reset() error {
-	p.mu.Lock()
-	conn := p.conn
-	p.mu.Unlock()
-
-	conn.NotifyReset()
-	return nil
-}
-
-// Close closes all the Conn's owned by this Picker.
-func (p *Picker) Close() error {
-	p.mu.Lock()
-	conn := p.conn
-	p.mu.Unlock()
-
-	return conn.Close()
-}

+ 43 - 13
vendor/src/github.com/google/certificate-transparency/go/client/logclient.go

@@ -17,7 +17,6 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/google/certificate-transparency/go"
 	"github.com/google/certificate-transparency/go"
-	"github.com/mreiferson/go-httpclient"
 	"golang.org/x/net/context"
 	"golang.org/x/net/context"
 )
 )
 
 
@@ -25,6 +24,7 @@ import (
 const (
 const (
 	AddChainPath    = "/ct/v1/add-chain"
 	AddChainPath    = "/ct/v1/add-chain"
 	AddPreChainPath = "/ct/v1/add-pre-chain"
 	AddPreChainPath = "/ct/v1/add-pre-chain"
+	AddJSONPath     = "/ct/v1/add-json"
 	GetSTHPath      = "/ct/v1/get-sth"
 	GetSTHPath      = "/ct/v1/get-sth"
 	GetEntriesPath  = "/ct/v1/get-entries"
 	GetEntriesPath  = "/ct/v1/get-entries"
 )
 )
@@ -57,6 +57,12 @@ type addChainResponse struct {
 	Signature  string     `json:"signature"`   // Log signature for this SCT
 	Signature  string     `json:"signature"`   // Log signature for this SCT
 }
 }
 
 
+// addJSONRequest represents the JSON request body sent ot the add-json CT
+// method.
+type addJSONRequest struct {
+	Data interface{} `json:"data"`
+}
+
 // getSTHResponse respresents the JSON response to the get-sth CT method
 // getSTHResponse respresents the JSON response to the get-sth CT method
 type getSTHResponse struct {
 type getSTHResponse struct {
 	TreeSize          uint64 `json:"tree_size"`           // Number of certs in the current tree
 	TreeSize          uint64 `json:"tree_size"`           // Number of certs in the current tree
@@ -102,18 +108,12 @@ type getEntryAndProofResponse struct {
 // New constructs a new LogClient instance.
 // New constructs a new LogClient instance.
 // |uri| is the base URI of the CT log instance to interact with, e.g.
 // |uri| is the base URI of the CT log instance to interact with, e.g.
 // http://ct.googleapis.com/pilot
 // http://ct.googleapis.com/pilot
-func New(uri string) *LogClient {
-	var c LogClient
-	c.uri = uri
-	transport := &httpclient.Transport{
-		ConnectTimeout:        10 * time.Second,
-		RequestTimeout:        30 * time.Second,
-		ResponseHeaderTimeout: 30 * time.Second,
-		MaxIdleConnsPerHost:   10,
-		DisableKeepAlives:     false,
+// |hc| is the underlying client to be used for HTTP requests to the CT log.
+func New(uri string, hc *http.Client) *LogClient {
+	if hc == nil {
+		hc = new(http.Client)
 	}
 	}
-	c.httpClient = &http.Client{Transport: transport}
-	return &c
+	return &LogClient{uri: uri, httpClient: hc}
 }
 }
 
 
 // Makes a HTTP call to |uri|, and attempts to parse the response as a JSON
 // Makes a HTTP call to |uri|, and attempts to parse the response as a JSON
@@ -154,7 +154,6 @@ func (c *LogClient) postAndParse(uri string, req interface{}, res interface{}) (
 	if err != nil {
 	if err != nil {
 		return nil, "", err
 		return nil, "", err
 	}
 	}
-	httpReq.Header.Set("Keep-Alive", "timeout=15, max=100")
 	httpReq.Header.Set("Content-Type", "application/json")
 	httpReq.Header.Set("Content-Type", "application/json")
 	resp, err := c.httpClient.Do(httpReq)
 	resp, err := c.httpClient.Do(httpReq)
 	// Read all of the body, if there is one, so that the http.Client can do
 	// Read all of the body, if there is one, so that the http.Client can do
@@ -277,6 +276,37 @@ func (c *LogClient) AddChainWithContext(ctx context.Context, chain []ct.ASN1Cert
 	return c.addChainWithRetry(ctx, AddChainPath, chain)
 	return c.addChainWithRetry(ctx, AddChainPath, chain)
 }
 }
 
 
+func (c *LogClient) AddJSON(data interface{}) (*ct.SignedCertificateTimestamp, error) {
+	req := addJSONRequest{
+		Data: data,
+	}
+	var resp addChainResponse
+	_, _, err := c.postAndParse(c.uri+AddJSONPath, &req, &resp)
+	if err != nil {
+		return nil, err
+	}
+	rawLogID, err := base64.StdEncoding.DecodeString(resp.ID)
+	if err != nil {
+		return nil, err
+	}
+	rawSignature, err := base64.StdEncoding.DecodeString(resp.Signature)
+	if err != nil {
+		return nil, err
+	}
+	ds, err := ct.UnmarshalDigitallySigned(bytes.NewReader(rawSignature))
+	if err != nil {
+		return nil, err
+	}
+	var logID ct.SHA256Hash
+	copy(logID[:], rawLogID)
+	return &ct.SignedCertificateTimestamp{
+		SCTVersion: resp.SCTVersion,
+		LogID:      logID,
+		Timestamp:  resp.Timestamp,
+		Extensions: ct.CTExtensions(resp.Extensions),
+		Signature:  *ds}, nil
+}
+
 // GetSTH retrieves the current STH from the log.
 // GetSTH retrieves the current STH from the log.
 // Returns a populated SignedTreeHead, or a non-nil error.
 // Returns a populated SignedTreeHead, or a non-nil error.
 func (c *LogClient) GetSTH() (sth *ct.SignedTreeHead, err error) {
 func (c *LogClient) GetSTH() (sth *ct.SignedTreeHead, err error) {

+ 56 - 5
vendor/src/github.com/google/certificate-transparency/go/serialization.go

@@ -4,6 +4,7 @@ import (
 	"bytes"
 	"bytes"
 	"container/list"
 	"container/list"
 	"crypto"
 	"crypto"
+	"encoding/asn1"
 	"encoding/binary"
 	"encoding/binary"
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
@@ -23,6 +24,8 @@ const (
 const (
 const (
 	MaxCertificateLength = (1 << 24) - 1
 	MaxCertificateLength = (1 << 24) - 1
 	MaxExtensionsLength  = (1 << 16) - 1
 	MaxExtensionsLength  = (1 << 16) - 1
+	MaxSCTInListLength   = (1 << 16) - 1
+	MaxSCTListLength     = (1 << 16) - 1
 )
 )
 
 
 func writeUint(w io.Writer, value uint64, numBytes int) error {
 func writeUint(w io.Writer, value uint64, numBytes int) error {
@@ -80,13 +83,12 @@ func readVarBytes(r io.Reader, numLenBytes int) ([]byte, error) {
 		return nil, err
 		return nil, err
 	}
 	}
 	data := make([]byte, l)
 	data := make([]byte, l)
-	n, err := r.Read(data)
-	if err != nil {
+	if n, err := io.ReadFull(r, data); err != nil {
+		if err == io.EOF || err == io.ErrUnexpectedEOF {
+			return nil, fmt.Errorf("short read: expected %d but got %d", l, n)
+		}
 		return nil, err
 		return nil, err
 	}
 	}
-	if n != int(l) {
-		return nil, fmt.Errorf("short read: expected %d but got %d", l, n)
-	}
 	return data, nil
 	return data, nil
 }
 }
 
 
@@ -510,3 +512,52 @@ func SerializeSTHSignatureInput(sth SignedTreeHead) ([]byte, error) {
 		return nil, fmt.Errorf("unsupported STH version %d", sth.Version)
 		return nil, fmt.Errorf("unsupported STH version %d", sth.Version)
 	}
 	}
 }
 }
+
+// SCTListSerializedLength determines the length of the required buffer should a SCT List need to be serialized
+func SCTListSerializedLength(scts []SignedCertificateTimestamp) (int, error) {
+	if len(scts) == 0 {
+		return 0, fmt.Errorf("SCT List empty")
+	}
+
+	sctListLen := 0
+	for i, sct := range scts {
+		n, err := sct.SerializedLength()
+		if err != nil {
+			return 0, fmt.Errorf("unable to determine length of SCT in position %d: %v", i, err)
+		}
+		if n > MaxSCTInListLength {
+			return 0, fmt.Errorf("SCT in position %d too large: %d", i, n)
+		}
+		sctListLen += 2 + n
+	}
+
+	return sctListLen, nil
+}
+
+// SerializeSCTList serializes the passed-in slice of SignedCertificateTimestamp into a
+// byte slice as a SignedCertificateTimestampList (see RFC6962 Section 3.3)
+func SerializeSCTList(scts []SignedCertificateTimestamp) ([]byte, error) {
+	size, err := SCTListSerializedLength(scts)
+	if err != nil {
+		return nil, err
+	}
+	fullSize := 2 + size // 2 bytes for length + size of SCT list
+	if fullSize > MaxSCTListLength {
+		return nil, fmt.Errorf("SCT List too large to serialize: %d", fullSize)
+	}
+	buf := new(bytes.Buffer)
+	buf.Grow(fullSize)
+	if err = writeUint(buf, uint64(size), 2); err != nil {
+		return nil, err
+	}
+	for _, sct := range scts {
+		serialized, err := SerializeSCT(sct)
+		if err != nil {
+			return nil, err
+		}
+		if err = writeVarBytes(buf, serialized, 2); err != nil {
+			return nil, err
+		}
+	}
+	return asn1.Marshal(buf.Bytes()) // transform to Octet String
+}

+ 0 - 1
vendor/src/github.com/mreiferson/go-httpclient/.gitignore

@@ -1 +0,0 @@
-*.sw[op]

+ 0 - 11
vendor/src/github.com/mreiferson/go-httpclient/.travis.yml

@@ -1,11 +0,0 @@
-language: go
-go:
-  - 1.1
-install:
-  - go get github.com/bmizerany/assert
-script:
-  - pushd $TRAVIS_BUILD_DIR
-  - go test
-  - popd
-notifications:
-  email: false

+ 0 - 41
vendor/src/github.com/mreiferson/go-httpclient/README.md

@@ -1,41 +0,0 @@
-## go-httpclient
-
-**requires Go 1.1+** as of `v0.4.0` the API has been completely re-written for Go 1.1 (for a Go
-1.0.x compatible release see [1adef50](https://github.com/mreiferson/go-httpclient/tree/1adef50))
-
-[![Build
-Status](https://secure.travis-ci.org/mreiferson/go-httpclient.png?branch=master)](http://travis-ci.org/mreiferson/go-httpclient)
-
-Provides an HTTP Transport that implements the `RoundTripper` interface and
-can be used as a built in replacement for the standard library's, providing:
-
- * connection timeouts
- * request timeouts
-
-This is a thin wrapper around `http.Transport` that sets dial timeouts and uses
-Go's internal timer scheduler to call the Go 1.1+ `CancelRequest()` API.
-
-### Example
-
-```go
-transport := &httpclient.Transport{
-    ConnectTimeout:        1*time.Second,
-    RequestTimeout:        10*time.Second,
-    ResponseHeaderTimeout: 5*time.Second,
-}
-defer transport.Close()
-
-client := &http.Client{Transport: transport}
-req, _ := http.NewRequest("GET", "http://127.0.0.1/test", nil)
-resp, err := client.Do(req)
-if err != nil {
-    return err
-}
-defer resp.Body.Close()
-```
-
-*Note:* you will want to re-use a single client object rather than creating one for each request, otherwise you will end up [leaking connections](https://code.google.com/p/go/issues/detail?id=4049#c3).
-
-### Reference Docs
-
-For API docs see [godoc](http://godoc.org/github.com/mreiferson/go-httpclient).

+ 0 - 237
vendor/src/github.com/mreiferson/go-httpclient/httpclient.go

@@ -1,237 +0,0 @@
-/*
-Provides an HTTP Transport that implements the `RoundTripper` interface and
-can be used as a built in replacement for the standard library's, providing:
-
-	* connection timeouts
-	* request timeouts
-
-This is a thin wrapper around `http.Transport` that sets dial timeouts and uses
-Go's internal timer scheduler to call the Go 1.1+ `CancelRequest()` API.
-*/
-package httpclient
-
-import (
-	"crypto/tls"
-	"errors"
-	"io"
-	"net"
-	"net/http"
-	"net/url"
-	"sync"
-	"time"
-)
-
-// returns the current version of the package
-func Version() string {
-	return "0.4.1"
-}
-
-// Transport implements the RoundTripper interface and can be used as a replacement
-// for Go's built in http.Transport implementing end-to-end request timeouts.
-//
-// 	transport := &httpclient.Transport{
-// 	    ConnectTimeout: 1*time.Second,
-// 	    ResponseHeaderTimeout: 5*time.Second,
-// 	    RequestTimeout: 10*time.Second,
-// 	}
-// 	defer transport.Close()
-//
-// 	client := &http.Client{Transport: transport}
-// 	req, _ := http.NewRequest("GET", "http://127.0.0.1/test", nil)
-// 	resp, err := client.Do(req)
-// 	if err != nil {
-// 	    return err
-// 	}
-// 	defer resp.Body.Close()
-//
-type Transport struct {
-	// Proxy specifies a function to return a proxy for a given
-	// *http.Request. If the function returns a non-nil error, the
-	// request is aborted with the provided error.
-	// If Proxy is nil or returns a nil *url.URL, no proxy is used.
-	Proxy func(*http.Request) (*url.URL, error)
-
-	// Dial specifies the dial function for creating TCP
-	// connections. This will override the Transport's ConnectTimeout and
-	// ReadWriteTimeout settings.
-	// If Dial is nil, a dialer is generated on demand matching the Transport's
-	// options.
-	Dial func(network, addr string) (net.Conn, error)
-
-	// TLSClientConfig specifies the TLS configuration to use with
-	// tls.Client. If nil, the default configuration is used.
-	TLSClientConfig *tls.Config
-
-	// DisableKeepAlives, if true, prevents re-use of TCP connections
-	// between different HTTP requests.
-	DisableKeepAlives bool
-
-	// DisableCompression, if true, prevents the Transport from
-	// requesting compression with an "Accept-Encoding: gzip"
-	// request header when the Request contains no existing
-	// Accept-Encoding value. If the Transport requests gzip on
-	// its own and gets a gzipped response, it's transparently
-	// decoded in the Response.Body. However, if the user
-	// explicitly requested gzip it is not automatically
-	// uncompressed.
-	DisableCompression bool
-
-	// MaxIdleConnsPerHost, if non-zero, controls the maximum idle
-	// (keep-alive) to keep per-host.  If zero,
-	// http.DefaultMaxIdleConnsPerHost is used.
-	MaxIdleConnsPerHost int
-
-	// ConnectTimeout, if non-zero, is the maximum amount of time a dial will wait for
-	// a connect to complete.
-	ConnectTimeout time.Duration
-
-	// ResponseHeaderTimeout, if non-zero, specifies the amount of
-	// time to wait for a server's response headers after fully
-	// writing the request (including its body, if any). This
-	// time does not include the time to read the response body.
-	ResponseHeaderTimeout time.Duration
-
-	// RequestTimeout, if non-zero, specifies the amount of time for the entire
-	// request to complete (including all of the above timeouts + entire response body).
-	// This should never be less than the sum total of the above two timeouts.
-	RequestTimeout time.Duration
-
-	// ReadWriteTimeout, if non-zero, will set a deadline for every Read and
-	// Write operation on the request connection.
-	ReadWriteTimeout time.Duration
-
-	// TCPWriteBufferSize, the size of the operating system's write
-	// buffer associated with the connection.
-	TCPWriteBufferSize int
-
-	// TCPReadBuffserSize, the size of the operating system's read
-	// buffer associated with the connection.
-	TCPReadBufferSize int
-
-	starter   sync.Once
-	transport *http.Transport
-}
-
-// Close cleans up the Transport, currently a no-op
-func (t *Transport) Close() error {
-	return nil
-}
-
-func (t *Transport) lazyStart() {
-	if t.Dial == nil {
-		t.Dial = func(netw, addr string) (net.Conn, error) {
-			c, err := net.DialTimeout(netw, addr, t.ConnectTimeout)
-			if err != nil {
-				return nil, err
-			}
-
-			if t.TCPReadBufferSize != 0 || t.TCPWriteBufferSize != 0 {
-				if tcpCon, ok := c.(*net.TCPConn); ok {
-					if t.TCPWriteBufferSize != 0 {
-						if err = tcpCon.SetWriteBuffer(t.TCPWriteBufferSize); err != nil {
-							return nil, err
-						}
-					}
-					if t.TCPReadBufferSize != 0 {
-						if err = tcpCon.SetReadBuffer(t.TCPReadBufferSize); err != nil {
-							return nil, err
-						}
-					}
-				} else {
-					err = errors.New("Not Tcp Connection")
-					return nil, err
-				}
-			}
-
-			if t.ReadWriteTimeout > 0 {
-				timeoutConn := &rwTimeoutConn{
-					TCPConn:   c.(*net.TCPConn),
-					rwTimeout: t.ReadWriteTimeout,
-				}
-				return timeoutConn, nil
-			}
-			return c, nil
-		}
-	}
-
-	t.transport = &http.Transport{
-		Dial:                  t.Dial,
-		Proxy:                 t.Proxy,
-		TLSClientConfig:       t.TLSClientConfig,
-		DisableKeepAlives:     t.DisableKeepAlives,
-		DisableCompression:    t.DisableCompression,
-		MaxIdleConnsPerHost:   t.MaxIdleConnsPerHost,
-		ResponseHeaderTimeout: t.ResponseHeaderTimeout,
-	}
-}
-
-func (t *Transport) CancelRequest(req *http.Request) {
-	t.starter.Do(t.lazyStart)
-
-	t.transport.CancelRequest(req)
-}
-
-func (t *Transport) CloseIdleConnections() {
-	t.starter.Do(t.lazyStart)
-
-	t.transport.CloseIdleConnections()
-}
-
-func (t *Transport) RegisterProtocol(scheme string, rt http.RoundTripper) {
-	t.starter.Do(t.lazyStart)
-
-	t.transport.RegisterProtocol(scheme, rt)
-}
-
-func (t *Transport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
-	t.starter.Do(t.lazyStart)
-
-	if t.RequestTimeout > 0 {
-		timer := time.AfterFunc(t.RequestTimeout, func() {
-			t.transport.CancelRequest(req)
-		})
-
-		resp, err = t.transport.RoundTrip(req)
-		if err != nil {
-			timer.Stop()
-		} else {
-			resp.Body = &bodyCloseInterceptor{ReadCloser: resp.Body, timer: timer}
-		}
-	} else {
-		resp, err = t.transport.RoundTrip(req)
-	}
-
-	return
-}
-
-type bodyCloseInterceptor struct {
-	io.ReadCloser
-	timer *time.Timer
-}
-
-func (bci *bodyCloseInterceptor) Close() error {
-	bci.timer.Stop()
-	return bci.ReadCloser.Close()
-}
-
-// A net.Conn that sets a deadline for every Read or Write operation
-type rwTimeoutConn struct {
-	*net.TCPConn
-	rwTimeout time.Duration
-}
-
-func (c *rwTimeoutConn) Read(b []byte) (int, error) {
-	err := c.TCPConn.SetDeadline(time.Now().Add(c.rwTimeout))
-	if err != nil {
-		return 0, err
-	}
-	return c.TCPConn.Read(b)
-}
-
-func (c *rwTimeoutConn) Write(b []byte) (int, error) {
-	err := c.TCPConn.SetDeadline(time.Now().Add(c.rwTimeout))
-	if err != nil {
-		return 0, err
-	}
-	return c.TCPConn.Write(b)
-}

Некоторые файлы не были показаны из-за большого количества измененных файлов