Browse Source

Merge pull request #27784 from yongtang/10262016-vendor-swarmkit

Revendor swarmkit to 0ec7c6ee4b3185ec4e3d6bd65f8f5542b1761421
Andrea Luzzardi 8 years ago
parent
commit
d6a5d54086
49 changed files with 3032 additions and 1488 deletions
  1. 1 1
      hack/vendor.sh
  2. 5 3
      vendor/src/github.com/docker/swarmkit/agent/agent.go
  3. 2 2
      vendor/src/github.com/docker/swarmkit/agent/config.go
  4. 1 1
      vendor/src/github.com/docker/swarmkit/agent/exec/controller.go
  5. 22 0
      vendor/src/github.com/docker/swarmkit/agent/exec/executor.go
  6. 0 53
      vendor/src/github.com/docker/swarmkit/agent/secrets.go
  7. 12 5
      vendor/src/github.com/docker/swarmkit/agent/worker.go
  8. 631 118
      vendor/src/github.com/docker/swarmkit/api/control.pb.go
  9. 26 0
      vendor/src/github.com/docker/swarmkit/api/control.proto
  10. 1 1
      vendor/src/github.com/docker/swarmkit/api/gen.go
  11. 29 0
      vendor/src/github.com/docker/swarmkit/api/naming/naming.go
  12. 240 102
      vendor/src/github.com/docker/swarmkit/api/objects.pb.go
  13. 3 2
      vendor/src/github.com/docker/swarmkit/api/objects.proto
  14. 552 117
      vendor/src/github.com/docker/swarmkit/api/specs.pb.go
  15. 27 0
      vendor/src/github.com/docker/swarmkit/api/specs.proto
  16. 336 307
      vendor/src/github.com/docker/swarmkit/api/types.pb.go
  17. 38 17
      vendor/src/github.com/docker/swarmkit/api/types.proto
  18. 8 10
      vendor/src/github.com/docker/swarmkit/ca/auth.go
  19. 13 10
      vendor/src/github.com/docker/swarmkit/ca/server.go
  20. 271 199
      vendor/src/github.com/docker/swarmkit/manager/allocator/network.go
  21. 20 0
      vendor/src/github.com/docker/swarmkit/manager/constraint/constraint.go
  22. 25 1
      vendor/src/github.com/docker/swarmkit/manager/controlapi/cluster.go
  23. 8 3
      vendor/src/github.com/docker/swarmkit/manager/controlapi/node.go
  24. 41 0
      vendor/src/github.com/docker/swarmkit/manager/controlapi/secret.go
  25. 76 19
      vendor/src/github.com/docker/swarmkit/manager/controlapi/service.go
  26. 3 2
      vendor/src/github.com/docker/swarmkit/manager/controlapi/task.go
  27. 21 18
      vendor/src/github.com/docker/swarmkit/manager/manager.go
  28. 3 3
      vendor/src/github.com/docker/swarmkit/manager/orchestrator/constraintenforcer/constraint_enforcer.go
  29. 38 43
      vendor/src/github.com/docker/swarmkit/manager/orchestrator/global/global.go
  30. 0 203
      vendor/src/github.com/docker/swarmkit/manager/orchestrator/replicated.go
  31. 108 0
      vendor/src/github.com/docker/swarmkit/manager/orchestrator/replicated/replicated.go
  32. 21 53
      vendor/src/github.com/docker/swarmkit/manager/orchestrator/replicated/services.go
  33. 55 0
      vendor/src/github.com/docker/swarmkit/manager/orchestrator/replicated/slot.go
  34. 16 15
      vendor/src/github.com/docker/swarmkit/manager/orchestrator/replicated/tasks.go
  35. 33 27
      vendor/src/github.com/docker/swarmkit/manager/orchestrator/restart/restart.go
  36. 61 0
      vendor/src/github.com/docker/swarmkit/manager/orchestrator/service.go
  37. 29 44
      vendor/src/github.com/docker/swarmkit/manager/orchestrator/slot.go
  38. 67 0
      vendor/src/github.com/docker/swarmkit/manager/orchestrator/task.go
  39. 3 3
      vendor/src/github.com/docker/swarmkit/manager/orchestrator/taskreaper/task_reaper.go
  40. 24 27
      vendor/src/github.com/docker/swarmkit/manager/orchestrator/update/updater.go
  41. 47 11
      vendor/src/github.com/docker/swarmkit/manager/scheduler/nodeinfo.go
  42. 13 0
      vendor/src/github.com/docker/swarmkit/manager/scheduler/nodeset.go
  43. 46 11
      vendor/src/github.com/docker/swarmkit/manager/scheduler/scheduler.go
  44. 25 20
      vendor/src/github.com/docker/swarmkit/manager/state/raft/raft.go
  45. 2 2
      vendor/src/github.com/docker/swarmkit/manager/state/store/memory.go
  46. 2 22
      vendor/src/github.com/docker/swarmkit/manager/state/store/tasks.go
  47. 7 2
      vendor/src/github.com/docker/swarmkit/manager/state/watch.go
  48. 19 10
      vendor/src/github.com/docker/swarmkit/node/node.go
  49. 1 1
      vendor/src/github.com/docker/swarmkit/protobuf/plugin/gen.go

+ 1 - 1
hack/vendor.sh

@@ -147,7 +147,7 @@ clone git github.com/docker/containerd 52ef1ceb4b660c42cf4ea9013180a5663968d4c7
 clone git github.com/tonistiigi/fifo 8c56881ce5e63e19e2dfc495c8af0fb90916467d
 
 # cluster
-clone git github.com/docker/swarmkit 3b221eb0391d34ae0b9dac65df02b5b64de6dff2
+clone git github.com/docker/swarmkit 0ec7c6ee4b3185ec4e3d6bd65f8f5542b1761421
 clone git github.com/golang/mock bd3c8e81be01eef76d4b503f5e687d2d1354d2d9
 clone git github.com/gogo/protobuf v0.3
 clone git github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a

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

@@ -48,9 +48,11 @@ func New(config *Config) (*Agent, error) {
 		return nil, err
 	}
 
+	worker := newWorker(config.DB, config.Executor)
+
 	a := &Agent{
 		config:   config,
-		worker:   newWorker(config.DB, config.Executor),
+		worker:   worker,
 		sessionq: make(chan sessionOperation),
 		started:  make(chan struct{}),
 		stopped:  make(chan struct{}),
@@ -278,8 +280,8 @@ func (a *Agent) handleSessionMessage(ctx context.Context, message *api.SessionMe
 
 	if message.Node != nil {
 		if a.node == nil || !nodesEqual(a.node, message.Node) {
-			if a.config.NotifyRoleChange != nil {
-				a.config.NotifyRoleChange <- message.Node.Spec.Role
+			if a.config.NotifyNodeChange != nil {
+				a.config.NotifyNodeChange <- message.Node.Copy()
 			}
 			a.node = message.Node.Copy()
 			if err := a.config.Executor.Configure(ctx, a.node); err != nil {

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

@@ -24,8 +24,8 @@ type Config struct {
 	// DB used for task storage. Must be open for the lifetime of the agent.
 	DB *bolt.DB
 
-	// NotifyRoleChange channel receives new roles from session messages.
-	NotifyRoleChange chan<- api.NodeRole
+	// NotifyNodeChange channel receives new node changes from session messages.
+	NotifyNodeChange chan<- *api.Node
 
 	// Credentials is credentials for grpc connection to manager.
 	Credentials credentials.TransportCredentials

+ 1 - 1
vendor/src/github.com/docker/swarmkit/agent/exec/controller.go

@@ -277,7 +277,7 @@ func Do(ctx context.Context, task *api.Task, ctlr Controller) (*api.TaskStatus,
 	}
 
 	switch status.State {
-	case api.TaskStateNew, api.TaskStateAllocated, api.TaskStateAssigned:
+	case api.TaskStateNew, api.TaskStatePending, api.TaskStateAssigned:
 		return transition(api.TaskStateAccepted, "accepted")
 	case api.TaskStateAccepted:
 		return transition(api.TaskStatePreparing, "preparing")

+ 22 - 0
vendor/src/github.com/docker/swarmkit/agent/exec/executor.go

@@ -21,3 +21,25 @@ type Executor interface {
 	// manager to the executor.
 	SetNetworkBootstrapKeys([]*api.EncryptionKey) error
 }
+
+// SecretsProvider is implemented by objects that can store secrets, typically
+// an executor.
+type SecretsProvider interface {
+	Secrets() SecretsManager
+}
+
+// SecretGetter contains secret data necessary for the Controller.
+type SecretGetter interface {
+	// Get returns the the secret with a specific secret ID, if available.
+	// When the secret is not available, the return will be nil.
+	Get(secretID string) *api.Secret
+}
+
+// SecretsManager is the interface for secret storage and updates.
+type SecretsManager interface {
+	SecretGetter
+
+	Add(secrets ...api.Secret) // add one or more secrets
+	Remove(secrets []string)   // remove the secrets by ID
+	Reset()                    // remove all secrets
+}

+ 0 - 53
vendor/src/github.com/docker/swarmkit/agent/secrets.go

@@ -1,53 +0,0 @@
-package agent
-
-import (
-	"sync"
-
-	"github.com/docker/swarmkit/api"
-)
-
-// secrets is a map that keeps all the currenty available secrets to the agent
-// mapped by secret ID
-type secrets struct {
-	mu sync.RWMutex
-	m  map[string]api.Secret
-}
-
-func newSecrets() *secrets {
-	return &secrets{
-		m: make(map[string]api.Secret),
-	}
-}
-
-// Get returns a secret by ID.  If the secret doesn't exist, returns nil.
-func (s *secrets) Get(secretID string) api.Secret {
-	s.mu.RLock()
-	defer s.mu.RUnlock()
-	return s.m[secretID]
-}
-
-// Add adds one or more secrets to the secret map
-func (s *secrets) Add(secrets ...api.Secret) {
-	s.mu.Lock()
-	defer s.mu.Unlock()
-	for _, secret := range secrets {
-		s.m[secret.ID] = secret
-	}
-}
-
-// Remove removes one or more secrets by ID from the secret map.  Succeeds
-// whether or not the given IDs are in the map.
-func (s *secrets) Remove(secrets []string) {
-	s.mu.Lock()
-	defer s.mu.Unlock()
-	for _, secret := range secrets {
-		delete(s.m, secret)
-	}
-}
-
-// Reset removes all the secrets
-func (s *secrets) Reset() {
-	s.mu.Lock()
-	defer s.mu.Unlock()
-	s.m = make(map[string]api.Secret)
-}

+ 12 - 5
vendor/src/github.com/docker/swarmkit/agent/worker.go

@@ -42,7 +42,6 @@ type worker struct {
 	db        *bolt.DB
 	executor  exec.Executor
 	listeners map[*statusReporterKey]struct{}
-	secrets   *secrets
 
 	taskManagers map[string]*taskManager
 	mu           sync.RWMutex
@@ -54,7 +53,6 @@ func newWorker(db *bolt.DB, executor exec.Executor) *worker {
 		executor:     executor,
 		listeners:    make(map[*statusReporterKey]struct{}),
 		taskManagers: make(map[string]*taskManager),
-		secrets:      newSecrets(),
 	}
 }
 
@@ -255,6 +253,15 @@ func reconcileTaskState(ctx context.Context, w *worker, assignments []*api.Assig
 }
 
 func reconcileSecrets(ctx context.Context, w *worker, assignments []*api.AssignmentChange, fullSnapshot bool) error {
+	var secrets exec.SecretsManager
+	provider, ok := w.executor.(exec.SecretsProvider)
+	if !ok {
+		log.G(ctx).Warn("secrets update ignored; executor does not support secrets")
+		return nil
+	}
+
+	secrets = provider.Secrets()
+
 	var (
 		updatedSecrets []api.Secret
 		removedSecrets []string
@@ -278,11 +285,11 @@ func reconcileSecrets(ctx context.Context, w *worker, assignments []*api.Assignm
 
 	// If this was a complete set of secrets, we're going to clear the secrets map and add all of them
 	if fullSnapshot {
-		w.secrets.Reset()
+		secrets.Reset()
 	} else {
-		w.secrets.Remove(removedSecrets)
+		secrets.Remove(removedSecrets)
 	}
-	w.secrets.Add(updatedSecrets...)
+	secrets.Add(updatedSecrets...)
 
 	return nil
 }

+ 631 - 118
vendor/src/github.com/docker/swarmkit/api/control.pb.go

@@ -459,6 +459,28 @@ func (m *GetSecretResponse) Reset()                    { *m = GetSecretResponse{
 func (*GetSecretResponse) ProtoMessage()               {}
 func (*GetSecretResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{40} }
 
+type UpdateSecretRequest struct {
+	// SecretID is the secret ID to update.
+	SecretID string `protobuf:"bytes,1,opt,name=secret_id,json=secretId,proto3" json:"secret_id,omitempty"`
+	// SecretVersion is the version of the secret being updated.
+	SecretVersion *Version `protobuf:"bytes,2,opt,name=secret_version,json=secretVersion" json:"secret_version,omitempty"`
+	// Spec is the new spec to apply to the Secret
+	// Only some fields are allowed to be updated.
+	Spec *SecretSpec `protobuf:"bytes,3,opt,name=spec" json:"spec,omitempty"`
+}
+
+func (m *UpdateSecretRequest) Reset()                    { *m = UpdateSecretRequest{} }
+func (*UpdateSecretRequest) ProtoMessage()               {}
+func (*UpdateSecretRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{41} }
+
+type UpdateSecretResponse struct {
+	Secret *Secret `protobuf:"bytes,1,opt,name=secret" json:"secret,omitempty"`
+}
+
+func (m *UpdateSecretResponse) Reset()                    { *m = UpdateSecretResponse{} }
+func (*UpdateSecretResponse) ProtoMessage()               {}
+func (*UpdateSecretResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{42} }
+
 // ListSecretRequest is the request to list all non-internal secrets in the secret store,
 // or all secrets filtered by (name or name prefix or id prefix) and labels.
 type ListSecretsRequest struct {
@@ -467,7 +489,7 @@ type ListSecretsRequest struct {
 
 func (m *ListSecretsRequest) Reset()                    { *m = ListSecretsRequest{} }
 func (*ListSecretsRequest) ProtoMessage()               {}
-func (*ListSecretsRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{41} }
+func (*ListSecretsRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{43} }
 
 type ListSecretsRequest_Filters struct {
 	Names        []string          `protobuf:"bytes,1,rep,name=names" json:"names,omitempty"`
@@ -479,7 +501,7 @@ type ListSecretsRequest_Filters struct {
 func (m *ListSecretsRequest_Filters) Reset()      { *m = ListSecretsRequest_Filters{} }
 func (*ListSecretsRequest_Filters) ProtoMessage() {}
 func (*ListSecretsRequest_Filters) Descriptor() ([]byte, []int) {
-	return fileDescriptorControl, []int{41, 0}
+	return fileDescriptorControl, []int{43, 0}
 }
 
 // ListSecretResponse contains a list of all the secrets that match the name or
@@ -492,7 +514,7 @@ type ListSecretsResponse struct {
 
 func (m *ListSecretsResponse) Reset()                    { *m = ListSecretsResponse{} }
 func (*ListSecretsResponse) ProtoMessage()               {}
-func (*ListSecretsResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{42} }
+func (*ListSecretsResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{44} }
 
 // CreateSecretRequest specifies a new secret (it will not update an existing
 // secret) to create.
@@ -502,7 +524,7 @@ type CreateSecretRequest struct {
 
 func (m *CreateSecretRequest) Reset()                    { *m = CreateSecretRequest{} }
 func (*CreateSecretRequest) ProtoMessage()               {}
-func (*CreateSecretRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{43} }
+func (*CreateSecretRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{45} }
 
 // CreateSecretResponse contains the newly created `Secret`` corresponding to the
 // name in `CreateSecretRequest`.  The `Secret.Spec.Data` field should be nil instead
@@ -513,7 +535,7 @@ type CreateSecretResponse struct {
 
 func (m *CreateSecretResponse) Reset()                    { *m = CreateSecretResponse{} }
 func (*CreateSecretResponse) ProtoMessage()               {}
-func (*CreateSecretResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{44} }
+func (*CreateSecretResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{46} }
 
 // RemoveSecretRequest contains the ID of the secret that should be removed.  This
 // removes all versions of the secret.
@@ -523,7 +545,7 @@ type RemoveSecretRequest struct {
 
 func (m *RemoveSecretRequest) Reset()                    { *m = RemoveSecretRequest{} }
 func (*RemoveSecretRequest) ProtoMessage()               {}
-func (*RemoveSecretRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{45} }
+func (*RemoveSecretRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{47} }
 
 // RemoveSecretResponse is an empty object indicating the successful removal of
 // a secret.
@@ -532,7 +554,7 @@ type RemoveSecretResponse struct {
 
 func (m *RemoveSecretResponse) Reset()                    { *m = RemoveSecretResponse{} }
 func (*RemoveSecretResponse) ProtoMessage()               {}
-func (*RemoveSecretResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{46} }
+func (*RemoveSecretResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{48} }
 
 func init() {
 	proto.RegisterType((*GetNodeRequest)(nil), "docker.swarmkit.v1.GetNodeRequest")
@@ -581,6 +603,8 @@ func init() {
 	proto.RegisterType((*UpdateClusterResponse)(nil), "docker.swarmkit.v1.UpdateClusterResponse")
 	proto.RegisterType((*GetSecretRequest)(nil), "docker.swarmkit.v1.GetSecretRequest")
 	proto.RegisterType((*GetSecretResponse)(nil), "docker.swarmkit.v1.GetSecretResponse")
+	proto.RegisterType((*UpdateSecretRequest)(nil), "docker.swarmkit.v1.UpdateSecretRequest")
+	proto.RegisterType((*UpdateSecretResponse)(nil), "docker.swarmkit.v1.UpdateSecretResponse")
 	proto.RegisterType((*ListSecretsRequest)(nil), "docker.swarmkit.v1.ListSecretsRequest")
 	proto.RegisterType((*ListSecretsRequest_Filters)(nil), "docker.swarmkit.v1.ListSecretsRequest.Filters")
 	proto.RegisterType((*ListSecretsResponse)(nil), "docker.swarmkit.v1.ListSecretsResponse")
@@ -762,6 +786,14 @@ func (p *authenticatedWrapperControlServer) GetSecret(ctx context.Context, r *Ge
 	return p.local.GetSecret(ctx, r)
 }
 
+func (p *authenticatedWrapperControlServer) UpdateSecret(ctx context.Context, r *UpdateSecretRequest) (*UpdateSecretResponse, error) {
+
+	if err := p.authorize(ctx, []string{"swarm-manager"}); err != nil {
+		return nil, err
+	}
+	return p.local.UpdateSecret(ctx, r)
+}
+
 func (p *authenticatedWrapperControlServer) ListSecrets(ctx context.Context, r *ListSecretsRequest) (*ListSecretsResponse, error) {
 
 	if err := p.authorize(ctx, []string{"swarm-manager"}); err != nil {
@@ -1491,6 +1523,32 @@ func (m *GetSecretResponse) Copy() *GetSecretResponse {
 	return o
 }
 
+func (m *UpdateSecretRequest) Copy() *UpdateSecretRequest {
+	if m == nil {
+		return nil
+	}
+
+	o := &UpdateSecretRequest{
+		SecretID:      m.SecretID,
+		SecretVersion: m.SecretVersion.Copy(),
+		Spec:          m.Spec.Copy(),
+	}
+
+	return o
+}
+
+func (m *UpdateSecretResponse) Copy() *UpdateSecretResponse {
+	if m == nil {
+		return nil
+	}
+
+	o := &UpdateSecretResponse{
+		Secret: m.Secret.Copy(),
+	}
+
+	return o
+}
+
 func (m *ListSecretsRequest) Copy() *ListSecretsRequest {
 	if m == nil {
 		return nil
@@ -2203,6 +2261,34 @@ func (this *GetSecretResponse) GoString() string {
 	s = append(s, "}")
 	return strings.Join(s, "")
 }
+func (this *UpdateSecretRequest) GoString() string {
+	if this == nil {
+		return "nil"
+	}
+	s := make([]string, 0, 7)
+	s = append(s, "&api.UpdateSecretRequest{")
+	s = append(s, "SecretID: "+fmt.Sprintf("%#v", this.SecretID)+",\n")
+	if this.SecretVersion != nil {
+		s = append(s, "SecretVersion: "+fmt.Sprintf("%#v", this.SecretVersion)+",\n")
+	}
+	if this.Spec != nil {
+		s = append(s, "Spec: "+fmt.Sprintf("%#v", this.Spec)+",\n")
+	}
+	s = append(s, "}")
+	return strings.Join(s, "")
+}
+func (this *UpdateSecretResponse) GoString() string {
+	if this == nil {
+		return "nil"
+	}
+	s := make([]string, 0, 5)
+	s = append(s, "&api.UpdateSecretResponse{")
+	if this.Secret != nil {
+		s = append(s, "Secret: "+fmt.Sprintf("%#v", this.Secret)+",\n")
+	}
+	s = append(s, "}")
+	return strings.Join(s, "")
+}
 func (this *ListSecretsRequest) GoString() string {
 	if this == nil {
 		return "nil"
@@ -2358,6 +2444,12 @@ type ControlClient interface {
 	// - Returns `InvalidArgument` if the `GetSecretRequest.SecretID` is empty.
 	// - Returns an error if getting fails.
 	GetSecret(ctx context.Context, in *GetSecretRequest, opts ...grpc.CallOption) (*GetSecretResponse, error)
+	// UpdateSecret returns a `UpdateSecretResponse` with a `Secret` with the same
+	// id as `GetSecretRequest.SecretID`
+	// - Returns `NotFound` if the Secret with the given id is not found.
+	// - Returns `InvalidArgument` if the `GetSecretRequest.SecretID` is empty.
+	// - Returns an error if updating fails.
+	UpdateSecret(ctx context.Context, in *UpdateSecretRequest, opts ...grpc.CallOption) (*UpdateSecretResponse, error)
 	// ListSecrets returns a `ListSecretResponse` with a list all non-internal `Secret`s being
 	// managed, or all secrets matching any name in `ListSecretsRequest.Names`, any
 	// name prefix in `ListSecretsRequest.NamePrefixes`, any id in
@@ -2565,6 +2657,15 @@ func (c *controlClient) GetSecret(ctx context.Context, in *GetSecretRequest, opt
 	return out, nil
 }
 
+func (c *controlClient) UpdateSecret(ctx context.Context, in *UpdateSecretRequest, opts ...grpc.CallOption) (*UpdateSecretResponse, error) {
+	out := new(UpdateSecretResponse)
+	err := grpc.Invoke(ctx, "/docker.swarmkit.v1.Control/UpdateSecret", in, out, c.cc, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
 func (c *controlClient) ListSecrets(ctx context.Context, in *ListSecretsRequest, opts ...grpc.CallOption) (*ListSecretsResponse, error) {
 	out := new(ListSecretsResponse)
 	err := grpc.Invoke(ctx, "/docker.swarmkit.v1.Control/ListSecrets", in, out, c.cc, opts...)
@@ -2620,6 +2721,12 @@ type ControlServer interface {
 	// - Returns `InvalidArgument` if the `GetSecretRequest.SecretID` is empty.
 	// - Returns an error if getting fails.
 	GetSecret(context.Context, *GetSecretRequest) (*GetSecretResponse, error)
+	// UpdateSecret returns a `UpdateSecretResponse` with a `Secret` with the same
+	// id as `GetSecretRequest.SecretID`
+	// - Returns `NotFound` if the Secret with the given id is not found.
+	// - Returns `InvalidArgument` if the `GetSecretRequest.SecretID` is empty.
+	// - Returns an error if updating fails.
+	UpdateSecret(context.Context, *UpdateSecretRequest) (*UpdateSecretResponse, error)
 	// ListSecrets returns a `ListSecretResponse` with a list all non-internal `Secret`s being
 	// managed, or all secrets matching any name in `ListSecretsRequest.Names`, any
 	// name prefix in `ListSecretsRequest.NamePrefixes`, any id in
@@ -3003,6 +3110,24 @@ func _Control_GetSecret_Handler(srv interface{}, ctx context.Context, dec func(i
 	return interceptor(ctx, in, info, handler)
 }
 
+func _Control_UpdateSecret_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(UpdateSecretRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(ControlServer).UpdateSecret(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/docker.swarmkit.v1.Control/UpdateSecret",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(ControlServer).UpdateSecret(ctx, req.(*UpdateSecretRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
 func _Control_ListSecrets_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
 	in := new(ListSecretsRequest)
 	if err := dec(in); err != nil {
@@ -3141,6 +3266,10 @@ var _Control_serviceDesc = grpc.ServiceDesc{
 			MethodName: "GetSecret",
 			Handler:    _Control_GetSecret_Handler,
 		},
+		{
+			MethodName: "UpdateSecret",
+			Handler:    _Control_UpdateSecret_Handler,
+		},
 		{
 			MethodName: "ListSecrets",
 			Handler:    _Control_ListSecrets_Handler,
@@ -4775,6 +4904,78 @@ func (m *GetSecretResponse) MarshalTo(data []byte) (int, error) {
 	return i, nil
 }
 
+func (m *UpdateSecretRequest) 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 *UpdateSecretRequest) MarshalTo(data []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	if len(m.SecretID) > 0 {
+		data[i] = 0xa
+		i++
+		i = encodeVarintControl(data, i, uint64(len(m.SecretID)))
+		i += copy(data[i:], m.SecretID)
+	}
+	if m.SecretVersion != nil {
+		data[i] = 0x12
+		i++
+		i = encodeVarintControl(data, i, uint64(m.SecretVersion.Size()))
+		n26, err := m.SecretVersion.MarshalTo(data[i:])
+		if err != nil {
+			return 0, err
+		}
+		i += n26
+	}
+	if m.Spec != nil {
+		data[i] = 0x1a
+		i++
+		i = encodeVarintControl(data, i, uint64(m.Spec.Size()))
+		n27, err := m.Spec.MarshalTo(data[i:])
+		if err != nil {
+			return 0, err
+		}
+		i += n27
+	}
+	return i, nil
+}
+
+func (m *UpdateSecretResponse) 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 *UpdateSecretResponse) MarshalTo(data []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	if m.Secret != nil {
+		data[i] = 0xa
+		i++
+		i = encodeVarintControl(data, i, uint64(m.Secret.Size()))
+		n28, err := m.Secret.MarshalTo(data[i:])
+		if err != nil {
+			return 0, err
+		}
+		i += n28
+	}
+	return i, nil
+}
+
 func (m *ListSecretsRequest) Marshal() (data []byte, err error) {
 	size := m.Size()
 	data = make([]byte, size)
@@ -4794,11 +4995,11 @@ func (m *ListSecretsRequest) MarshalTo(data []byte) (int, error) {
 		data[i] = 0xa
 		i++
 		i = encodeVarintControl(data, i, uint64(m.Filters.Size()))
-		n26, err := m.Filters.MarshalTo(data[i:])
+		n29, err := m.Filters.MarshalTo(data[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n26
+		i += n29
 	}
 	return i, nil
 }
@@ -4932,11 +5133,11 @@ func (m *CreateSecretRequest) MarshalTo(data []byte) (int, error) {
 		data[i] = 0xa
 		i++
 		i = encodeVarintControl(data, i, uint64(m.Spec.Size()))
-		n27, err := m.Spec.MarshalTo(data[i:])
+		n30, err := m.Spec.MarshalTo(data[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n27
+		i += n30
 	}
 	return i, nil
 }
@@ -4960,11 +5161,11 @@ func (m *CreateSecretResponse) MarshalTo(data []byte) (int, error) {
 		data[i] = 0xa
 		i++
 		i = encodeVarintControl(data, i, uint64(m.Secret.Size()))
-		n28, err := m.Secret.MarshalTo(data[i:])
+		n31, err := m.Secret.MarshalTo(data[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n28
+		i += n31
 	}
 	return i, nil
 }
@@ -5725,6 +5926,37 @@ func (p *raftProxyControlServer) GetSecret(ctx context.Context, r *GetSecretRequ
 	return resp, err
 }
 
+func (p *raftProxyControlServer) UpdateSecret(ctx context.Context, r *UpdateSecretRequest) (*UpdateSecretResponse, error) {
+
+	conn, err := p.connSelector.LeaderConn(ctx)
+	if err != nil {
+		if err == raftselector.ErrIsLeader {
+			return p.local.UpdateSecret(ctx, r)
+		}
+		return nil, err
+	}
+	modCtx, err := p.runCtxMods(ctx)
+	if err != nil {
+		return nil, err
+	}
+
+	resp, err := NewControlClient(conn).UpdateSecret(modCtx, r)
+	if err != nil {
+		if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") {
+			return resp, err
+		}
+		conn, err := p.pollNewLeaderConn(ctx)
+		if err != nil {
+			if err == raftselector.ErrIsLeader {
+				return p.local.UpdateSecret(ctx, r)
+			}
+			return nil, err
+		}
+		return NewControlClient(conn).UpdateSecret(modCtx, r)
+	}
+	return resp, err
+}
+
 func (p *raftProxyControlServer) ListSecrets(ctx context.Context, r *ListSecretsRequest) (*ListSecretsResponse, error) {
 
 	conn, err := p.connSelector.LeaderConn(ctx)
@@ -6448,6 +6680,34 @@ func (m *GetSecretResponse) Size() (n int) {
 	return n
 }
 
+func (m *UpdateSecretRequest) Size() (n int) {
+	var l int
+	_ = l
+	l = len(m.SecretID)
+	if l > 0 {
+		n += 1 + l + sovControl(uint64(l))
+	}
+	if m.SecretVersion != nil {
+		l = m.SecretVersion.Size()
+		n += 1 + l + sovControl(uint64(l))
+	}
+	if m.Spec != nil {
+		l = m.Spec.Size()
+		n += 1 + l + sovControl(uint64(l))
+	}
+	return n
+}
+
+func (m *UpdateSecretResponse) Size() (n int) {
+	var l int
+	_ = l
+	if m.Secret != nil {
+		l = m.Secret.Size()
+		n += 1 + l + sovControl(uint64(l))
+	}
+	return n
+}
+
 func (m *ListSecretsRequest) Size() (n int) {
 	var l int
 	_ = l
@@ -7088,6 +7348,28 @@ func (this *GetSecretResponse) String() string {
 	}, "")
 	return s
 }
+func (this *UpdateSecretRequest) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&UpdateSecretRequest{`,
+		`SecretID:` + fmt.Sprintf("%v", this.SecretID) + `,`,
+		`SecretVersion:` + strings.Replace(fmt.Sprintf("%v", this.SecretVersion), "Version", "Version", 1) + `,`,
+		`Spec:` + strings.Replace(fmt.Sprintf("%v", this.Spec), "SecretSpec", "SecretSpec", 1) + `,`,
+		`}`,
+	}, "")
+	return s
+}
+func (this *UpdateSecretResponse) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&UpdateSecretResponse{`,
+		`Secret:` + strings.Replace(fmt.Sprintf("%v", this.Secret), "Secret", "Secret", 1) + `,`,
+		`}`,
+	}, "")
+	return s
+}
 func (this *ListSecretsRequest) String() string {
 	if this == nil {
 		return "nil"
@@ -12083,6 +12365,234 @@ func (m *GetSecretResponse) Unmarshal(data []byte) error {
 	}
 	return nil
 }
+func (m *UpdateSecretRequest) 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 ErrIntOverflowControl
+			}
+			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: UpdateSecretRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: UpdateSecretRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field SecretID", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowControl
+				}
+				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 ErrInvalidLengthControl
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.SecretID = string(data[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field SecretVersion", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowControl
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := data[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthControl
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.SecretVersion == nil {
+				m.SecretVersion = &Version{}
+			}
+			if err := m.SecretVersion.Unmarshal(data[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Spec", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowControl
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := data[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthControl
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Spec == nil {
+				m.Spec = &SecretSpec{}
+			}
+			if err := m.Spec.Unmarshal(data[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipControl(data[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthControl
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *UpdateSecretResponse) 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 ErrIntOverflowControl
+			}
+			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: UpdateSecretResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: UpdateSecretResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Secret", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowControl
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := data[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthControl
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Secret == nil {
+				m.Secret = &Secret{}
+			}
+			if err := m.Secret.Unmarshal(data[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipControl(data[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthControl
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
 func (m *ListSecretsRequest) Unmarshal(data []byte) error {
 	l := len(data)
 	iNdEx := 0
@@ -12903,114 +13413,117 @@ var (
 func init() { proto.RegisterFile("control.proto", fileDescriptorControl) }
 
 var fileDescriptorControl = []byte{
-	// 1731 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x5a, 0x5f, 0x6f, 0x1b, 0xc5,
-	0x16, 0xaf, 0xed, 0x24, 0x4e, 0x8e, 0x93, 0xb4, 0x99, 0x38, 0xf7, 0x5a, 0xdb, 0x5e, 0xa7, 0xda,
-	0xde, 0xa6, 0x8e, 0xd4, 0xeb, 0xf4, 0xba, 0x54, 0x94, 0x22, 0xfe, 0x25, 0xa6, 0xc1, 0xfd, 0x13,
-	0xaa, 0x4d, 0x0b, 0xbc, 0x45, 0x8e, 0x3d, 0x0d, 0x8b, 0x1d, 0xaf, 0xd9, 0xdd, 0xa4, 0xad, 0x78,
-	0x01, 0x09, 0x24, 0x3e, 0x02, 0xaf, 0xbc, 0xf2, 0x80, 0xc4, 0x27, 0xe0, 0xb5, 0xe2, 0x89, 0x47,
-	0x9e, 0x2c, 0x6a, 0x09, 0x89, 0x27, 0xc4, 0x27, 0x40, 0x68, 0x66, 0xce, 0xec, 0xae, 0xd7, 0xb3,
-	0xbb, 0x76, 0x12, 0x94, 0x3e, 0x65, 0x77, 0xf6, 0x77, 0xe6, 0x9c, 0x99, 0xf3, 0x9b, 0x9f, 0xcf,
-	0x1c, 0x05, 0xe6, 0x1a, 0x56, 0xc7, 0xb5, 0xad, 0x76, 0xb9, 0x6b, 0x5b, 0xae, 0x45, 0x48, 0xd3,
-	0x6a, 0xb4, 0xa8, 0x5d, 0x76, 0x9e, 0xd4, 0xed, 0xfd, 0x96, 0xe9, 0x96, 0x0f, 0xff, 0xaf, 0xe5,
-	0x9c, 0x2e, 0x6d, 0x38, 0x02, 0xa0, 0xcd, 0x59, 0xbb, 0x9f, 0xd0, 0x86, 0x2b, 0x5f, 0x73, 0xee,
-	0xb3, 0x2e, 0x95, 0x2f, 0xf9, 0x3d, 0x6b, 0xcf, 0xe2, 0x8f, 0x6b, 0xec, 0x09, 0x47, 0x17, 0xbb,
-	0xed, 0x83, 0x3d, 0xb3, 0xb3, 0x26, 0xfe, 0x88, 0x41, 0xfd, 0x06, 0xcc, 0x6f, 0x52, 0x77, 0xcb,
-	0x6a, 0x52, 0x83, 0x7e, 0x7a, 0x40, 0x1d, 0x97, 0x5c, 0x82, 0x6c, 0xc7, 0x6a, 0xd2, 0x1d, 0xb3,
-	0x59, 0x48, 0x5d, 0x4c, 0x95, 0x66, 0xd6, 0xa1, 0xdf, 0x5b, 0x9e, 0x62, 0x88, 0x5a, 0xd5, 0x98,
-	0x62, 0x9f, 0x6a, 0x4d, 0xfd, 0x2d, 0x38, 0xeb, 0x99, 0x39, 0x5d, 0xab, 0xe3, 0x50, 0x72, 0x15,
-	0x26, 0xd8, 0x47, 0x6e, 0x94, 0xab, 0x14, 0xca, 0xc3, 0x0b, 0x28, 0x73, 0x3c, 0x47, 0xe9, 0xbd,
-	0x0c, 0x9c, 0xbb, 0x67, 0x3a, 0x7c, 0x0a, 0x47, 0xba, 0xbe, 0x0d, 0xd9, 0xc7, 0x66, 0xdb, 0xa5,
-	0xb6, 0x83, 0xb3, 0x5c, 0x55, 0xcd, 0x12, 0x36, 0x2b, 0xdf, 0x16, 0x36, 0x86, 0x34, 0xd6, 0xbe,
-	0xc8, 0x40, 0x16, 0x07, 0x49, 0x1e, 0x26, 0x3b, 0xf5, 0x7d, 0xca, 0x66, 0xcc, 0x94, 0x66, 0x0c,
-	0xf1, 0x42, 0xd6, 0x20, 0x67, 0x36, 0x77, 0xba, 0x36, 0x7d, 0x6c, 0x3e, 0xa5, 0x4e, 0x21, 0xcd,
-	0xbe, 0xad, 0xcf, 0xf7, 0x7b, 0xcb, 0x50, 0xab, 0x3e, 0xc0, 0x51, 0x03, 0xcc, 0xa6, 0x7c, 0x26,
-	0x0f, 0x60, 0xaa, 0x5d, 0xdf, 0xa5, 0x6d, 0xa7, 0x90, 0xb9, 0x98, 0x29, 0xe5, 0x2a, 0x37, 0xc7,
-	0x89, 0xac, 0x7c, 0x8f, 0x9b, 0xbe, 0xdb, 0x71, 0xed, 0x67, 0x06, 0xce, 0x43, 0x6a, 0x90, 0xdb,
-	0xa7, 0xfb, 0xbb, 0xd4, 0x76, 0x3e, 0x36, 0xbb, 0x4e, 0x61, 0xe2, 0x62, 0xa6, 0x34, 0x5f, 0xb9,
-	0x12, 0xb5, 0x6d, 0xdb, 0x5d, 0xda, 0x28, 0xdf, 0xf7, 0xf0, 0x46, 0xd0, 0x96, 0x54, 0x60, 0xd2,
-	0xb6, 0xda, 0xd4, 0x29, 0x4c, 0xf2, 0x49, 0x2e, 0x44, 0xee, 0xbd, 0xd5, 0xa6, 0x86, 0x80, 0x92,
-	0x4b, 0x30, 0xc7, 0xb6, 0xc2, 0xdf, 0x83, 0x29, 0xbe, 0x3f, 0xb3, 0x6c, 0x50, 0xae, 0x5a, 0x7b,
-	0x0d, 0x72, 0x81, 0xd0, 0xc9, 0x39, 0xc8, 0xb4, 0xe8, 0x33, 0x41, 0x0b, 0x83, 0x3d, 0xb2, 0xdd,
-	0x3d, 0xac, 0xb7, 0x0f, 0x68, 0x21, 0xcd, 0xc7, 0xc4, 0xcb, 0xad, 0xf4, 0xcd, 0x94, 0xbe, 0x01,
-	0x0b, 0x81, 0xed, 0x40, 0x8e, 0x94, 0x61, 0x92, 0x65, 0x5f, 0x24, 0x23, 0x8e, 0x24, 0x02, 0xa6,
-	0x7f, 0x97, 0x82, 0x85, 0x47, 0xdd, 0x66, 0xdd, 0xa5, 0xe3, 0x32, 0x94, 0xbc, 0x09, 0xb3, 0x1c,
-	0x74, 0x48, 0x6d, 0xc7, 0xb4, 0x3a, 0x3c, 0xc0, 0x5c, 0xe5, 0xbc, 0xca, 0xe3, 0x07, 0x02, 0x62,
-	0xe4, 0x98, 0x01, 0xbe, 0x90, 0x6b, 0x30, 0xc1, 0x8e, 0x5b, 0x21, 0xc3, 0xed, 0x2e, 0xc4, 0xe5,
-	0xc5, 0xe0, 0x48, 0x7d, 0x1d, 0x48, 0x30, 0xd6, 0x23, 0x1d, 0x8b, 0x2d, 0x58, 0x30, 0xe8, 0xbe,
-	0x75, 0x38, 0xfe, 0x7a, 0xf3, 0x30, 0xf9, 0xd8, 0xb2, 0x1b, 0x22, 0x13, 0xd3, 0x86, 0x78, 0xd1,
-	0xf3, 0x40, 0x82, 0xf3, 0x89, 0x98, 0xf0, 0xd0, 0x3f, 0xac, 0x3b, 0xad, 0x80, 0x0b, 0xb7, 0xee,
-	0xb4, 0x42, 0x2e, 0x18, 0x82, 0xb9, 0x60, 0x9f, 0xbc, 0x43, 0x2f, 0xcc, 0xfc, 0xd5, 0xb1, 0x8f,
-	0x71, 0xab, 0xe3, 0x78, 0x8e, 0xd2, 0x6f, 0xca, 0xd5, 0x8d, 0xed, 0xda, 0x5b, 0x47, 0xd0, 0xbb,
-	0xfe, 0x17, 0x8a, 0x08, 0x1b, 0x3c, 0x82, 0x88, 0x04, 0xcd, 0x86, 0x45, 0xe4, 0xdb, 0x53, 0x14,
-	0x11, 0x55, 0x64, 0x4a, 0x11, 0x59, 0x83, 0x9c, 0x43, 0xed, 0x43, 0xb3, 0xc1, 0xd8, 0x21, 0x44,
-	0x04, 0x43, 0xd8, 0x16, 0xc3, 0xb5, 0xaa, 0x63, 0x00, 0x42, 0x6a, 0x4d, 0x87, 0xac, 0xc0, 0x34,
-	0x72, 0x49, 0xa8, 0xc5, 0xcc, 0x7a, 0xae, 0xdf, 0x5b, 0xce, 0x0a, 0x32, 0x39, 0x46, 0x56, 0xb0,
-	0xc9, 0x21, 0x55, 0x98, 0x6f, 0x52, 0xc7, 0xb4, 0x69, 0x73, 0xc7, 0x71, 0xeb, 0x2e, 0xea, 0xc3,
-	0x7c, 0xe5, 0x3f, 0x51, 0x29, 0xde, 0x66, 0x28, 0x63, 0x0e, 0x8d, 0xf8, 0x9b, 0x42, 0x64, 0xb2,
+	// 1777 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x5a, 0xcf, 0x6f, 0xdb, 0xc6,
+	0x12, 0x8e, 0x24, 0xdb, 0xb2, 0x47, 0x96, 0x13, 0xaf, 0x95, 0x3c, 0x81, 0xc9, 0x93, 0x03, 0xe6,
+	0xc5, 0x91, 0x81, 0x3c, 0x39, 0x4f, 0x79, 0x41, 0xd3, 0x14, 0xfd, 0x65, 0xbb, 0x71, 0x95, 0x1f,
+	0x6e, 0x40, 0x27, 0x6d, 0x6f, 0x86, 0x2c, 0x6d, 0x5c, 0x56, 0xb2, 0xa8, 0x92, 0xb4, 0x93, 0xa0,
+	0x97, 0x16, 0x68, 0x81, 0xfe, 0x09, 0xbd, 0xf6, 0xda, 0x02, 0x3d, 0xf7, 0xd6, 0x6b, 0xd0, 0x53,
+	0x8f, 0x3d, 0x19, 0x8d, 0x80, 0x02, 0x3d, 0x15, 0xfd, 0x0b, 0x8a, 0x62, 0x77, 0x67, 0x49, 0x8a,
+	0x5a, 0x92, 0x92, 0xe5, 0xc2, 0x39, 0x99, 0x5c, 0x7e, 0xb3, 0x33, 0xbb, 0xf3, 0xed, 0xa7, 0xd9,
+	0x81, 0x21, 0xdf, 0xb0, 0x3a, 0xae, 0x6d, 0xb5, 0x2b, 0x5d, 0xdb, 0x72, 0x2d, 0x42, 0x9a, 0x56,
+	0xa3, 0x45, 0xed, 0x8a, 0xf3, 0xa4, 0x6e, 0xef, 0xb5, 0x4c, 0xb7, 0x72, 0xf0, 0x3f, 0x2d, 0xe7,
+	0x74, 0x69, 0xc3, 0x11, 0x00, 0x2d, 0x6f, 0xed, 0x7c, 0x4c, 0x1b, 0xae, 0x7c, 0xcd, 0xb9, 0xcf,
+	0xba, 0x54, 0xbe, 0x14, 0x76, 0xad, 0x5d, 0x8b, 0x3f, 0xae, 0xb0, 0x27, 0x1c, 0x5d, 0xe8, 0xb6,
+	0xf7, 0x77, 0xcd, 0xce, 0x8a, 0xf8, 0x23, 0x06, 0xf5, 0x1b, 0x30, 0xb7, 0x41, 0xdd, 0x4d, 0xab,
+	0x49, 0x0d, 0xfa, 0xc9, 0x3e, 0x75, 0x5c, 0x72, 0x09, 0xb2, 0x1d, 0xab, 0x49, 0xb7, 0xcd, 0x66,
+	0x31, 0x75, 0x31, 0x55, 0x9e, 0x59, 0x85, 0xde, 0xe1, 0xe2, 0x14, 0x43, 0xd4, 0xd6, 0x8d, 0x29,
+	0xf6, 0xa9, 0xd6, 0xd4, 0xdf, 0x84, 0xd3, 0x9e, 0x99, 0xd3, 0xb5, 0x3a, 0x0e, 0x25, 0x57, 0x61,
+	0x82, 0x7d, 0xe4, 0x46, 0xb9, 0x6a, 0xb1, 0x32, 0xb8, 0x80, 0x0a, 0xc7, 0x73, 0x94, 0x7e, 0x98,
+	0x81, 0x33, 0xf7, 0x4c, 0x87, 0x4f, 0xe1, 0x48, 0xd7, 0xb7, 0x21, 0xfb, 0xd8, 0x6c, 0xbb, 0xd4,
+	0x76, 0x70, 0x96, 0xab, 0xaa, 0x59, 0xc2, 0x66, 0x95, 0xdb, 0xc2, 0xc6, 0x90, 0xc6, 0xda, 0xe7,
+	0x19, 0xc8, 0xe2, 0x20, 0x29, 0xc0, 0x64, 0xa7, 0xbe, 0x47, 0xd9, 0x8c, 0x99, 0xf2, 0x8c, 0x21,
+	0x5e, 0xc8, 0x0a, 0xe4, 0xcc, 0xe6, 0x76, 0xd7, 0xa6, 0x8f, 0xcd, 0xa7, 0xd4, 0x29, 0xa6, 0xd9,
+	0xb7, 0xd5, 0xb9, 0xde, 0xe1, 0x22, 0xd4, 0xd6, 0x1f, 0xe0, 0xa8, 0x01, 0x66, 0x53, 0x3e, 0x93,
+	0x07, 0x30, 0xd5, 0xae, 0xef, 0xd0, 0xb6, 0x53, 0xcc, 0x5c, 0xcc, 0x94, 0x73, 0xd5, 0x9b, 0xa3,
+	0x44, 0x56, 0xb9, 0xc7, 0x4d, 0xdf, 0xe9, 0xb8, 0xf6, 0x33, 0x03, 0xe7, 0x21, 0x35, 0xc8, 0xed,
+	0xd1, 0xbd, 0x1d, 0x6a, 0x3b, 0x1f, 0x99, 0x5d, 0xa7, 0x38, 0x71, 0x31, 0x53, 0x9e, 0xab, 0x5e,
+	0x89, 0xda, 0xb6, 0xad, 0x2e, 0x6d, 0x54, 0xee, 0x7b, 0x78, 0x23, 0x68, 0x4b, 0xaa, 0x30, 0x69,
+	0x5b, 0x6d, 0xea, 0x14, 0x27, 0xf9, 0x24, 0x17, 0x22, 0xf7, 0xde, 0x6a, 0x53, 0x43, 0x40, 0xc9,
+	0x25, 0xc8, 0xb3, 0xad, 0xf0, 0xf7, 0x60, 0x8a, 0xef, 0xcf, 0x2c, 0x1b, 0x94, 0xab, 0xd6, 0x5e,
+	0x85, 0x5c, 0x20, 0x74, 0x72, 0x06, 0x32, 0x2d, 0xfa, 0x4c, 0xd0, 0xc2, 0x60, 0x8f, 0x6c, 0x77,
+	0x0f, 0xea, 0xed, 0x7d, 0x5a, 0x4c, 0xf3, 0x31, 0xf1, 0x72, 0x2b, 0x7d, 0x33, 0xa5, 0xaf, 0xc1,
+	0x7c, 0x60, 0x3b, 0x90, 0x23, 0x15, 0x98, 0x64, 0xd9, 0x17, 0xc9, 0x88, 0x23, 0x89, 0x80, 0xe9,
+	0xdf, 0xa6, 0x60, 0xfe, 0x51, 0xb7, 0x59, 0x77, 0xe9, 0xa8, 0x0c, 0x25, 0x6f, 0xc0, 0x2c, 0x07,
+	0x1d, 0x50, 0xdb, 0x31, 0xad, 0x0e, 0x0f, 0x30, 0x57, 0x3d, 0xaf, 0xf2, 0xf8, 0xbe, 0x80, 0x18,
+	0x39, 0x66, 0x80, 0x2f, 0xe4, 0x1a, 0x4c, 0xb0, 0xe3, 0x56, 0xcc, 0x70, 0xbb, 0x0b, 0x71, 0x79,
+	0x31, 0x38, 0x52, 0x5f, 0x05, 0x12, 0x8c, 0xf5, 0x48, 0xc7, 0x62, 0x13, 0xe6, 0x0d, 0xba, 0x67,
+	0x1d, 0x8c, 0xbe, 0xde, 0x02, 0x4c, 0x3e, 0xb6, 0xec, 0x86, 0xc8, 0xc4, 0xb4, 0x21, 0x5e, 0xf4,
+	0x02, 0x90, 0xe0, 0x7c, 0x22, 0x26, 0x3c, 0xf4, 0x0f, 0xeb, 0x4e, 0x2b, 0xe0, 0xc2, 0xad, 0x3b,
+	0xad, 0x90, 0x0b, 0x86, 0x60, 0x2e, 0xd8, 0x27, 0xef, 0xd0, 0x0b, 0x33, 0x7f, 0x75, 0xec, 0x63,
+	0xdc, 0xea, 0x38, 0x9e, 0xa3, 0xf4, 0x9b, 0x72, 0x75, 0x23, 0xbb, 0xf6, 0xd6, 0x11, 0xf4, 0xae,
+	0xff, 0x85, 0x22, 0xc2, 0x06, 0x8f, 0x20, 0x22, 0x41, 0xb3, 0x41, 0x11, 0xf9, 0xe6, 0x04, 0x45,
+	0x44, 0x15, 0x99, 0x52, 0x44, 0x56, 0x20, 0xe7, 0x50, 0xfb, 0xc0, 0x6c, 0x30, 0x76, 0x08, 0x11,
+	0xc1, 0x10, 0xb6, 0xc4, 0x70, 0x6d, 0xdd, 0x31, 0x00, 0x21, 0xb5, 0xa6, 0x43, 0x96, 0x60, 0x1a,
+	0xb9, 0x24, 0xd4, 0x62, 0x66, 0x35, 0xd7, 0x3b, 0x5c, 0xcc, 0x0a, 0x32, 0x39, 0x46, 0x56, 0xb0,
+	0xc9, 0x21, 0xeb, 0x30, 0xd7, 0xa4, 0x8e, 0x69, 0xd3, 0xe6, 0xb6, 0xe3, 0xd6, 0x5d, 0xd4, 0x87,
+	0xb9, 0xea, 0xbf, 0xa3, 0x52, 0xbc, 0xc5, 0x50, 0x46, 0x1e, 0x8d, 0xf8, 0x9b, 0x42, 0x64, 0xb2,
 	0xff, 0x88, 0xc8, 0xe0, 0x76, 0xf9, 0x22, 0xc3, 0x58, 0x13, 0x2b, 0x32, 0x9c, 0x46, 0x02, 0xa6,
-	0xdf, 0x85, 0xfc, 0x86, 0x4d, 0xeb, 0x2e, 0xc5, 0x2d, 0x93, 0x44, 0xba, 0x8e, 0x0a, 0x20, 0x58,
-	0xb4, 0xac, 0x9a, 0x06, 0x2d, 0x02, 0x22, 0xb0, 0x05, 0x4b, 0xa1, 0xc9, 0x30, 0xaa, 0x1b, 0x90,
-	0xc5, 0x34, 0xe0, 0x84, 0xe7, 0x63, 0x26, 0x34, 0x24, 0x56, 0x7f, 0x07, 0x16, 0x36, 0xa9, 0x1b,
-	0x8a, 0xec, 0x2a, 0x80, 0x9f, 0x75, 0x3c, 0x35, 0x73, 0xfd, 0xde, 0xf2, 0x8c, 0x97, 0x74, 0x63,
-	0xc6, 0xcb, 0xb9, 0x7e, 0x17, 0x48, 0x70, 0x8a, 0xe3, 0xc5, 0xf3, 0x63, 0x0a, 0xf2, 0x42, 0xe5,
-	0x8e, 0x13, 0x13, 0xa9, 0xc2, 0x59, 0x89, 0x1e, 0x43, 0xa0, 0xe7, 0xd1, 0x46, 0x6a, 0xf4, 0xf5,
-	0x01, 0x8d, 0x1e, 0x3d, 0x43, 0xa1, 0x05, 0x1c, 0x6f, 0x47, 0xaa, 0x90, 0x17, 0xd2, 0x74, 0xac,
-	0x24, 0xfd, 0x1b, 0x96, 0x42, 0xb3, 0xa0, 0xc6, 0xfd, 0x9e, 0x86, 0x45, 0xc6, 0x71, 0x1c, 0xf7,
-	0x64, 0xae, 0x16, 0x96, 0xb9, 0xb5, 0x28, 0x31, 0x09, 0x59, 0x0e, 0x2b, 0xdd, 0x57, 0xe9, 0x13,
-	0x57, 0xba, 0xed, 0x90, 0xd2, 0xbd, 0x3e, 0x66, 0x70, 0x4a, 0xb1, 0x1b, 0x52, 0x93, 0x89, 0x93,
-	0x55, 0x93, 0xf7, 0x21, 0x3f, 0x18, 0x12, 0x12, 0xe3, 0x55, 0x98, 0xc6, 0x44, 0x49, 0x4d, 0x89,
-	0x65, 0x86, 0x07, 0xf6, 0x95, 0x65, 0x8b, 0xba, 0x4f, 0x2c, 0xbb, 0x35, 0x86, 0xb2, 0xa0, 0x85,
+	0xdf, 0x85, 0xc2, 0x9a, 0x4d, 0xeb, 0x2e, 0xc5, 0x2d, 0x93, 0x44, 0xba, 0x8e, 0x0a, 0x20, 0x58,
+	0xb4, 0xa8, 0x9a, 0x06, 0x2d, 0x02, 0x22, 0xb0, 0x09, 0x67, 0x43, 0x93, 0x61, 0x54, 0x37, 0x20,
+	0x8b, 0x69, 0xc0, 0x09, 0xcf, 0xc7, 0x4c, 0x68, 0x48, 0xac, 0xfe, 0x36, 0xcc, 0x6f, 0x50, 0x37,
+	0x14, 0xd9, 0x55, 0x00, 0x3f, 0xeb, 0x78, 0x6a, 0xf2, 0xbd, 0xc3, 0xc5, 0x19, 0x2f, 0xe9, 0xc6,
+	0x8c, 0x97, 0x73, 0xfd, 0x2e, 0x90, 0xe0, 0x14, 0xe3, 0xc5, 0xf3, 0x63, 0x0a, 0x0a, 0x42, 0xe5,
+	0xc6, 0x89, 0x89, 0xac, 0xc3, 0x69, 0x89, 0x1e, 0x41, 0xa0, 0xe7, 0xd0, 0x46, 0x6a, 0xf4, 0xf5,
+	0x3e, 0x8d, 0x1e, 0x3e, 0x43, 0xa1, 0x05, 0x8c, 0xb7, 0x23, 0xeb, 0x50, 0x10, 0xd2, 0x34, 0x56,
+	0x92, 0xfe, 0x05, 0x67, 0x43, 0xb3, 0xa0, 0xc6, 0xfd, 0x9e, 0x86, 0x05, 0xc6, 0x71, 0x1c, 0xf7,
+	0x64, 0xae, 0x16, 0x96, 0xb9, 0x95, 0x28, 0x31, 0x09, 0x59, 0x0e, 0x2a, 0xdd, 0x97, 0xe9, 0x63,
+	0x57, 0xba, 0xad, 0x90, 0xd2, 0xbd, 0x36, 0x62, 0x70, 0x4a, 0xb1, 0x1b, 0x50, 0x93, 0x89, 0xe3,
+	0x55, 0x93, 0xf7, 0xa0, 0xd0, 0x1f, 0x12, 0x12, 0xe3, 0x15, 0x98, 0xc6, 0x44, 0x49, 0x4d, 0x89,
+	0x65, 0x86, 0x07, 0xf6, 0x95, 0x65, 0x93, 0xba, 0x4f, 0x2c, 0xbb, 0x35, 0x82, 0xb2, 0xa0, 0x85,
 	0x4a, 0x59, 0xbc, 0xc9, 0x7c, 0xde, 0x76, 0xc4, 0x50, 0x1c, 0x6f, 0xa5, 0x95, 0xc4, 0xea, 0x8f,
 	0xb8, 0xb2, 0x84, 0x22, 0x23, 0x30, 0xc1, 0x76, 0x13, 0xf7, 0x8b, 0x3f, 0x33, 0x22, 0xa3, 0x0d,
-	0x23, 0x72, 0xda, 0x27, 0x32, 0xda, 0x32, 0x22, 0x23, 0xc0, 0x53, 0x9b, 0x13, 0x8a, 0xf1, 0x23,
-	0x79, 0xb6, 0x4e, 0x3c, 0x4c, 0xef, 0xbc, 0x85, 0x22, 0xf5, 0xce, 0x1b, 0x8e, 0x1f, 0xe1, 0xbc,
-	0x85, 0x2c, 0x5f, 0xae, 0xf3, 0x16, 0x11, 0xdc, 0x69, 0x9e, 0x37, 0x3f, 0x24, 0xff, 0xbc, 0x61,
-	0xa2, 0x62, 0xcf, 0x9b, 0xcc, 0x9c, 0x07, 0xc6, 0x1f, 0xcb, 0x8d, 0xf6, 0x81, 0xe3, 0x52, 0x3b,
+	0x23, 0x72, 0xda, 0x27, 0x32, 0xda, 0x32, 0x22, 0x23, 0xc0, 0x53, 0x9b, 0x63, 0x8a, 0xf1, 0x43,
+	0x79, 0xb6, 0x8e, 0x3d, 0x4c, 0xef, 0xbc, 0x85, 0x22, 0xf5, 0xce, 0x1b, 0x8e, 0x1f, 0xe1, 0xbc,
+	0x85, 0x2c, 0x5f, 0xae, 0xf3, 0x16, 0x11, 0xdc, 0x49, 0x9e, 0x37, 0x3f, 0x24, 0xff, 0xbc, 0x61,
+	0xa2, 0x62, 0xcf, 0x9b, 0xcc, 0x9c, 0x07, 0xc6, 0x1f, 0xcb, 0xb5, 0xf6, 0xbe, 0xe3, 0x52, 0x3b,
 	0xa0, 0xc3, 0x0d, 0x31, 0x12, 0xd2, 0x61, 0xc4, 0x31, 0x5e, 0x20, 0xc0, 0xa3, 0xaf, 0x37, 0x85,
 	0x4f, 0x5f, 0x84, 0xc4, 0xd1, 0x57, 0x5a, 0x49, 0xac, 0xc7, 0x25, 0xfc, 0x70, 0x04, 0x2e, 0x85,
-	0x2c, 0x5f, 0x2e, 0x2e, 0x45, 0x04, 0x77, 0x9a, 0x5c, 0xf2, 0x43, 0xf2, 0xb9, 0x84, 0xd9, 0x88,
-	0xe5, 0x92, 0x4c, 0x9d, 0x07, 0xd6, 0x0f, 0x60, 0xe1, 0x8e, 0x65, 0x76, 0x1e, 0x5a, 0x2d, 0xda,
-	0x31, 0x2c, 0xb7, 0xee, 0xb2, 0x82, 0xa3, 0x0c, 0x8b, 0x36, 0x7b, 0xa6, 0x3b, 0x8c, 0x70, 0xd4,
-	0xde, 0x71, 0xd9, 0x67, 0x1e, 0xe1, 0xb4, 0xb1, 0x20, 0x3e, 0x7d, 0xc8, 0xbf, 0x70, 0x3b, 0x72,
-	0x0d, 0xf2, 0x88, 0xdf, 0xaf, 0x77, 0xea, 0x7b, 0x9e, 0x81, 0xb8, 0xa3, 0x11, 0xf1, 0xed, 0xbe,
-	0xf8, 0xc4, 0x2d, 0xf4, 0xaf, 0xd3, 0xb2, 0xbe, 0x3a, 0x0e, 0x8d, 0x59, 0x7d, 0x25, 0xd1, 0xe3,
-	0xd4, 0x57, 0x68, 0x33, 0x46, 0x7d, 0x85, 0xde, 0xfd, 0xdf, 0x29, 0xb2, 0x09, 0xd3, 0x36, 0xee,
-	0x57, 0x61, 0x82, 0x1b, 0x5e, 0x56, 0x19, 0x0e, 0x6d, 0xee, 0xfa, 0xc4, 0xf3, 0xde, 0xf2, 0x19,
-	0xc3, 0x33, 0xf6, 0x0b, 0xb5, 0x13, 0x3a, 0x8d, 0x6f, 0xc0, 0x39, 0x5e, 0x07, 0x37, 0x6c, 0xea,
-	0xca, 0x5d, 0x5d, 0x85, 0x19, 0x87, 0x0f, 0xf8, 0x9b, 0x3a, 0xdb, 0xef, 0x2d, 0x4f, 0x0b, 0x54,
-	0xad, 0xca, 0x7e, 0xcc, 0xf9, 0x53, 0x53, 0xdf, 0xc4, 0x4a, 0x5c, 0x98, 0x63, 0x28, 0x15, 0x98,
-	0x12, 0x00, 0x8c, 0x44, 0x53, 0x17, 0x06, 0xdc, 0x06, 0x91, 0xfa, 0x6f, 0x69, 0x20, 0xa2, 0xce,
-	0x60, 0xaf, 0x9e, 0x28, 0xbc, 0x17, 0x16, 0x85, 0x72, 0x74, 0xcd, 0x14, 0x34, 0x1c, 0xd6, 0x84,
-	0x2f, 0x4f, 0x5e, 0x13, 0x8c, 0x90, 0x26, 0xdc, 0x1a, 0x2f, 0xb6, 0x53, 0x91, 0x84, 0xbb, 0xb2,
-	0x70, 0xc6, 0x88, 0x30, 0x65, 0xaf, 0xb0, 0x32, 0x9f, 0x0f, 0xa1, 0x20, 0xc4, 0xe5, 0x4c, 0x42,
-	0xf5, 0x1a, 0x2c, 0xca, 0x7b, 0x5d, 0x90, 0x3f, 0x95, 0x81, 0x4a, 0xae, 0x18, 0x3d, 0x53, 0xa0,
-	0x90, 0xbb, 0xe3, 0xdf, 0x37, 0x8f, 0xcd, 0xa5, 0xb7, 0x61, 0x51, 0x5e, 0x1b, 0x8e, 0x48, 0xeb,
-	0x7f, 0xf9, 0xd7, 0x97, 0x60, 0x34, 0x95, 0x1f, 0x96, 0x20, 0xbb, 0x21, 0x5a, 0xd2, 0xc4, 0x84,
-	0x2c, 0x76, 0x7b, 0x89, 0xae, 0x0a, 0x6a, 0xb0, 0x83, 0xac, 0x5d, 0x8a, 0xc5, 0x60, 0x9d, 0xb5,
-	0xf4, 0xd3, 0xf7, 0x7f, 0x7c, 0x93, 0x3e, 0x0b, 0x73, 0x1c, 0xf4, 0x3f, 0xd4, 0x47, 0x62, 0xc1,
-	0x8c, 0xd7, 0x36, 0x24, 0xff, 0x1d, 0xa5, 0xc9, 0xaa, 0x5d, 0x4e, 0x40, 0xc5, 0x3b, 0xb4, 0x01,
-	0xfc, 0xae, 0x1d, 0x51, 0xce, 0x35, 0xd4, 0x81, 0xd4, 0x56, 0x92, 0x60, 0x89, 0x3e, 0xfd, 0xae,
-	0x9c, 0xda, 0xe7, 0x50, 0x17, 0x50, 0xed, 0x53, 0xd1, 0xdc, 0x8b, 0xf0, 0x29, 0x72, 0xf8, 0xb0,
-	0xee, 0xb4, 0x22, 0x73, 0x18, 0xe8, 0xca, 0x45, 0xe6, 0x70, 0xa0, 0xff, 0x16, 0x9f, 0x43, 0xde,
-	0x95, 0x89, 0xce, 0x61, 0xb0, 0xc7, 0x15, 0x9d, 0xc3, 0x81, 0xd6, 0x4e, 0xe2, 0x7e, 0xf2, 0xe5,
-	0xc5, 0xec, 0x67, 0x70, 0x85, 0x2b, 0x49, 0xb0, 0x44, 0x9f, 0x7e, 0x57, 0x45, 0xed, 0x73, 0xa8,
-	0x71, 0xa3, 0xf6, 0x39, 0xdc, 0x9c, 0x89, 0xf2, 0xf9, 0x14, 0x66, 0x83, 0x17, 0x54, 0x72, 0x65,
-	0xc4, 0x5b, 0xb5, 0x56, 0x4a, 0x06, 0xc6, 0x7b, 0xfe, 0x0c, 0xe6, 0x06, 0xda, 0x5a, 0x44, 0x39,
-	0xa3, 0xaa, 0x8d, 0xa6, 0xad, 0x8e, 0x80, 0x4c, 0x74, 0x3e, 0xd0, 0xb1, 0x51, 0x3b, 0x57, 0x75,
-	0xa5, 0xd4, 0xce, 0x95, 0xed, 0x9f, 0x18, 0xe7, 0x03, 0x8d, 0x19, 0xb5, 0x73, 0x55, 0x07, 0x48,
-	0xed, 0x5c, 0xdd, 0xe5, 0x89, 0x25, 0x19, 0x5e, 0x74, 0x22, 0x49, 0x36, 0x78, 0x39, 0x8e, 0x24,
-	0x59, 0xf8, 0xa6, 0x1b, 0x4f, 0x32, 0x79, 0x2b, 0x8b, 0x26, 0x59, 0xe8, 0x2a, 0x19, 0x4d, 0xb2,
-	0xf0, 0x05, 0x2f, 0x91, 0x64, 0x72, 0xc1, 0x31, 0x24, 0x0b, 0xad, 0x79, 0x75, 0x04, 0xe4, 0x88,
-	0x79, 0x8e, 0x75, 0xae, 0xea, 0x46, 0xc4, 0xe5, 0x79, 0x44, 0xe7, 0x22, 0xcf, 0x58, 0xb1, 0x46,
-	0xe6, 0x79, 0xf0, 0x46, 0x10, 0x99, 0xe7, 0x50, 0xb9, 0x9c, 0x90, 0x67, 0x79, 0x63, 0x8a, 0xce,
-	0x73, 0xe8, 0x9a, 0x17, 0x9d, 0xe7, 0xf0, 0xe5, 0x2b, 0xf1, 0x3c, 0xcb, 0x05, 0xc7, 0x9c, 0xe7,
-	0xd0, 0x9a, 0x57, 0x47, 0x40, 0x26, 0xfe, 0x38, 0x79, 0x65, 0xbc, 0xfa, 0xc7, 0x29, 0x7c, 0x49,
-	0xd0, 0x2e, 0x27, 0xa0, 0xe2, 0x1d, 0x1e, 0x40, 0x2e, 0x50, 0x86, 0x92, 0x95, 0xd1, 0x2a, 0x67,
-	0xed, 0x4a, 0x22, 0x2e, 0x31, 0xbd, 0xc1, 0x2a, 0x53, 0x9d, 0x5e, 0x45, 0x49, 0xab, 0x95, 0x92,
-	0x81, 0x89, 0x9e, 0x83, 0x15, 0xa5, 0xda, 0xb3, 0xa2, 0x6a, 0xd5, 0x4a, 0xc9, 0xc0, 0x58, 0xcf,
-	0xeb, 0x17, 0x9e, 0xbf, 0x28, 0x9e, 0xf9, 0xe5, 0x45, 0xf1, 0xcc, 0x9f, 0x2f, 0x8a, 0xa9, 0xcf,
-	0xfb, 0xc5, 0xd4, 0xf3, 0x7e, 0x31, 0xf5, 0x73, 0xbf, 0x98, 0xfa, 0xb5, 0x5f, 0x4c, 0xed, 0x4e,
-	0xf1, 0xff, 0x78, 0xb8, 0xfe, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0xde, 0x36, 0x11, 0xa9, 0x6a,
-	0x21, 0x00, 0x00,
+	0x2c, 0x5f, 0x2e, 0x2e, 0x45, 0x04, 0x77, 0x92, 0x5c, 0xf2, 0x43, 0xf2, 0xb9, 0x84, 0xd9, 0x88,
+	0xe5, 0x92, 0x4c, 0x9d, 0x07, 0xd6, 0xf7, 0x61, 0xfe, 0x8e, 0x65, 0x76, 0x1e, 0x5a, 0x2d, 0xda,
+	0x31, 0x2c, 0xb7, 0xee, 0xb2, 0x82, 0xa3, 0x02, 0x0b, 0x36, 0x7b, 0xa6, 0xdb, 0x8c, 0x70, 0xd4,
+	0xde, 0x76, 0xd9, 0x67, 0x1e, 0xe1, 0xb4, 0x31, 0x2f, 0x3e, 0x7d, 0xc0, 0xbf, 0x70, 0x3b, 0x72,
+	0x0d, 0x0a, 0x88, 0xdf, 0xab, 0x77, 0xea, 0xbb, 0x9e, 0x81, 0xb8, 0xa3, 0x11, 0xf1, 0xed, 0xbe,
+	0xf8, 0xc4, 0x2d, 0xf4, 0xaf, 0xd2, 0xb2, 0xbe, 0x1a, 0x87, 0xc6, 0xac, 0xbe, 0x92, 0xe8, 0x51,
+	0xea, 0x2b, 0xb4, 0x19, 0xa1, 0xbe, 0x42, 0xef, 0xfe, 0xef, 0x14, 0xd9, 0x80, 0x69, 0x1b, 0xf7,
+	0xab, 0x38, 0xc1, 0x0d, 0x2f, 0xab, 0x0c, 0x07, 0x36, 0x77, 0x75, 0xe2, 0xf9, 0xe1, 0xe2, 0x29,
+	0xc3, 0x33, 0xf6, 0x0b, 0xb5, 0x63, 0x3a, 0x8d, 0xaf, 0xc3, 0x19, 0x5e, 0x07, 0x37, 0x6c, 0xea,
+	0xca, 0x5d, 0x5d, 0x86, 0x19, 0x87, 0x0f, 0xf8, 0x9b, 0x3a, 0xdb, 0x3b, 0x5c, 0x9c, 0x16, 0xa8,
+	0xda, 0x3a, 0xfb, 0x31, 0xe7, 0x4f, 0x4d, 0x7d, 0x03, 0x2b, 0x71, 0x61, 0x8e, 0xa1, 0x54, 0x61,
+	0x4a, 0x00, 0x30, 0x12, 0x4d, 0x5d, 0x18, 0x70, 0x1b, 0x44, 0xea, 0x3f, 0xa4, 0x60, 0x41, 0x56,
+	0xa0, 0x47, 0x8b, 0x85, 0xac, 0xc2, 0x1c, 0x42, 0x47, 0xc8, 0x6e, 0x5e, 0x98, 0xc8, 0xe4, 0x56,
+	0xfb, 0x92, 0x5b, 0x8a, 0x0e, 0x3c, 0x50, 0x83, 0xdc, 0xf1, 0x8b, 0xff, 0xb1, 0xb7, 0xe1, 0xb7,
+	0x34, 0x10, 0x51, 0x6e, 0xb1, 0x57, 0x4f, 0x1b, 0xdf, 0x0d, 0x6b, 0x63, 0x25, 0xba, 0x74, 0x0c,
+	0x1a, 0x0e, 0x4a, 0xe3, 0x17, 0xc7, 0x2f, 0x8d, 0x46, 0x48, 0x1a, 0x6f, 0x8d, 0x16, 0xdb, 0x89,
+	0x28, 0xe3, 0x5d, 0x79, 0x7f, 0xc0, 0x88, 0x30, 0x65, 0xff, 0x67, 0xb7, 0x1d, 0x3e, 0x84, 0xba,
+	0x18, 0x97, 0x33, 0x09, 0xd5, 0x6b, 0xb0, 0x20, 0xaf, 0xb7, 0x41, 0xea, 0x56, 0xfb, 0x0a, 0xda,
+	0xa1, 0xb9, 0xd4, 0x3f, 0xd5, 0x18, 0x5c, 0x7a, 0x0b, 0x16, 0xe4, 0xed, 0xe9, 0x88, 0xa7, 0xfb,
+	0x9c, 0x7f, 0x8b, 0x0b, 0x46, 0x53, 0xfd, 0xee, 0x1c, 0x64, 0xd7, 0x44, 0x67, 0x9e, 0x98, 0x90,
+	0xc5, 0xa6, 0x37, 0xd1, 0x55, 0x41, 0xf5, 0x37, 0xd2, 0xb5, 0x4b, 0xb1, 0x18, 0x2c, 0x37, 0xcf,
+	0xfe, 0xf4, 0xfd, 0x1f, 0x5f, 0xa7, 0x4f, 0x43, 0x9e, 0x83, 0xfe, 0x8b, 0x3f, 0x13, 0xc4, 0x82,
+	0x19, 0xaf, 0x7b, 0x4a, 0xfe, 0x33, 0x4c, 0xaf, 0x59, 0xbb, 0x9c, 0x80, 0x8a, 0x77, 0x68, 0x03,
+	0xf8, 0xcd, 0x4b, 0xa2, 0x9c, 0x6b, 0xa0, 0x11, 0xab, 0x2d, 0x25, 0xc1, 0x12, 0x7d, 0xfa, 0xcd,
+	0x49, 0xb5, 0xcf, 0x81, 0x66, 0xa8, 0xda, 0xa7, 0xa2, 0xc7, 0x19, 0xe1, 0x53, 0xe4, 0xf0, 0x61,
+	0xdd, 0x69, 0x45, 0xe6, 0x30, 0xd0, 0x9c, 0x8c, 0xcc, 0x61, 0x5f, 0x1b, 0x32, 0x3e, 0x87, 0xbc,
+	0x39, 0x15, 0x9d, 0xc3, 0x60, 0xab, 0x2f, 0x3a, 0x87, 0x7d, 0x1d, 0xae, 0xc4, 0xfd, 0xe4, 0xcb,
+	0x8b, 0xd9, 0xcf, 0xe0, 0x0a, 0x97, 0x92, 0x60, 0x89, 0x3e, 0xfd, 0xe6, 0x92, 0xda, 0xe7, 0x40,
+	0xff, 0x4a, 0xed, 0x73, 0xb0, 0x47, 0x15, 0xe5, 0xf3, 0x29, 0xcc, 0x06, 0xef, 0xe9, 0xe4, 0xca,
+	0x90, 0xcd, 0x05, 0xad, 0x9c, 0x0c, 0x8c, 0xf7, 0xfc, 0x29, 0xe4, 0xfb, 0xba, 0x7b, 0x44, 0x39,
+	0xa3, 0xaa, 0x9b, 0xa8, 0x2d, 0x0f, 0x81, 0x4c, 0x74, 0xde, 0xd7, 0xb8, 0x52, 0x3b, 0x57, 0x35,
+	0xe7, 0xd4, 0xce, 0x95, 0x5d, 0xb0, 0x18, 0xe7, 0x7d, 0xfd, 0x29, 0xb5, 0x73, 0x55, 0x23, 0x4c,
+	0xed, 0x5c, 0xdd, 0xec, 0x8a, 0x25, 0x19, 0xde, 0xf7, 0x22, 0x49, 0xd6, 0xdf, 0x23, 0x88, 0x24,
+	0x59, 0xf8, 0xc2, 0x1f, 0x4f, 0x32, 0x79, 0x39, 0x8d, 0x26, 0x59, 0xe8, 0x46, 0x1d, 0x4d, 0xb2,
+	0xf0, 0x3d, 0x37, 0x91, 0x64, 0x72, 0xc1, 0x31, 0x24, 0x0b, 0xad, 0x79, 0x79, 0x08, 0xe4, 0x90,
+	0x79, 0x8e, 0x75, 0xae, 0x6a, 0xca, 0xc4, 0xe5, 0x79, 0x48, 0xe7, 0x22, 0xcf, 0x58, 0xb8, 0x47,
+	0xe6, 0xb9, 0xff, 0x62, 0x14, 0x99, 0xe7, 0xd0, 0xad, 0x21, 0x21, 0xcf, 0xf2, 0xe2, 0x18, 0x9d,
+	0xe7, 0xd0, 0x6d, 0x37, 0x3a, 0xcf, 0xe1, 0x3b, 0x68, 0xe2, 0x79, 0x96, 0x0b, 0x8e, 0x39, 0xcf,
+	0xa1, 0x35, 0x2f, 0x0f, 0x81, 0x4c, 0xfc, 0x71, 0xf2, 0x6e, 0x33, 0xea, 0x1f, 0xa7, 0xf0, 0x5d,
+	0x49, 0xbb, 0x9c, 0x80, 0x4a, 0xdc, 0xe7, 0xe0, 0xd5, 0x41, 0xbd, 0xcf, 0x8a, 0x6b, 0x91, 0x56,
+	0x4e, 0x06, 0xc6, 0x7b, 0xde, 0x87, 0x5c, 0xa0, 0x00, 0x26, 0x4b, 0xc3, 0xd5, 0xec, 0xda, 0x95,
+	0x44, 0x5c, 0xe2, 0x82, 0x83, 0xf5, 0xad, 0x7a, 0xc1, 0x8a, 0x62, 0x5a, 0x2b, 0x27, 0x03, 0x13,
+	0x3d, 0x07, 0x6b, 0x59, 0xb5, 0x67, 0x45, 0xbd, 0xac, 0x95, 0x93, 0x81, 0xb1, 0x9e, 0x57, 0x2f,
+	0x3c, 0x7f, 0x51, 0x3a, 0xf5, 0xcb, 0x8b, 0xd2, 0xa9, 0x3f, 0x5f, 0x94, 0x52, 0x9f, 0xf5, 0x4a,
+	0xa9, 0xe7, 0xbd, 0x52, 0xea, 0xe7, 0x5e, 0x29, 0xf5, 0x6b, 0xaf, 0x94, 0xda, 0x99, 0xe2, 0xff,
+	0x72, 0x72, 0xfd, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x2a, 0x7c, 0x4c, 0x3e, 0xeb, 0x22, 0x00,
+	0x00,
 }

+ 26 - 0
vendor/src/github.com/docker/swarmkit/api/control.proto

@@ -83,6 +83,15 @@ service Control {
 		option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
 	}
 
+	// UpdateSecret returns a `UpdateSecretResponse` with a `Secret` with the same
+	// id as `GetSecretRequest.SecretID`
+	// - Returns `NotFound` if the Secret with the given id is not found.
+	// - Returns `InvalidArgument` if the `GetSecretRequest.SecretID` is empty.
+	// - Returns an error if updating fails.
+	rpc UpdateSecret(UpdateSecretRequest) returns (UpdateSecretResponse) {
+		option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
+	};
+
 	// ListSecrets returns a `ListSecretResponse` with a list all non-internal `Secret`s being
 	// managed, or all secrets matching any name in `ListSecretsRequest.Names`, any
 	// name prefix in `ListSecretsRequest.NamePrefixes`, any id in
@@ -342,6 +351,23 @@ message GetSecretResponse {
 	Secret secret = 1;
 }
 
+message UpdateSecretRequest {
+	// SecretID is the secret ID to update.
+	string secret_id = 1 [(gogoproto.customname) = "SecretID"];
+
+	// SecretVersion is the version of the secret being updated.
+	Version secret_version = 2;
+
+	// Spec is the new spec to apply to the Secret
+	// Only some fields are allowed to be updated.
+	SecretSpec spec = 3;
+}
+
+message UpdateSecretResponse {
+	Secret secret = 1;
+}
+
+
 // ListSecretRequest is the request to list all non-internal secrets in the secret store,
 // or all secrets filtered by (name or name prefix or id prefix) and labels.
 message ListSecretsRequest {

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

@@ -1,3 +1,3 @@
 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 resource.proto
+//go:generate protoc -I.:../protobuf:../vendor:../vendor/github.com/gogo/protobuf:../vendor/github.com/gogo/protobuf/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

+ 29 - 0
vendor/src/github.com/docker/swarmkit/api/naming/naming.go

@@ -0,0 +1,29 @@
+// Package naming centralizes the naming of SwarmKit objects.
+package naming
+
+import (
+	"fmt"
+
+	"github.com/docker/swarmkit/api"
+)
+
+// Task returns the task name from Annotations.Name,
+// and, in case Annotations.Name is missing, fallback
+// to construct the name from othere information.
+func Task(t *api.Task) string {
+	if t.Annotations.Name != "" {
+		// if set, use the container Annotations.Name field, set in the orchestrator.
+		return t.Annotations.Name
+	}
+
+	slot := fmt.Sprint(t.Slot)
+	if slot == "" || t.Slot == 0 {
+		// when no slot id is assigned, we assume that this is node-bound task.
+		slot = t.NodeID
+	}
+
+	// fallback to service.instance.id.
+	return fmt.Sprintf("%s.%s.%s", t.ServiceAnnotations.Name, slot, t.ID)
+}
+
+// TODO(stevvooe): Consolidate "Hostname" style validation here.

+ 240 - 102
vendor/src/github.com/docker/swarmkit/api/objects.pb.go

@@ -15,6 +15,7 @@ import github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto"
 import sort "sort"
 import strconv "strconv"
 import reflect "reflect"
+import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
 
 import io "io"
 
@@ -227,9 +228,10 @@ type Cluster struct {
 	// and agents to unambiguously identify the older key to be deleted when
 	// a new key is allocated on key rotation.
 	EncryptionKeyLamportClock uint64 `protobuf:"varint,6,opt,name=encryption_key_lamport_clock,json=encryptionKeyLamportClock,proto3" json:"encryption_key_lamport_clock,omitempty"`
-	// RemovedNodes is the list of nodes that have been removed from the
+	// BlacklistedCertificates tracks certificates that should no longer
+	// be honored. It's a mapping from CN -> BlacklistedCertificate.
 	// swarm. Their certificates should effectively be blacklisted.
-	RemovedNodes []*RemovedNode `protobuf:"bytes,7,rep,name=removed_nodes,json=removedNodes" json:"removed_nodes,omitempty"`
+	BlacklistedCertificates map[string]*BlacklistedCertificate `protobuf:"bytes,8,rep,name=blacklisted_certificates,json=blacklistedCertificates" json:"blacklisted_certificates,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"`
 }
 
 func (m *Cluster) Reset()                    { *m = Cluster{} }
@@ -451,10 +453,10 @@ func (m *Cluster) Copy() *Cluster {
 		}
 	}
 
-	if m.RemovedNodes != nil {
-		o.RemovedNodes = make([]*RemovedNode, 0, len(m.RemovedNodes))
-		for _, v := range m.RemovedNodes {
-			o.RemovedNodes = append(o.RemovedNodes, v.Copy())
+	if m.BlacklistedCertificates != nil {
+		o.BlacklistedCertificates = make(map[string]*BlacklistedCertificate)
+		for k, v := range m.BlacklistedCertificates {
+			o.BlacklistedCertificates[k] = v.Copy()
 		}
 	}
 
@@ -641,8 +643,18 @@ func (this *Cluster) GoString() string {
 		s = append(s, "NetworkBootstrapKeys: "+fmt.Sprintf("%#v", this.NetworkBootstrapKeys)+",\n")
 	}
 	s = append(s, "EncryptionKeyLamportClock: "+fmt.Sprintf("%#v", this.EncryptionKeyLamportClock)+",\n")
-	if this.RemovedNodes != nil {
-		s = append(s, "RemovedNodes: "+fmt.Sprintf("%#v", this.RemovedNodes)+",\n")
+	keysForBlacklistedCertificates := make([]string, 0, len(this.BlacklistedCertificates))
+	for k, _ := range this.BlacklistedCertificates {
+		keysForBlacklistedCertificates = append(keysForBlacklistedCertificates, k)
+	}
+	github_com_gogo_protobuf_sortkeys.Strings(keysForBlacklistedCertificates)
+	mapStringForBlacklistedCertificates := "map[string]*BlacklistedCertificate{"
+	for _, k := range keysForBlacklistedCertificates {
+		mapStringForBlacklistedCertificates += fmt.Sprintf("%#v: %#v,", k, this.BlacklistedCertificates[k])
+	}
+	mapStringForBlacklistedCertificates += "}"
+	if this.BlacklistedCertificates != nil {
+		s = append(s, "BlacklistedCertificates: "+mapStringForBlacklistedCertificates+",\n")
 	}
 	s = append(s, "}")
 	return strings.Join(s, "")
@@ -1270,16 +1282,32 @@ func (m *Cluster) MarshalTo(data []byte) (int, error) {
 		i++
 		i = encodeVarintObjects(data, i, uint64(m.EncryptionKeyLamportClock))
 	}
-	if len(m.RemovedNodes) > 0 {
-		for _, msg := range m.RemovedNodes {
-			data[i] = 0x3a
+	if len(m.BlacklistedCertificates) > 0 {
+		for k, _ := range m.BlacklistedCertificates {
+			data[i] = 0x42
 			i++
-			i = encodeVarintObjects(data, i, uint64(msg.Size()))
-			n, err := msg.MarshalTo(data[i:])
-			if err != nil {
-				return 0, err
+			v := m.BlacklistedCertificates[k]
+			msgSize := 0
+			if v != nil {
+				msgSize = v.Size()
+				msgSize += 1 + sovObjects(uint64(msgSize))
+			}
+			mapSize := 1 + len(k) + sovObjects(uint64(len(k))) + msgSize
+			i = encodeVarintObjects(data, i, uint64(mapSize))
+			data[i] = 0xa
+			i++
+			i = encodeVarintObjects(data, i, uint64(len(k)))
+			i += copy(data[i:], k)
+			if v != nil {
+				data[i] = 0x12
+				i++
+				i = encodeVarintObjects(data, i, uint64(v.Size()))
+				n32, err := v.MarshalTo(data[i:])
+				if err != nil {
+					return 0, err
+				}
+				i += n32
 			}
-			i += n
 		}
 	}
 	return i, nil
@@ -1309,19 +1337,19 @@ func (m *Secret) MarshalTo(data []byte) (int, error) {
 	data[i] = 0x12
 	i++
 	i = encodeVarintObjects(data, i, uint64(m.Meta.Size()))
-	n32, err := m.Meta.MarshalTo(data[i:])
+	n33, err := m.Meta.MarshalTo(data[i:])
 	if err != nil {
 		return 0, err
 	}
-	i += n32
+	i += n33
 	data[i] = 0x1a
 	i++
 	i = encodeVarintObjects(data, i, uint64(m.Spec.Size()))
-	n33, err := m.Spec.MarshalTo(data[i:])
+	n34, err := m.Spec.MarshalTo(data[i:])
 	if err != nil {
 		return 0, err
 	}
-	i += n33
+	i += n34
 	if len(m.Digest) > 0 {
 		data[i] = 0x22
 		i++
@@ -1596,10 +1624,17 @@ func (m *Cluster) Size() (n int) {
 	if m.EncryptionKeyLamportClock != 0 {
 		n += 1 + sovObjects(uint64(m.EncryptionKeyLamportClock))
 	}
-	if len(m.RemovedNodes) > 0 {
-		for _, e := range m.RemovedNodes {
-			l = e.Size()
-			n += 1 + l + sovObjects(uint64(l))
+	if len(m.BlacklistedCertificates) > 0 {
+		for k, v := range m.BlacklistedCertificates {
+			_ = k
+			_ = v
+			l = 0
+			if v != nil {
+				l = v.Size()
+				l += 1 + sovObjects(uint64(l))
+			}
+			mapEntrySize := 1 + len(k) + sovObjects(uint64(len(k))) + l
+			n += mapEntrySize + 1 + sovObjects(uint64(mapEntrySize))
 		}
 	}
 	return n
@@ -1761,6 +1796,16 @@ func (this *Cluster) String() string {
 	if this == nil {
 		return "nil"
 	}
+	keysForBlacklistedCertificates := make([]string, 0, len(this.BlacklistedCertificates))
+	for k, _ := range this.BlacklistedCertificates {
+		keysForBlacklistedCertificates = append(keysForBlacklistedCertificates, k)
+	}
+	github_com_gogo_protobuf_sortkeys.Strings(keysForBlacklistedCertificates)
+	mapStringForBlacklistedCertificates := "map[string]*BlacklistedCertificate{"
+	for _, k := range keysForBlacklistedCertificates {
+		mapStringForBlacklistedCertificates += fmt.Sprintf("%v: %v,", k, this.BlacklistedCertificates[k])
+	}
+	mapStringForBlacklistedCertificates += "}"
 	s := strings.Join([]string{`&Cluster{`,
 		`ID:` + fmt.Sprintf("%v", this.ID) + `,`,
 		`Meta:` + strings.Replace(strings.Replace(this.Meta.String(), "Meta", "Meta", 1), `&`, ``, 1) + `,`,
@@ -1768,7 +1813,7 @@ func (this *Cluster) String() string {
 		`RootCA:` + strings.Replace(strings.Replace(this.RootCA.String(), "RootCA", "RootCA", 1), `&`, ``, 1) + `,`,
 		`NetworkBootstrapKeys:` + strings.Replace(fmt.Sprintf("%v", this.NetworkBootstrapKeys), "EncryptionKey", "EncryptionKey", 1) + `,`,
 		`EncryptionKeyLamportClock:` + fmt.Sprintf("%v", this.EncryptionKeyLamportClock) + `,`,
-		`RemovedNodes:` + strings.Replace(fmt.Sprintf("%v", this.RemovedNodes), "RemovedNode", "RemovedNode", 1) + `,`,
+		`BlacklistedCertificates:` + mapStringForBlacklistedCertificates + `,`,
 		`}`,
 	}, "")
 	return s
@@ -3697,9 +3742,9 @@ func (m *Cluster) Unmarshal(data []byte) error {
 					break
 				}
 			}
-		case 7:
+		case 8:
 			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field RemovedNodes", wireType)
+				return fmt.Errorf("proto: wrong wireType = %d for field BlacklistedCertificates", wireType)
 			}
 			var msglen int
 			for shift := uint(0); ; shift += 7 {
@@ -3723,9 +3768,99 @@ func (m *Cluster) Unmarshal(data []byte) error {
 			if postIndex > l {
 				return io.ErrUnexpectedEOF
 			}
-			m.RemovedNodes = append(m.RemovedNodes, &RemovedNode{})
-			if err := m.RemovedNodes[len(m.RemovedNodes)-1].Unmarshal(data[iNdEx:postIndex]); err != nil {
-				return err
+			var keykey uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowObjects
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := data[iNdEx]
+				iNdEx++
+				keykey |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			var stringLenmapkey uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowObjects
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := data[iNdEx]
+				iNdEx++
+				stringLenmapkey |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLenmapkey := int(stringLenmapkey)
+			if intStringLenmapkey < 0 {
+				return ErrInvalidLengthObjects
+			}
+			postStringIndexmapkey := iNdEx + intStringLenmapkey
+			if postStringIndexmapkey > l {
+				return io.ErrUnexpectedEOF
+			}
+			mapkey := string(data[iNdEx:postStringIndexmapkey])
+			iNdEx = postStringIndexmapkey
+			if m.BlacklistedCertificates == nil {
+				m.BlacklistedCertificates = make(map[string]*BlacklistedCertificate)
+			}
+			if iNdEx < postIndex {
+				var valuekey uint64
+				for shift := uint(0); ; shift += 7 {
+					if shift >= 64 {
+						return ErrIntOverflowObjects
+					}
+					if iNdEx >= l {
+						return io.ErrUnexpectedEOF
+					}
+					b := data[iNdEx]
+					iNdEx++
+					valuekey |= (uint64(b) & 0x7F) << shift
+					if b < 0x80 {
+						break
+					}
+				}
+				var mapmsglen int
+				for shift := uint(0); ; shift += 7 {
+					if shift >= 64 {
+						return ErrIntOverflowObjects
+					}
+					if iNdEx >= l {
+						return io.ErrUnexpectedEOF
+					}
+					b := data[iNdEx]
+					iNdEx++
+					mapmsglen |= (int(b) & 0x7F) << shift
+					if b < 0x80 {
+						break
+					}
+				}
+				if mapmsglen < 0 {
+					return ErrInvalidLengthObjects
+				}
+				postmsgIndex := iNdEx + mapmsglen
+				if mapmsglen < 0 {
+					return ErrInvalidLengthObjects
+				}
+				if postmsgIndex > l {
+					return io.ErrUnexpectedEOF
+				}
+				mapvalue := &BlacklistedCertificate{}
+				if err := mapvalue.Unmarshal(data[iNdEx:postmsgIndex]); err != nil {
+					return err
+				}
+				iNdEx = postmsgIndex
+				m.BlacklistedCertificates[mapkey] = mapvalue
+			} else {
+				var mapvalue *BlacklistedCertificate
+				m.BlacklistedCertificates[mapkey] = mapvalue
 			}
 			iNdEx = postIndex
 		default:
@@ -4064,76 +4199,79 @@ var (
 func init() { proto.RegisterFile("objects.proto", fileDescriptorObjects) }
 
 var fileDescriptorObjects = []byte{
-	// 1126 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xbc, 0x57, 0x4d, 0x6f, 0x1b, 0xc5,
-	0x1b, 0xef, 0xda, 0x5b, 0xbf, 0x3c, 0xb6, 0x23, 0xfd, 0xe7, 0x5f, 0x45, 0xdb, 0x10, 0xec, 0xe0,
-	0x0a, 0xd4, 0x43, 0xe5, 0x8a, 0x52, 0x50, 0x2b, 0x5a, 0x21, 0xbf, 0x44, 0x60, 0x95, 0x40, 0x34,
-	0x29, 0xe9, 0x71, 0x35, 0xd9, 0x9d, 0x9a, 0xc5, 0xf6, 0xce, 0x6a, 0x66, 0xec, 0x2a, 0x3d, 0x21,
-	0x3e, 0x00, 0x1f, 0x81, 0x6f, 0xc1, 0x99, 0x6b, 0x0e, 0x1c, 0xb8, 0xc1, 0xc9, 0x22, 0x3e, 0x20,
-	0x71, 0xe3, 0x23, 0xa0, 0x79, 0x59, 0xdb, 0x91, 0xd7, 0x21, 0x95, 0xaa, 0xdc, 0xe6, 0xf1, 0xfc,
-	0x7e, 0xbf, 0x79, 0xde, 0xe6, 0x99, 0x35, 0xd4, 0xd8, 0xc9, 0x77, 0x34, 0x90, 0xa2, 0x95, 0x70,
-	0x26, 0x19, 0x42, 0x21, 0x0b, 0x86, 0x94, 0xb7, 0xc4, 0x2b, 0xc2, 0xc7, 0xc3, 0x48, 0xb6, 0xa6,
-	0x1f, 0xee, 0x54, 0xe4, 0x69, 0x42, 0x2d, 0x60, 0xa7, 0x22, 0x12, 0x1a, 0xa4, 0xc6, 0x6d, 0x19,
-	0x8d, 0xa9, 0x90, 0x64, 0x9c, 0xdc, 0x5f, 0xac, 0xec, 0xd6, 0xad, 0x01, 0x1b, 0x30, 0xbd, 0xbc,
-	0xaf, 0x56, 0xe6, 0xd7, 0xe6, 0x2f, 0x0e, 0xb8, 0x07, 0x54, 0x12, 0xf4, 0x29, 0x14, 0xa7, 0x94,
-	0x8b, 0x88, 0xc5, 0x9e, 0xb3, 0xe7, 0xdc, 0xad, 0x3c, 0x78, 0xa7, 0xb5, 0x7e, 0x72, 0xeb, 0xd8,
-	0x40, 0x3a, 0xee, 0xd9, 0xac, 0x71, 0x03, 0xa7, 0x0c, 0xf4, 0x04, 0x20, 0xe0, 0x94, 0x48, 0x1a,
-	0xfa, 0x44, 0x7a, 0x39, 0xcd, 0x7f, 0x37, 0x8b, 0xff, 0x3c, 0x75, 0x0a, 0x97, 0x2d, 0xa1, 0x2d,
-	0x15, 0x7b, 0x92, 0x84, 0x29, 0x3b, 0x7f, 0x25, 0xb6, 0x25, 0xb4, 0x65, 0xf3, 0xef, 0x3c, 0xb8,
-	0x5f, 0xb1, 0x90, 0xa2, 0x6d, 0xc8, 0x45, 0xa1, 0x76, 0xbe, 0xdc, 0x29, 0xcc, 0x67, 0x8d, 0x5c,
-	0xbf, 0x87, 0x73, 0x51, 0x88, 0x1e, 0x80, 0x3b, 0xa6, 0x92, 0x58, 0xb7, 0xbc, 0x2c, 0x61, 0x95,
-	0x01, 0x1b, 0x93, 0xc6, 0xa2, 0x4f, 0xc0, 0x55, 0x69, 0xb5, 0xce, 0xec, 0x66, 0x71, 0xd4, 0x99,
-	0x47, 0x09, 0x0d, 0x52, 0x9e, 0xc2, 0xa3, 0x7d, 0xa8, 0x84, 0x54, 0x04, 0x3c, 0x4a, 0xa4, 0xca,
-	0xa4, 0xab, 0xe9, 0x77, 0x36, 0xd1, 0x7b, 0x4b, 0x28, 0x5e, 0xe5, 0xa1, 0x27, 0x50, 0x10, 0x92,
-	0xc8, 0x89, 0xf0, 0x6e, 0x6a, 0x85, 0xfa, 0x46, 0x07, 0x34, 0xca, 0xba, 0x60, 0x39, 0xe8, 0x0b,
-	0xd8, 0x1a, 0x93, 0x98, 0x0c, 0x28, 0xf7, 0xad, 0x4a, 0x41, 0xab, 0xbc, 0x97, 0x19, 0xba, 0x41,
-	0x1a, 0x21, 0x5c, 0x1b, 0xaf, 0x9a, 0x68, 0x1f, 0x80, 0x48, 0x49, 0x82, 0x6f, 0xc7, 0x34, 0x96,
-	0x5e, 0x51, 0xab, 0xbc, 0x9f, 0xe9, 0x0b, 0x95, 0xaf, 0x18, 0x1f, 0xb6, 0x17, 0x60, 0xbc, 0x42,
-	0x44, 0x9f, 0x43, 0x25, 0xa0, 0x5c, 0x46, 0x2f, 0xa3, 0x80, 0x48, 0xea, 0x95, 0xb4, 0x4e, 0x23,
-	0x4b, 0xa7, 0xbb, 0x84, 0xd9, 0xa0, 0x56, 0x99, 0xcd, 0xdf, 0x73, 0x50, 0x3c, 0xa2, 0x7c, 0x1a,
-	0x05, 0x6f, 0xb7, 0xdc, 0x8f, 0x2f, 0x94, 0x3b, 0xd3, 0x33, 0x7b, 0xec, 0x5a, 0xc5, 0x1f, 0x41,
-	0x89, 0xc6, 0x61, 0xc2, 0xa2, 0x58, 0xda, 0x72, 0x67, 0x76, 0xcb, 0xbe, 0xc5, 0xe0, 0x05, 0x1a,
-	0xed, 0x43, 0xcd, 0x74, 0xb1, 0x7f, 0xa1, 0xd6, 0x7b, 0x59, 0xf4, 0x6f, 0x34, 0xd0, 0x16, 0xa9,
-	0x3a, 0x59, 0xb1, 0x50, 0x0f, 0x6a, 0x09, 0xa7, 0xd3, 0x88, 0x4d, 0x84, 0xaf, 0x83, 0x28, 0x5c,
-	0x29, 0x08, 0x5c, 0x4d, 0x59, 0xca, 0x6a, 0xfe, 0x94, 0x83, 0x52, 0xea, 0x23, 0x7a, 0x68, 0xd3,
-	0xe1, 0x6c, 0x76, 0x28, 0xc5, 0x6a, 0x29, 0x93, 0x89, 0x87, 0x70, 0x33, 0x61, 0x5c, 0x0a, 0x2f,
-	0xb7, 0x97, 0xdf, 0xd4, 0xb3, 0x87, 0x8c, 0xcb, 0x2e, 0x8b, 0x5f, 0x46, 0x03, 0x6c, 0xc0, 0xe8,
-	0x05, 0x54, 0xa6, 0x11, 0x97, 0x13, 0x32, 0xf2, 0xa3, 0x44, 0x78, 0x79, 0xcd, 0xfd, 0xe0, 0xb2,
-	0x23, 0x5b, 0xc7, 0x06, 0xdf, 0x3f, 0xec, 0x6c, 0xcd, 0x67, 0x0d, 0x58, 0x98, 0x02, 0x83, 0x95,
-	0xea, 0x27, 0x62, 0xe7, 0x00, 0xca, 0x8b, 0x1d, 0x74, 0x0f, 0x20, 0x36, 0x2d, 0xea, 0x2f, 0x9a,
-	0xa6, 0x36, 0x9f, 0x35, 0xca, 0xb6, 0x71, 0xfb, 0x3d, 0x5c, 0xb6, 0x80, 0x7e, 0x88, 0x10, 0xb8,
-	0x24, 0x0c, 0xb9, 0x6e, 0xa1, 0x32, 0xd6, 0xeb, 0xe6, 0xaf, 0x37, 0xc1, 0x7d, 0x4e, 0xc4, 0xf0,
-	0xba, 0xc7, 0x8c, 0x3a, 0x73, 0xad, 0xe9, 0xee, 0x01, 0x08, 0x53, 0x4a, 0x15, 0x8e, 0xbb, 0x0c,
-	0xc7, 0x16, 0x58, 0x85, 0x63, 0x01, 0x26, 0x1c, 0x31, 0x62, 0x52, 0xf7, 0x97, 0x8b, 0xf5, 0x1a,
-	0xdd, 0x81, 0x62, 0xcc, 0x42, 0x4d, 0x2f, 0x68, 0x3a, 0xcc, 0x67, 0x8d, 0x82, 0x1a, 0x29, 0xfd,
-	0x1e, 0x2e, 0xa8, 0xad, 0x7e, 0xa8, 0xee, 0x2d, 0x89, 0x63, 0x26, 0x89, 0x1a, 0x4a, 0xc2, 0xde,
-	0xff, 0xcc, 0xc6, 0x6a, 0x2f, 0x61, 0xe9, 0xbd, 0x5d, 0x61, 0xa2, 0x63, 0xf8, 0x7f, 0xea, 0xef,
-	0xaa, 0x60, 0xe9, 0x4d, 0x04, 0x91, 0x55, 0x58, 0xd9, 0x59, 0x99, 0x93, 0xe5, 0xcd, 0x73, 0x52,
-	0x67, 0x30, 0x6b, 0x4e, 0x76, 0xa0, 0x16, 0x52, 0x11, 0x71, 0x1a, 0xea, 0x1b, 0x48, 0x3d, 0xd8,
-	0x73, 0xee, 0x6e, 0x6d, 0x78, 0x7a, 0xac, 0x08, 0xc5, 0x55, 0xcb, 0xd1, 0x16, 0x6a, 0x43, 0xc9,
-	0xf6, 0x8d, 0xf0, 0x2a, 0xba, 0x77, 0xaf, 0x38, 0x1f, 0x17, 0xb4, 0x0b, 0x13, 0xa4, 0xfa, 0x46,
-	0x13, 0xe4, 0x31, 0xc0, 0x88, 0x0d, 0xfc, 0x90, 0x47, 0x53, 0xca, 0xbd, 0x9a, 0xe6, 0xee, 0x64,
-	0x71, 0x7b, 0x1a, 0x81, 0xcb, 0x23, 0x36, 0x30, 0xcb, 0xe6, 0x0f, 0x0e, 0xfc, 0x6f, 0xcd, 0x29,
-	0xf4, 0x31, 0x14, 0xad, 0x5b, 0x97, 0x7d, 0x04, 0x58, 0x1e, 0x4e, 0xb1, 0x68, 0x17, 0xca, 0xea,
-	0x8e, 0x50, 0x21, 0xa8, 0xb9, 0xfd, 0x65, 0xbc, 0xfc, 0x01, 0x79, 0x50, 0x24, 0xa3, 0x88, 0xa8,
-	0xbd, 0xbc, 0xde, 0x4b, 0xcd, 0xe6, 0x8f, 0x39, 0x28, 0x5a, 0xb1, 0xeb, 0x1e, 0xe7, 0xf6, 0xd8,
-	0xb5, 0x9b, 0xf5, 0x14, 0xaa, 0x26, 0x9d, 0xb6, 0x25, 0xdc, 0xff, 0x4c, 0x6a, 0xc5, 0xe0, 0x4d,
-	0x3b, 0x3c, 0x05, 0x37, 0x4a, 0xc8, 0xd8, 0x8e, 0xf2, 0xcc, 0x93, 0xfb, 0x87, 0xed, 0x83, 0xaf,
-	0x13, 0xd3, 0xd9, 0xa5, 0xf9, 0xac, 0xe1, 0xaa, 0x1f, 0xb0, 0xa6, 0x35, 0x7f, 0xce, 0x43, 0xb1,
-	0x3b, 0x9a, 0x08, 0x49, 0xf9, 0x75, 0x27, 0xc4, 0x1e, 0xbb, 0x96, 0x90, 0x2e, 0x14, 0x39, 0x63,
-	0xd2, 0x0f, 0xc8, 0x65, 0xb9, 0xc0, 0x8c, 0xc9, 0x6e, 0xbb, 0xb3, 0xa5, 0x88, 0x6a, 0x90, 0x18,
-	0x1b, 0x17, 0x14, 0xb5, 0x4b, 0xd0, 0x0b, 0xd8, 0x4e, 0xc7, 0xef, 0x09, 0x63, 0x52, 0x48, 0x4e,
-	0x12, 0x7f, 0x48, 0x4f, 0xd5, 0x9b, 0x97, 0xdf, 0xf4, 0x65, 0xb2, 0x1f, 0x07, 0xfc, 0x54, 0x27,
-	0xea, 0x19, 0x3d, 0xc5, 0xb7, 0xac, 0x40, 0x27, 0xe5, 0x3f, 0xa3, 0xa7, 0x02, 0x7d, 0x06, 0xbb,
-	0x74, 0x01, 0x53, 0x8a, 0xfe, 0x88, 0x8c, 0xd5, 0xc3, 0xe2, 0x07, 0x23, 0x16, 0x0c, 0xf5, 0x6c,
-	0x73, 0xf1, 0x6d, 0xba, 0x2a, 0xf5, 0xa5, 0x41, 0x74, 0x15, 0x40, 0xbd, 0x9e, 0x9c, 0x8e, 0xd9,
-	0x94, 0x86, 0xbe, 0x1a, 0x7a, 0x6a, 0xc8, 0xe5, 0x37, 0xa5, 0x08, 0x1b, 0xa0, 0x1a, 0x92, 0xb8,
-	0xca, 0x97, 0x86, 0x68, 0xfe, 0xe5, 0x40, 0xe1, 0x88, 0x06, 0x9c, 0xca, 0xb7, 0x5a, 0xb6, 0x47,
-	0x17, 0xca, 0x56, 0xcf, 0x7e, 0xd1, 0xd5, 0xa9, 0x6b, 0x55, 0xdb, 0x86, 0x42, 0x18, 0x0d, 0xa8,
-	0x30, 0xdf, 0x24, 0x65, 0x6c, 0x2d, 0xd4, 0x04, 0x57, 0x44, 0xaf, 0xa9, 0xee, 0xcf, 0xbc, 0x79,
-	0x3e, 0xad, 0x42, 0xf4, 0x9a, 0x62, 0xbd, 0x87, 0x76, 0xa0, 0x14, 0xc5, 0x92, 0xf2, 0x98, 0x8c,
-	0x74, 0xfe, 0x4a, 0x78, 0x61, 0x77, 0x76, 0xcf, 0xce, 0xeb, 0x37, 0xfe, 0x38, 0xaf, 0xdf, 0xf8,
-	0xe7, 0xbc, 0xee, 0x7c, 0x3f, 0xaf, 0x3b, 0x67, 0xf3, 0xba, 0xf3, 0xdb, 0xbc, 0xee, 0xfc, 0x39,
-	0xaf, 0x3b, 0x27, 0x05, 0xfd, 0x9f, 0xe2, 0xa3, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xf7, 0x71,
-	0xe0, 0xa4, 0xc3, 0x0c, 0x00, 0x00,
+	// 1174 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xbc, 0x57, 0x4d, 0x8f, 0x1b, 0x35,
+	0x18, 0xee, 0x24, 0xb3, 0xf9, 0x78, 0xb3, 0x59, 0x81, 0xa9, 0xca, 0x34, 0x2c, 0xc9, 0x92, 0x0a,
+	0x54, 0xa1, 0x2a, 0x15, 0xa5, 0xa0, 0x2d, 0xb4, 0x82, 0x7c, 0x09, 0xa2, 0x52, 0xa8, 0xdc, 0xd2,
+	0x1e, 0x23, 0xef, 0x8c, 0x1b, 0x86, 0x4c, 0xc6, 0x23, 0xdb, 0x49, 0x95, 0x9e, 0x10, 0x3f, 0x80,
+	0x9f, 0xc0, 0x5f, 0xe1, 0xba, 0x07, 0x0e, 0xdc, 0xe0, 0x80, 0x22, 0x36, 0x07, 0x24, 0x6e, 0xfc,
+	0x04, 0x64, 0x8f, 0x27, 0x99, 0x55, 0x26, 0xcb, 0x56, 0xaa, 0xf6, 0xe6, 0x37, 0x7e, 0x9e, 0xc7,
+	0xef, 0x97, 0xdf, 0x71, 0xa0, 0xca, 0x8e, 0xbe, 0xa7, 0xae, 0x14, 0xad, 0x88, 0x33, 0xc9, 0x10,
+	0xf2, 0x98, 0x3b, 0xa6, 0xbc, 0x25, 0x9e, 0x13, 0x3e, 0x19, 0xfb, 0xb2, 0x35, 0xfb, 0xa0, 0x56,
+	0x91, 0xf3, 0x88, 0x1a, 0x40, 0xad, 0x22, 0x22, 0xea, 0x26, 0xc6, 0x55, 0xe9, 0x4f, 0xa8, 0x90,
+	0x64, 0x12, 0xdd, 0x5c, 0xad, 0xcc, 0xd6, 0xe5, 0x11, 0x1b, 0x31, 0xbd, 0xbc, 0xa9, 0x56, 0xf1,
+	0xaf, 0xcd, 0x5f, 0x2c, 0xb0, 0x1f, 0x50, 0x49, 0xd0, 0xa7, 0x50, 0x9c, 0x51, 0x2e, 0x7c, 0x16,
+	0x3a, 0xd6, 0x81, 0x75, 0xbd, 0x72, 0xeb, 0xad, 0xd6, 0xe6, 0xc9, 0xad, 0x27, 0x31, 0xa4, 0x63,
+	0x1f, 0x2f, 0x1a, 0x97, 0x70, 0xc2, 0x40, 0x77, 0x01, 0x5c, 0x4e, 0x89, 0xa4, 0xde, 0x90, 0x48,
+	0x27, 0xa7, 0xf9, 0x6f, 0x67, 0xf1, 0x1f, 0x27, 0x4e, 0xe1, 0xb2, 0x21, 0xb4, 0xa5, 0x62, 0x4f,
+	0x23, 0x2f, 0x61, 0xe7, 0xcf, 0xc5, 0x36, 0x84, 0xb6, 0x6c, 0xfe, 0x93, 0x07, 0xfb, 0x6b, 0xe6,
+	0x51, 0x74, 0x05, 0x72, 0xbe, 0xa7, 0x9d, 0x2f, 0x77, 0x0a, 0xcb, 0x45, 0x23, 0x37, 0xe8, 0xe1,
+	0x9c, 0xef, 0xa1, 0x5b, 0x60, 0x4f, 0xa8, 0x24, 0xc6, 0x2d, 0x27, 0x4b, 0x58, 0x65, 0xc0, 0xc4,
+	0xa4, 0xb1, 0xe8, 0x63, 0xb0, 0x55, 0x5a, 0x8d, 0x33, 0xfb, 0x59, 0x1c, 0x75, 0xe6, 0xa3, 0x88,
+	0xba, 0x09, 0x4f, 0xe1, 0x51, 0x1f, 0x2a, 0x1e, 0x15, 0x2e, 0xf7, 0x23, 0xa9, 0x32, 0x69, 0x6b,
+	0xfa, 0xb5, 0x6d, 0xf4, 0xde, 0x1a, 0x8a, 0xd3, 0x3c, 0x74, 0x17, 0x0a, 0x42, 0x12, 0x39, 0x15,
+	0xce, 0x8e, 0x56, 0xa8, 0x6f, 0x75, 0x40, 0xa3, 0x8c, 0x0b, 0x86, 0x83, 0xbe, 0x84, 0xbd, 0x09,
+	0x09, 0xc9, 0x88, 0xf2, 0xa1, 0x51, 0x29, 0x68, 0x95, 0x77, 0x32, 0x43, 0x8f, 0x91, 0xb1, 0x10,
+	0xae, 0x4e, 0xd2, 0x26, 0xea, 0x03, 0x10, 0x29, 0x89, 0xfb, 0xdd, 0x84, 0x86, 0xd2, 0x29, 0x6a,
+	0x95, 0x77, 0x33, 0x7d, 0xa1, 0xf2, 0x39, 0xe3, 0xe3, 0xf6, 0x0a, 0x8c, 0x53, 0x44, 0xf4, 0x05,
+	0x54, 0x5c, 0xca, 0xa5, 0xff, 0xcc, 0x77, 0x89, 0xa4, 0x4e, 0x49, 0xeb, 0x34, 0xb2, 0x74, 0xba,
+	0x6b, 0x98, 0x09, 0x2a, 0xcd, 0x6c, 0xfe, 0x9e, 0x83, 0xe2, 0x23, 0xca, 0x67, 0xbe, 0xfb, 0x6a,
+	0xcb, 0x7d, 0xe7, 0x54, 0xb9, 0x33, 0x3d, 0x33, 0xc7, 0x6e, 0x54, 0xfc, 0x10, 0x4a, 0x34, 0xf4,
+	0x22, 0xe6, 0x87, 0xd2, 0x94, 0x3b, 0xb3, 0x5b, 0xfa, 0x06, 0x83, 0x57, 0x68, 0xd4, 0x87, 0x6a,
+	0xdc, 0xc5, 0xc3, 0x53, 0xb5, 0x3e, 0xc8, 0xa2, 0x7f, 0xab, 0x81, 0xa6, 0x48, 0xbb, 0xd3, 0x94,
+	0x85, 0x7a, 0x50, 0x8d, 0x38, 0x9d, 0xf9, 0x6c, 0x2a, 0x86, 0x3a, 0x88, 0xc2, 0xb9, 0x82, 0xc0,
+	0xbb, 0x09, 0x4b, 0x59, 0xcd, 0x9f, 0x73, 0x50, 0x4a, 0x7c, 0x44, 0xb7, 0x4d, 0x3a, 0xac, 0xed,
+	0x0e, 0x25, 0x58, 0x2d, 0x15, 0x67, 0xe2, 0x36, 0xec, 0x44, 0x8c, 0x4b, 0xe1, 0xe4, 0x0e, 0xf2,
+	0xdb, 0x7a, 0xf6, 0x21, 0xe3, 0xb2, 0xcb, 0xc2, 0x67, 0xfe, 0x08, 0xc7, 0x60, 0xf4, 0x14, 0x2a,
+	0x33, 0x9f, 0xcb, 0x29, 0x09, 0x86, 0x7e, 0x24, 0x9c, 0xbc, 0xe6, 0xbe, 0x77, 0xd6, 0x91, 0xad,
+	0x27, 0x31, 0x7e, 0xf0, 0xb0, 0xb3, 0xb7, 0x5c, 0x34, 0x60, 0x65, 0x0a, 0x0c, 0x46, 0x6a, 0x10,
+	0x89, 0xda, 0x03, 0x28, 0xaf, 0x76, 0xd0, 0x0d, 0x80, 0x30, 0x6e, 0xd1, 0xe1, 0xaa, 0x69, 0xaa,
+	0xcb, 0x45, 0xa3, 0x6c, 0x1a, 0x77, 0xd0, 0xc3, 0x65, 0x03, 0x18, 0x78, 0x08, 0x81, 0x4d, 0x3c,
+	0x8f, 0xeb, 0x16, 0x2a, 0x63, 0xbd, 0x6e, 0xfe, 0xba, 0x03, 0xf6, 0x63, 0x22, 0xc6, 0x17, 0x3d,
+	0x66, 0xd4, 0x99, 0x1b, 0x4d, 0x77, 0x03, 0x40, 0xc4, 0xa5, 0x54, 0xe1, 0xd8, 0xeb, 0x70, 0x4c,
+	0x81, 0x55, 0x38, 0x06, 0x10, 0x87, 0x23, 0x02, 0x26, 0x75, 0x7f, 0xd9, 0x58, 0xaf, 0xd1, 0x35,
+	0x28, 0x86, 0xcc, 0xd3, 0xf4, 0x82, 0xa6, 0xc3, 0x72, 0xd1, 0x28, 0xa8, 0x91, 0x32, 0xe8, 0xe1,
+	0x82, 0xda, 0x1a, 0x78, 0xea, 0xde, 0x92, 0x30, 0x64, 0x92, 0xa8, 0xa1, 0x24, 0xcc, 0xfd, 0xcf,
+	0x6c, 0xac, 0xf6, 0x1a, 0x96, 0xdc, 0xdb, 0x14, 0x13, 0x3d, 0x81, 0x37, 0x12, 0x7f, 0xd3, 0x82,
+	0xa5, 0x97, 0x11, 0x44, 0x46, 0x21, 0xb5, 0x93, 0x9a, 0x93, 0xe5, 0xed, 0x73, 0x52, 0x67, 0x30,
+	0x6b, 0x4e, 0x76, 0xa0, 0xea, 0x51, 0xe1, 0x73, 0xea, 0xe9, 0x1b, 0x48, 0x1d, 0x38, 0xb0, 0xae,
+	0xef, 0x6d, 0xf9, 0xf4, 0x18, 0x11, 0x8a, 0x77, 0x0d, 0x47, 0x5b, 0xa8, 0x0d, 0x25, 0xd3, 0x37,
+	0xc2, 0xa9, 0xe8, 0xde, 0x3d, 0xe7, 0x7c, 0x5c, 0xd1, 0x4e, 0x4d, 0x90, 0xdd, 0x97, 0x9a, 0x20,
+	0x77, 0x00, 0x02, 0x36, 0x1a, 0x7a, 0xdc, 0x9f, 0x51, 0xee, 0x54, 0x35, 0xb7, 0x96, 0xc5, 0xed,
+	0x69, 0x04, 0x2e, 0x07, 0x6c, 0x14, 0x2f, 0x9b, 0x3f, 0x5a, 0xf0, 0xfa, 0x86, 0x53, 0xe8, 0x23,
+	0x28, 0x1a, 0xb7, 0xce, 0x7a, 0x04, 0x18, 0x1e, 0x4e, 0xb0, 0x68, 0x1f, 0xca, 0xea, 0x8e, 0x50,
+	0x21, 0x68, 0x7c, 0xfb, 0xcb, 0x78, 0xfd, 0x03, 0x72, 0xa0, 0x48, 0x02, 0x9f, 0xa8, 0xbd, 0xbc,
+	0xde, 0x4b, 0xcc, 0xe6, 0x4f, 0x39, 0x28, 0x1a, 0xb1, 0x8b, 0x1e, 0xe7, 0xe6, 0xd8, 0x8d, 0x9b,
+	0x75, 0x0f, 0x76, 0xe3, 0x74, 0x9a, 0x96, 0xb0, 0xff, 0x37, 0xa9, 0x95, 0x18, 0x1f, 0xb7, 0xc3,
+	0x3d, 0xb0, 0xfd, 0x88, 0x4c, 0xcc, 0x28, 0xcf, 0x3c, 0x79, 0xf0, 0xb0, 0xfd, 0xe0, 0x9b, 0x28,
+	0xee, 0xec, 0xd2, 0x72, 0xd1, 0xb0, 0xd5, 0x0f, 0x58, 0xd3, 0x9a, 0x7f, 0xda, 0x50, 0xec, 0x06,
+	0x53, 0x21, 0x29, 0xbf, 0xe8, 0x84, 0x98, 0x63, 0x37, 0x12, 0xd2, 0x85, 0x22, 0x67, 0x4c, 0x0e,
+	0x5d, 0x72, 0x56, 0x2e, 0x30, 0x63, 0xb2, 0xdb, 0xee, 0xec, 0x29, 0xa2, 0x1a, 0x24, 0xb1, 0x8d,
+	0x0b, 0x8a, 0xda, 0x25, 0xe8, 0x29, 0x5c, 0x49, 0xc6, 0xef, 0x11, 0x63, 0x52, 0x48, 0x4e, 0xa2,
+	0xe1, 0x98, 0xce, 0xd5, 0x37, 0x2f, 0xbf, 0xed, 0x65, 0xd2, 0x0f, 0x5d, 0x3e, 0xd7, 0x89, 0xba,
+	0x4f, 0xe7, 0xf8, 0xb2, 0x11, 0xe8, 0x24, 0xfc, 0xfb, 0x74, 0x2e, 0xd0, 0x67, 0xb0, 0x4f, 0x57,
+	0x30, 0xa5, 0x38, 0x0c, 0xc8, 0x44, 0x7d, 0x58, 0x86, 0x6e, 0xc0, 0xdc, 0xb1, 0x9e, 0x6d, 0x36,
+	0xbe, 0x4a, 0xd3, 0x52, 0x5f, 0xc5, 0x88, 0xae, 0x02, 0x20, 0x01, 0xce, 0x51, 0x40, 0xdc, 0x71,
+	0xe0, 0x0b, 0xf5, 0xfe, 0x4c, 0x3d, 0x36, 0xd4, 0x78, 0x52, 0xbe, 0x1d, 0x9e, 0x91, 0xad, 0x56,
+	0x67, 0xcd, 0x4d, 0x3d, 0x5d, 0x44, 0x3f, 0x94, 0x7c, 0x8e, 0xdf, 0x3c, 0xca, 0xde, 0xad, 0xcd,
+	0x60, 0xff, 0x2c, 0x22, 0x7a, 0x0d, 0xf2, 0x63, 0x3a, 0x8f, 0x6b, 0x8f, 0xd5, 0x12, 0x7d, 0x0e,
+	0x3b, 0x33, 0x12, 0x4c, 0xa9, 0xa9, 0xfa, 0xfb, 0x59, 0x3e, 0x65, 0x4b, 0xe2, 0x98, 0xf8, 0x49,
+	0xee, 0xd0, 0x6a, 0xfe, 0x6d, 0x41, 0xe1, 0x11, 0x75, 0x39, 0x95, 0xaf, 0xb4, 0xbb, 0x0e, 0x4f,
+	0x75, 0x57, 0x3d, 0xfb, 0xe1, 0xa1, 0x4e, 0xdd, 0x68, 0xae, 0x2b, 0x50, 0xf0, 0xfc, 0x11, 0x15,
+	0xf1, 0xd3, 0xa9, 0x8c, 0x8d, 0x85, 0x9a, 0x60, 0x0b, 0xff, 0x05, 0xd5, 0xd7, 0x28, 0x1f, 0x7f,
+	0xe5, 0x8d, 0x82, 0xff, 0x82, 0x62, 0xbd, 0x87, 0x6a, 0x50, 0xf2, 0x43, 0x49, 0x79, 0x48, 0x02,
+	0x5d, 0xe6, 0x12, 0x5e, 0xd9, 0x9d, 0xfd, 0xe3, 0x93, 0xfa, 0xa5, 0x3f, 0x4e, 0xea, 0x97, 0xfe,
+	0x3d, 0xa9, 0x5b, 0x3f, 0x2c, 0xeb, 0xd6, 0xf1, 0xb2, 0x6e, 0xfd, 0xb6, 0xac, 0x5b, 0x7f, 0x2d,
+	0xeb, 0xd6, 0x51, 0x41, 0xff, 0xf5, 0xf9, 0xf0, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x40, 0xcf,
+	0x57, 0x63, 0x6a, 0x0d, 0x00, 0x00,
 }

+ 3 - 2
vendor/src/github.com/docker/swarmkit/api/objects.proto

@@ -226,9 +226,10 @@ message Cluster {
 	// a new key is allocated on key rotation.
 	uint64 encryption_key_lamport_clock = 6;
 
-	// RemovedNodes is the list of nodes that have been removed from the
+	// BlacklistedCertificates tracks certificates that should no longer
+	// be honored. It's a mapping from CN -> BlacklistedCertificate.
 	// swarm. Their certificates should effectively be blacklisted.
-	repeated RemovedNode removed_nodes = 7;
+	map<string, BlacklistedCertificate> blacklisted_certificates = 8;
 }
 
 // Secret represents a secret that should be passed to a container or a node,

+ 552 - 117
vendor/src/github.com/docker/swarmkit/api/specs.pb.go

@@ -458,6 +458,9 @@ type ContainerSpec struct {
 	//
 	// If Command and Args are provided, Args will be appended to Command.
 	Args []string `protobuf:"bytes,4,rep,name=args" json:"args,omitempty"`
+	// Hostname specifies the hostname that will be set on containers created by docker swarm.
+	// All containers for a given service will have the same hostname
+	Hostname string `protobuf:"bytes,14,opt,name=hostname,proto3" json:"hostname,omitempty"`
 	// Env specifies the environment variables for the container in NAME=VALUE
 	// format. These must be compliant with  [IEEE Std
 	// 1003.1-2001](http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html).
@@ -472,7 +475,10 @@ type ContainerSpec struct {
 	User string `protobuf:"bytes,7,opt,name=user,proto3" json:"user,omitempty"`
 	// Groups specifies supplementary groups available to the user.
 	Groups []string `protobuf:"bytes,11,rep,name=groups" json:"groups,omitempty"`
-	Mounts []Mount  `protobuf:"bytes,8,rep,name=mounts" json:"mounts"`
+	// TTY declares that a TTY should be attached to the standard streams,
+	// including stdin if it is still open.
+	TTY    bool    `protobuf:"varint,13,opt,name=tty,proto3" json:"tty,omitempty"`
+	Mounts []Mount `protobuf:"bytes,8,rep,name=mounts" json:"mounts"`
 	// StopGracePeriod the grace period for stopping the container before
 	// forcefully killing the container.
 	StopGracePeriod *docker_swarmkit_v11.Duration `protobuf:"bytes,9,opt,name=stop_grace_period,json=stopGracePeriod" json:"stop_grace_period,omitempty"`
@@ -481,6 +487,8 @@ type ContainerSpec struct {
 	// SecretReference contains references to zero or more secrets that
 	// will be exposed to the container.
 	Secrets []*SecretReference `protobuf:"bytes,12,rep,name=secrets" json:"secrets,omitempty"`
+	// DNSConfig allows one to specify DNS related configuration in resolv.conf
+	DNSConfig *ContainerSpec_DNSConfig `protobuf:"bytes,15,opt,name=dns_config,json=dnsConfig" json:"dns_config,omitempty"`
 }
 
 func (m *ContainerSpec) Reset()                    { *m = ContainerSpec{} }
@@ -502,6 +510,23 @@ func (*ContainerSpec_PullOptions) Descriptor() ([]byte, []int) {
 	return fileDescriptorSpecs, []int{6, 1}
 }
 
+// DNSConfig specifies DNS related configurations in resolver configuration file (resolv.conf)
+// Detailed documentation is available in:
+// http://man7.org/linux/man-pages/man5/resolv.conf.5.html
+// TODO: domain is not supported yet
+type ContainerSpec_DNSConfig struct {
+	// Nameservers specifies the IP addresses of the name servers
+	Nameservers []string `protobuf:"bytes,1,rep,name=nameservers" json:"nameservers,omitempty"`
+	// Search specifies the search list for host-name lookup
+	Search []string `protobuf:"bytes,2,rep,name=search" json:"search,omitempty"`
+	// Options allows certain internal resolver variables to be modified
+	Options []string `protobuf:"bytes,3,rep,name=options" json:"options,omitempty"`
+}
+
+func (m *ContainerSpec_DNSConfig) Reset()                    { *m = ContainerSpec_DNSConfig{} }
+func (*ContainerSpec_DNSConfig) ProtoMessage()               {}
+func (*ContainerSpec_DNSConfig) Descriptor() ([]byte, []int) { return fileDescriptorSpecs, []int{6, 2} }
+
 // EndpointSpec defines the properties that can be configured to
 // access and loadbalance the service.
 type EndpointSpec struct {
@@ -583,6 +608,7 @@ func init() {
 	proto.RegisterType((*NetworkAttachmentSpec)(nil), "docker.swarmkit.v1.NetworkAttachmentSpec")
 	proto.RegisterType((*ContainerSpec)(nil), "docker.swarmkit.v1.ContainerSpec")
 	proto.RegisterType((*ContainerSpec_PullOptions)(nil), "docker.swarmkit.v1.ContainerSpec.PullOptions")
+	proto.RegisterType((*ContainerSpec_DNSConfig)(nil), "docker.swarmkit.v1.ContainerSpec.DNSConfig")
 	proto.RegisterType((*EndpointSpec)(nil), "docker.swarmkit.v1.EndpointSpec")
 	proto.RegisterType((*NetworkSpec)(nil), "docker.swarmkit.v1.NetworkSpec")
 	proto.RegisterType((*ClusterSpec)(nil), "docker.swarmkit.v1.ClusterSpec")
@@ -723,10 +749,13 @@ func (m *ContainerSpec) Copy() *ContainerSpec {
 
 	o := &ContainerSpec{
 		Image:           m.Image,
+		Hostname:        m.Hostname,
 		Dir:             m.Dir,
 		User:            m.User,
+		TTY:             m.TTY,
 		StopGracePeriod: m.StopGracePeriod.Copy(),
 		PullOptions:     m.PullOptions.Copy(),
+		DNSConfig:       m.DNSConfig.Copy(),
 	}
 
 	if m.Labels != nil {
@@ -785,6 +814,31 @@ func (m *ContainerSpec_PullOptions) Copy() *ContainerSpec_PullOptions {
 	return o
 }
 
+func (m *ContainerSpec_DNSConfig) Copy() *ContainerSpec_DNSConfig {
+	if m == nil {
+		return nil
+	}
+
+	o := &ContainerSpec_DNSConfig{}
+
+	if m.Nameservers != nil {
+		o.Nameservers = make([]string, 0, len(m.Nameservers))
+		o.Nameservers = append(o.Nameservers, m.Nameservers...)
+	}
+
+	if m.Search != nil {
+		o.Search = make([]string, 0, len(m.Search))
+		o.Search = append(o.Search, m.Search...)
+	}
+
+	if m.Options != nil {
+		o.Options = make([]string, 0, len(m.Options))
+		o.Options = append(o.Options, m.Options...)
+	}
+
+	return o
+}
+
 func (m *EndpointSpec) Copy() *EndpointSpec {
 	if m == nil {
 		return nil
@@ -981,7 +1035,7 @@ func (this *ContainerSpec) GoString() string {
 	if this == nil {
 		return "nil"
 	}
-	s := make([]string, 0, 16)
+	s := make([]string, 0, 19)
 	s = append(s, "&api.ContainerSpec{")
 	s = append(s, "Image: "+fmt.Sprintf("%#v", this.Image)+",\n")
 	keysForLabels := make([]string, 0, len(this.Labels))
@@ -999,10 +1053,12 @@ func (this *ContainerSpec) GoString() string {
 	}
 	s = append(s, "Command: "+fmt.Sprintf("%#v", this.Command)+",\n")
 	s = append(s, "Args: "+fmt.Sprintf("%#v", this.Args)+",\n")
+	s = append(s, "Hostname: "+fmt.Sprintf("%#v", this.Hostname)+",\n")
 	s = append(s, "Env: "+fmt.Sprintf("%#v", this.Env)+",\n")
 	s = append(s, "Dir: "+fmt.Sprintf("%#v", this.Dir)+",\n")
 	s = append(s, "User: "+fmt.Sprintf("%#v", this.User)+",\n")
 	s = append(s, "Groups: "+fmt.Sprintf("%#v", this.Groups)+",\n")
+	s = append(s, "TTY: "+fmt.Sprintf("%#v", this.TTY)+",\n")
 	if this.Mounts != nil {
 		s = append(s, "Mounts: "+fmt.Sprintf("%#v", this.Mounts)+",\n")
 	}
@@ -1015,6 +1071,9 @@ func (this *ContainerSpec) GoString() string {
 	if this.Secrets != nil {
 		s = append(s, "Secrets: "+fmt.Sprintf("%#v", this.Secrets)+",\n")
 	}
+	if this.DNSConfig != nil {
+		s = append(s, "DNSConfig: "+fmt.Sprintf("%#v", this.DNSConfig)+",\n")
+	}
 	s = append(s, "}")
 	return strings.Join(s, "")
 }
@@ -1028,6 +1087,18 @@ func (this *ContainerSpec_PullOptions) GoString() string {
 	s = append(s, "}")
 	return strings.Join(s, "")
 }
+func (this *ContainerSpec_DNSConfig) GoString() string {
+	if this == nil {
+		return "nil"
+	}
+	s := make([]string, 0, 7)
+	s = append(s, "&api.ContainerSpec_DNSConfig{")
+	s = append(s, "Nameservers: "+fmt.Sprintf("%#v", this.Nameservers)+",\n")
+	s = append(s, "Search: "+fmt.Sprintf("%#v", this.Search)+",\n")
+	s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
+	s = append(s, "}")
+	return strings.Join(s, "")
+}
 func (this *EndpointSpec) GoString() string {
 	if this == nil {
 		return "nil"
@@ -1584,6 +1655,32 @@ func (m *ContainerSpec) MarshalTo(data []byte) (int, error) {
 			i += n
 		}
 	}
+	if m.TTY {
+		data[i] = 0x68
+		i++
+		if m.TTY {
+			data[i] = 1
+		} else {
+			data[i] = 0
+		}
+		i++
+	}
+	if len(m.Hostname) > 0 {
+		data[i] = 0x72
+		i++
+		i = encodeVarintSpecs(data, i, uint64(len(m.Hostname)))
+		i += copy(data[i:], m.Hostname)
+	}
+	if m.DNSConfig != nil {
+		data[i] = 0x7a
+		i++
+		i = encodeVarintSpecs(data, i, uint64(m.DNSConfig.Size()))
+		n18, err := m.DNSConfig.MarshalTo(data[i:])
+		if err != nil {
+			return 0, err
+		}
+		i += n18
+	}
 	return i, nil
 }
 
@@ -1613,6 +1710,69 @@ func (m *ContainerSpec_PullOptions) MarshalTo(data []byte) (int, error) {
 	return i, nil
 }
 
+func (m *ContainerSpec_DNSConfig) 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 *ContainerSpec_DNSConfig) MarshalTo(data []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	if len(m.Nameservers) > 0 {
+		for _, s := range m.Nameservers {
+			data[i] = 0xa
+			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.Search) > 0 {
+		for _, s := range m.Search {
+			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.Options) > 0 {
+		for _, s := range m.Options {
+			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 *EndpointSpec) Marshal() (data []byte, err error) {
 	size := m.Size()
 	data = make([]byte, size)
@@ -1666,20 +1826,20 @@ func (m *NetworkSpec) MarshalTo(data []byte) (int, error) {
 	data[i] = 0xa
 	i++
 	i = encodeVarintSpecs(data, i, uint64(m.Annotations.Size()))
-	n18, err := m.Annotations.MarshalTo(data[i:])
+	n19, err := m.Annotations.MarshalTo(data[i:])
 	if err != nil {
 		return 0, err
 	}
-	i += n18
+	i += n19
 	if m.DriverConfig != nil {
 		data[i] = 0x12
 		i++
 		i = encodeVarintSpecs(data, i, uint64(m.DriverConfig.Size()))
-		n19, err := m.DriverConfig.MarshalTo(data[i:])
+		n20, err := m.DriverConfig.MarshalTo(data[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n19
+		i += n20
 	}
 	if m.Ipv6Enabled {
 		data[i] = 0x18
@@ -1705,11 +1865,11 @@ func (m *NetworkSpec) MarshalTo(data []byte) (int, error) {
 		data[i] = 0x2a
 		i++
 		i = encodeVarintSpecs(data, i, uint64(m.IPAM.Size()))
-		n20, err := m.IPAM.MarshalTo(data[i:])
+		n21, err := m.IPAM.MarshalTo(data[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n20
+		i += n21
 	}
 	if m.Attachable {
 		data[i] = 0x30
@@ -1742,59 +1902,59 @@ func (m *ClusterSpec) MarshalTo(data []byte) (int, error) {
 	data[i] = 0xa
 	i++
 	i = encodeVarintSpecs(data, i, uint64(m.Annotations.Size()))
-	n21, err := m.Annotations.MarshalTo(data[i:])
+	n22, err := m.Annotations.MarshalTo(data[i:])
 	if err != nil {
 		return 0, err
 	}
-	i += n21
+	i += n22
 	data[i] = 0x12
 	i++
 	i = encodeVarintSpecs(data, i, uint64(m.AcceptancePolicy.Size()))
-	n22, err := m.AcceptancePolicy.MarshalTo(data[i:])
+	n23, err := m.AcceptancePolicy.MarshalTo(data[i:])
 	if err != nil {
 		return 0, err
 	}
-	i += n22
+	i += n23
 	data[i] = 0x1a
 	i++
 	i = encodeVarintSpecs(data, i, uint64(m.Orchestration.Size()))
-	n23, err := m.Orchestration.MarshalTo(data[i:])
+	n24, err := m.Orchestration.MarshalTo(data[i:])
 	if err != nil {
 		return 0, err
 	}
-	i += n23
+	i += n24
 	data[i] = 0x22
 	i++
 	i = encodeVarintSpecs(data, i, uint64(m.Raft.Size()))
-	n24, err := m.Raft.MarshalTo(data[i:])
+	n25, err := m.Raft.MarshalTo(data[i:])
 	if err != nil {
 		return 0, err
 	}
-	i += n24
+	i += n25
 	data[i] = 0x2a
 	i++
 	i = encodeVarintSpecs(data, i, uint64(m.Dispatcher.Size()))
-	n25, err := m.Dispatcher.MarshalTo(data[i:])
+	n26, err := m.Dispatcher.MarshalTo(data[i:])
 	if err != nil {
 		return 0, err
 	}
-	i += n25
+	i += n26
 	data[i] = 0x32
 	i++
 	i = encodeVarintSpecs(data, i, uint64(m.CAConfig.Size()))
-	n26, err := m.CAConfig.MarshalTo(data[i:])
+	n27, err := m.CAConfig.MarshalTo(data[i:])
 	if err != nil {
 		return 0, err
 	}
-	i += n26
+	i += n27
 	data[i] = 0x3a
 	i++
 	i = encodeVarintSpecs(data, i, uint64(m.TaskDefaults.Size()))
-	n27, err := m.TaskDefaults.MarshalTo(data[i:])
+	n28, err := m.TaskDefaults.MarshalTo(data[i:])
 	if err != nil {
 		return 0, err
 	}
-	i += n27
+	i += n28
 	return i, nil
 }
 
@@ -1816,11 +1976,11 @@ func (m *SecretSpec) MarshalTo(data []byte) (int, error) {
 	data[i] = 0xa
 	i++
 	i = encodeVarintSpecs(data, i, uint64(m.Annotations.Size()))
-	n28, err := m.Annotations.MarshalTo(data[i:])
+	n29, err := m.Annotations.MarshalTo(data[i:])
 	if err != nil {
 		return 0, err
 	}
-	i += n28
+	i += n29
 	if len(m.Data) > 0 {
 		data[i] = 0x12
 		i++
@@ -2064,6 +2224,17 @@ func (m *ContainerSpec) Size() (n int) {
 			n += 1 + l + sovSpecs(uint64(l))
 		}
 	}
+	if m.TTY {
+		n += 2
+	}
+	l = len(m.Hostname)
+	if l > 0 {
+		n += 1 + l + sovSpecs(uint64(l))
+	}
+	if m.DNSConfig != nil {
+		l = m.DNSConfig.Size()
+		n += 1 + l + sovSpecs(uint64(l))
+	}
 	return n
 }
 
@@ -2077,6 +2248,30 @@ func (m *ContainerSpec_PullOptions) Size() (n int) {
 	return n
 }
 
+func (m *ContainerSpec_DNSConfig) Size() (n int) {
+	var l int
+	_ = l
+	if len(m.Nameservers) > 0 {
+		for _, s := range m.Nameservers {
+			l = len(s)
+			n += 1 + l + sovSpecs(uint64(l))
+		}
+	}
+	if len(m.Search) > 0 {
+		for _, s := range m.Search {
+			l = len(s)
+			n += 1 + l + sovSpecs(uint64(l))
+		}
+	}
+	if len(m.Options) > 0 {
+		for _, s := range m.Options {
+			l = len(s)
+			n += 1 + l + sovSpecs(uint64(l))
+		}
+	}
+	return n
+}
+
 func (m *EndpointSpec) Size() (n int) {
 	var l int
 	_ = l
@@ -2302,6 +2497,9 @@ func (this *ContainerSpec) String() string {
 		`PullOptions:` + strings.Replace(fmt.Sprintf("%v", this.PullOptions), "ContainerSpec_PullOptions", "ContainerSpec_PullOptions", 1) + `,`,
 		`Groups:` + fmt.Sprintf("%v", this.Groups) + `,`,
 		`Secrets:` + strings.Replace(fmt.Sprintf("%v", this.Secrets), "SecretReference", "SecretReference", 1) + `,`,
+		`TTY:` + fmt.Sprintf("%v", this.TTY) + `,`,
+		`Hostname:` + fmt.Sprintf("%v", this.Hostname) + `,`,
+		`DNSConfig:` + strings.Replace(fmt.Sprintf("%v", this.DNSConfig), "ContainerSpec_DNSConfig", "ContainerSpec_DNSConfig", 1) + `,`,
 		`}`,
 	}, "")
 	return s
@@ -2316,6 +2514,18 @@ func (this *ContainerSpec_PullOptions) String() string {
 	}, "")
 	return s
 }
+func (this *ContainerSpec_DNSConfig) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&ContainerSpec_DNSConfig{`,
+		`Nameservers:` + fmt.Sprintf("%v", this.Nameservers) + `,`,
+		`Search:` + fmt.Sprintf("%v", this.Search) + `,`,
+		`Options:` + fmt.Sprintf("%v", this.Options) + `,`,
+		`}`,
+	}, "")
+	return s
+}
 func (this *EndpointSpec) String() string {
 	if this == nil {
 		return "nil"
@@ -3755,6 +3965,88 @@ func (m *ContainerSpec) Unmarshal(data []byte) error {
 				return err
 			}
 			iNdEx = postIndex
+		case 13:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TTY", wireType)
+			}
+			var v int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowSpecs
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := data[iNdEx]
+				iNdEx++
+				v |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			m.TTY = bool(v != 0)
+		case 14:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Hostname", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowSpecs
+				}
+				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 ErrInvalidLengthSpecs
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Hostname = string(data[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 15:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field DNSConfig", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowSpecs
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := data[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthSpecs
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.DNSConfig == nil {
+				m.DNSConfig = &ContainerSpec_DNSConfig{}
+			}
+			if err := m.DNSConfig.Unmarshal(data[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
 			skippy, err := skipSpecs(data[iNdEx:])
@@ -3855,6 +4147,143 @@ func (m *ContainerSpec_PullOptions) Unmarshal(data []byte) error {
 	}
 	return nil
 }
+func (m *ContainerSpec_DNSConfig) 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 ErrIntOverflowSpecs
+			}
+			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: DNSConfig: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: DNSConfig: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Nameservers", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowSpecs
+				}
+				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 ErrInvalidLengthSpecs
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Nameservers = append(m.Nameservers, string(data[iNdEx:postIndex]))
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Search", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowSpecs
+				}
+				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 ErrInvalidLengthSpecs
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Search = append(m.Search, string(data[iNdEx:postIndex]))
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowSpecs
+				}
+				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 ErrInvalidLengthSpecs
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Options = append(m.Options, string(data[iNdEx:postIndex]))
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipSpecs(data[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthSpecs
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
 func (m *EndpointSpec) Unmarshal(data []byte) error {
 	l := len(data)
 	iNdEx := 0
@@ -4640,97 +5069,103 @@ var (
 func init() { proto.RegisterFile("specs.proto", fileDescriptorSpecs) }
 
 var fileDescriptorSpecs = []byte{
-	// 1457 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x57, 0x4d, 0x6f, 0x1b, 0xb9,
-	0x19, 0xd6, 0xd8, 0x63, 0x59, 0x7a, 0x47, 0x4e, 0x14, 0x22, 0x1f, 0x13, 0x25, 0x95, 0x15, 0x25,
-	0x4d, 0x9d, 0x16, 0xb5, 0x5b, 0xb5, 0x48, 0x93, 0xa6, 0x41, 0xab, 0xaf, 0x3a, 0xaa, 0x6b, 0x47,
-	0xa0, 0x93, 0x00, 0x3d, 0x09, 0xf4, 0x0c, 0x2d, 0x0f, 0x3c, 0x1a, 0x4e, 0x39, 0x1c, 0x05, 0xbe,
-	0xed, 0x31, 0xf0, 0x61, 0xff, 0x81, 0x4f, 0x0b, 0xec, 0x3f, 0xd8, 0xff, 0x90, 0xe3, 0x1e, 0xf7,
-	0x64, 0xac, 0x7d, 0x5f, 0x60, 0x81, 0xfd, 0x03, 0x0b, 0x72, 0x28, 0x69, 0xb4, 0x19, 0x27, 0x01,
-	0xd6, 0x37, 0xf2, 0xe5, 0xf3, 0xbc, 0xa4, 0xde, 0xf7, 0x99, 0x87, 0x14, 0x58, 0x51, 0x48, 0x9d,
-	0x68, 0x3d, 0xe4, 0x4c, 0x30, 0x84, 0x5c, 0xe6, 0x1c, 0x52, 0xbe, 0x1e, 0xbd, 0x25, 0x7c, 0x74,
-	0xe8, 0x89, 0xf5, 0xf1, 0x9f, 0x2b, 0x96, 0x38, 0x0a, 0xa9, 0x06, 0x54, 0xae, 0x0f, 0xd9, 0x90,
-	0xa9, 0xe1, 0x86, 0x1c, 0xe9, 0xe8, 0x2d, 0x37, 0xe6, 0x44, 0x78, 0x2c, 0xd8, 0x98, 0x0c, 0x92,
-	0x85, 0xfa, 0x97, 0x26, 0x14, 0x76, 0x98, 0x4b, 0x77, 0x43, 0xea, 0xa0, 0x4d, 0xb0, 0x48, 0x10,
-	0x30, 0xa1, 0x00, 0x91, 0x6d, 0xd4, 0x8c, 0x35, 0xab, 0xb1, 0xba, 0xfe, 0xe1, 0x96, 0xeb, 0xcd,
-	0x19, 0xac, 0x65, 0xbe, 0x3f, 0x5d, 0xcd, 0xe1, 0x34, 0x13, 0xfd, 0x09, 0x4c, 0xce, 0x7c, 0x6a,
-	0x2f, 0xd4, 0x8c, 0xb5, 0x2b, 0x8d, 0xbb, 0x59, 0x19, 0xe4, 0xa6, 0x98, 0xf9, 0x14, 0x2b, 0x24,
-	0xda, 0x04, 0x18, 0xd1, 0xd1, 0x1e, 0xe5, 0xd1, 0x81, 0x17, 0xda, 0x8b, 0x8a, 0xf7, 0xbb, 0x8b,
-	0x78, 0xf2, 0xb0, 0xeb, 0xdb, 0x53, 0x38, 0x4e, 0x51, 0xd1, 0x36, 0x94, 0xc8, 0x98, 0x78, 0x3e,
-	0xd9, 0xf3, 0x7c, 0x4f, 0x1c, 0xd9, 0xa6, 0x4a, 0xf5, 0xe8, 0xa3, 0xa9, 0x9a, 0x29, 0x02, 0x9e,
-	0xa3, 0xd7, 0x5d, 0x80, 0xd9, 0x46, 0xe8, 0x21, 0x2c, 0xf7, 0xbb, 0x3b, 0x9d, 0xde, 0xce, 0x66,
-	0x39, 0x57, 0xb9, 0x7d, 0x7c, 0x52, 0xbb, 0x21, 0x73, 0xcc, 0x00, 0x7d, 0x1a, 0xb8, 0x5e, 0x30,
-	0x44, 0x6b, 0x50, 0x68, 0xb6, 0xdb, 0xdd, 0xfe, 0xab, 0x6e, 0xa7, 0x6c, 0x54, 0x2a, 0xc7, 0x27,
-	0xb5, 0x9b, 0xf3, 0xc0, 0xa6, 0xe3, 0xd0, 0x50, 0x50, 0xb7, 0x62, 0xbe, 0xfb, 0xaa, 0x9a, 0xab,
-	0xbf, 0x33, 0xa0, 0x94, 0x3e, 0x04, 0x7a, 0x08, 0xf9, 0x66, 0xfb, 0x55, 0xef, 0x4d, 0xb7, 0x9c,
-	0x9b, 0xd1, 0xd3, 0x88, 0xa6, 0x23, 0xbc, 0x31, 0x45, 0x0f, 0x60, 0xa9, 0xdf, 0x7c, 0xbd, 0xdb,
-	0x2d, 0x1b, 0xb3, 0xe3, 0xa4, 0x61, 0x7d, 0x12, 0x47, 0x0a, 0xd5, 0xc1, 0xcd, 0xde, 0x4e, 0x79,
-	0x21, 0x1b, 0xd5, 0xe1, 0xc4, 0x0b, 0xf4, 0x51, 0xce, 0x16, 0xc1, 0xda, 0xa5, 0x7c, 0xec, 0x39,
-	0x97, 0xac, 0x89, 0xc7, 0x60, 0x0a, 0x12, 0x1d, 0x2a, 0x4d, 0x58, 0xd9, 0x9a, 0x78, 0x45, 0xa2,
-	0x43, 0xb9, 0xa9, 0xa6, 0x2b, 0xbc, 0x54, 0x06, 0xa7, 0xa1, 0xef, 0x39, 0x44, 0x50, 0x57, 0x29,
-	0xc3, 0x6a, 0xfc, 0x36, 0x8b, 0x8d, 0xa7, 0x28, 0x7d, 0xfe, 0x17, 0x39, 0x9c, 0xa2, 0xa2, 0x67,
-	0x90, 0x1f, 0xfa, 0x6c, 0x8f, 0xf8, 0x4a, 0x13, 0x56, 0xe3, 0x5e, 0x56, 0x92, 0x4d, 0x85, 0x98,
-	0x25, 0xd0, 0x14, 0xf4, 0x04, 0xf2, 0x71, 0xe8, 0x12, 0x41, 0xed, 0xbc, 0x22, 0xd7, 0xb2, 0xc8,
-	0xaf, 0x15, 0xa2, 0xcd, 0x82, 0x7d, 0x6f, 0x88, 0x35, 0x1e, 0x6d, 0x41, 0x21, 0xa0, 0xe2, 0x2d,
-	0xe3, 0x87, 0x91, 0xbd, 0x5c, 0x5b, 0x5c, 0xb3, 0x1a, 0x7f, 0xc8, 0x14, 0x63, 0x82, 0x69, 0x0a,
-	0x41, 0x9c, 0x83, 0x11, 0x0d, 0x44, 0x92, 0xa6, 0xb5, 0x60, 0x1b, 0x78, 0x9a, 0x00, 0xfd, 0x03,
-	0x0a, 0x34, 0x70, 0x43, 0xe6, 0x05, 0xc2, 0x2e, 0x5c, 0x7c, 0x90, 0xae, 0xc6, 0xc8, 0x62, 0xe2,
-	0x29, 0xa3, 0x95, 0x07, 0x73, 0xc4, 0x5c, 0x5a, 0xdf, 0x80, 0x6b, 0x1f, 0x14, 0x0b, 0x55, 0xa0,
-	0xa0, 0x8b, 0x95, 0x74, 0xd9, 0xc4, 0xd3, 0x79, 0xfd, 0x2a, 0xac, 0xcc, 0x15, 0x46, 0xd9, 0xc6,
-	0xa4, 0x5b, 0xa8, 0x09, 0x45, 0x87, 0x05, 0x82, 0x78, 0x01, 0xe5, 0x5a, 0x20, 0x99, 0xb5, 0x6d,
-	0x4f, 0x40, 0x92, 0xf5, 0x22, 0x87, 0x67, 0x2c, 0xf4, 0x6f, 0x28, 0x72, 0x1a, 0xb1, 0x98, 0x3b,
-	0x34, 0xd2, 0x0a, 0x59, 0xcb, 0xee, 0x71, 0x02, 0xc2, 0xf4, 0xff, 0xb1, 0xc7, 0xa9, 0xac, 0x53,
-	0x84, 0x67, 0x54, 0xf4, 0x0c, 0x96, 0x39, 0x8d, 0x04, 0xe1, 0xe2, 0x63, 0x4d, 0xc6, 0x09, 0xa4,
-	0xcf, 0x7c, 0xcf, 0x39, 0xc2, 0x13, 0x06, 0x7a, 0x06, 0xc5, 0xd0, 0x27, 0x8e, 0xca, 0x6a, 0x2f,
-	0x29, 0xfa, 0x6f, 0xb2, 0xe8, 0xfd, 0x09, 0x08, 0xcf, 0xf0, 0xe8, 0x29, 0x80, 0xcf, 0x86, 0x03,
-	0x97, 0x7b, 0x63, 0xca, 0xb5, 0x48, 0x2a, 0x59, 0xec, 0x8e, 0x42, 0xe0, 0xa2, 0xcf, 0x86, 0xc9,
-	0x10, 0x6d, 0xfe, 0x2a, 0x85, 0xa4, 0xd4, 0xb1, 0x05, 0x40, 0xa6, 0xab, 0x5a, 0x1f, 0x8f, 0x3e,
-	0x2b, 0x95, 0xee, 0x48, 0x8a, 0x8e, 0xee, 0x41, 0x69, 0x9f, 0x71, 0x87, 0x0e, 0xb4, 0xee, 0x8b,
-	0x4a, 0x13, 0x96, 0x8a, 0x25, 0x42, 0x6f, 0x15, 0x61, 0x99, 0xc7, 0x81, 0xf0, 0x46, 0xb4, 0xbe,
-	0x05, 0x37, 0x32, 0x93, 0xa2, 0x06, 0x94, 0xa6, 0x6d, 0x1e, 0x78, 0xae, 0xd2, 0x47, 0xb1, 0x75,
-	0xf5, 0xfc, 0x74, 0xd5, 0x9a, 0xea, 0xa1, 0xd7, 0xc1, 0xd6, 0x14, 0xd4, 0x73, 0xeb, 0x3f, 0x98,
-	0xb0, 0x32, 0x27, 0x16, 0x74, 0x1d, 0x96, 0xbc, 0x11, 0x19, 0xd2, 0x84, 0x8e, 0x93, 0x09, 0xea,
-	0x42, 0xde, 0x27, 0x7b, 0xd4, 0x97, 0x92, 0x91, 0x65, 0xfb, 0xe3, 0x27, 0x55, 0xb7, 0xfe, 0x5f,
-	0x85, 0xef, 0x06, 0x82, 0x1f, 0x61, 0x4d, 0x46, 0x36, 0x2c, 0x3b, 0x6c, 0x34, 0x22, 0x81, 0xb4,
-	0x97, 0xc5, 0xb5, 0x22, 0x9e, 0x4c, 0x11, 0x02, 0x93, 0xf0, 0x61, 0x64, 0x9b, 0x2a, 0xac, 0xc6,
-	0xa8, 0x0c, 0x8b, 0x34, 0x18, 0xdb, 0x4b, 0x2a, 0x24, 0x87, 0x32, 0xe2, 0x7a, 0x49, 0xcf, 0x8b,
-	0x58, 0x0e, 0x25, 0x2f, 0x8e, 0x28, 0xb7, 0x97, 0x55, 0x48, 0x8d, 0xd1, 0xdf, 0x20, 0x3f, 0x62,
-	0x71, 0x20, 0x22, 0xbb, 0xa0, 0x0e, 0x7b, 0x3b, 0xeb, 0xb0, 0xdb, 0x12, 0xa1, 0xed, 0x4f, 0xc3,
-	0xd1, 0x0b, 0xb8, 0x16, 0x09, 0x16, 0x0e, 0x86, 0x9c, 0x38, 0x74, 0x10, 0x52, 0xee, 0x31, 0x57,
-	0x75, 0xe3, 0x02, 0x17, 0xed, 0xe8, 0x1b, 0x1e, 0x5f, 0x95, 0xb4, 0x4d, 0xc9, 0xea, 0x2b, 0x12,
-	0xea, 0x43, 0x29, 0x8c, 0x7d, 0x7f, 0xc0, 0xc2, 0xc4, 0xcc, 0x41, 0x25, 0xf9, 0x8c, 0xaa, 0xf5,
-	0x63, 0xdf, 0x7f, 0x99, 0x90, 0xb0, 0x15, 0xce, 0x26, 0xe8, 0x26, 0xe4, 0x87, 0x9c, 0xc5, 0x61,
-	0x64, 0x5b, 0xaa, 0x1e, 0x7a, 0x86, 0x9e, 0xc3, 0x72, 0x44, 0x1d, 0x4e, 0x45, 0x64, 0x97, 0xd4,
-	0xaf, 0xbd, 0x9f, 0xb5, 0xc9, 0xae, 0x82, 0x60, 0xba, 0x4f, 0x39, 0x0d, 0x1c, 0x8a, 0x27, 0x9c,
-	0xca, 0x53, 0xb0, 0x52, 0x8d, 0x92, 0x05, 0x3e, 0xa4, 0x47, 0xba, 0xf7, 0x72, 0x28, 0xf5, 0x30,
-	0x26, 0x7e, 0x9c, 0xbc, 0x30, 0x8a, 0x38, 0x99, 0xfc, 0x7d, 0xe1, 0x89, 0x51, 0x69, 0x80, 0x95,
-	0x3a, 0x2d, 0xba, 0x0f, 0x2b, 0x9c, 0x0e, 0xbd, 0x48, 0xf0, 0xa3, 0x01, 0x89, 0xc5, 0x81, 0xfd,
-	0x2f, 0x45, 0x28, 0x4d, 0x82, 0xcd, 0x58, 0x1c, 0xd4, 0x7f, 0x32, 0xa0, 0x94, 0xb6, 0x4c, 0xd4,
-	0x4e, 0x8c, 0x52, 0xed, 0x78, 0xa5, 0xb1, 0xf1, 0x29, 0x8b, 0x55, 0xb6, 0xe4, 0xc7, 0x72, 0xc7,
-	0x6d, 0xf9, 0xac, 0x51, 0x64, 0xf4, 0x57, 0x58, 0x0a, 0x19, 0x17, 0x13, 0x71, 0x56, 0x33, 0xad,
-	0x84, 0xf1, 0xc9, 0x67, 0x9c, 0x80, 0xeb, 0x07, 0x70, 0x65, 0x3e, 0x1b, 0x7a, 0x00, 0x8b, 0x6f,
-	0x7a, 0xfd, 0x72, 0xae, 0x72, 0xe7, 0xf8, 0xa4, 0x76, 0x6b, 0x7e, 0xf1, 0x8d, 0xc7, 0x45, 0x4c,
-	0xfc, 0x5e, 0x1f, 0xfd, 0x1e, 0x96, 0x3a, 0x3b, 0xbb, 0x18, 0x97, 0x8d, 0xca, 0xea, 0xf1, 0x49,
-	0xed, 0xce, 0x3c, 0x4e, 0x2e, 0xb1, 0x38, 0x70, 0x31, 0xdb, 0x9b, 0xde, 0xf4, 0xdf, 0x2c, 0x80,
-	0xa5, 0xbf, 0xd9, 0xcb, 0xbd, 0xe9, 0xff, 0x09, 0x2b, 0x89, 0x0d, 0x0e, 0x1c, 0xf5, 0xd3, 0xb4,
-	0xa1, 0x7f, 0xcc, 0x0d, 0x4b, 0x09, 0x21, 0x29, 0x85, 0xb4, 0x1e, 0x2f, 0x1c, 0x3f, 0x1e, 0xd0,
-	0x80, 0xec, 0xf9, 0xfa, 0xd2, 0x2f, 0x60, 0x4b, 0xc6, 0xba, 0x49, 0x48, 0xde, 0x56, 0x5e, 0x20,
-	0x28, 0x0f, 0xf4, 0x75, 0x5e, 0xc0, 0xd3, 0x39, 0x7a, 0x0e, 0xa6, 0x17, 0x92, 0x91, 0xb6, 0xf0,
-	0xcc, 0x5f, 0xd0, 0xeb, 0x37, 0xb7, 0xb5, 0x44, 0x5a, 0x85, 0xf3, 0xd3, 0x55, 0x53, 0x06, 0xb0,
-	0xa2, 0xa1, 0xea, 0xc4, 0x45, 0xe5, 0x4e, 0xea, 0xab, 0x2e, 0xe0, 0x54, 0xa4, 0xfe, 0xb5, 0x09,
-	0x56, 0xdb, 0x8f, 0x23, 0xa1, 0xbd, 0xe9, 0xd2, 0xea, 0xf6, 0x3f, 0xb8, 0x46, 0xd4, 0xbb, 0x90,
-	0x04, 0xf2, 0x43, 0x57, 0xb7, 0x93, 0xae, 0xdd, 0x83, 0xcc, 0x74, 0x53, 0x70, 0x72, 0x93, 0xb5,
-	0xf2, 0x32, 0xa7, 0x6d, 0xe0, 0x32, 0xf9, 0xc5, 0x0a, 0xda, 0x85, 0x15, 0xc6, 0x9d, 0x03, 0x1a,
-	0x89, 0xc4, 0x1b, 0xf4, 0x3b, 0x2a, 0xf3, 0x85, 0xfd, 0x32, 0x0d, 0xd4, 0xaf, 0x90, 0xe4, 0xb4,
-	0xf3, 0x39, 0xd0, 0x13, 0x30, 0x39, 0xd9, 0x9f, 0xdc, 0xb4, 0x99, 0xfa, 0xc6, 0x64, 0x5f, 0xcc,
-	0xa5, 0x50, 0x0c, 0xf4, 0x1f, 0x00, 0xd7, 0x8b, 0x42, 0x22, 0x9c, 0x03, 0xca, 0x75, 0x9f, 0x32,
-	0x7f, 0x62, 0x67, 0x8a, 0x9a, 0xcb, 0x92, 0x62, 0xa3, 0x2d, 0x28, 0x3a, 0x64, 0xa2, 0xb4, 0xfc,
-	0xc5, 0xb6, 0xd8, 0x6e, 0xea, 0x14, 0x65, 0x99, 0xe2, 0xfc, 0x74, 0xb5, 0x30, 0x89, 0xe0, 0x82,
-	0x43, 0xb4, 0xf2, 0xb6, 0x60, 0x45, 0x3e, 0x3a, 0x07, 0x2e, 0xdd, 0x27, 0xb1, 0x2f, 0x22, 0xe5,
-	0xe0, 0x17, 0x3c, 0xb2, 0xe4, 0xfb, 0xa7, 0xa3, 0x71, 0xfa, 0x5c, 0x25, 0x91, 0x8a, 0xd5, 0x3d,
-	0x80, 0xc4, 0xe1, 0x2e, 0x57, 0x26, 0x08, 0x4c, 0x97, 0x08, 0xa2, 0x94, 0x51, 0xc2, 0x6a, 0xdc,
-	0xba, 0xfb, 0xfe, 0xac, 0x9a, 0xfb, 0xee, 0xac, 0x9a, 0xfb, 0xf1, 0xac, 0x6a, 0x7c, 0x71, 0x5e,
-	0x35, 0xde, 0x9f, 0x57, 0x8d, 0x6f, 0xcf, 0xab, 0xc6, 0xf7, 0xe7, 0x55, 0x63, 0x2f, 0xaf, 0xfe,
-	0xeb, 0xfd, 0xe5, 0xe7, 0x00, 0x00, 0x00, 0xff, 0xff, 0xb6, 0x26, 0x4a, 0x64, 0x4a, 0x0e, 0x00,
-	0x00,
+	// 1563 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x57, 0xcd, 0x6e, 0x23, 0xc7,
+	0x11, 0xe6, 0x88, 0x14, 0x7f, 0x6a, 0xc8, 0x5d, 0x6e, 0xc3, 0x3f, 0xb3, 0xb4, 0x43, 0x72, 0xe9,
+	0x8d, 0x23, 0xc7, 0x88, 0x36, 0x61, 0x02, 0x67, 0x9d, 0x8d, 0x91, 0xf0, 0x2f, 0x5a, 0x46, 0x91,
+	0x4c, 0xb4, 0xe4, 0x05, 0xf6, 0x44, 0xb4, 0x66, 0x5a, 0xe4, 0x40, 0xc3, 0xe9, 0x49, 0x4f, 0x0f,
+	0x0d, 0xdd, 0x72, 0x34, 0xf6, 0x90, 0x37, 0xd0, 0x29, 0x40, 0xde, 0x20, 0xef, 0xb0, 0xc7, 0x1c,
+	0x73, 0x12, 0x2c, 0x3e, 0x41, 0x80, 0xbc, 0x40, 0xd0, 0x3d, 0x3d, 0xe4, 0x30, 0x1e, 0x59, 0x06,
+	0xa2, 0x5b, 0x77, 0xcd, 0xf7, 0x55, 0x77, 0x57, 0x7d, 0xac, 0x2a, 0x82, 0x19, 0x06, 0xd4, 0x0e,
+	0xf7, 0x03, 0xce, 0x04, 0x43, 0xc8, 0x61, 0xf6, 0x05, 0xe5, 0xfb, 0xe1, 0xd7, 0x84, 0x2f, 0x2e,
+	0x5c, 0xb1, 0xbf, 0xfc, 0x45, 0xc3, 0x14, 0x97, 0x01, 0xd5, 0x80, 0xc6, 0x3b, 0x33, 0x36, 0x63,
+	0x6a, 0xf9, 0x4c, 0xae, 0xb4, 0xf5, 0x7d, 0x27, 0xe2, 0x44, 0xb8, 0xcc, 0x7f, 0x96, 0x2c, 0xe2,
+	0x0f, 0x9d, 0xbf, 0x16, 0xa0, 0x7c, 0xcc, 0x1c, 0x7a, 0x12, 0x50, 0x1b, 0x1d, 0x80, 0x49, 0x7c,
+	0x9f, 0x09, 0x05, 0x08, 0x2d, 0xa3, 0x6d, 0xec, 0x99, 0xdd, 0xd6, 0xfe, 0x77, 0x8f, 0xdc, 0xef,
+	0x6d, 0x60, 0xfd, 0xc2, 0xdb, 0xeb, 0x56, 0x0e, 0xa7, 0x99, 0xe8, 0xe7, 0x50, 0xe0, 0xcc, 0xa3,
+	0xd6, 0x4e, 0xdb, 0xd8, 0x7b, 0xd0, 0xfd, 0x30, 0xcb, 0x83, 0x3c, 0x14, 0x33, 0x8f, 0x62, 0x85,
+	0x44, 0x07, 0x00, 0x0b, 0xba, 0x38, 0xa3, 0x3c, 0x9c, 0xbb, 0x81, 0x95, 0x57, 0xbc, 0x9f, 0xdc,
+	0xc6, 0x93, 0x97, 0xdd, 0x3f, 0x5a, 0xc3, 0x71, 0x8a, 0x8a, 0x8e, 0xa0, 0x4a, 0x96, 0xc4, 0xf5,
+	0xc8, 0x99, 0xeb, 0xb9, 0xe2, 0xd2, 0x2a, 0x28, 0x57, 0x9f, 0x7c, 0xaf, 0xab, 0x5e, 0x8a, 0x80,
+	0xb7, 0xe8, 0x1d, 0x07, 0x60, 0x73, 0x10, 0xfa, 0x18, 0x4a, 0x93, 0xd1, 0xf1, 0x70, 0x7c, 0x7c,
+	0x50, 0xcf, 0x35, 0x1e, 0xbf, 0xb9, 0x6a, 0xbf, 0x2b, 0x7d, 0x6c, 0x00, 0x13, 0xea, 0x3b, 0xae,
+	0x3f, 0x43, 0x7b, 0x50, 0xee, 0x0d, 0x06, 0xa3, 0xc9, 0xe9, 0x68, 0x58, 0x37, 0x1a, 0x8d, 0x37,
+	0x57, 0xed, 0xf7, 0xb6, 0x81, 0x3d, 0xdb, 0xa6, 0x81, 0xa0, 0x4e, 0xa3, 0xf0, 0xcd, 0xdf, 0x9a,
+	0xb9, 0xce, 0x37, 0x06, 0x54, 0xd3, 0x97, 0x40, 0x1f, 0x43, 0xb1, 0x37, 0x38, 0x1d, 0xbf, 0x1a,
+	0xd5, 0x73, 0x1b, 0x7a, 0x1a, 0xd1, 0xb3, 0x85, 0xbb, 0xa4, 0xe8, 0x29, 0xec, 0x4e, 0x7a, 0x5f,
+	0x9d, 0x8c, 0xea, 0xc6, 0xe6, 0x3a, 0x69, 0xd8, 0x84, 0x44, 0xa1, 0x42, 0x0d, 0x71, 0x6f, 0x7c,
+	0x5c, 0xdf, 0xc9, 0x46, 0x0d, 0x39, 0x71, 0x7d, 0x7d, 0x95, 0x9b, 0x3c, 0x98, 0x27, 0x94, 0x2f,
+	0x5d, 0xfb, 0x9e, 0x35, 0xf1, 0x19, 0x14, 0x04, 0x09, 0x2f, 0x94, 0x26, 0xcc, 0x6c, 0x4d, 0x9c,
+	0x92, 0xf0, 0x42, 0x1e, 0xaa, 0xe9, 0x0a, 0x2f, 0x95, 0xc1, 0x69, 0xe0, 0xb9, 0x36, 0x11, 0xd4,
+	0x51, 0xca, 0x30, 0xbb, 0x3f, 0xce, 0x62, 0xe3, 0x35, 0x4a, 0xdf, 0xff, 0x65, 0x0e, 0xa7, 0xa8,
+	0xe8, 0x05, 0x14, 0x67, 0x1e, 0x3b, 0x23, 0x9e, 0xd2, 0x84, 0xd9, 0x7d, 0x92, 0xe5, 0xe4, 0x40,
+	0x21, 0x36, 0x0e, 0x34, 0x05, 0x3d, 0x87, 0x62, 0x14, 0x38, 0x44, 0x50, 0xab, 0xa8, 0xc8, 0xed,
+	0x2c, 0xf2, 0x57, 0x0a, 0x31, 0x60, 0xfe, 0xb9, 0x3b, 0xc3, 0x1a, 0x8f, 0x0e, 0xa1, 0xec, 0x53,
+	0xf1, 0x35, 0xe3, 0x17, 0xa1, 0x55, 0x6a, 0xe7, 0xf7, 0xcc, 0xee, 0xa7, 0x99, 0x62, 0x8c, 0x31,
+	0x3d, 0x21, 0x88, 0x3d, 0x5f, 0x50, 0x5f, 0xc4, 0x6e, 0xfa, 0x3b, 0x96, 0x81, 0xd7, 0x0e, 0xd0,
+	0x6f, 0xa1, 0x4c, 0x7d, 0x27, 0x60, 0xae, 0x2f, 0xac, 0xf2, 0xed, 0x17, 0x19, 0x69, 0x8c, 0x0c,
+	0x26, 0x5e, 0x33, 0xfa, 0x45, 0x28, 0x2c, 0x98, 0x43, 0x3b, 0xcf, 0xe0, 0xd1, 0x77, 0x82, 0x85,
+	0x1a, 0x50, 0xd6, 0xc1, 0x8a, 0xb3, 0x5c, 0xc0, 0xeb, 0x7d, 0xe7, 0x21, 0xd4, 0xb6, 0x02, 0xa3,
+	0xca, 0x46, 0x92, 0x2d, 0xd4, 0x83, 0x8a, 0xcd, 0x7c, 0x41, 0x5c, 0x9f, 0x72, 0x2d, 0x90, 0xcc,
+	0xd8, 0x0e, 0x12, 0x90, 0x64, 0xbd, 0xcc, 0xe1, 0x0d, 0x0b, 0xfd, 0x01, 0x2a, 0x9c, 0x86, 0x2c,
+	0xe2, 0x36, 0x0d, 0xb5, 0x42, 0xf6, 0xb2, 0x73, 0x1c, 0x83, 0x30, 0xfd, 0x73, 0xe4, 0x72, 0x2a,
+	0xe3, 0x14, 0xe2, 0x0d, 0x15, 0xbd, 0x80, 0x12, 0xa7, 0xa1, 0x20, 0x5c, 0x7c, 0x5f, 0x92, 0x71,
+	0x0c, 0x99, 0x30, 0xcf, 0xb5, 0x2f, 0x71, 0xc2, 0x40, 0x2f, 0xa0, 0x12, 0x78, 0xc4, 0x56, 0x5e,
+	0xad, 0x5d, 0x45, 0xff, 0x51, 0x16, 0x7d, 0x92, 0x80, 0xf0, 0x06, 0x8f, 0x3e, 0x07, 0xf0, 0xd8,
+	0x6c, 0xea, 0x70, 0x77, 0x49, 0xb9, 0x16, 0x49, 0x23, 0x8b, 0x3d, 0x54, 0x08, 0x5c, 0xf1, 0xd8,
+	0x2c, 0x5e, 0xa2, 0x83, 0xff, 0x4b, 0x21, 0x29, 0x75, 0x1c, 0x02, 0x90, 0xf5, 0x57, 0xad, 0x8f,
+	0x4f, 0x7e, 0x90, 0x2b, 0x9d, 0x91, 0x14, 0x1d, 0x3d, 0x81, 0xea, 0x39, 0xe3, 0x36, 0x9d, 0x6a,
+	0xdd, 0x57, 0x94, 0x26, 0x4c, 0x65, 0x8b, 0x85, 0xde, 0xaf, 0x40, 0x89, 0x47, 0xbe, 0x70, 0x17,
+	0xb4, 0x73, 0x08, 0xef, 0x66, 0x3a, 0x45, 0x5d, 0xa8, 0xae, 0xd3, 0x3c, 0x75, 0x1d, 0xa5, 0x8f,
+	0x4a, 0xff, 0xe1, 0xea, 0xba, 0x65, 0xae, 0xf5, 0x30, 0x1e, 0x62, 0x73, 0x0d, 0x1a, 0x3b, 0x9d,
+	0x6f, 0x8b, 0x50, 0xdb, 0x12, 0x0b, 0x7a, 0x07, 0x76, 0xdd, 0x05, 0x99, 0xd1, 0x98, 0x8e, 0xe3,
+	0x0d, 0x1a, 0x41, 0xd1, 0x23, 0x67, 0xd4, 0x93, 0x92, 0x91, 0x61, 0xfb, 0xd9, 0x9d, 0xaa, 0xdb,
+	0xff, 0x93, 0xc2, 0x8f, 0x7c, 0xc1, 0x2f, 0xb1, 0x26, 0x23, 0x0b, 0x4a, 0x36, 0x5b, 0x2c, 0x88,
+	0x2f, 0xcb, 0x4b, 0x7e, 0xaf, 0x82, 0x93, 0x2d, 0x42, 0x50, 0x20, 0x7c, 0x16, 0x5a, 0x05, 0x65,
+	0x56, 0x6b, 0x54, 0x87, 0x3c, 0xf5, 0x97, 0xd6, 0xae, 0x32, 0xc9, 0xa5, 0xb4, 0x38, 0x6e, 0x9c,
+	0xf3, 0x0a, 0x96, 0x4b, 0xc9, 0x8b, 0x42, 0xca, 0xad, 0x92, 0x32, 0xa9, 0x35, 0xfa, 0x35, 0x14,
+	0x17, 0x2c, 0xf2, 0x45, 0x68, 0x95, 0xd5, 0x65, 0x1f, 0x67, 0x5d, 0xf6, 0x48, 0x22, 0x74, 0xf9,
+	0xd3, 0x70, 0xf4, 0x12, 0x1e, 0x85, 0x82, 0x05, 0xd3, 0x19, 0x27, 0x36, 0x9d, 0x06, 0x94, 0xbb,
+	0xcc, 0x51, 0xd9, 0xb8, 0xa5, 0x8a, 0x0e, 0x75, 0x87, 0xc7, 0x0f, 0x25, 0xed, 0x40, 0xb2, 0x26,
+	0x8a, 0x84, 0x26, 0x50, 0x0d, 0x22, 0xcf, 0x9b, 0xb2, 0x20, 0x2e, 0xe6, 0xa0, 0x9c, 0xfc, 0x80,
+	0xa8, 0x4d, 0x22, 0xcf, 0xfb, 0x32, 0x26, 0x61, 0x33, 0xd8, 0x6c, 0xd0, 0x7b, 0x50, 0x9c, 0x71,
+	0x16, 0x05, 0xa1, 0x65, 0xaa, 0x78, 0xe8, 0x1d, 0xfa, 0x02, 0x4a, 0x21, 0xb5, 0x39, 0x15, 0xa1,
+	0x55, 0x55, 0xaf, 0xfd, 0x28, 0xeb, 0x90, 0x13, 0x05, 0xc1, 0xf4, 0x9c, 0x72, 0xea, 0xdb, 0x14,
+	0x27, 0x1c, 0xf4, 0x18, 0xf2, 0x42, 0x5c, 0x5a, 0xb5, 0xb6, 0xb1, 0x57, 0xee, 0x97, 0x56, 0xd7,
+	0xad, 0xfc, 0xe9, 0xe9, 0x6b, 0x2c, 0x6d, 0xb2, 0x4c, 0xcd, 0x59, 0x28, 0x7c, 0xb2, 0xa0, 0xd6,
+	0x03, 0x15, 0xde, 0xf5, 0x1e, 0xbd, 0x06, 0x70, 0xfc, 0x70, 0x6a, 0xab, 0xdf, 0x85, 0xf5, 0x50,
+	0xbd, 0xee, 0xd3, 0xbb, 0x5f, 0x37, 0x3c, 0x3e, 0xd1, 0xc5, 0xb6, 0xb6, 0xba, 0x6e, 0x55, 0xd6,
+	0x5b, 0x5c, 0x71, 0xfc, 0x30, 0x5e, 0x36, 0x3e, 0x07, 0x33, 0x25, 0x1d, 0x99, 0xf2, 0x0b, 0x7a,
+	0xa9, 0xd5, 0x28, 0x97, 0x52, 0xa1, 0x4b, 0xe2, 0x45, 0xf1, 0xcc, 0x53, 0xc1, 0xf1, 0xe6, 0x37,
+	0x3b, 0xcf, 0x8d, 0x46, 0x17, 0xcc, 0x54, 0xfc, 0xd0, 0x47, 0x50, 0xe3, 0x74, 0xe6, 0x86, 0x82,
+	0x5f, 0x4e, 0x49, 0x24, 0xe6, 0xd6, 0xef, 0x15, 0xa1, 0x9a, 0x18, 0x7b, 0x91, 0x98, 0x37, 0xa6,
+	0xb0, 0xb9, 0x06, 0x6a, 0x83, 0x29, 0x9f, 0x17, 0x52, 0xbe, 0xa4, 0x5c, 0x16, 0x67, 0x19, 0xe9,
+	0xb4, 0x49, 0xa6, 0x21, 0xa4, 0x84, 0xdb, 0x73, 0xf5, 0x43, 0xa8, 0x60, 0xbd, 0x93, 0xca, 0x4e,
+	0x72, 0xad, 0x95, 0xad, 0xb7, 0x9d, 0xff, 0x18, 0x50, 0x4d, 0x77, 0x09, 0x34, 0x88, 0x7b, 0x83,
+	0x7a, 0xd2, 0x83, 0xee, 0xb3, 0xbb, 0xba, 0x8a, 0xaa, 0xc4, 0x5e, 0x24, 0x9d, 0x1d, 0xc9, 0x49,
+	0x4e, 0x91, 0xd1, 0xaf, 0x60, 0x37, 0x60, 0x5c, 0x24, 0xbf, 0xc7, 0x66, 0x66, 0xf5, 0x64, 0x3c,
+	0xa9, 0x5c, 0x31, 0xb8, 0x33, 0x87, 0x07, 0xdb, 0xde, 0xd0, 0x53, 0xc8, 0xbf, 0x1a, 0x4f, 0xea,
+	0xb9, 0xc6, 0x07, 0x6f, 0xae, 0xda, 0xef, 0x6f, 0x7f, 0x7c, 0xe5, 0x72, 0x11, 0x11, 0x6f, 0x3c,
+	0x41, 0x3f, 0x85, 0xdd, 0xe1, 0xf1, 0x09, 0xc6, 0x75, 0xa3, 0xd1, 0x7a, 0x73, 0xd5, 0xfe, 0x60,
+	0x1b, 0x27, 0x3f, 0xb1, 0xc8, 0x77, 0x30, 0x3b, 0x5b, 0x0f, 0x37, 0xff, 0xd8, 0x01, 0x53, 0x97,
+	0xa9, 0xfb, 0x1d, 0x6e, 0x7e, 0x07, 0xb5, 0xb8, 0xf2, 0x27, 0xe2, 0xdb, 0xb9, 0xb3, 0x01, 0x54,
+	0x63, 0x82, 0xce, 0xf1, 0x13, 0xa8, 0xba, 0xc1, 0xf2, 0xb3, 0x29, 0xf5, 0xc9, 0x99, 0xa7, 0xe7,
+	0x9c, 0x32, 0x36, 0xa5, 0x6d, 0x14, 0x9b, 0xa4, 0xf2, 0x5d, 0x5f, 0x50, 0xee, 0xeb, 0x09, 0xa6,
+	0x8c, 0xd7, 0x7b, 0xf4, 0x05, 0x14, 0xdc, 0x80, 0x2c, 0x74, 0xd7, 0xca, 0x7c, 0xc1, 0x78, 0xd2,
+	0x3b, 0xd2, 0x1a, 0xec, 0x97, 0x57, 0xd7, 0xad, 0x82, 0x34, 0x60, 0x45, 0x43, 0xcd, 0xa4, 0x71,
+	0xc8, 0x93, 0x54, 0x21, 0x2b, 0xe3, 0x94, 0xa5, 0xf3, 0xf7, 0x02, 0x98, 0x03, 0x2f, 0x0a, 0x85,
+	0x2e, 0xc7, 0xf7, 0x16, 0xb7, 0xd7, 0xf0, 0x88, 0xa8, 0x51, 0x98, 0xf8, 0xb2, 0xb6, 0xa9, 0x86,
+	0xac, 0x63, 0xf7, 0x34, 0xd3, 0xdd, 0x1a, 0x1c, 0x37, 0xef, 0x7e, 0x51, 0xfa, 0xb4, 0x0c, 0x5c,
+	0x27, 0xff, 0xf3, 0x05, 0x9d, 0x40, 0x8d, 0x71, 0x7b, 0x4e, 0x43, 0x11, 0x97, 0x43, 0x3d, 0x3a,
+	0x66, 0xfe, 0xa9, 0xf8, 0x32, 0x0d, 0xd4, 0xb5, 0x20, 0xbe, 0xed, 0xb6, 0x0f, 0xf4, 0x1c, 0x0a,
+	0x9c, 0x9c, 0x27, 0xc3, 0x45, 0xa6, 0xbe, 0x31, 0x39, 0x17, 0x5b, 0x2e, 0x14, 0x03, 0xfd, 0x11,
+	0xc0, 0x71, 0xc3, 0x80, 0x08, 0x7b, 0x4e, 0xb9, 0xce, 0x53, 0xe6, 0x13, 0x87, 0x6b, 0xd4, 0x96,
+	0x97, 0x14, 0x1b, 0x1d, 0x42, 0xc5, 0x26, 0x89, 0xd2, 0x8a, 0xb7, 0x77, 0x82, 0x41, 0x4f, 0xbb,
+	0xa8, 0x4b, 0x17, 0xab, 0xeb, 0x56, 0x39, 0xb1, 0xe0, 0xb2, 0x4d, 0xb4, 0xf2, 0x0e, 0xa1, 0x26,
+	0xe7, 0xec, 0xa9, 0x43, 0xcf, 0x49, 0xe4, 0x89, 0x50, 0x35, 0xad, 0x5b, 0xe6, 0x4a, 0x39, 0xf2,
+	0x0d, 0x35, 0x4e, 0xdf, 0xab, 0x2a, 0x52, 0xb6, 0x8e, 0x0b, 0x10, 0x17, 0xf5, 0xfb, 0x95, 0x09,
+	0x82, 0x82, 0x43, 0x04, 0x51, 0xca, 0xa8, 0x62, 0xb5, 0xee, 0x7f, 0xf8, 0xf6, 0xa6, 0x99, 0xfb,
+	0xd7, 0x4d, 0x33, 0xf7, 0xef, 0x9b, 0xa6, 0xf1, 0x97, 0x55, 0xd3, 0x78, 0xbb, 0x6a, 0x1a, 0xff,
+	0x5c, 0x35, 0x8d, 0x6f, 0x57, 0x4d, 0xe3, 0xac, 0xa8, 0xfe, 0xde, 0xfe, 0xf2, 0xbf, 0x01, 0x00,
+	0x00, 0xff, 0xff, 0x2a, 0x90, 0x7c, 0x40, 0x3d, 0x0f, 0x00, 0x00,
 }

+ 27 - 0
vendor/src/github.com/docker/swarmkit/api/specs.proto

@@ -128,6 +128,7 @@ message NetworkAttachmentSpec {
 	string container_id = 1 [(gogoproto.customname) = "ContainerID"];
 }
 
+
 // Container specifies runtime parameters for a container.
 message ContainerSpec {
 	// image defines the image reference, as specified in the
@@ -159,6 +160,10 @@ message ContainerSpec {
 	// If Command and Args are provided, Args will be appended to Command.
 	repeated string args = 4;
 
+	// Hostname specifies the hostname that will be set on containers created by docker swarm.
+	// All containers for a given service will have the same hostname
+	string hostname = 14;
+
 	// Env specifies the environment variables for the container in NAME=VALUE
 	// format. These must be compliant with  [IEEE Std
 	// 1003.1-2001](http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html).
@@ -177,6 +182,10 @@ message ContainerSpec {
 	// Groups specifies supplementary groups available to the user.
 	repeated string groups = 11;
 
+	// TTY declares that a TTY should be attached to the standard streams,
+	// including stdin if it is still open.
+	bool tty = 13 [(gogoproto.customname) = "TTY"];
+
 	repeated Mount mounts = 8 [(gogoproto.nullable) = false];
 
 	// StopGracePeriod the grace period for stopping the container before
@@ -198,6 +207,24 @@ message ContainerSpec {
 	// SecretReference contains references to zero or more secrets that
 	// will be exposed to the container.
 	repeated SecretReference secrets = 12;
+
+	// DNSConfig specifies DNS related configurations in resolver configuration file (resolv.conf)
+	// Detailed documentation is available in:
+	// http://man7.org/linux/man-pages/man5/resolv.conf.5.html
+	// TODO: domain is not supported yet
+	message DNSConfig {
+		// Nameservers specifies the IP addresses of the name servers
+		repeated string nameservers = 1;
+
+		// Search specifies the search list for host-name lookup
+		repeated string search = 2;
+
+		// Options allows certain internal resolver variables to be modified
+		repeated string options = 3;
+	}
+
+	// DNSConfig allows one to specify DNS related configuration in resolv.conf
+	DNSConfig dns_config = 15 [(gogoproto.customname) = "DNSConfig"];
 }
 
 // EndpointSpec defines the properties that can be configured to

+ 336 - 307
vendor/src/github.com/docker/swarmkit/api/types.pb.go

@@ -57,7 +57,7 @@
 		EncryptionKey
 		ManagerStatus
 		SecretReference
-		RemovedNode
+		BlacklistedCertificate
 		NodeSpec
 		ServiceSpec
 		ReplicatedService
@@ -119,6 +119,8 @@
 		UpdateClusterResponse
 		GetSecretRequest
 		GetSecretResponse
+		UpdateSecretRequest
+		UpdateSecretResponse
 		ListSecretsRequest
 		ListSecretsResponse
 		CreateSecretRequest
@@ -202,8 +204,7 @@ type TaskState int32
 
 const (
 	TaskStateNew       TaskState = 0
-	TaskStateAllocated TaskState = 64
-	TaskStatePending   TaskState = 128
+	TaskStatePending   TaskState = 64
 	TaskStateAssigned  TaskState = 192
 	TaskStateAccepted  TaskState = 256
 	TaskStatePreparing TaskState = 320
@@ -218,8 +219,7 @@ const (
 
 var TaskState_name = map[int32]string{
 	0:   "NEW",
-	64:  "ALLOCATED",
-	128: "PENDING",
+	64:  "PENDING",
 	192: "ASSIGNED",
 	256: "ACCEPTED",
 	320: "PREPARING",
@@ -233,8 +233,7 @@ var TaskState_name = map[int32]string{
 }
 var TaskState_value = map[string]int32{
 	"NEW":       0,
-	"ALLOCATED": 64,
-	"PENDING":   128,
+	"PENDING":   64,
 	"ASSIGNED":  192,
 	"ACCEPTED":  256,
 	"PREPARING": 320,
@@ -540,14 +539,50 @@ func (x PortConfig_Protocol) String() string {
 }
 func (PortConfig_Protocol) EnumDescriptor() ([]byte, []int) { return fileDescriptorTypes, []int{19, 0} }
 
+// PublishMode controls how ports are published on the swarm.
+type PortConfig_PublishMode int32
+
+const (
+	// PublishModeIngress exposes the port across the cluster on all nodes.
+	PublishModeIngress PortConfig_PublishMode = 0
+	// PublishModeHost exposes the port on just the target host.  If the
+	// published port is undefined, an ephemeral port will be allocated. If
+	// the published port is defined, the node will attempt to allocate it,
+	// erroring the task if it fails.
+	PublishModeHost PortConfig_PublishMode = 1
+)
+
+var PortConfig_PublishMode_name = map[int32]string{
+	0: "INGRESS",
+	1: "HOST",
+}
+var PortConfig_PublishMode_value = map[string]int32{
+	"INGRESS": 0,
+	"HOST":    1,
+}
+
+func (x PortConfig_PublishMode) String() string {
+	return proto.EnumName(PortConfig_PublishMode_name, int32(x))
+}
+func (PortConfig_PublishMode) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptorTypes, []int{19, 1}
+}
+
 type IssuanceStatus_State int32
 
 const (
 	IssuanceStateUnknown IssuanceStatus_State = 0
-	IssuanceStateRenew   IssuanceStatus_State = 1
+	// A new certificate should be issued
+	IssuanceStateRenew IssuanceStatus_State = 1
+	// Certificate is pending acceptance
 	IssuanceStatePending IssuanceStatus_State = 2
-	IssuanceStateIssued  IssuanceStatus_State = 3
-	IssuanceStateFailed  IssuanceStatus_State = 4
+	// successful completion certificate issuance
+	IssuanceStateIssued IssuanceStatus_State = 3
+	// Certificate issuance failed
+	IssuanceStateFailed IssuanceStatus_State = 4
+	// Signals workers to renew their certificate. From the CA's perspective
+	// this is equivalent to IssuanceStateIssued: a noop.
+	IssuanceStateRotate IssuanceStatus_State = 5
 )
 
 var IssuanceStatus_State_name = map[int32]string{
@@ -556,6 +591,7 @@ var IssuanceStatus_State_name = map[int32]string{
 	2: "PENDING",
 	3: "ISSUED",
 	4: "FAILED",
+	5: "ROTATE",
 }
 var IssuanceStatus_State_value = map[string]int32{
 	"UNKNOWN": 0,
@@ -563,6 +599,7 @@ var IssuanceStatus_State_value = map[string]int32{
 	"PENDING": 2,
 	"ISSUED":  3,
 	"FAILED":  4,
+	"ROTATE":  5,
 }
 
 func (x IssuanceStatus_State) String() string {
@@ -1106,11 +1143,12 @@ type PortConfig struct {
 	Protocol PortConfig_Protocol `protobuf:"varint,2,opt,name=protocol,proto3,enum=docker.swarmkit.v1.PortConfig_Protocol" json:"protocol,omitempty"`
 	// The port which the application is exposing and is bound to.
 	TargetPort uint32 `protobuf:"varint,3,opt,name=target_port,json=targetPort,proto3" json:"target_port,omitempty"`
-	// PublishedPort specifies the port on which the service is
-	// exposed. If specified, the port must be
-	// within the available range. If not specified, an available
-	// port is automatically assigned.
+	// PublishedPort specifies the port on which the service is exposed. If
+	// specified, the port must be within the available range. If not specified
+	// (value is zero), an available port is automatically assigned.
 	PublishedPort uint32 `protobuf:"varint,4,opt,name=published_port,json=publishedPort,proto3" json:"published_port,omitempty"`
+	// PublishMode controls how the port is published.
+	PublishMode PortConfig_PublishMode `protobuf:"varint,5,opt,name=publish_mode,json=publishMode,proto3,enum=docker.swarmkit.v1.PortConfig_PublishMode" json:"publish_mode,omitempty"`
 }
 
 func (m *PortConfig) Reset()                    { *m = PortConfig{} }
@@ -1397,18 +1435,17 @@ func (m *SecretReference) Reset()                    { *m = SecretReference{} }
 func (*SecretReference) ProtoMessage()               {}
 func (*SecretReference) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{38} }
 
-// RemovedNode is a record for a node that has been removed from the swarm.
-type RemovedNode struct {
-	// ID is the ID of the removed node.
-	ID string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+// BlacklistedCertificate is a record for a blacklisted certificate. It does not
+// contain the certificate's CN, because these records are indexed by CN.
+type BlacklistedCertificate struct {
 	// Expiry is the latest known expiration time of a certificate that
-	// was issued to this node.
-	Expiry *docker_swarmkit_v1.Timestamp `protobuf:"bytes,2,opt,name=expiry" json:"expiry,omitempty"`
+	// was issued for the given CN.
+	Expiry *docker_swarmkit_v1.Timestamp `protobuf:"bytes,1,opt,name=expiry" json:"expiry,omitempty"`
 }
 
-func (m *RemovedNode) Reset()                    { *m = RemovedNode{} }
-func (*RemovedNode) ProtoMessage()               {}
-func (*RemovedNode) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{39} }
+func (m *BlacklistedCertificate) Reset()                    { *m = BlacklistedCertificate{} }
+func (*BlacklistedCertificate) ProtoMessage()               {}
+func (*BlacklistedCertificate) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{39} }
 
 func init() {
 	proto.RegisterType((*Version)(nil), "docker.swarmkit.v1.Version")
@@ -1455,7 +1492,7 @@ func init() {
 	proto.RegisterType((*EncryptionKey)(nil), "docker.swarmkit.v1.EncryptionKey")
 	proto.RegisterType((*ManagerStatus)(nil), "docker.swarmkit.v1.ManagerStatus")
 	proto.RegisterType((*SecretReference)(nil), "docker.swarmkit.v1.SecretReference")
-	proto.RegisterType((*RemovedNode)(nil), "docker.swarmkit.v1.RemovedNode")
+	proto.RegisterType((*BlacklistedCertificate)(nil), "docker.swarmkit.v1.BlacklistedCertificate")
 	proto.RegisterEnum("docker.swarmkit.v1.TaskState", TaskState_name, TaskState_value)
 	proto.RegisterEnum("docker.swarmkit.v1.NodeRole", NodeRole_name, NodeRole_value)
 	proto.RegisterEnum("docker.swarmkit.v1.RaftMemberStatus_Reachability", RaftMemberStatus_Reachability_name, RaftMemberStatus_Reachability_value)
@@ -1467,6 +1504,7 @@ func init() {
 	proto.RegisterEnum("docker.swarmkit.v1.UpdateStatus_UpdateState", UpdateStatus_UpdateState_name, UpdateStatus_UpdateState_value)
 	proto.RegisterEnum("docker.swarmkit.v1.IPAMConfig_AddressFamily", IPAMConfig_AddressFamily_name, IPAMConfig_AddressFamily_value)
 	proto.RegisterEnum("docker.swarmkit.v1.PortConfig_Protocol", PortConfig_Protocol_name, PortConfig_Protocol_value)
+	proto.RegisterEnum("docker.swarmkit.v1.PortConfig_PublishMode", PortConfig_PublishMode_name, PortConfig_PublishMode_value)
 	proto.RegisterEnum("docker.swarmkit.v1.IssuanceStatus_State", IssuanceStatus_State_name, IssuanceStatus_State_value)
 	proto.RegisterEnum("docker.swarmkit.v1.ExternalCA_CAProtocol", ExternalCA_CAProtocol_name, ExternalCA_CAProtocol_value)
 	proto.RegisterEnum("docker.swarmkit.v1.EncryptionKey_Algorithm", EncryptionKey_Algorithm_name, EncryptionKey_Algorithm_value)
@@ -1837,6 +1875,7 @@ func (m *PortConfig) Copy() *PortConfig {
 		Protocol:      m.Protocol,
 		TargetPort:    m.TargetPort,
 		PublishedPort: m.PublishedPort,
+		PublishMode:   m.PublishMode,
 	}
 
 	return o
@@ -2158,13 +2197,12 @@ func (m *SecretReference) Copy() *SecretReference {
 	return o
 }
 
-func (m *RemovedNode) Copy() *RemovedNode {
+func (m *BlacklistedCertificate) Copy() *BlacklistedCertificate {
 	if m == nil {
 		return nil
 	}
 
-	o := &RemovedNode{
-		ID:     m.ID,
+	o := &BlacklistedCertificate{
 		Expiry: m.Expiry.Copy(),
 	}
 
@@ -2529,12 +2567,13 @@ func (this *PortConfig) GoString() string {
 	if this == nil {
 		return "nil"
 	}
-	s := make([]string, 0, 8)
+	s := make([]string, 0, 9)
 	s = append(s, "&api.PortConfig{")
 	s = append(s, "Name: "+fmt.Sprintf("%#v", this.Name)+",\n")
 	s = append(s, "Protocol: "+fmt.Sprintf("%#v", this.Protocol)+",\n")
 	s = append(s, "TargetPort: "+fmt.Sprintf("%#v", this.TargetPort)+",\n")
 	s = append(s, "PublishedPort: "+fmt.Sprintf("%#v", this.PublishedPort)+",\n")
+	s = append(s, "PublishMode: "+fmt.Sprintf("%#v", this.PublishMode)+",\n")
 	s = append(s, "}")
 	return strings.Join(s, "")
 }
@@ -2822,13 +2861,12 @@ func (this *SecretReference) GoString() string {
 	s = append(s, "}")
 	return strings.Join(s, "")
 }
-func (this *RemovedNode) GoString() string {
+func (this *BlacklistedCertificate) GoString() string {
 	if this == nil {
 		return "nil"
 	}
-	s := make([]string, 0, 6)
-	s = append(s, "&api.RemovedNode{")
-	s = append(s, "ID: "+fmt.Sprintf("%#v", this.ID)+",\n")
+	s := make([]string, 0, 5)
+	s = append(s, "&api.BlacklistedCertificate{")
 	if this.Expiry != nil {
 		s = append(s, "Expiry: "+fmt.Sprintf("%#v", this.Expiry)+",\n")
 	}
@@ -3827,6 +3865,11 @@ func (m *PortConfig) MarshalTo(data []byte) (int, error) {
 		i++
 		i = encodeVarintTypes(data, i, uint64(m.PublishedPort))
 	}
+	if m.PublishMode != 0 {
+		data[i] = 0x28
+		i++
+		i = encodeVarintTypes(data, i, uint64(m.PublishMode))
+	}
 	return i, nil
 }
 
@@ -4595,7 +4638,7 @@ func (m *SecretReference) MarshalTo(data []byte) (int, error) {
 	return i, nil
 }
 
-func (m *RemovedNode) Marshal() (data []byte, err error) {
+func (m *BlacklistedCertificate) Marshal() (data []byte, err error) {
 	size := m.Size()
 	data = make([]byte, size)
 	n, err := m.MarshalTo(data)
@@ -4605,19 +4648,13 @@ func (m *RemovedNode) Marshal() (data []byte, err error) {
 	return data[:n], nil
 }
 
-func (m *RemovedNode) MarshalTo(data []byte) (int, error) {
+func (m *BlacklistedCertificate) MarshalTo(data []byte) (int, error) {
 	var i int
 	_ = i
 	var l int
 	_ = l
-	if len(m.ID) > 0 {
-		data[i] = 0xa
-		i++
-		i = encodeVarintTypes(data, i, uint64(len(m.ID)))
-		i += copy(data[i:], m.ID)
-	}
 	if m.Expiry != nil {
-		data[i] = 0x12
+		data[i] = 0xa
 		i++
 		i = encodeVarintTypes(data, i, uint64(m.Expiry.Size()))
 		n27, err := m.Expiry.MarshalTo(data[i:])
@@ -5075,6 +5112,9 @@ func (m *PortConfig) Size() (n int) {
 	if m.PublishedPort != 0 {
 		n += 1 + sovTypes(uint64(m.PublishedPort))
 	}
+	if m.PublishMode != 0 {
+		n += 1 + sovTypes(uint64(m.PublishMode))
+	}
 	return n
 }
 
@@ -5410,13 +5450,9 @@ func (m *SecretReference) Size() (n int) {
 	return n
 }
 
-func (m *RemovedNode) Size() (n int) {
+func (m *BlacklistedCertificate) Size() (n int) {
 	var l int
 	_ = l
-	l = len(m.ID)
-	if l > 0 {
-		n += 1 + l + sovTypes(uint64(l))
-	}
 	if m.Expiry != nil {
 		l = m.Expiry.Size()
 		n += 1 + l + sovTypes(uint64(l))
@@ -5760,6 +5796,7 @@ func (this *PortConfig) String() string {
 		`Protocol:` + fmt.Sprintf("%v", this.Protocol) + `,`,
 		`TargetPort:` + fmt.Sprintf("%v", this.TargetPort) + `,`,
 		`PublishedPort:` + fmt.Sprintf("%v", this.PublishedPort) + `,`,
+		`PublishMode:` + fmt.Sprintf("%v", this.PublishMode) + `,`,
 		`}`,
 	}, "")
 	return s
@@ -6026,12 +6063,11 @@ func (this *SecretReference) String() string {
 	}, "")
 	return s
 }
-func (this *RemovedNode) String() string {
+func (this *BlacklistedCertificate) String() string {
 	if this == nil {
 		return "nil"
 	}
-	s := strings.Join([]string{`&RemovedNode{`,
-		`ID:` + fmt.Sprintf("%v", this.ID) + `,`,
+	s := strings.Join([]string{`&BlacklistedCertificate{`,
 		`Expiry:` + strings.Replace(fmt.Sprintf("%v", this.Expiry), "Timestamp", "docker_swarmkit_v1.Timestamp", 1) + `,`,
 		`}`,
 	}, "")
@@ -9366,6 +9402,25 @@ func (m *PortConfig) Unmarshal(data []byte) error {
 					break
 				}
 			}
+		case 5:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field PublishMode", wireType)
+			}
+			m.PublishMode = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := data[iNdEx]
+				iNdEx++
+				m.PublishMode |= (PortConfig_PublishMode(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
 		default:
 			iNdEx = preIndex
 			skippy, err := skipTypes(data[iNdEx:])
@@ -12014,7 +12069,7 @@ func (m *SecretReference) Unmarshal(data []byte) error {
 	}
 	return nil
 }
-func (m *RemovedNode) Unmarshal(data []byte) error {
+func (m *BlacklistedCertificate) Unmarshal(data []byte) error {
 	l := len(data)
 	iNdEx := 0
 	for iNdEx < l {
@@ -12037,42 +12092,13 @@ func (m *RemovedNode) Unmarshal(data []byte) error {
 		fieldNum := int32(wire >> 3)
 		wireType := int(wire & 0x7)
 		if wireType == 4 {
-			return fmt.Errorf("proto: RemovedNode: wiretype end group for non-group")
+			return fmt.Errorf("proto: BlacklistedCertificate: wiretype end group for non-group")
 		}
 		if fieldNum <= 0 {
-			return fmt.Errorf("proto: RemovedNode: illegal tag %d (wire type %d)", fieldNum, wire)
+			return fmt.Errorf("proto: BlacklistedCertificate: illegal tag %d (wire type %d)", fieldNum, wire)
 		}
 		switch fieldNum {
 		case 1:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field ID", 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.ID = string(data[iNdEx:postIndex])
-			iNdEx = postIndex
-		case 2:
 			if wireType != 2 {
 				return fmt.Errorf("proto: wrong wireType = %d for field Expiry", wireType)
 			}
@@ -12234,233 +12260,236 @@ var (
 func init() { proto.RegisterFile("types.proto", fileDescriptorTypes) }
 
 var fileDescriptorTypes = []byte{
-	// 3635 bytes of a gzipped FileDescriptorProto
+	// 3694 bytes of a gzipped FileDescriptorProto
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x59, 0xcd, 0x6f, 0x23, 0x47,
 	0x76, 0x17, 0x3f, 0x45, 0x3e, 0x52, 0x52, 0x4f, 0xcd, 0xec, 0x58, 0x43, 0x8f, 0x25, 0xba, 0xc7,
-	0xb3, 0x1e, 0x7b, 0x1d, 0xda, 0x96, 0x77, 0x8d, 0x59, 0xcf, 0x66, 0xed, 0x16, 0x49, 0xcd, 0x70,
-	0x47, 0xa2, 0x88, 0x22, 0x39, 0x03, 0x23, 0x41, 0x88, 0x52, 0x77, 0x89, 0x6a, 0xab, 0xd9, 0xc5,
+	0xb3, 0x1e, 0xcf, 0x3a, 0xb4, 0x2d, 0xef, 0x1a, 0xb3, 0x9e, 0xcd, 0xda, 0x2d, 0x92, 0x1a, 0x71,
+	0x47, 0x22, 0x89, 0x22, 0x39, 0x03, 0x23, 0x40, 0x88, 0x52, 0x77, 0x89, 0x6a, 0xab, 0xd9, 0xcd,
 	0x74, 0x17, 0xa5, 0x61, 0x82, 0x00, 0x93, 0x1c, 0x92, 0x40, 0xa7, 0xdc, 0x03, 0x61, 0x11, 0x24,
-	0xc8, 0x2d, 0xe7, 0x00, 0x39, 0xf9, 0xe8, 0xe3, 0x06, 0x01, 0x82, 0xc5, 0x06, 0x19, 0xc4, 0xca,
-	0x3f, 0xb0, 0x40, 0x10, 0xec, 0x21, 0x39, 0x04, 0xf5, 0xd1, 0xcd, 0x8f, 0xe1, 0xc8, 0x72, 0xd6,
-	0x27, 0xb2, 0x5e, 0xfd, 0xde, 0xab, 0x57, 0x55, 0xaf, 0x5e, 0xfd, 0x5e, 0x35, 0x14, 0xf8, 0x78,
-	0x48, 0xc3, 0xca, 0x30, 0x60, 0x9c, 0x21, 0xe4, 0x30, 0xfb, 0x98, 0x06, 0x95, 0xf0, 0x94, 0x04,
-	0x83, 0x63, 0x97, 0x57, 0x4e, 0x3e, 0x2c, 0xdd, 0xe2, 0xee, 0x80, 0x86, 0x9c, 0x0c, 0x86, 0xef,
-	0xc7, 0xff, 0x14, 0xbc, 0xf4, 0x9a, 0x33, 0x0a, 0x08, 0x77, 0x99, 0xff, 0x7e, 0xf4, 0x47, 0x77,
-	0xdc, 0xe8, 0xb3, 0x3e, 0x93, 0x7f, 0xdf, 0x17, 0xff, 0x94, 0xd4, 0xdc, 0x84, 0xe5, 0x27, 0x34,
-	0x08, 0x5d, 0xe6, 0xa3, 0x1b, 0x90, 0x71, 0x7d, 0x87, 0x3e, 0x5b, 0x4f, 0x94, 0x13, 0xf7, 0xd2,
-	0x58, 0x35, 0xcc, 0xbf, 0x49, 0x40, 0xc1, 0xf2, 0x7d, 0xc6, 0xa5, 0xad, 0x10, 0x21, 0x48, 0xfb,
-	0x64, 0x40, 0x25, 0x28, 0x8f, 0xe5, 0x7f, 0x54, 0x85, 0xac, 0x47, 0x0e, 0xa8, 0x17, 0xae, 0x27,
-	0xcb, 0xa9, 0x7b, 0x85, 0xad, 0x1f, 0x54, 0x5e, 0xf6, 0xb9, 0x32, 0x65, 0xa4, 0xb2, 0x2b, 0xd1,
-	0x75, 0x9f, 0x07, 0x63, 0xac, 0x55, 0x4b, 0x3f, 0x86, 0xc2, 0x94, 0x18, 0x19, 0x90, 0x3a, 0xa6,
-	0x63, 0x3d, 0x8c, 0xf8, 0x2b, 0xfc, 0x3b, 0x21, 0xde, 0x88, 0xae, 0x27, 0xa5, 0x4c, 0x35, 0x3e,
-	0x49, 0xde, 0x4f, 0x98, 0x9f, 0x43, 0x1e, 0xd3, 0x90, 0x8d, 0x02, 0x9b, 0x86, 0xe8, 0x1d, 0xc8,
-	0xfb, 0xc4, 0x67, 0x3d, 0x7b, 0x38, 0x0a, 0xa5, 0x7a, 0x6a, 0xbb, 0x78, 0xf1, 0x62, 0x33, 0xd7,
-	0x24, 0x3e, 0xab, 0xb6, 0xba, 0x21, 0xce, 0x89, 0xee, 0xea, 0x70, 0x14, 0xa2, 0x37, 0xa1, 0x38,
-	0xa0, 0x03, 0x16, 0x8c, 0x7b, 0x07, 0x63, 0x4e, 0x43, 0x69, 0x38, 0x85, 0x0b, 0x4a, 0xb6, 0x2d,
-	0x44, 0xe6, 0x5f, 0x25, 0xe0, 0x46, 0x64, 0x1b, 0xd3, 0x3f, 0x1c, 0xb9, 0x01, 0x1d, 0x50, 0x9f,
-	0x87, 0xe8, 0x47, 0x90, 0xf5, 0xdc, 0x81, 0xcb, 0xd5, 0x18, 0x85, 0xad, 0x37, 0x16, 0xcd, 0x39,
-	0xf6, 0x0a, 0x6b, 0x30, 0xb2, 0xa0, 0x18, 0xd0, 0x90, 0x06, 0x27, 0x6a, 0x25, 0xe4, 0x90, 0xdf,
-	0xa8, 0x3c, 0xa3, 0x62, 0xee, 0x40, 0xae, 0xe5, 0x11, 0x7e, 0xc8, 0x82, 0x01, 0x32, 0xa1, 0x48,
-	0x02, 0xfb, 0xc8, 0xe5, 0xd4, 0xe6, 0xa3, 0x20, 0xda, 0x95, 0x19, 0x19, 0xba, 0x09, 0x49, 0xa6,
-	0x06, 0xca, 0x6f, 0x67, 0x2f, 0x5e, 0x6c, 0x26, 0xf7, 0xdb, 0x38, 0xc9, 0x42, 0xf3, 0x01, 0x5c,
-	0x6b, 0x79, 0xa3, 0xbe, 0xeb, 0xd7, 0x68, 0x68, 0x07, 0xee, 0x50, 0x58, 0x17, 0xdb, 0x2b, 0x82,
-	0x2f, 0xda, 0x5e, 0xf1, 0x3f, 0xde, 0xf2, 0xe4, 0x64, 0xcb, 0xcd, 0xbf, 0x48, 0xc2, 0xb5, 0xba,
-	0xdf, 0x77, 0x7d, 0x3a, 0xad, 0x7d, 0x17, 0x56, 0xa9, 0x14, 0xf6, 0x4e, 0x54, 0x50, 0x69, 0x3b,
-	0x2b, 0x4a, 0x1a, 0x45, 0x5a, 0x63, 0x2e, 0x5e, 0x3e, 0x5c, 0x34, 0xfd, 0x97, 0xac, 0x2f, 0x8a,
-	0x1a, 0x54, 0x87, 0xe5, 0xa1, 0x9c, 0x44, 0xb8, 0x9e, 0x92, 0xb6, 0xee, 0x2e, 0xb2, 0xf5, 0xd2,
-	0x3c, 0xb7, 0xd3, 0x5f, 0xbd, 0xd8, 0x5c, 0xc2, 0x91, 0xee, 0x6f, 0x13, 0x7c, 0xff, 0x99, 0x80,
-	0xb5, 0x26, 0x73, 0x66, 0xd6, 0xa1, 0x04, 0xb9, 0x23, 0x16, 0xf2, 0xa9, 0x83, 0x12, 0xb7, 0xd1,
-	0x7d, 0xc8, 0x0d, 0xf5, 0xf6, 0xe9, 0xdd, 0xbf, 0xbd, 0xd8, 0x65, 0x85, 0xc1, 0x31, 0x1a, 0x3d,
-	0x80, 0x7c, 0x10, 0xc5, 0xc4, 0x7a, 0xea, 0x2a, 0x81, 0x33, 0xc1, 0xa3, 0xdf, 0x85, 0xac, 0xda,
-	0x84, 0xf5, 0xb4, 0xd4, 0xbc, 0x7b, 0xa5, 0x35, 0xc7, 0x5a, 0xc9, 0xfc, 0x65, 0x02, 0x0c, 0x4c,
-	0x0e, 0xf9, 0x1e, 0x1d, 0x1c, 0xd0, 0xa0, 0xcd, 0x09, 0x1f, 0x85, 0xe8, 0x26, 0x64, 0x3d, 0x4a,
-	0x1c, 0x1a, 0xc8, 0x49, 0xe6, 0xb0, 0x6e, 0xa1, 0xae, 0x08, 0x72, 0x62, 0x1f, 0x91, 0x03, 0xd7,
-	0x73, 0xf9, 0x58, 0x4e, 0x73, 0x75, 0xf1, 0x2e, 0xcf, 0xdb, 0xac, 0xe0, 0x29, 0x45, 0x3c, 0x63,
-	0x06, 0xad, 0xc3, 0xf2, 0x80, 0x86, 0x21, 0xe9, 0x53, 0x39, 0xfb, 0x3c, 0x8e, 0x9a, 0xe6, 0x03,
-	0x28, 0x4e, 0xeb, 0xa1, 0x02, 0x2c, 0x77, 0x9b, 0x8f, 0x9b, 0xfb, 0x4f, 0x9b, 0xc6, 0x12, 0x5a,
-	0x83, 0x42, 0xb7, 0x89, 0xeb, 0x56, 0xf5, 0x91, 0xb5, 0xbd, 0x5b, 0x37, 0x12, 0x68, 0x05, 0xf2,
-	0x93, 0x66, 0xd2, 0xfc, 0x79, 0x02, 0x40, 0x6c, 0xa0, 0x9e, 0xd4, 0x27, 0x90, 0x09, 0x39, 0xe1,
-	0x6a, 0xe3, 0x56, 0xb7, 0xde, 0x5a, 0xe4, 0xf5, 0x04, 0x5e, 0x11, 0x3f, 0x14, 0x2b, 0x95, 0x69,
-	0x0f, 0x93, 0xf3, 0x1e, 0x66, 0x24, 0x72, 0xd6, 0xb5, 0x1c, 0xa4, 0x6b, 0xe2, 0x5f, 0x02, 0xe5,
-	0x21, 0x83, 0xeb, 0x56, 0xed, 0x73, 0x23, 0x89, 0x0c, 0x28, 0xd6, 0x1a, 0xed, 0xea, 0x7e, 0xb3,
-	0x59, 0xaf, 0x76, 0xea, 0x35, 0x23, 0x65, 0xde, 0x85, 0x4c, 0x63, 0x40, 0xfa, 0x14, 0xdd, 0x16,
-	0x11, 0x70, 0x48, 0x03, 0xea, 0xdb, 0x51, 0x60, 0x4d, 0x04, 0xe6, 0x2f, 0xf2, 0x90, 0xd9, 0x63,
-	0x23, 0x9f, 0xa3, 0xad, 0xa9, 0x53, 0xbc, 0xba, 0xb5, 0xb1, 0x68, 0x0a, 0x12, 0x58, 0xe9, 0x8c,
-	0x87, 0x54, 0x9f, 0xf2, 0x9b, 0x90, 0x55, 0xb1, 0xa2, 0x5d, 0xd7, 0x2d, 0x21, 0xe7, 0x24, 0xe8,
-	0x53, 0xae, 0x17, 0x5d, 0xb7, 0xd0, 0x3d, 0xc8, 0x05, 0x94, 0x38, 0xcc, 0xf7, 0xc6, 0x32, 0xa4,
-	0x72, 0x2a, 0xcd, 0x62, 0x4a, 0x9c, 0x7d, 0xdf, 0x1b, 0xe3, 0xb8, 0x17, 0x3d, 0x82, 0xe2, 0x81,
-	0xeb, 0x3b, 0x3d, 0x36, 0x54, 0x39, 0x2f, 0xf3, 0xea, 0x00, 0x54, 0x5e, 0x6d, 0xbb, 0xbe, 0xb3,
-	0xaf, 0xc0, 0xb8, 0x70, 0x30, 0x69, 0xa0, 0x26, 0xac, 0x9e, 0x30, 0x6f, 0x34, 0xa0, 0xb1, 0xad,
-	0xac, 0xb4, 0xf5, 0xf6, 0xab, 0x6d, 0x3d, 0x91, 0xf8, 0xc8, 0xda, 0xca, 0xc9, 0x74, 0x13, 0x3d,
-	0x86, 0x15, 0x3e, 0x18, 0x1e, 0x86, 0xb1, 0xb9, 0x65, 0x69, 0xee, 0xfb, 0x97, 0x2c, 0x98, 0x80,
-	0x47, 0xd6, 0x8a, 0x7c, 0xaa, 0x55, 0xfa, 0xb3, 0x14, 0x14, 0xa6, 0x3c, 0x47, 0x6d, 0x28, 0x0c,
-	0x03, 0x36, 0x24, 0x7d, 0x99, 0xb7, 0xf5, 0x5e, 0x7c, 0x78, 0xa5, 0x59, 0x57, 0x5a, 0x13, 0x45,
-	0x3c, 0x6d, 0xc5, 0x3c, 0x4f, 0x42, 0x61, 0xaa, 0x13, 0xbd, 0x0b, 0x39, 0xdc, 0xc2, 0x8d, 0x27,
-	0x56, 0xa7, 0x6e, 0x2c, 0x95, 0x6e, 0x9f, 0x9d, 0x97, 0xd7, 0xa5, 0xb5, 0x69, 0x03, 0xad, 0xc0,
-	0x3d, 0x11, 0xa1, 0x77, 0x0f, 0x96, 0x23, 0x68, 0xa2, 0xf4, 0xfa, 0xd9, 0x79, 0xf9, 0xb5, 0x79,
-	0xe8, 0x14, 0x12, 0xb7, 0x1f, 0x59, 0xb8, 0x5e, 0x33, 0x92, 0x8b, 0x91, 0xb8, 0x7d, 0x44, 0x02,
-	0xea, 0xa0, 0xef, 0x43, 0x56, 0x03, 0x53, 0xa5, 0xd2, 0xd9, 0x79, 0xf9, 0xe6, 0x3c, 0x70, 0x82,
-	0xc3, 0xed, 0x5d, 0xeb, 0x49, 0xdd, 0x48, 0x2f, 0xc6, 0xe1, 0xb6, 0x47, 0x4e, 0x28, 0x7a, 0x0b,
-	0x32, 0x0a, 0x96, 0x29, 0xdd, 0x3a, 0x3b, 0x2f, 0x7f, 0xef, 0x25, 0x73, 0x02, 0x55, 0x5a, 0xff,
-	0xcb, 0xbf, 0xdd, 0x58, 0xfa, 0xa7, 0xbf, 0xdb, 0x30, 0xe6, 0xbb, 0x4b, 0xff, 0x9b, 0x80, 0x95,
-	0x99, 0x2d, 0x47, 0x26, 0x64, 0x7d, 0x66, 0xb3, 0xa1, 0x4a, 0xe7, 0xb9, 0x6d, 0xb8, 0x78, 0xb1,
-	0x99, 0x6d, 0xb2, 0x2a, 0x1b, 0x8e, 0xb1, 0xee, 0x41, 0x8f, 0xe7, 0x2e, 0xa4, 0x8f, 0xae, 0x18,
-	0x4f, 0x0b, 0xaf, 0xa4, 0x4f, 0x61, 0xc5, 0x09, 0xdc, 0x13, 0x1a, 0xf4, 0x6c, 0xe6, 0x1f, 0xba,
-	0x7d, 0x9d, 0xaa, 0x4b, 0x8b, 0x6c, 0xd6, 0x24, 0x10, 0x17, 0x95, 0x42, 0x55, 0xe2, 0x7f, 0x8b,
-	0xcb, 0xa8, 0xf4, 0x04, 0x8a, 0xd3, 0x11, 0x8a, 0xde, 0x00, 0x08, 0xdd, 0x3f, 0xa2, 0x9a, 0xdf,
-	0x48, 0x36, 0x84, 0xf3, 0x42, 0x22, 0xd9, 0x0d, 0x7a, 0x1b, 0xd2, 0x03, 0xe6, 0x28, 0x3b, 0x99,
-	0xed, 0xeb, 0xe2, 0x4e, 0xfc, 0xd5, 0x8b, 0xcd, 0x02, 0x0b, 0x2b, 0x3b, 0xae, 0x47, 0xf7, 0x98,
-	0x43, 0xb1, 0x04, 0x98, 0x27, 0x90, 0x16, 0xa9, 0x02, 0xbd, 0x0e, 0xe9, 0xed, 0x46, 0xb3, 0x66,
-	0x2c, 0x95, 0xae, 0x9d, 0x9d, 0x97, 0x57, 0xe4, 0x92, 0x88, 0x0e, 0x11, 0xbb, 0x68, 0x13, 0xb2,
-	0x4f, 0xf6, 0x77, 0xbb, 0x7b, 0x22, 0xbc, 0xae, 0x9f, 0x9d, 0x97, 0xd7, 0xe2, 0x6e, 0xb5, 0x68,
-	0xe8, 0x0d, 0xc8, 0x74, 0xf6, 0x5a, 0x3b, 0x6d, 0x23, 0x59, 0x42, 0x67, 0xe7, 0xe5, 0xd5, 0xb8,
-	0x5f, 0xfa, 0x5c, 0xba, 0xa6, 0x77, 0x35, 0x1f, 0xcb, 0xcd, 0xff, 0x49, 0xc2, 0x0a, 0x16, 0xfc,
-	0x36, 0xe0, 0x2d, 0xe6, 0xb9, 0xf6, 0x18, 0xb5, 0x20, 0x6f, 0x33, 0xdf, 0x71, 0xa7, 0xce, 0xd4,
-	0xd6, 0x2b, 0x2e, 0xc1, 0x89, 0x56, 0xd4, 0xaa, 0x46, 0x9a, 0x78, 0x62, 0x04, 0x6d, 0x41, 0xc6,
-	0xa1, 0x1e, 0x19, 0x5f, 0x76, 0x1b, 0xd7, 0x34, 0x97, 0xc6, 0x0a, 0x2a, 0x99, 0x23, 0x79, 0xd6,
-	0x23, 0x9c, 0xd3, 0xc1, 0x90, 0xab, 0xdb, 0x38, 0x8d, 0x0b, 0x03, 0xf2, 0xcc, 0xd2, 0x22, 0xf4,
-	0x43, 0xc8, 0x9e, 0xba, 0xbe, 0xc3, 0x4e, 0xf5, 0x85, 0x7b, 0xb9, 0x5d, 0x8d, 0x35, 0xcf, 0xc4,
-	0x3d, 0x3b, 0xe7, 0xac, 0x58, 0xf5, 0xe6, 0x7e, 0xb3, 0x1e, 0xad, 0xba, 0xee, 0xdf, 0xf7, 0x9b,
-	0xcc, 0x17, 0x27, 0x06, 0xf6, 0x9b, 0xbd, 0x1d, 0xab, 0xb1, 0xdb, 0xc5, 0x62, 0xe5, 0x6f, 0x9c,
-	0x9d, 0x97, 0x8d, 0x18, 0xb2, 0x43, 0x5c, 0x4f, 0x90, 0xc0, 0x5b, 0x90, 0xb2, 0x9a, 0x9f, 0x1b,
-	0xc9, 0x92, 0x71, 0x76, 0x5e, 0x2e, 0xc6, 0xdd, 0x96, 0x3f, 0x9e, 0x1c, 0xa6, 0xf9, 0x71, 0xcd,
-	0x7f, 0x4f, 0x42, 0xb1, 0x3b, 0x74, 0x08, 0xa7, 0x2a, 0x32, 0x51, 0x19, 0x0a, 0x43, 0x12, 0x10,
-	0xcf, 0xa3, 0x9e, 0x1b, 0x0e, 0x74, 0xa1, 0x30, 0x2d, 0x42, 0xf7, 0xbf, 0xc5, 0x62, 0x6a, 0x12,
-	0xa6, 0x97, 0xb4, 0x0b, 0xab, 0x87, 0xca, 0xd9, 0x1e, 0xb1, 0xe5, 0xee, 0xa6, 0xe4, 0xee, 0x56,
-	0x16, 0x99, 0x98, 0xf6, 0xaa, 0xa2, 0xe7, 0x68, 0x49, 0x2d, 0xbc, 0x72, 0x38, 0xdd, 0x44, 0x1f,
-	0xc3, 0xf2, 0x80, 0xf9, 0x2e, 0x67, 0xc1, 0x95, 0xf6, 0x21, 0x02, 0xa3, 0x77, 0xe1, 0x9a, 0xd8,
-	0xe1, 0xc8, 0x25, 0xd9, 0x2d, 0x6f, 0xae, 0x24, 0x5e, 0x1b, 0x90, 0x67, 0x7a, 0x4c, 0x2c, 0xc4,
-	0xe6, 0xc7, 0xb0, 0x32, 0xe3, 0x83, 0xb8, 0xcd, 0x5b, 0x56, 0xb7, 0x5d, 0x37, 0x96, 0x50, 0x11,
-	0x72, 0xd5, 0xfd, 0x66, 0xa7, 0xd1, 0xec, 0x0a, 0xea, 0x51, 0x84, 0x1c, 0xde, 0xdf, 0xdd, 0xdd,
-	0xb6, 0xaa, 0x8f, 0x8d, 0xa4, 0xf9, 0xdf, 0xf1, 0xfa, 0x6a, 0xee, 0xb1, 0x3d, 0xcb, 0x3d, 0xde,
-	0x7b, 0xf5, 0xd4, 0x35, 0xfb, 0x98, 0x34, 0x62, 0x0e, 0xf2, 0x13, 0x00, 0xb9, 0x8d, 0xd4, 0xe9,
-	0x11, 0x7e, 0x59, 0x7d, 0xd1, 0x89, 0x2a, 0x47, 0x9c, 0xd7, 0x0a, 0x16, 0x47, 0x9f, 0x41, 0xd1,
-	0x66, 0x83, 0xa1, 0x47, 0xb5, 0x7e, 0xea, 0x2a, 0xfa, 0x85, 0x58, 0xc5, 0xe2, 0xd3, 0x1c, 0x28,
-	0x3d, 0xcb, 0x81, 0xfe, 0x3c, 0x01, 0x85, 0x29, 0x87, 0x67, 0xa9, 0x50, 0x11, 0x72, 0xdd, 0x56,
-	0xcd, 0xea, 0x34, 0x9a, 0x0f, 0x8d, 0x04, 0x02, 0xc8, 0xca, 0x05, 0xac, 0x19, 0x49, 0x41, 0xd7,
-	0xaa, 0xfb, 0x7b, 0xad, 0xdd, 0xba, 0x24, 0x43, 0xe8, 0x06, 0x18, 0xd1, 0x12, 0xf6, 0xda, 0x1d,
-	0x0b, 0x0b, 0x69, 0x1a, 0x5d, 0x87, 0xb5, 0x58, 0xaa, 0x35, 0x33, 0xe8, 0x26, 0xa0, 0x58, 0x38,
-	0x31, 0x91, 0x35, 0xff, 0x04, 0xd6, 0xaa, 0xcc, 0xe7, 0xc4, 0xf5, 0x63, 0x2a, 0xbb, 0x25, 0xe6,
-	0xad, 0x45, 0x3d, 0xd7, 0x51, 0xd9, 0x76, 0x7b, 0xed, 0xe2, 0xc5, 0x66, 0x21, 0x86, 0x36, 0x6a,
-	0x62, 0xa6, 0x51, 0xc3, 0x11, 0x67, 0x6a, 0xe8, 0x3a, 0x3a, 0x79, 0x2e, 0x5f, 0xbc, 0xd8, 0x4c,
-	0xb5, 0x1a, 0x35, 0x2c, 0x64, 0xe8, 0x75, 0xc8, 0xd3, 0x67, 0x2e, 0xef, 0xd9, 0x22, 0xbb, 0x8a,
-	0x35, 0xcc, 0xe0, 0x9c, 0x10, 0x54, 0x45, 0x32, 0xfd, 0xd3, 0x24, 0x40, 0x87, 0x84, 0xc7, 0x7a,
-	0xe8, 0x07, 0x90, 0x8f, 0x8b, 0xf8, 0xcb, 0x8a, 0xc9, 0xa9, 0xfd, 0x8a, 0xf1, 0xe8, 0xa3, 0x28,
-	0x62, 0x14, 0xc7, 0x5e, 0xac, 0xa8, 0xc7, 0x5a, 0x44, 0x53, 0x67, 0x89, 0xb4, 0xb8, 0x6b, 0x68,
-	0x10, 0xe8, 0x8d, 0x13, 0x7f, 0x51, 0x55, 0xe6, 0x5b, 0x35, 0x67, 0xcd, 0xdc, 0xee, 0x2c, 0x1a,
-	0x64, 0x6e, 0x41, 0x1f, 0x2d, 0xe1, 0x89, 0xde, 0xb6, 0x01, 0xab, 0xc1, 0xc8, 0x17, 0x5e, 0xf7,
-	0x42, 0xd9, 0x6d, 0xba, 0xf0, 0x5a, 0x93, 0xf2, 0x53, 0x16, 0x1c, 0x5b, 0x9c, 0x13, 0xfb, 0x48,
-	0x14, 0xd5, 0x3a, 0xc9, 0x4c, 0x08, 0x67, 0x62, 0x86, 0x70, 0xae, 0xc3, 0x32, 0xf1, 0x5c, 0x12,
-	0x52, 0x75, 0x4b, 0xe7, 0x71, 0xd4, 0x14, 0xb4, 0x98, 0x38, 0x4e, 0x40, 0xc3, 0x90, 0xaa, 0x32,
-	0x30, 0x8f, 0x27, 0x02, 0xf3, 0x5f, 0x92, 0x00, 0x8d, 0x96, 0xb5, 0xa7, 0xcd, 0xd7, 0x20, 0x7b,
-	0x48, 0x06, 0xae, 0x37, 0xbe, 0xec, 0x90, 0x4d, 0xf0, 0x15, 0x4b, 0x19, 0xda, 0x91, 0x3a, 0x58,
-	0xeb, 0x4a, 0xb6, 0x3c, 0x3a, 0xf0, 0x29, 0x8f, 0xd9, 0xb2, 0x6c, 0x89, 0xab, 0x39, 0x20, 0x7e,
-	0xbc, 0xb0, 0xaa, 0x21, 0x5c, 0xef, 0x13, 0x4e, 0x4f, 0xc9, 0x38, 0x3a, 0x13, 0xba, 0x89, 0x1e,
-	0x09, 0x16, 0x2d, 0x8a, 0x7b, 0xea, 0xac, 0x67, 0x24, 0xf7, 0xf8, 0x26, 0x7f, 0xb0, 0x86, 0x2b,
-	0xd2, 0x11, 0x6b, 0x97, 0x1e, 0xc8, 0x9b, 0x72, 0xd2, 0xf5, 0xad, 0x8a, 0xd8, 0x0f, 0x60, 0x65,
-	0x66, 0x9e, 0x2f, 0x95, 0x29, 0x8d, 0xd6, 0x93, 0x1f, 0x1a, 0x69, 0xfd, 0xef, 0x63, 0x23, 0x6b,
-	0xfe, 0x57, 0x02, 0xa0, 0xc5, 0x82, 0x68, 0xd3, 0x16, 0x3f, 0x0b, 0xe5, 0xe4, 0x23, 0x93, 0xcd,
-	0x3c, 0x1d, 0x9e, 0x0b, 0x79, 0xfa, 0xc4, 0x8a, 0xa0, 0xbd, 0x12, 0x8e, 0x63, 0x45, 0xb4, 0x09,
-	0x05, 0xb5, 0xff, 0xbd, 0x21, 0x0b, 0x54, 0x3e, 0x5a, 0xc1, 0xa0, 0x44, 0x42, 0x13, 0xdd, 0x85,
-	0xd5, 0xe1, 0xe8, 0xc0, 0x73, 0xc3, 0x23, 0xea, 0x28, 0x4c, 0x5a, 0x62, 0x56, 0x62, 0xa9, 0x80,
-	0x99, 0x35, 0xc8, 0x45, 0xd6, 0xd1, 0x3a, 0xa4, 0x3a, 0xd5, 0x96, 0xb1, 0x54, 0x5a, 0x3b, 0x3b,
-	0x2f, 0x17, 0x22, 0x71, 0xa7, 0xda, 0x12, 0x3d, 0xdd, 0x5a, 0xcb, 0x48, 0xcc, 0xf6, 0x74, 0x6b,
-	0xad, 0x52, 0x5a, 0xdc, 0x92, 0xe6, 0x5f, 0x27, 0x20, 0xab, 0x38, 0xdb, 0xc2, 0x19, 0x5b, 0xb0,
-	0x1c, 0x55, 0x12, 0x8a, 0x48, 0xbe, 0xfd, 0x6a, 0xd2, 0x57, 0xd1, 0x1c, 0x4d, 0xed, 0x63, 0xa4,
-	0x57, 0xfa, 0x04, 0x8a, 0xd3, 0x1d, 0xdf, 0x6a, 0x17, 0xff, 0x18, 0x0a, 0x22, 0x50, 0x22, 0xf2,
-	0xb7, 0x05, 0x59, 0xc5, 0x2b, 0x75, 0x56, 0xb9, 0x8c, 0x81, 0x6a, 0x24, 0xba, 0x0f, 0xcb, 0x8a,
-	0xb5, 0x46, 0xef, 0x29, 0x1b, 0x97, 0x87, 0x23, 0x8e, 0xe0, 0xe6, 0xa7, 0x90, 0x6e, 0x51, 0x1a,
-	0xa0, 0x3b, 0xb0, 0xec, 0x33, 0x87, 0x4e, 0x92, 0xa8, 0x26, 0xdc, 0x0e, 0x6d, 0xd4, 0x04, 0xe1,
-	0x76, 0x68, 0xc3, 0x11, 0x8b, 0x27, 0x0e, 0x68, 0xf4, 0xa4, 0x24, 0xfe, 0x9b, 0x1d, 0x28, 0x3e,
-	0xa5, 0x6e, 0xff, 0x88, 0x53, 0x47, 0x1a, 0x7a, 0x0f, 0xd2, 0x43, 0x1a, 0x3b, 0xbf, 0xbe, 0x30,
-	0x74, 0x28, 0x0d, 0xb0, 0x44, 0x89, 0x03, 0x79, 0x2a, 0xb5, 0xf5, 0x2b, 0x9e, 0x6e, 0x99, 0xff,
-	0x90, 0x84, 0xd5, 0x46, 0x18, 0x8e, 0x88, 0x6f, 0x47, 0xb7, 0xec, 0x4f, 0x67, 0x6f, 0xd9, 0x7b,
-	0x0b, 0x67, 0x38, 0xa3, 0x32, 0x5b, 0xe5, 0xeb, 0x24, 0x99, 0x8c, 0x93, 0xa4, 0xf9, 0x55, 0x22,
-	0x2a, 0xef, 0xef, 0x4e, 0x9d, 0x9b, 0xd2, 0xfa, 0xd9, 0x79, 0xf9, 0xc6, 0xb4, 0x25, 0xda, 0xf5,
-	0x8f, 0x7d, 0x76, 0xea, 0xa3, 0x37, 0x45, 0xb9, 0xdf, 0xac, 0x3f, 0x35, 0x12, 0xa5, 0x9b, 0x67,
-	0xe7, 0x65, 0x34, 0x03, 0xc2, 0xd4, 0xa7, 0xa7, 0xc2, 0x52, 0xab, 0xde, 0xac, 0x89, 0xfb, 0x30,
-	0xb9, 0xc0, 0x52, 0x8b, 0xfa, 0x8e, 0xeb, 0xf7, 0xd1, 0x1d, 0xc8, 0x36, 0xda, 0xed, 0xae, 0x2c,
-	0xc0, 0x5e, 0x3b, 0x3b, 0x2f, 0x5f, 0x9f, 0x41, 0x89, 0x06, 0x75, 0x04, 0x48, 0x10, 0x44, 0x71,
-	0x53, 0x2e, 0x00, 0x09, 0xee, 0x42, 0x1d, 0x1d, 0xe1, 0xff, 0x96, 0x04, 0xc3, 0xb2, 0x6d, 0x3a,
-	0xe4, 0xa2, 0x5f, 0x93, 0xee, 0x0e, 0xe4, 0x86, 0xe2, 0x9f, 0x2b, 0x8b, 0x08, 0x11, 0x16, 0xf7,
-	0x17, 0x3e, 0xf1, 0xce, 0xe9, 0x55, 0x30, 0xf3, 0xa8, 0xe5, 0x0c, 0xdc, 0x30, 0x14, 0xc5, 0xa5,
-	0x94, 0xe1, 0xd8, 0x52, 0xe9, 0xd7, 0x09, 0xb8, 0xbe, 0x00, 0x81, 0x3e, 0x80, 0x74, 0xc0, 0xbc,
-	0x68, 0x7b, 0x6e, 0xbf, 0xea, 0x01, 0x46, 0xa8, 0x62, 0x89, 0x44, 0x1b, 0x00, 0x64, 0xc4, 0x19,
-	0x91, 0xe3, 0xcb, 0x8d, 0xc9, 0xe1, 0x29, 0x09, 0x7a, 0x0a, 0xd9, 0x90, 0xda, 0x01, 0x8d, 0xf8,
-	0xcc, 0xa7, 0xff, 0x5f, 0xef, 0x2b, 0x6d, 0x69, 0x06, 0x6b, 0x73, 0xa5, 0x0a, 0x64, 0x95, 0x44,
-	0x44, 0xb4, 0x43, 0x38, 0x91, 0x4e, 0x17, 0xb1, 0xfc, 0x2f, 0x02, 0x85, 0x78, 0xfd, 0x28, 0x50,
-	0x88, 0xd7, 0x37, 0x7f, 0x9e, 0x04, 0xa8, 0x3f, 0xe3, 0x34, 0xf0, 0x89, 0x57, 0xb5, 0x50, 0x7d,
-	0x2a, 0x43, 0xaa, 0xd9, 0xbe, 0xb3, 0xf0, 0x59, 0x2e, 0xd6, 0xa8, 0x54, 0xad, 0x05, 0x39, 0xf2,
-	0x16, 0xa4, 0x46, 0x81, 0xa7, 0x9f, 0x78, 0x25, 0x11, 0xe9, 0xe2, 0x5d, 0x2c, 0x64, 0xa8, 0x3e,
-	0xc9, 0x48, 0xa9, 0x57, 0xbf, 0xcd, 0x4f, 0x0d, 0xf0, 0xdd, 0x67, 0xa5, 0xf7, 0x00, 0x26, 0x5e,
-	0xa3, 0x0d, 0xc8, 0x54, 0x77, 0xda, 0xed, 0x5d, 0x63, 0x49, 0xd5, 0x88, 0x93, 0x2e, 0x29, 0x36,
-	0xff, 0x3e, 0x01, 0xb9, 0xaa, 0xa5, 0x6f, 0x95, 0x1d, 0x30, 0x64, 0x2e, 0xb1, 0x69, 0xc0, 0x7b,
-	0xf4, 0xd9, 0xd0, 0x0d, 0xc6, 0x3a, 0x1d, 0x5c, 0xce, 0xe2, 0x57, 0x85, 0x56, 0x95, 0x06, 0xbc,
-	0x2e, 0x75, 0x10, 0x86, 0x22, 0xd5, 0x53, 0xec, 0xd9, 0x24, 0x4a, 0xce, 0x1b, 0x97, 0x2f, 0x85,
-	0x62, 0x7f, 0x93, 0x76, 0x88, 0x0b, 0x91, 0x91, 0x2a, 0x09, 0xcd, 0x27, 0x70, 0x7d, 0x3f, 0xb0,
-	0x8f, 0x68, 0xc8, 0xd5, 0xa0, 0xda, 0xe5, 0x4f, 0xe1, 0x36, 0x27, 0xe1, 0x71, 0xef, 0xc8, 0x0d,
-	0x39, 0x0b, 0xc6, 0xbd, 0x80, 0x72, 0xea, 0x8b, 0xfe, 0x9e, 0xfc, 0x02, 0xa0, 0x6b, 0xf0, 0x5b,
-	0x02, 0xf3, 0x48, 0x41, 0x70, 0x84, 0xd8, 0x15, 0x00, 0xb3, 0x01, 0x45, 0x41, 0xd8, 0x6a, 0xf4,
-	0x90, 0x8c, 0x3c, 0x1e, 0xa2, 0x1f, 0x03, 0x78, 0xac, 0xdf, 0xbb, 0x72, 0x26, 0xcf, 0x7b, 0xac,
-	0xaf, 0xfe, 0x9a, 0xbf, 0x07, 0x46, 0xcd, 0x0d, 0x87, 0x84, 0xdb, 0x47, 0xd1, 0xe3, 0x02, 0x7a,
-	0x08, 0xc6, 0x11, 0x25, 0x01, 0x3f, 0xa0, 0x84, 0xf7, 0x86, 0x34, 0x70, 0x99, 0x73, 0xa5, 0x25,
-	0x5d, 0x8b, 0xb5, 0x5a, 0x52, 0xc9, 0xfc, 0x4d, 0x02, 0x00, 0x93, 0xc3, 0x88, 0x00, 0xfc, 0x00,
-	0xae, 0x85, 0x3e, 0x19, 0x86, 0x47, 0x8c, 0xf7, 0x5c, 0x9f, 0xd3, 0xe0, 0x84, 0x78, 0xba, 0x40,
-	0x34, 0xa2, 0x8e, 0x86, 0x96, 0xa3, 0xf7, 0x00, 0x1d, 0x53, 0x3a, 0xec, 0x31, 0xcf, 0xe9, 0x45,
-	0x9d, 0xea, 0x13, 0x45, 0x1a, 0x1b, 0xa2, 0x67, 0xdf, 0x73, 0xda, 0x91, 0x1c, 0x6d, 0xc3, 0x86,
-	0x58, 0x01, 0xea, 0xf3, 0xc0, 0xa5, 0x61, 0xef, 0x90, 0x05, 0xbd, 0xd0, 0x63, 0xa7, 0xbd, 0x43,
-	0xe6, 0x79, 0xec, 0x94, 0x06, 0x51, 0xf9, 0x5d, 0xf2, 0x58, 0xbf, 0xae, 0x40, 0x3b, 0x2c, 0x68,
-	0x7b, 0xec, 0x74, 0x27, 0x42, 0x08, 0x96, 0x30, 0x99, 0x36, 0x77, 0xed, 0xe3, 0x88, 0x25, 0xc4,
-	0xd2, 0x8e, 0x6b, 0x1f, 0xa3, 0x3b, 0xb0, 0x42, 0x3d, 0x2a, 0x8b, 0x38, 0x85, 0xca, 0x48, 0x54,
-	0x31, 0x12, 0x0a, 0x90, 0xf9, 0x3b, 0x90, 0x6f, 0x79, 0xc4, 0x96, 0x1f, 0x82, 0x44, 0x49, 0x6c,
-	0x33, 0x5f, 0x04, 0x81, 0xeb, 0x73, 0x95, 0x1d, 0xf3, 0x78, 0x5a, 0x64, 0xfe, 0x14, 0xe0, 0x67,
-	0xcc, 0xf5, 0x3b, 0xec, 0x98, 0xfa, 0xf2, 0xcd, 0x5c, 0xb0, 0x5e, 0xbd, 0x95, 0x79, 0xac, 0x5b,
-	0x92, 0x93, 0x13, 0x9f, 0xf4, 0x69, 0x10, 0x3f, 0x1d, 0xab, 0xa6, 0xb8, 0x5c, 0xb2, 0x98, 0x31,
-	0x5e, 0xb5, 0x50, 0x19, 0xb2, 0x36, 0xe9, 0x45, 0x27, 0xaf, 0xb8, 0x9d, 0xbf, 0x78, 0xb1, 0x99,
-	0xa9, 0x5a, 0x8f, 0xe9, 0x18, 0x67, 0x6c, 0xf2, 0x98, 0x8e, 0xc5, 0xed, 0x6b, 0x13, 0x79, 0x5e,
-	0xa4, 0x99, 0xa2, 0xba, 0x7d, 0xab, 0x96, 0x38, 0x0c, 0x38, 0x6b, 0x13, 0xf1, 0x8b, 0x3e, 0x80,
-	0xa2, 0x06, 0xf5, 0x8e, 0x48, 0x78, 0xa4, 0xb8, 0xea, 0xf6, 0xea, 0xc5, 0x8b, 0x4d, 0x50, 0xc8,
-	0x47, 0x24, 0x3c, 0xc2, 0xa0, 0xd0, 0xe2, 0x3f, 0xaa, 0x43, 0xe1, 0x0b, 0xe6, 0xfa, 0x3d, 0x2e,
-	0x27, 0xa1, 0x2b, 0xe9, 0x85, 0xe7, 0x67, 0x32, 0x55, 0x5d, 0xde, 0xc3, 0x17, 0xb1, 0xc4, 0xfc,
-	0xd7, 0x04, 0x14, 0x84, 0x4d, 0xf7, 0xd0, 0xb5, 0xc5, 0x6d, 0xf9, 0xed, 0x33, 0xfd, 0x2d, 0x48,
-	0xd9, 0x61, 0xa0, 0xe7, 0x26, 0x53, 0x5d, 0xb5, 0x8d, 0xb1, 0x90, 0xa1, 0xcf, 0x20, 0xab, 0x8a,
-	0x0b, 0x9d, 0xe4, 0xcd, 0x6f, 0xbe, 0xd7, 0xb5, 0x8b, 0x5a, 0x4f, 0xee, 0xe5, 0xc4, 0x3b, 0x39,
-	0xcb, 0x22, 0x9e, 0x16, 0xa1, 0x9b, 0x90, 0xb4, 0x7d, 0x19, 0x14, 0xfa, 0x5b, 0x5a, 0xb5, 0x89,
-	0x93, 0xb6, 0x6f, 0xfe, 0x73, 0x02, 0x56, 0xea, 0xbe, 0x1d, 0x8c, 0x65, 0x92, 0x14, 0x1b, 0x71,
-	0x1b, 0xf2, 0xe1, 0xe8, 0x20, 0x1c, 0x87, 0x9c, 0x0e, 0xa2, 0xa7, 0xfa, 0x58, 0x80, 0x1a, 0x90,
-	0x27, 0x5e, 0x9f, 0x05, 0x2e, 0x3f, 0x1a, 0x68, 0x6e, 0xbc, 0x38, 0x31, 0x4f, 0xdb, 0xac, 0x58,
-	0x91, 0x0a, 0x9e, 0x68, 0x47, 0xa9, 0x38, 0x25, 0x9d, 0x95, 0xa9, 0xf8, 0x4d, 0x28, 0x7a, 0x64,
-	0x20, 0xa8, 0x70, 0x4f, 0x94, 0x5c, 0x72, 0x1e, 0x69, 0x5c, 0xd0, 0x32, 0x51, 0x46, 0x9a, 0x26,
-	0xe4, 0x63, 0x63, 0x68, 0x0d, 0x0a, 0x56, 0xbd, 0xdd, 0xfb, 0x70, 0xeb, 0x7e, 0xef, 0x61, 0x75,
-	0xcf, 0x58, 0xd2, 0x4c, 0xe0, 0x1f, 0x13, 0xb0, 0xb2, 0xa7, 0x62, 0x50, 0x13, 0xa7, 0x3b, 0xb0,
-	0x1c, 0x90, 0x43, 0x1e, 0x51, 0xbb, 0xb4, 0x0a, 0x2e, 0x91, 0x04, 0x04, 0xb5, 0x13, 0x5d, 0x8b,
-	0xa9, 0xdd, 0xd4, 0x87, 0xa2, 0xd4, 0xa5, 0x1f, 0x8a, 0xd2, 0xdf, 0xc9, 0x87, 0x22, 0xf3, 0x57,
-	0x09, 0x58, 0xd3, 0x17, 0x75, 0xf4, 0x71, 0x04, 0xbd, 0x03, 0x79, 0x75, 0x67, 0x4f, 0x88, 0xa9,
-	0xfc, 0x5e, 0xa1, 0x70, 0x8d, 0x1a, 0xce, 0xa9, 0xee, 0x86, 0x83, 0x7e, 0x32, 0xf5, 0x2a, 0xfa,
-	0x0a, 0x7a, 0x38, 0x67, 0xbd, 0x32, 0x79, 0x2a, 0x7d, 0xe5, 0xf7, 0x92, 0x4d, 0x28, 0x68, 0x07,
-	0x64, 0xd9, 0xa0, 0xea, 0x40, 0x50, 0xa2, 0x26, 0x19, 0x50, 0xf3, 0x2e, 0xa4, 0x85, 0x19, 0x04,
-	0x90, 0x6d, 0x7f, 0xde, 0xee, 0xd4, 0xf7, 0x54, 0xe5, 0xb5, 0xd3, 0x90, 0x1f, 0xad, 0x96, 0x21,
-	0x55, 0x6f, 0x3e, 0x31, 0x92, 0xe6, 0xef, 0x43, 0x01, 0xd3, 0x01, 0x3b, 0xa1, 0x4e, 0x53, 0x0d,
-	0x97, 0x8c, 0x27, 0x24, 0x23, 0xb2, 0x51, 0xc3, 0x49, 0xd7, 0x41, 0x3f, 0x82, 0xac, 0xbe, 0x30,
-	0xaf, 0xf4, 0x04, 0xa4, 0xc1, 0xef, 0xfe, 0x26, 0x05, 0xf9, 0xf8, 0xbd, 0x40, 0x9c, 0x36, 0x41,
-	0x52, 0x97, 0xd4, 0xab, 0x61, 0x2c, 0x6f, 0x4a, 0x7a, 0x9a, 0xb7, 0x76, 0x77, 0xf7, 0xab, 0x56,
-	0xa7, 0x5e, 0x33, 0x3e, 0x53, 0x2c, 0x36, 0x06, 0x58, 0x9e, 0xc7, 0xc4, 0x79, 0x71, 0x90, 0x39,
-	0x61, 0xb1, 0xcf, 0xf5, 0xdb, 0x64, 0x8c, 0x8a, 0x28, 0xec, 0x5b, 0x90, 0xb3, 0xda, 0xed, 0xc6,
-	0xc3, 0x66, 0xbd, 0x66, 0x7c, 0x99, 0x28, 0x7d, 0xef, 0xec, 0xbc, 0x7c, 0x6d, 0x62, 0x2a, 0x0c,
-	0xdd, 0xbe, 0x4f, 0x1d, 0x89, 0xaa, 0x56, 0xeb, 0x2d, 0x31, 0xde, 0xf3, 0xe4, 0x3c, 0x4a, 0x72,
-	0x37, 0xf9, 0x9d, 0x21, 0xdf, 0xc2, 0xf5, 0x96, 0x85, 0xc5, 0x88, 0x5f, 0x26, 0xe7, 0xfc, 0x6a,
-	0x05, 0x74, 0x48, 0x02, 0x31, 0xe6, 0x46, 0xf4, 0xbd, 0xed, 0x79, 0x4a, 0xbd, 0x45, 0x4f, 0x1e,
-	0x49, 0x28, 0x71, 0xc6, 0x62, 0x34, 0xf9, 0xb8, 0x24, 0xcd, 0xa4, 0xe6, 0x46, 0x6b, 0x73, 0x12,
-	0x70, 0x61, 0xc5, 0x84, 0x65, 0xdc, 0x6d, 0x36, 0xe5, 0xec, 0xd2, 0x73, 0xb3, 0xc3, 0x23, 0xdf,
-	0x17, 0x98, 0xbb, 0x90, 0x8b, 0xde, 0x9e, 0x8c, 0x2f, 0xd3, 0x73, 0x0e, 0x55, 0xa3, 0x87, 0x33,
-	0x39, 0xe0, 0xa3, 0x6e, 0x47, 0x7e, 0x0e, 0x7c, 0x9e, 0x99, 0x1f, 0xf0, 0x68, 0xc4, 0x1d, 0x51,
-	0x37, 0x94, 0x63, 0x22, 0xff, 0x65, 0x46, 0xf1, 0xa7, 0x18, 0xa3, 0x58, 0xbc, 0xb0, 0x83, 0xeb,
-	0x3f, 0x53, 0x5f, 0x0e, 0x9f, 0x67, 0xe7, 0xec, 0x60, 0xfa, 0x05, 0xb5, 0x39, 0x75, 0x26, 0x4f,
-	0xed, 0x71, 0xd7, 0xbb, 0x7f, 0x00, 0xb9, 0x28, 0xd7, 0xa2, 0x0d, 0xc8, 0x3e, 0xdd, 0xc7, 0x8f,
-	0xeb, 0xd8, 0x58, 0x52, 0xab, 0x13, 0xf5, 0x3c, 0x55, 0x97, 0x55, 0x19, 0x96, 0xf7, 0xac, 0xa6,
-	0xf5, 0xb0, 0x8e, 0xa3, 0xa7, 0xfe, 0x08, 0xa0, 0x13, 0x46, 0xc9, 0xd0, 0x03, 0xc4, 0x36, 0xb7,
-	0x6f, 0x7f, 0xf5, 0xf5, 0xc6, 0xd2, 0x2f, 0xbf, 0xde, 0x58, 0xfa, 0xf5, 0xd7, 0x1b, 0x89, 0xe7,
-	0x17, 0x1b, 0x89, 0xaf, 0x2e, 0x36, 0x12, 0xbf, 0xb8, 0xd8, 0x48, 0xfc, 0xc7, 0xc5, 0x46, 0xe2,
-	0x20, 0x2b, 0xc9, 0xec, 0x47, 0xff, 0x17, 0x00, 0x00, 0xff, 0xff, 0x1f, 0x9b, 0xee, 0x67, 0xfb,
-	0x22, 0x00, 0x00,
+	0xc8, 0x21, 0xff, 0x40, 0x80, 0x9c, 0x7c, 0xf4, 0x2d, 0x9b, 0x04, 0x08, 0x16, 0x1b, 0x64, 0x10,
+	0x2b, 0xe7, 0x00, 0x7b, 0x09, 0x72, 0x48, 0x0e, 0x41, 0x7d, 0x74, 0xb3, 0xc9, 0xa1, 0x34, 0xe3,
+	0xac, 0x2f, 0x64, 0xd7, 0xab, 0xdf, 0x7b, 0xf5, 0xaa, 0xea, 0xd5, 0xab, 0x5f, 0x55, 0x41, 0x81,
+	0x4d, 0x46, 0x34, 0xa8, 0x8c, 0x7c, 0x8f, 0x79, 0x08, 0x59, 0x9e, 0x79, 0x4c, 0xfd, 0x4a, 0x70,
+	0x4a, 0xfc, 0xe1, 0xb1, 0xcd, 0x2a, 0x27, 0x1f, 0x95, 0x6e, 0x31, 0x7b, 0x48, 0x03, 0x46, 0x86,
+	0xa3, 0x0f, 0xa2, 0x2f, 0x09, 0x2f, 0xbd, 0x61, 0x8d, 0x7d, 0xc2, 0x6c, 0xcf, 0xfd, 0x20, 0xfc,
+	0x50, 0x15, 0x37, 0x06, 0xde, 0xc0, 0x13, 0x9f, 0x1f, 0xf0, 0x2f, 0x29, 0xd5, 0x37, 0x61, 0xf9,
+	0x09, 0xf5, 0x03, 0xdb, 0x73, 0xd1, 0x0d, 0xc8, 0xd8, 0xae, 0x45, 0x9f, 0xad, 0x27, 0xca, 0x89,
+	0x7b, 0x69, 0x2c, 0x0b, 0xfa, 0x5f, 0x26, 0xa0, 0x60, 0xb8, 0xae, 0xc7, 0x84, 0xad, 0x00, 0x21,
+	0x48, 0xbb, 0x64, 0x48, 0x05, 0x28, 0x8f, 0xc5, 0x37, 0xaa, 0x42, 0xd6, 0x21, 0x07, 0xd4, 0x09,
+	0xd6, 0x93, 0xe5, 0xd4, 0xbd, 0xc2, 0xd6, 0x0f, 0x2a, 0x2f, 0xfb, 0x5c, 0x89, 0x19, 0xa9, 0xec,
+	0x09, 0x74, 0xdd, 0x65, 0xfe, 0x04, 0x2b, 0xd5, 0xd2, 0x8f, 0xa1, 0x10, 0x13, 0x23, 0x0d, 0x52,
+	0xc7, 0x74, 0xa2, 0x9a, 0xe1, 0x9f, 0xdc, 0xbf, 0x13, 0xe2, 0x8c, 0xe9, 0x7a, 0x52, 0xc8, 0x64,
+	0xe1, 0xd3, 0xe4, 0x83, 0x84, 0xfe, 0x05, 0xe4, 0x31, 0x0d, 0xbc, 0xb1, 0x6f, 0xd2, 0x00, 0xbd,
+	0x07, 0x79, 0x97, 0xb8, 0x5e, 0xdf, 0x1c, 0x8d, 0x03, 0xa1, 0x9e, 0xda, 0x2e, 0x5e, 0xbc, 0xd8,
+	0xcc, 0x35, 0x89, 0xeb, 0x55, 0xdb, 0xbd, 0x00, 0xe7, 0x78, 0x75, 0x75, 0x34, 0x0e, 0xd0, 0xdb,
+	0x50, 0x1c, 0xd2, 0xa1, 0xe7, 0x4f, 0xfa, 0x07, 0x13, 0x46, 0x03, 0x61, 0x38, 0x85, 0x0b, 0x52,
+	0xb6, 0xcd, 0x45, 0xfa, 0x9f, 0x27, 0xe0, 0x46, 0x68, 0x1b, 0xd3, 0xdf, 0x1b, 0xdb, 0x3e, 0x1d,
+	0x52, 0x97, 0x05, 0xe8, 0x47, 0x90, 0x75, 0xec, 0xa1, 0xcd, 0x64, 0x1b, 0x85, 0xad, 0xb7, 0x16,
+	0xf5, 0x39, 0xf2, 0x0a, 0x2b, 0x30, 0x32, 0xa0, 0xe8, 0xd3, 0x80, 0xfa, 0x27, 0x72, 0x24, 0x44,
+	0x93, 0xaf, 0x54, 0x9e, 0x51, 0xd1, 0x77, 0x20, 0xd7, 0x76, 0x08, 0x3b, 0xf4, 0xfc, 0x21, 0xd2,
+	0xa1, 0x48, 0x7c, 0xf3, 0xc8, 0x66, 0xd4, 0x64, 0x63, 0x3f, 0x9c, 0x95, 0x19, 0x19, 0xba, 0x09,
+	0x49, 0x4f, 0x36, 0x94, 0xdf, 0xce, 0x5e, 0xbc, 0xd8, 0x4c, 0xb6, 0x3a, 0x38, 0xe9, 0x05, 0xfa,
+	0x43, 0xb8, 0xd6, 0x76, 0xc6, 0x03, 0xdb, 0xad, 0xd1, 0xc0, 0xf4, 0xed, 0x11, 0xb7, 0xce, 0xa7,
+	0x97, 0x07, 0x5f, 0x38, 0xbd, 0xfc, 0x3b, 0x9a, 0xf2, 0xe4, 0x74, 0xca, 0xf5, 0x3f, 0x4d, 0xc2,
+	0xb5, 0xba, 0x3b, 0xb0, 0x5d, 0x1a, 0xd7, 0xbe, 0x0b, 0xab, 0x54, 0x08, 0xfb, 0x27, 0x32, 0xa8,
+	0x94, 0x9d, 0x15, 0x29, 0x0d, 0x23, 0xad, 0x31, 0x17, 0x2f, 0x1f, 0x2d, 0xea, 0xfe, 0x4b, 0xd6,
+	0x17, 0x45, 0x0d, 0xaa, 0xc3, 0xf2, 0x48, 0x74, 0x22, 0x58, 0x4f, 0x09, 0x5b, 0x77, 0x17, 0xd9,
+	0x7a, 0xa9, 0x9f, 0xdb, 0xe9, 0xaf, 0x5f, 0x6c, 0x2e, 0xe1, 0x50, 0xf7, 0x37, 0x09, 0xbe, 0xff,
+	0x48, 0xc0, 0x5a, 0xd3, 0xb3, 0x66, 0xc6, 0xa1, 0x04, 0xb9, 0x23, 0x2f, 0x60, 0xb1, 0x85, 0x12,
+	0x95, 0xd1, 0x03, 0xc8, 0x8d, 0xd4, 0xf4, 0xa9, 0xd9, 0xbf, 0xbd, 0xd8, 0x65, 0x89, 0xc1, 0x11,
+	0x1a, 0x3d, 0x84, 0xbc, 0x1f, 0xc6, 0xc4, 0x7a, 0xea, 0x75, 0x02, 0x67, 0x8a, 0x47, 0xbf, 0x0d,
+	0x59, 0x39, 0x09, 0xeb, 0x69, 0xa1, 0x79, 0xf7, 0xb5, 0xc6, 0x1c, 0x2b, 0x25, 0xfd, 0x97, 0x09,
+	0xd0, 0x30, 0x39, 0x64, 0xfb, 0x74, 0x78, 0x40, 0xfd, 0x0e, 0x23, 0x6c, 0x1c, 0xa0, 0x9b, 0x90,
+	0x75, 0x28, 0xb1, 0xa8, 0x2f, 0x3a, 0x99, 0xc3, 0xaa, 0x84, 0x7a, 0x3c, 0xc8, 0x89, 0x79, 0x44,
+	0x0e, 0x6c, 0xc7, 0x66, 0x13, 0xd1, 0xcd, 0xd5, 0xc5, 0xb3, 0x3c, 0x6f, 0xb3, 0x82, 0x63, 0x8a,
+	0x78, 0xc6, 0x0c, 0x5a, 0x87, 0xe5, 0x21, 0x0d, 0x02, 0x32, 0xa0, 0xa2, 0xf7, 0x79, 0x1c, 0x16,
+	0xf5, 0x87, 0x50, 0x8c, 0xeb, 0xa1, 0x02, 0x2c, 0xf7, 0x9a, 0x8f, 0x9b, 0xad, 0xa7, 0x4d, 0x6d,
+	0x09, 0xad, 0x41, 0xa1, 0xd7, 0xc4, 0x75, 0xa3, 0xba, 0x6b, 0x6c, 0xef, 0xd5, 0xb5, 0x04, 0x5a,
+	0x81, 0xfc, 0xb4, 0x98, 0xd4, 0x7f, 0x9e, 0x00, 0xe0, 0x13, 0xa8, 0x3a, 0xf5, 0x29, 0x64, 0x02,
+	0x46, 0x98, 0x9c, 0xb8, 0xd5, 0xad, 0x77, 0x16, 0x79, 0x3d, 0x85, 0x57, 0xf8, 0x1f, 0xc5, 0x52,
+	0x25, 0xee, 0x61, 0x72, 0xde, 0xc3, 0x8c, 0x40, 0xce, 0xba, 0x96, 0x83, 0x74, 0x8d, 0x7f, 0x25,
+	0x50, 0x1e, 0x32, 0xb8, 0x6e, 0xd4, 0xbe, 0xd0, 0x92, 0x48, 0x83, 0x62, 0xad, 0xd1, 0xa9, 0xb6,
+	0x9a, 0xcd, 0x7a, 0xb5, 0x5b, 0xaf, 0x69, 0x29, 0xfd, 0x2e, 0x64, 0x1a, 0x43, 0x32, 0xa0, 0xe8,
+	0x36, 0x8f, 0x80, 0x43, 0xea, 0x53, 0xd7, 0x0c, 0x03, 0x6b, 0x2a, 0xd0, 0x7f, 0x91, 0x87, 0xcc,
+	0xbe, 0x37, 0x76, 0x19, 0xda, 0x8a, 0xad, 0xe2, 0xd5, 0xad, 0x8d, 0x45, 0x5d, 0x10, 0xc0, 0x4a,
+	0x77, 0x32, 0xa2, 0x6a, 0x95, 0xdf, 0x84, 0xac, 0x8c, 0x15, 0xe5, 0xba, 0x2a, 0x71, 0x39, 0x23,
+	0xfe, 0x80, 0x32, 0x35, 0xe8, 0xaa, 0x84, 0xee, 0x41, 0xce, 0xa7, 0xc4, 0xf2, 0x5c, 0x67, 0x22,
+	0x42, 0x2a, 0x27, 0xd3, 0x2c, 0xa6, 0xc4, 0x6a, 0xb9, 0xce, 0x04, 0x47, 0xb5, 0x68, 0x17, 0x8a,
+	0x07, 0xb6, 0x6b, 0xf5, 0xbd, 0x91, 0xcc, 0x79, 0x99, 0xcb, 0x03, 0x50, 0x7a, 0xb5, 0x6d, 0xbb,
+	0x56, 0x4b, 0x82, 0x71, 0xe1, 0x60, 0x5a, 0x40, 0x4d, 0x58, 0x3d, 0xf1, 0x9c, 0xf1, 0x90, 0x46,
+	0xb6, 0xb2, 0xc2, 0xd6, 0xbb, 0x97, 0xdb, 0x7a, 0x22, 0xf0, 0xa1, 0xb5, 0x95, 0x93, 0x78, 0x11,
+	0x3d, 0x86, 0x15, 0x36, 0x1c, 0x1d, 0x06, 0x91, 0xb9, 0x65, 0x61, 0xee, 0xfb, 0x57, 0x0c, 0x18,
+	0x87, 0x87, 0xd6, 0x8a, 0x2c, 0x56, 0x2a, 0xfd, 0x71, 0x0a, 0x0a, 0x31, 0xcf, 0x51, 0x07, 0x0a,
+	0x23, 0xdf, 0x1b, 0x91, 0x81, 0xc8, 0xdb, 0x6a, 0x2e, 0x3e, 0x7a, 0xad, 0x5e, 0x57, 0xda, 0x53,
+	0x45, 0x1c, 0xb7, 0xa2, 0x9f, 0x27, 0xa1, 0x10, 0xab, 0x44, 0xf7, 0x21, 0x87, 0xdb, 0xb8, 0xf1,
+	0xc4, 0xe8, 0xd6, 0xb5, 0xa5, 0xd2, 0xed, 0xb3, 0xf3, 0xf2, 0xba, 0xb0, 0x16, 0x37, 0xd0, 0xf6,
+	0xed, 0x13, 0x1e, 0x7a, 0xf7, 0x60, 0x39, 0x84, 0x26, 0x4a, 0x6f, 0x9e, 0x9d, 0x97, 0xdf, 0x98,
+	0x87, 0xc6, 0x90, 0xb8, 0xb3, 0x6b, 0xe0, 0x7a, 0x4d, 0x4b, 0x2e, 0x46, 0xe2, 0xce, 0x11, 0xf1,
+	0xa9, 0x85, 0xbe, 0x0f, 0x59, 0x05, 0x4c, 0x95, 0x4a, 0x67, 0xe7, 0xe5, 0x9b, 0xf3, 0xc0, 0x29,
+	0x0e, 0x77, 0xf6, 0x8c, 0x27, 0x75, 0x2d, 0xbd, 0x18, 0x87, 0x3b, 0x0e, 0x39, 0xa1, 0xe8, 0x1d,
+	0xc8, 0x48, 0x58, 0xa6, 0x74, 0xeb, 0xec, 0xbc, 0xfc, 0xbd, 0x97, 0xcc, 0x71, 0x54, 0x69, 0xfd,
+	0xcf, 0xfe, 0x6a, 0x63, 0xe9, 0xef, 0xff, 0x7a, 0x43, 0x9b, 0xaf, 0x2e, 0xfd, 0x6f, 0x02, 0x56,
+	0x66, 0xa6, 0x1c, 0xe9, 0x90, 0x75, 0x3d, 0xd3, 0x1b, 0xc9, 0x74, 0x9e, 0xdb, 0x86, 0x8b, 0x17,
+	0x9b, 0xd9, 0xa6, 0x57, 0xf5, 0x46, 0x13, 0xac, 0x6a, 0xd0, 0xe3, 0xb9, 0x0d, 0xe9, 0xe3, 0xd7,
+	0x8c, 0xa7, 0x85, 0x5b, 0xd2, 0x67, 0xb0, 0x62, 0xf9, 0xf6, 0x09, 0xf5, 0xfb, 0xa6, 0xe7, 0x1e,
+	0xda, 0x03, 0x95, 0xaa, 0x4b, 0x8b, 0x6c, 0xd6, 0x04, 0x10, 0x17, 0xa5, 0x42, 0x55, 0xe0, 0x7f,
+	0x83, 0xcd, 0xa8, 0xf4, 0x04, 0x8a, 0xf1, 0x08, 0x45, 0x6f, 0x01, 0x04, 0xf6, 0xef, 0x53, 0xc5,
+	0x6f, 0x04, 0x1b, 0xc2, 0x79, 0x2e, 0x11, 0xec, 0x06, 0xbd, 0x0b, 0xe9, 0xa1, 0x67, 0x49, 0x3b,
+	0x99, 0xed, 0xeb, 0x7c, 0x4f, 0xfc, 0xd5, 0x8b, 0xcd, 0x82, 0x17, 0x54, 0x76, 0x6c, 0x87, 0xee,
+	0x7b, 0x16, 0xc5, 0x02, 0xa0, 0x9f, 0x40, 0x9a, 0xa7, 0x0a, 0xf4, 0x26, 0xa4, 0xb7, 0x1b, 0xcd,
+	0x9a, 0xb6, 0x54, 0xba, 0x76, 0x76, 0x5e, 0x5e, 0x11, 0x43, 0xc2, 0x2b, 0x78, 0xec, 0xa2, 0x4d,
+	0xc8, 0x3e, 0x69, 0xed, 0xf5, 0xf6, 0x79, 0x78, 0x5d, 0x3f, 0x3b, 0x2f, 0xaf, 0x45, 0xd5, 0x72,
+	0xd0, 0xd0, 0x5b, 0x90, 0xe9, 0xee, 0xb7, 0x77, 0x3a, 0x5a, 0xb2, 0x84, 0xce, 0xce, 0xcb, 0xab,
+	0x51, 0xbd, 0xf0, 0xb9, 0x74, 0x4d, 0xcd, 0x6a, 0x3e, 0x92, 0xeb, 0xff, 0x93, 0x84, 0x15, 0xcc,
+	0xf9, 0xad, 0xcf, 0xda, 0x9e, 0x63, 0x9b, 0x13, 0xd4, 0x86, 0xbc, 0xe9, 0xb9, 0x96, 0x1d, 0x5b,
+	0x53, 0x5b, 0x97, 0x6c, 0x82, 0x53, 0xad, 0xb0, 0x54, 0x0d, 0x35, 0xf1, 0xd4, 0x08, 0xda, 0x82,
+	0x8c, 0x45, 0x1d, 0x32, 0xb9, 0x6a, 0x37, 0xae, 0x29, 0x2e, 0x8d, 0x25, 0x54, 0x30, 0x47, 0xf2,
+	0xac, 0x4f, 0x18, 0xa3, 0xc3, 0x11, 0x93, 0xbb, 0x71, 0x1a, 0x17, 0x86, 0xe4, 0x99, 0xa1, 0x44,
+	0xe8, 0x87, 0x90, 0x3d, 0xb5, 0x5d, 0xcb, 0x3b, 0x55, 0x1b, 0xee, 0xd5, 0x76, 0x15, 0x56, 0x3f,
+	0xe3, 0xfb, 0xec, 0x9c, 0xb3, 0x7c, 0xd4, 0x9b, 0xad, 0x66, 0x3d, 0x1c, 0x75, 0x55, 0xdf, 0x72,
+	0x9b, 0x9e, 0xcb, 0x57, 0x0c, 0xb4, 0x9a, 0xfd, 0x1d, 0xa3, 0xb1, 0xd7, 0xc3, 0x7c, 0xe4, 0x6f,
+	0x9c, 0x9d, 0x97, 0xb5, 0x08, 0xb2, 0x43, 0x6c, 0x87, 0x93, 0xc0, 0x5b, 0x90, 0x32, 0x9a, 0x5f,
+	0x68, 0xc9, 0x92, 0x76, 0x76, 0x5e, 0x2e, 0x46, 0xd5, 0x86, 0x3b, 0x99, 0x2e, 0xa6, 0xf9, 0x76,
+	0xf5, 0x7f, 0x4b, 0x42, 0xb1, 0x37, 0xb2, 0x08, 0xa3, 0x32, 0x32, 0x51, 0x19, 0x0a, 0x23, 0xe2,
+	0x13, 0xc7, 0xa1, 0x8e, 0x1d, 0x0c, 0xd5, 0x41, 0x21, 0x2e, 0x42, 0x0f, 0xbe, 0xc5, 0x60, 0x2a,
+	0x12, 0xa6, 0x86, 0xb4, 0x07, 0xab, 0x87, 0xd2, 0xd9, 0x3e, 0x31, 0xc5, 0xec, 0xa6, 0xc4, 0xec,
+	0x56, 0x16, 0x99, 0x88, 0x7b, 0x55, 0x51, 0x7d, 0x34, 0x84, 0x16, 0x5e, 0x39, 0x8c, 0x17, 0xd1,
+	0x27, 0xb0, 0x3c, 0xf4, 0x5c, 0x9b, 0x79, 0xfe, 0x6b, 0xcd, 0x43, 0x08, 0x46, 0xf7, 0xe1, 0x1a,
+	0x9f, 0xe1, 0xd0, 0x25, 0x51, 0x2d, 0x76, 0xae, 0x24, 0x5e, 0x1b, 0x92, 0x67, 0xaa, 0x4d, 0xcc,
+	0xc5, 0xfa, 0x27, 0xb0, 0x32, 0xe3, 0x03, 0xdf, 0xcd, 0xdb, 0x46, 0xaf, 0x53, 0xd7, 0x96, 0x50,
+	0x11, 0x72, 0xd5, 0x56, 0xb3, 0xdb, 0x68, 0xf6, 0x38, 0xf5, 0x28, 0x42, 0x0e, 0xb7, 0xf6, 0xf6,
+	0xb6, 0x8d, 0xea, 0x63, 0x2d, 0xa9, 0xff, 0x57, 0x34, 0xbe, 0x8a, 0x7b, 0x6c, 0xcf, 0x72, 0x8f,
+	0xf7, 0x2f, 0xef, 0xba, 0x62, 0x1f, 0xd3, 0x42, 0xc4, 0x41, 0x7e, 0x02, 0x20, 0xa6, 0x91, 0x5a,
+	0x7d, 0xc2, 0xae, 0x3a, 0x5f, 0x74, 0xc3, 0x93, 0x23, 0xce, 0x2b, 0x05, 0x83, 0xa1, 0xcf, 0xa1,
+	0x68, 0x7a, 0xc3, 0x91, 0x43, 0x95, 0x7e, 0xea, 0x75, 0xf4, 0x0b, 0x91, 0x8a, 0xc1, 0xe2, 0x1c,
+	0x28, 0x3d, 0xcb, 0x81, 0xfe, 0x24, 0x01, 0x85, 0x98, 0xc3, 0xb3, 0x54, 0xa8, 0x08, 0xb9, 0x5e,
+	0xbb, 0x66, 0x74, 0x1b, 0xcd, 0x47, 0x5a, 0x02, 0x01, 0x64, 0xc5, 0x00, 0xd6, 0xb4, 0x24, 0xa7,
+	0x6b, 0xd5, 0xd6, 0x7e, 0x7b, 0xaf, 0x2e, 0xc8, 0x10, 0xba, 0x01, 0x5a, 0x38, 0x84, 0xfd, 0x4e,
+	0xd7, 0xc0, 0x5c, 0x9a, 0x46, 0xd7, 0x61, 0x2d, 0x92, 0x2a, 0xcd, 0x0c, 0xba, 0x09, 0x28, 0x12,
+	0x4e, 0x4d, 0x64, 0xf5, 0x3f, 0x84, 0xb5, 0xaa, 0xe7, 0x32, 0x62, 0xbb, 0x11, 0x95, 0xdd, 0xe2,
+	0xfd, 0x56, 0xa2, 0xbe, 0x6d, 0xc9, 0x6c, 0xbb, 0xbd, 0x76, 0xf1, 0x62, 0xb3, 0x10, 0x41, 0x1b,
+	0x35, 0xde, 0xd3, 0xb0, 0x60, 0xf1, 0x35, 0x35, 0xb2, 0x2d, 0x95, 0x3c, 0x97, 0x2f, 0x5e, 0x6c,
+	0xa6, 0xda, 0x8d, 0x1a, 0xe6, 0x32, 0xf4, 0x26, 0xe4, 0xe9, 0x33, 0x9b, 0xf5, 0x4d, 0x9e, 0x5d,
+	0xf9, 0x18, 0x66, 0x70, 0x8e, 0x0b, 0xaa, 0x3c, 0x99, 0xfe, 0x51, 0x12, 0xa0, 0x4b, 0x82, 0x63,
+	0xd5, 0xf4, 0x43, 0xc8, 0x47, 0x87, 0xf8, 0xab, 0x0e, 0x93, 0xb1, 0xf9, 0x8a, 0xf0, 0xe8, 0xe3,
+	0x30, 0x62, 0x24, 0xc7, 0x5e, 0xac, 0xa8, 0xda, 0x5a, 0x44, 0x53, 0x67, 0x89, 0x34, 0xdf, 0x6b,
+	0xa8, 0xef, 0xab, 0x89, 0xe3, 0x9f, 0xa8, 0x2a, 0xf2, 0xad, 0xec, 0xb3, 0x62, 0x6e, 0x77, 0x16,
+	0x35, 0x32, 0x37, 0xa0, 0xbb, 0x4b, 0x78, 0xaa, 0xb7, 0xad, 0xc1, 0xaa, 0x3f, 0x76, 0xb9, 0xd7,
+	0xfd, 0x40, 0x54, 0xeb, 0x36, 0xbc, 0xd1, 0xa4, 0xec, 0xd4, 0xf3, 0x8f, 0x0d, 0xc6, 0x88, 0x79,
+	0xc4, 0x0f, 0xd5, 0x2a, 0xc9, 0x4c, 0x09, 0x67, 0x62, 0x86, 0x70, 0xae, 0xc3, 0x32, 0x71, 0x6c,
+	0x12, 0x50, 0xb9, 0x4b, 0xe7, 0x71, 0x58, 0xe4, 0xb4, 0x98, 0x58, 0x96, 0x4f, 0x83, 0x80, 0xca,
+	0x63, 0x60, 0x1e, 0x4f, 0x05, 0xfa, 0x3f, 0x27, 0x01, 0x1a, 0x6d, 0x63, 0x5f, 0x99, 0xaf, 0x41,
+	0xf6, 0x90, 0x0c, 0x6d, 0x67, 0x72, 0xd5, 0x22, 0x9b, 0xe2, 0x2b, 0x86, 0x34, 0xb4, 0x23, 0x74,
+	0xb0, 0xd2, 0x15, 0x6c, 0x79, 0x7c, 0xe0, 0x52, 0x16, 0xb1, 0x65, 0x51, 0xe2, 0x5b, 0xb3, 0x4f,
+	0xdc, 0x68, 0x60, 0x65, 0x81, 0xbb, 0x3e, 0x20, 0x8c, 0x9e, 0x92, 0x49, 0xb8, 0x26, 0x54, 0x11,
+	0xed, 0x72, 0x16, 0xcd, 0x0f, 0xf7, 0xd4, 0x5a, 0xcf, 0x08, 0xee, 0xf1, 0x2a, 0x7f, 0xb0, 0x82,
+	0x4b, 0xd2, 0x11, 0x69, 0x97, 0x1e, 0x8a, 0x9d, 0x72, 0x5a, 0xf5, 0xad, 0x0e, 0xb1, 0x1f, 0xc2,
+	0xca, 0x4c, 0x3f, 0x5f, 0x3a, 0xa6, 0x34, 0xda, 0x4f, 0x7e, 0xa8, 0xa5, 0xd5, 0xd7, 0x27, 0x5a,
+	0x56, 0xff, 0xdb, 0x14, 0x40, 0xdb, 0xf3, 0xc3, 0x49, 0x5b, 0x7c, 0x2d, 0x94, 0x13, 0x97, 0x4c,
+	0xa6, 0xe7, 0xa8, 0xf0, 0x5c, 0xc8, 0xd3, 0xa7, 0x56, 0x38, 0xed, 0x15, 0x70, 0x1c, 0x29, 0xa2,
+	0x4d, 0x28, 0xc8, 0xf9, 0xef, 0x8f, 0x3c, 0x5f, 0xe6, 0xa3, 0x15, 0x0c, 0x52, 0xc4, 0x35, 0xd1,
+	0x5d, 0x58, 0x1d, 0x8d, 0x0f, 0x1c, 0x3b, 0x38, 0xa2, 0x96, 0xc4, 0xa4, 0x05, 0x66, 0x25, 0x92,
+	0x0a, 0xd8, 0x3e, 0x14, 0x95, 0xa0, 0x2f, 0x28, 0x4f, 0x46, 0x38, 0x74, 0xff, 0x55, 0x0e, 0x49,
+	0x15, 0xc1, 0x84, 0x0a, 0xa3, 0x69, 0x41, 0xaf, 0x41, 0x2e, 0x74, 0x16, 0xad, 0x43, 0xaa, 0x5b,
+	0x6d, 0x6b, 0x4b, 0xa5, 0xb5, 0xb3, 0xf3, 0x72, 0x21, 0x14, 0x77, 0xab, 0x6d, 0x5e, 0xd3, 0xab,
+	0xb5, 0xb5, 0xc4, 0x6c, 0x4d, 0xaf, 0xd6, 0x2e, 0xa5, 0xf9, 0xa6, 0xab, 0x1f, 0x42, 0x21, 0xd6,
+	0x02, 0xba, 0x03, 0xcb, 0x8d, 0xe6, 0x23, 0x5c, 0xef, 0x74, 0xb4, 0xa5, 0xd2, 0xcd, 0xb3, 0xf3,
+	0x32, 0x8a, 0xd5, 0x36, 0xdc, 0x01, 0x9f, 0x1f, 0xf4, 0x16, 0xa4, 0x77, 0x5b, 0x9d, 0x6e, 0xc8,
+	0xb1, 0x62, 0x88, 0x5d, 0x2f, 0x60, 0xa5, 0xeb, 0x6a, 0x37, 0x8f, 0x1b, 0xd6, 0xff, 0x22, 0x01,
+	0x59, 0x49, 0x35, 0x17, 0x4e, 0x94, 0x01, 0xcb, 0xe1, 0x01, 0x48, 0xf2, 0xdf, 0x77, 0x2f, 0xe7,
+	0xaa, 0x15, 0x45, 0x2d, 0x65, 0xf8, 0x85, 0x7a, 0xa5, 0x4f, 0xa1, 0x18, 0xaf, 0xf8, 0x56, 0xc1,
+	0xf7, 0x07, 0x50, 0xe0, 0xf1, 0x1d, 0x72, 0xd6, 0x2d, 0xc8, 0x4a, 0x3a, 0xac, 0x92, 0xe1, 0x55,
+	0xc4, 0x59, 0x21, 0xd1, 0x03, 0x58, 0x96, 0x64, 0x3b, 0xbc, 0x06, 0xda, 0xb8, 0x7a, 0x15, 0xe1,
+	0x10, 0xae, 0x7f, 0x06, 0xe9, 0x36, 0xa5, 0x3e, 0x1f, 0x7b, 0xd7, 0xb3, 0xe8, 0x34, 0xf7, 0xab,
+	0x73, 0x82, 0x45, 0x1b, 0x35, 0x7e, 0x4e, 0xb0, 0x68, 0xc3, 0xe2, 0x83, 0xc7, 0xf3, 0x4a, 0x78,
+	0x13, 0xc6, 0xbf, 0xf5, 0x2e, 0x14, 0x9f, 0x52, 0x7b, 0x70, 0xc4, 0xa8, 0x25, 0x0c, 0xbd, 0x0f,
+	0xe9, 0x11, 0x8d, 0x9c, 0x5f, 0x5f, 0x18, 0x60, 0x94, 0xfa, 0x58, 0xa0, 0x78, 0x1e, 0x39, 0x15,
+	0xda, 0xea, 0xf2, 0x51, 0x95, 0xf4, 0x7f, 0x4a, 0xc2, 0x6a, 0x23, 0x08, 0xc6, 0xc4, 0x35, 0x43,
+	0x72, 0xf0, 0xd3, 0x59, 0x72, 0x70, 0x6f, 0x61, 0x0f, 0x67, 0x54, 0x66, 0x2f, 0x27, 0x54, 0x6e,
+	0x4f, 0x46, 0xb9, 0x5d, 0xff, 0xcf, 0x44, 0x78, 0x2b, 0x71, 0x37, 0xb6, 0xdc, 0x4b, 0xeb, 0x67,
+	0xe7, 0xe5, 0x1b, 0x71, 0x4b, 0xb4, 0xe7, 0x1e, 0xbb, 0xde, 0xa9, 0x8b, 0xde, 0x86, 0x0c, 0xae,
+	0x37, 0xeb, 0x4f, 0xb5, 0x84, 0x0c, 0xcf, 0x19, 0x10, 0xa6, 0x2e, 0x3d, 0xe5, 0x96, 0xda, 0xf5,
+	0x66, 0x8d, 0x6f, 0xe3, 0xc9, 0x05, 0x96, 0xda, 0xd4, 0xb5, 0x6c, 0x77, 0x80, 0xee, 0x40, 0xb6,
+	0xd1, 0xe9, 0xf4, 0xc4, 0xb9, 0xf1, 0x8d, 0xb3, 0xf3, 0xf2, 0xf5, 0x19, 0x14, 0x2f, 0x50, 0x8b,
+	0x83, 0x38, 0xaf, 0xe5, 0x1b, 0xfc, 0x02, 0x10, 0xa7, 0x5c, 0x12, 0x84, 0x5b, 0x5d, 0x7e, 0xa8,
+	0xcd, 0x2c, 0x00, 0x61, 0x8f, 0xff, 0xaa, 0xe5, 0xf6, 0xaf, 0x49, 0xd0, 0x0c, 0xd3, 0xa4, 0x23,
+	0xc6, 0xeb, 0xd5, 0x81, 0xa2, 0x0b, 0xb9, 0x11, 0xff, 0xb2, 0xc5, 0x01, 0x89, 0xc7, 0xce, 0x83,
+	0x85, 0xd7, 0xd7, 0x73, 0x7a, 0x15, 0xec, 0x39, 0xd4, 0xb0, 0x86, 0x76, 0x10, 0xf0, 0x83, 0xb3,
+	0x90, 0xe1, 0xc8, 0x52, 0xe9, 0xd7, 0x09, 0xb8, 0xbe, 0x00, 0x81, 0x3e, 0x84, 0xb4, 0xef, 0x39,
+	0xe1, 0x1c, 0xde, 0xbe, 0xec, 0x72, 0x89, 0xab, 0x62, 0x81, 0x44, 0x1b, 0x00, 0x64, 0xcc, 0x3c,
+	0x22, 0xda, 0x17, 0xb3, 0x97, 0xc3, 0x31, 0x09, 0x7a, 0x0a, 0xd9, 0x80, 0x9a, 0x3e, 0x0d, 0xb9,
+	0xda, 0x67, 0xff, 0x5f, 0xef, 0x2b, 0x1d, 0x61, 0x06, 0x2b, 0x73, 0xa5, 0x0a, 0x64, 0xa5, 0x84,
+	0x87, 0xbd, 0x45, 0x18, 0x11, 0x4e, 0x17, 0xb1, 0xf8, 0xe6, 0xd1, 0x44, 0x9c, 0x41, 0x18, 0x4d,
+	0xc4, 0x19, 0xe8, 0x3f, 0x4f, 0x02, 0xd4, 0x9f, 0x31, 0xea, 0xbb, 0xc4, 0xa9, 0x1a, 0xa8, 0x1e,
+	0xcb, 0xfe, 0xb2, 0xb7, 0xef, 0x2d, 0xbc, 0x72, 0x8c, 0x34, 0x2a, 0x55, 0x63, 0x41, 0xfe, 0xbf,
+	0x05, 0xa9, 0xb1, 0xef, 0xa8, 0xeb, 0x6b, 0x41, 0xb2, 0x7a, 0x78, 0x0f, 0x73, 0x19, 0xaa, 0x4f,
+	0xd3, 0x56, 0xea, 0xf2, 0x77, 0x87, 0x58, 0x03, 0xdf, 0x7d, 0xea, 0x7a, 0x1f, 0x60, 0xea, 0x35,
+	0xda, 0x80, 0x4c, 0x75, 0xa7, 0xd3, 0xd9, 0xd3, 0x96, 0x64, 0x6e, 0x9e, 0x56, 0x09, 0xb1, 0xfe,
+	0x37, 0x09, 0xc8, 0x55, 0x0d, 0xb5, 0x63, 0xee, 0x80, 0x26, 0x12, 0x8e, 0x49, 0x7d, 0xd6, 0xa7,
+	0xcf, 0x46, 0xb6, 0x3f, 0x51, 0x39, 0xe3, 0xea, 0x13, 0xca, 0x2a, 0xd7, 0xaa, 0x52, 0x9f, 0xd5,
+	0x85, 0x0e, 0xc2, 0x50, 0xa4, 0xaa, 0x8b, 0x7d, 0x93, 0x84, 0x19, 0x7c, 0xe3, 0xea, 0xa1, 0x90,
+	0xcc, 0x76, 0x5a, 0x0e, 0x70, 0x21, 0x34, 0x52, 0x25, 0x81, 0xfe, 0x04, 0xae, 0xb7, 0x7c, 0xf3,
+	0x88, 0x06, 0x4c, 0x36, 0xaa, 0x5c, 0xfe, 0x0c, 0x6e, 0x33, 0x12, 0x1c, 0xf7, 0x8f, 0xec, 0x80,
+	0x79, 0xfe, 0xa4, 0xef, 0x53, 0x46, 0x5d, 0x5e, 0xdf, 0x17, 0xaf, 0x1b, 0xea, 0x7e, 0xe1, 0x16,
+	0xc7, 0xec, 0x4a, 0x08, 0x0e, 0x11, 0x7b, 0x1c, 0xa0, 0x37, 0xa0, 0xc8, 0xc9, 0x68, 0x8d, 0x1e,
+	0x92, 0xb1, 0xc3, 0x02, 0xf4, 0x63, 0x00, 0xc7, 0x1b, 0xf4, 0x5f, 0x3b, 0xdd, 0xe7, 0x1d, 0x6f,
+	0x20, 0x3f, 0xf5, 0xdf, 0x01, 0xad, 0x66, 0x07, 0x23, 0xc2, 0xcc, 0xa3, 0xf0, 0xe2, 0x04, 0x3d,
+	0x02, 0xed, 0x88, 0x12, 0x9f, 0x1d, 0x50, 0xc2, 0xfa, 0x23, 0xea, 0xdb, 0x9e, 0xf5, 0x5a, 0x43,
+	0xba, 0x16, 0x69, 0xb5, 0x85, 0x92, 0xfe, 0xdf, 0x09, 0x00, 0x4c, 0x0e, 0x43, 0x72, 0xf3, 0x03,
+	0xb8, 0x16, 0xb8, 0x64, 0x14, 0x1c, 0x79, 0xac, 0x6f, 0xbb, 0x8c, 0xfa, 0x27, 0xc4, 0x51, 0x87,
+	0x5f, 0x2d, 0xac, 0x68, 0x28, 0x39, 0x7a, 0x1f, 0xd0, 0x31, 0xa5, 0xa3, 0xbe, 0xe7, 0x58, 0xfd,
+	0xb0, 0x52, 0x3e, 0xbf, 0xa4, 0xb1, 0xc6, 0x6b, 0x5a, 0x8e, 0xd5, 0x09, 0xe5, 0x68, 0x1b, 0x36,
+	0xf8, 0x08, 0x50, 0x97, 0xf9, 0x36, 0x0d, 0xfa, 0x87, 0x9e, 0xdf, 0x0f, 0x1c, 0xef, 0xb4, 0x7f,
+	0xe8, 0x39, 0x8e, 0x77, 0x4a, 0xfd, 0xf0, 0x6a, 0xa1, 0xe4, 0x78, 0x83, 0xba, 0x04, 0xed, 0x78,
+	0x7e, 0xc7, 0xf1, 0x4e, 0x77, 0x42, 0x04, 0x67, 0x40, 0xd3, 0x6e, 0x33, 0xdb, 0x3c, 0x0e, 0x19,
+	0x50, 0x24, 0xed, 0xda, 0xe6, 0x31, 0xba, 0x03, 0x2b, 0xd4, 0xa1, 0xe2, 0x80, 0x2a, 0x51, 0x19,
+	0x81, 0x2a, 0x86, 0x42, 0x0e, 0xd2, 0x7f, 0x0b, 0xf2, 0x6d, 0x87, 0x98, 0xe2, 0x91, 0x8b, 0x1f,
+	0xf7, 0x4d, 0xcf, 0xe5, 0x41, 0x60, 0xbb, 0x4c, 0x66, 0xc7, 0x3c, 0x8e, 0x8b, 0xf4, 0x9f, 0x02,
+	0xfc, 0xcc, 0xb3, 0xdd, 0xae, 0x77, 0x4c, 0x5d, 0xf1, 0x1e, 0xc0, 0x19, 0xbd, 0x9a, 0xca, 0x3c,
+	0x56, 0x25, 0x71, 0xde, 0x20, 0x2e, 0x19, 0x50, 0x3f, 0xba, 0x16, 0x97, 0x45, 0xfd, 0xeb, 0x04,
+	0x64, 0xb1, 0xe7, 0xb1, 0xaa, 0x81, 0xca, 0x90, 0x35, 0x49, 0x3f, 0x5c, 0x79, 0xc5, 0xed, 0xfc,
+	0xc5, 0x8b, 0xcd, 0x4c, 0xd5, 0x78, 0x4c, 0x27, 0x38, 0x63, 0x92, 0xc7, 0x74, 0xc2, 0xb7, 0x68,
+	0x93, 0x88, 0xf5, 0x22, 0xcc, 0x14, 0xe5, 0x16, 0x5d, 0x35, 0xf8, 0x62, 0xc0, 0x59, 0x93, 0xf0,
+	0x7f, 0xf4, 0x21, 0x14, 0x15, 0xa8, 0x7f, 0x44, 0x82, 0x23, 0xc9, 0xc3, 0xb7, 0x57, 0x2f, 0x5e,
+	0x6c, 0x82, 0x44, 0xee, 0x92, 0xe0, 0x08, 0x83, 0x44, 0xf3, 0x6f, 0x54, 0x87, 0xc2, 0x97, 0x9e,
+	0xed, 0xf6, 0x99, 0xe8, 0x84, 0xba, 0x25, 0x58, 0xb8, 0x7e, 0xa6, 0x5d, 0x55, 0x57, 0x17, 0xf0,
+	0x65, 0x24, 0xd1, 0xff, 0x25, 0x01, 0x05, 0x6e, 0xd3, 0x3e, 0xb4, 0x4d, 0xbe, 0xa5, 0x7e, 0xfb,
+	0x4c, 0x7f, 0x0b, 0x52, 0x66, 0xe0, 0xab, 0xbe, 0x89, 0x54, 0x57, 0xed, 0x60, 0xcc, 0x65, 0xe8,
+	0x73, 0xc8, 0xca, 0x83, 0x93, 0x4a, 0xf2, 0xfa, 0xab, 0x37, 0x7f, 0xe5, 0xa2, 0xd2, 0x13, 0x73,
+	0x39, 0xf5, 0x4e, 0xf4, 0xb2, 0x88, 0xe3, 0x22, 0x74, 0x13, 0x92, 0xa6, 0x2b, 0x82, 0x42, 0xbd,
+	0x13, 0x56, 0x9b, 0x38, 0x69, 0xba, 0xfa, 0x3f, 0x26, 0x60, 0xa5, 0xee, 0x9a, 0xfe, 0x44, 0x24,
+	0x49, 0x3e, 0x11, 0xb7, 0x21, 0x1f, 0x8c, 0x0f, 0x82, 0x49, 0xc0, 0xe8, 0x30, 0x7c, 0x86, 0x88,
+	0x04, 0xa8, 0x01, 0x79, 0xe2, 0x0c, 0x3c, 0xdf, 0x66, 0x47, 0x43, 0xc5, 0xfb, 0x17, 0x27, 0xe6,
+	0xb8, 0xcd, 0x8a, 0x11, 0xaa, 0xe0, 0xa9, 0x76, 0x98, 0x8a, 0x53, 0xc2, 0x59, 0x91, 0x8a, 0xdf,
+	0x86, 0xa2, 0x43, 0x86, 0x9c, 0xe6, 0xf7, 0xf9, 0x71, 0x52, 0xf4, 0x23, 0x8d, 0x0b, 0x4a, 0xc6,
+	0x8f, 0xc8, 0xba, 0x0e, 0xf9, 0xc8, 0x18, 0x5a, 0x83, 0x82, 0x51, 0xef, 0xf4, 0x3f, 0xda, 0x7a,
+	0xd0, 0x7f, 0x54, 0xdd, 0xd7, 0x96, 0x14, 0x13, 0xf8, 0xbb, 0x04, 0xac, 0xec, 0xcb, 0x18, 0x54,
+	0xec, 0xea, 0x0e, 0x2c, 0xfb, 0xe4, 0x90, 0x85, 0xfc, 0x2f, 0x2d, 0x83, 0x8b, 0x27, 0x01, 0xce,
+	0xff, 0x78, 0xd5, 0x62, 0xfe, 0x17, 0x7b, 0x04, 0x4b, 0x5d, 0xf9, 0x08, 0x96, 0xfe, 0x4e, 0x1e,
+	0xc1, 0xf4, 0x5f, 0x25, 0x60, 0x4d, 0x6d, 0xd4, 0xe1, 0xc3, 0x0f, 0x7a, 0x0f, 0xf2, 0x72, 0xcf,
+	0x9e, 0xb2, 0x57, 0xf1, 0x16, 0x23, 0x71, 0x8d, 0x1a, 0xce, 0xc9, 0xea, 0x86, 0x85, 0x7e, 0x12,
+	0xbb, 0xf1, 0xbd, 0x84, 0x43, 0xce, 0x59, 0xaf, 0x4c, 0xaf, 0x81, 0x2f, 0x7d, 0x0b, 0xda, 0x84,
+	0x82, 0x72, 0x40, 0x9c, 0x2d, 0xe4, 0x19, 0x17, 0xa4, 0xa8, 0x49, 0x86, 0x54, 0xbf, 0x0b, 0x69,
+	0x71, 0xc2, 0x01, 0xc8, 0x76, 0xbe, 0xe8, 0x74, 0xeb, 0xfb, 0xf2, 0x54, 0xb9, 0xd3, 0x10, 0x0f,
+	0x72, 0xcb, 0x90, 0xaa, 0x37, 0x9f, 0x68, 0x49, 0xbd, 0x05, 0x37, 0xb7, 0x1d, 0x62, 0x1e, 0x3b,
+	0x76, 0xc0, 0xa8, 0x15, 0x5f, 0x4d, 0x3f, 0x82, 0xec, 0xcc, 0x1e, 0xf9, 0x8a, 0x1b, 0x12, 0x05,
+	0xbe, 0xff, 0x0f, 0x29, 0xc8, 0x47, 0xd7, 0x1f, 0x7c, 0x81, 0x71, 0xf2, 0xba, 0x24, 0x2f, 0x41,
+	0x23, 0x79, 0x93, 0x9e, 0xa2, 0xb7, 0xa7, 0xb4, 0xf5, 0x73, 0x79, 0x85, 0x1a, 0x55, 0x87, 0x94,
+	0xf5, 0x1d, 0xc8, 0x19, 0x9d, 0x4e, 0xe3, 0x51, 0xb3, 0x5e, 0xd3, 0xbe, 0x4a, 0x94, 0xbe, 0x77,
+	0x76, 0x5e, 0xbe, 0x16, 0x81, 0x8c, 0x20, 0xb0, 0x07, 0x2e, 0xb5, 0x04, 0xaa, 0x5a, 0xad, 0xb7,
+	0xbb, 0xf5, 0x9a, 0xf6, 0x3c, 0x39, 0x8f, 0x12, 0x34, 0x4c, 0x3c, 0x87, 0xe4, 0xdb, 0xb8, 0xde,
+	0x36, 0x30, 0x6f, 0xf0, 0xab, 0xa4, 0x64, 0xd3, 0xd3, 0x16, 0x7d, 0x3a, 0x22, 0x3e, 0x6f, 0x73,
+	0x23, 0x7c, 0x16, 0x7c, 0x9e, 0x92, 0x57, 0xe6, 0xd3, 0xbb, 0x1c, 0x4a, 0xac, 0x09, 0x6f, 0x4d,
+	0xdc, 0x81, 0x09, 0x33, 0xa9, 0xb9, 0xd6, 0x3a, 0x8c, 0xf8, 0x8c, 0x5b, 0xd1, 0x61, 0x19, 0xf7,
+	0x9a, 0x4d, 0x0e, 0x7a, 0x9e, 0x9e, 0xeb, 0x1d, 0x1e, 0xbb, 0x2e, 0xc7, 0xdc, 0x85, 0x5c, 0x78,
+	0x45, 0xa6, 0x7d, 0x95, 0x9e, 0x73, 0xa8, 0x1a, 0xde, 0xef, 0x89, 0x06, 0x77, 0x7b, 0x5d, 0xf1,
+	0x6a, 0xf9, 0x3c, 0x33, 0xdf, 0xe0, 0xd1, 0x98, 0x59, 0xfc, 0x9c, 0x50, 0x8e, 0x88, 0xfb, 0x57,
+	0x19, 0x49, 0x85, 0x22, 0x8c, 0x62, 0xed, 0xef, 0x40, 0x0e, 0xd7, 0x7f, 0x26, 0x1f, 0x38, 0x9f,
+	0x67, 0xe7, 0xec, 0x60, 0xfa, 0x25, 0x35, 0x19, 0xb5, 0xa6, 0x2f, 0x02, 0x51, 0xd5, 0xfd, 0xdf,
+	0x85, 0x5c, 0x98, 0x36, 0xd1, 0x06, 0x64, 0x9f, 0xb6, 0xf0, 0xe3, 0x3a, 0xd6, 0x96, 0xe4, 0xe8,
+	0x84, 0x35, 0x4f, 0xe5, 0xbe, 0x53, 0x86, 0xe5, 0x7d, 0xa3, 0x69, 0x3c, 0xaa, 0xe3, 0xf0, 0xb4,
+	0x1c, 0x02, 0xd4, 0xda, 0x2f, 0x69, 0xaa, 0x81, 0xc8, 0xe6, 0xf6, 0xed, 0xaf, 0xbf, 0xd9, 0x58,
+	0xfa, 0xe5, 0x37, 0x1b, 0x4b, 0xbf, 0xfe, 0x66, 0x23, 0xf1, 0xfc, 0x62, 0x23, 0xf1, 0xf5, 0xc5,
+	0x46, 0xe2, 0x17, 0x17, 0x1b, 0x89, 0x7f, 0xbf, 0xd8, 0x48, 0x1c, 0x64, 0x05, 0x2f, 0xfd, 0xf8,
+	0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0xb4, 0x2d, 0x4d, 0x67, 0xa2, 0x23, 0x00, 0x00,
 }

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

@@ -371,8 +371,7 @@ enum TaskState {
 	option (gogoproto.goproto_enum_prefix) = false;
 	option (gogoproto.enum_customname) = "TaskState";
 	NEW = 0 [(gogoproto.enumvalue_customname)="TaskStateNew"];
-	ALLOCATED = 64 [(gogoproto.enumvalue_customname)="TaskStateAllocated"]; // successful allocation of resources that the task needs
-	PENDING = 128 [(gogoproto.enumvalue_customname) = "TaskStatePending"]; // observed by scheduler but unassigned.
+	PENDING = 64 [(gogoproto.enumvalue_customname)="TaskStatePending"]; // waiting for scheduling decision
 	ASSIGNED = 192 [(gogoproto.enumvalue_customname)="TaskStateAssigned"];
 	ACCEPTED = 256 [(gogoproto.enumvalue_customname)="TaskStateAccepted"]; // task has been accepted by an agent.
 	PREPARING = 320 [(gogoproto.enumvalue_customname)="TaskStatePreparing"];
@@ -506,6 +505,21 @@ message PortConfig {
 		UDP = 1 [(gogoproto.enumvalue_customname) = "ProtocolUDP"];
 	}
 
+	// PublishMode controls how ports are published on the swarm.
+	enum PublishMode {
+		option (gogoproto.enum_customname) = "PublishMode";
+		option (gogoproto.goproto_enum_prefix) = false;
+
+		// PublishModeIngress exposes the port across the cluster on all nodes.
+		INGRESS = 0 [(gogoproto.enumvalue_customname) = "PublishModeIngress"];
+
+		// PublishModeHost exposes the port on just the target host.  If the
+		// published port is undefined, an ephemeral port will be allocated. If
+		// the published port is defined, the node will attempt to allocate it,
+		// erroring the task if it fails.
+		HOST = 1 [(gogoproto.enumvalue_customname) = "PublishModeHost"];
+	}
+
 	// Name for the port. If provided the port information can
 	// be queried using the name as in a DNS SRV query.
 	string name = 1;
@@ -516,11 +530,13 @@ message PortConfig {
 	// The port which the application is exposing and is bound to.
 	uint32 target_port = 3;
 
-	// PublishedPort specifies the port on which the service is
-	// exposed. If specified, the port must be
-	// within the available range. If not specified, an available
-	// port is automatically assigned.
+	// PublishedPort specifies the port on which the service is exposed. If
+	// specified, the port must be within the available range. If not specified
+	// (value is zero), an available port is automatically assigned.
 	uint32 published_port = 4;
+
+	// PublishMode controls how the port is published.
+	PublishMode publish_mode = 5;
 }
 
 // Driver is a generic driver type to be used throughout the API. For now, a
@@ -556,10 +572,17 @@ message IssuanceStatus {
 		option (gogoproto.goproto_enum_prefix) = false;
 
 		UNKNOWN = 0 [(gogoproto.enumvalue_customname) = "IssuanceStateUnknown"];
-		RENEW = 1 [(gogoproto.enumvalue_customname)="IssuanceStateRenew"]; // Certificate should be issued
-		PENDING = 2 [(gogoproto.enumvalue_customname)="IssuanceStatePending"]; // Certificate is pending acceptance
-		ISSUED = 3 [(gogoproto.enumvalue_customname)="IssuanceStateIssued"]; // successful completion certificate issuance
-		FAILED = 4 [(gogoproto.enumvalue_customname)="IssuanceStateFailed"]; // Certificate issuance failed
+		// A new certificate should be issued
+		RENEW = 1 [(gogoproto.enumvalue_customname)="IssuanceStateRenew"];
+		// Certificate is pending acceptance
+		PENDING = 2 [(gogoproto.enumvalue_customname)="IssuanceStatePending"];
+		// successful completion certificate issuance
+		ISSUED = 3 [(gogoproto.enumvalue_customname)="IssuanceStateIssued"];
+		// Certificate issuance failed
+		FAILED = 4 [(gogoproto.enumvalue_customname)="IssuanceStateFailed"];
+		// Signals workers to renew their certificate. From the CA's perspective
+		// this is equivalent to IssuanceStateIssued: a noop.
+		ROTATE = 5 [(gogoproto.enumvalue_customname)="IssuanceStateRotate"];
 	}
 	State state = 1;
 
@@ -777,12 +800,10 @@ message SecretReference {
 	string secret_name = 4;
 }
 
-// RemovedNode is a record for a node that has been removed from the swarm.
-message RemovedNode {
-	// ID is the ID of the removed node.
-	string id = 1 [(gogoproto.customname) = "ID"];
-
+// BlacklistedCertificate is a record for a blacklisted certificate. It does not
+// contain the certificate's CN, because these records are indexed by CN.
+message BlacklistedCertificate {
 	// Expiry is the latest known expiration time of a certificate that
-	// was issued to this node.
-	Timestamp expiry = 2;
+	// was issued for the given CN.
+	Timestamp expiry = 1;
 }

+ 8 - 10
vendor/src/github.com/docker/swarmkit/ca/auth.go

@@ -80,7 +80,7 @@ func certSubjectFromContext(ctx context.Context) (pkix.Name, error) {
 
 // AuthorizeOrgAndRole takes in a context and a list of roles, and returns
 // the Node ID of the node.
-func AuthorizeOrgAndRole(ctx context.Context, org string, removedNodes []*api.RemovedNode, ou ...string) (string, error) {
+func AuthorizeOrgAndRole(ctx context.Context, org string, blacklistedCerts map[string]*api.BlacklistedCertificate, ou ...string) (string, error) {
 	certSubj, err := certSubjectFromContext(ctx)
 	if err != nil {
 		return "", err
@@ -88,7 +88,7 @@ func AuthorizeOrgAndRole(ctx context.Context, org string, removedNodes []*api.Re
 	// Check if the current certificate has an OU that authorizes
 	// access to this method
 	if intersectArrays(certSubj.OrganizationalUnit, ou) {
-		return authorizeOrg(certSubj, org, removedNodes)
+		return authorizeOrg(certSubj, org, blacklistedCerts)
 	}
 
 	return "", grpc.Errorf(codes.PermissionDenied, "Permission denied: remote certificate not part of OUs: %v", ou)
@@ -96,11 +96,9 @@ func AuthorizeOrgAndRole(ctx context.Context, org string, removedNodes []*api.Re
 
 // authorizeOrg takes in a certificate subject and an organization, and returns
 // the Node ID of the node.
-func authorizeOrg(certSubj pkix.Name, org string, removedNodes []*api.RemovedNode) (string, error) {
-	for _, removedNode := range removedNodes {
-		if removedNode.ID == certSubj.CommonName {
-			return "", grpc.Errorf(codes.PermissionDenied, "Permission denied: node %s was removed from swarm", certSubj.CommonName)
-		}
+func authorizeOrg(certSubj pkix.Name, org string, blacklistedCerts map[string]*api.BlacklistedCertificate) (string, error) {
+	if _, ok := blacklistedCerts[certSubj.CommonName]; ok {
+		return "", grpc.Errorf(codes.PermissionDenied, "Permission denied: node %s was removed from swarm", certSubj.CommonName)
 	}
 
 	if len(certSubj.Organization) > 0 && certSubj.Organization[0] == org {
@@ -114,9 +112,9 @@ func authorizeOrg(certSubj pkix.Name, org string, removedNodes []*api.RemovedNod
 // been proxied by a manager, in which case the manager is authenticated and
 // so is the certificate information that it forwarded. It returns the node ID
 // of the original client.
-func AuthorizeForwardedRoleAndOrg(ctx context.Context, authorizedRoles, forwarderRoles []string, org string, removedNodes []*api.RemovedNode) (string, error) {
+func AuthorizeForwardedRoleAndOrg(ctx context.Context, authorizedRoles, forwarderRoles []string, org string, blacklistedCerts map[string]*api.BlacklistedCertificate) (string, error) {
 	if isForwardedRequest(ctx) {
-		_, err := AuthorizeOrgAndRole(ctx, org, removedNodes, forwarderRoles...)
+		_, err := AuthorizeOrgAndRole(ctx, org, blacklistedCerts, forwarderRoles...)
 		if err != nil {
 			return "", grpc.Errorf(codes.PermissionDenied, "Permission denied: unauthorized forwarder role: %v", err)
 		}
@@ -142,7 +140,7 @@ func AuthorizeForwardedRoleAndOrg(ctx context.Context, authorizedRoles, forwarde
 	}
 
 	// There wasn't any node being forwarded, check if this is a direct call by the expected role
-	nodeID, err := AuthorizeOrgAndRole(ctx, org, removedNodes, authorizedRoles...)
+	nodeID, err := AuthorizeOrgAndRole(ctx, org, blacklistedCerts, authorizedRoles...)
 	if err == nil {
 		return nodeID, nil
 	}

+ 13 - 10
vendor/src/github.com/docker/swarmkit/ca/server.go

@@ -168,9 +168,9 @@ func (s *Server) IssueNodeCertificate(ctx context.Context, request *api.IssueNod
 	defer s.doneTask()
 
 	var (
-		removedNodes []*api.RemovedNode
-		clusters     []*api.Cluster
-		err          error
+		blacklistedCerts map[string]*api.BlacklistedCertificate
+		clusters         []*api.Cluster
+		err              error
 	)
 
 	s.store.View(func(readTx store.ReadTx) {
@@ -181,19 +181,19 @@ func (s *Server) IssueNodeCertificate(ctx context.Context, request *api.IssueNod
 	// Not having a cluster object yet means we can't check
 	// the blacklist.
 	if err == nil && len(clusters) == 1 {
-		removedNodes = clusters[0].RemovedNodes
+		blacklistedCerts = clusters[0].BlacklistedCertificates
 	}
 
 	// If the remote node is a worker (either forwarded by a manager, or calling directly),
 	// issue a renew worker certificate entry with the correct ID
-	nodeID, err := AuthorizeForwardedRoleAndOrg(ctx, []string{WorkerRole}, []string{ManagerRole}, s.securityConfig.ClientTLSCreds.Organization(), removedNodes)
+	nodeID, err := AuthorizeForwardedRoleAndOrg(ctx, []string{WorkerRole}, []string{ManagerRole}, s.securityConfig.ClientTLSCreds.Organization(), blacklistedCerts)
 	if err == nil {
 		return s.issueRenewCertificate(ctx, nodeID, request.CSR)
 	}
 
 	// If the remote node is a manager (either forwarded by another manager, or calling directly),
 	// issue a renew certificate entry with the correct ID
-	nodeID, err = AuthorizeForwardedRoleAndOrg(ctx, []string{ManagerRole}, []string{ManagerRole}, s.securityConfig.ClientTLSCreds.Organization(), removedNodes)
+	nodeID, err = AuthorizeForwardedRoleAndOrg(ctx, []string{ManagerRole}, []string{ManagerRole}, s.securityConfig.ClientTLSCreds.Organization(), blacklistedCerts)
 	if err == nil {
 		return s.issueRenewCertificate(ctx, nodeID, request.CSR)
 	}
@@ -542,18 +542,20 @@ func (s *Server) updateCluster(ctx context.Context, cluster *api.Cluster) {
 func (s *Server) evaluateAndSignNodeCert(ctx context.Context, node *api.Node) error {
 	// If the desired membership and actual state are in sync, there's
 	// nothing to do.
-	if node.Spec.Membership == api.NodeMembershipAccepted && node.Certificate.Status.State == api.IssuanceStateIssued {
+	certState := node.Certificate.Status.State
+	if node.Spec.Membership == api.NodeMembershipAccepted &&
+		(certState == api.IssuanceStateIssued || certState == api.IssuanceStateRotate) {
 		return nil
 	}
 
 	// If the certificate state is renew, then it is a server-sided accepted cert (cert renewals)
-	if node.Certificate.Status.State == api.IssuanceStateRenew {
+	if certState == api.IssuanceStateRenew {
 		return s.signNodeCert(ctx, node)
 	}
 
 	// Sign this certificate if a user explicitly changed it to Accepted, and
 	// the certificate is in pending state
-	if node.Spec.Membership == api.NodeMembershipAccepted && node.Certificate.Status.State == api.IssuanceStatePending {
+	if node.Spec.Membership == api.NodeMembershipAccepted && certState == api.IssuanceStatePending {
 		return s.signNodeCert(ctx, node)
 	}
 
@@ -688,7 +690,8 @@ func (s *Server) reconcileNodeCertificates(ctx context.Context, nodes []*api.Nod
 
 // A successfully issued certificate and a failed certificate are our current final states
 func isFinalState(status api.IssuanceStatus) bool {
-	if status.State == api.IssuanceStateIssued || status.State == api.IssuanceStateFailed {
+	if status.State == api.IssuanceStateIssued || status.State == api.IssuanceStateFailed ||
+		status.State == api.IssuanceStateRotate {
 		return true
 	}
 

+ 271 - 199
vendor/src/github.com/docker/swarmkit/manager/allocator/network.go

@@ -22,8 +22,12 @@ const (
 
 	ingressNetworkName = "ingress"
 	ingressSubnet      = "10.255.0.0/16"
+
+	allocatedStatusMessage = "pending task scheduling"
 )
 
+var errNoChanges = errors.New("task unchanged")
+
 func newIngressNetwork() *api.Network {
 	return &api.Network{
 		Spec: api.NetworkSpec{
@@ -134,17 +138,13 @@ func (a *Allocator) doNetworkInit(ctx context.Context) (err error) {
 	if !na.IsAllocated(nc.ingressNetwork) {
 		if err := a.allocateNetwork(ctx, nc.ingressNetwork); err != nil {
 			log.G(ctx).WithError(err).Error("failed allocating ingress network during init")
-		}
-
-		// Update store after allocation
-		if err := a.store.Update(func(tx store.Tx) error {
-			if err := store.UpdateNetwork(tx, nc.ingressNetwork); err != nil {
-				return err
+		} else if _, err := a.store.Batch(func(batch *store.Batch) error {
+			if err := a.commitAllocatedNetwork(ctx, batch, nc.ingressNetwork); err != nil {
+				log.G(ctx).WithError(err).Error("failed committing allocation of ingress network during init")
 			}
-
 			return nil
 		}); err != nil {
-			return errors.Wrap(err, "failed to create ingress network")
+			log.G(ctx).WithError(err).Error("failed committing allocation of ingress network during init")
 		}
 	}
 
@@ -157,6 +157,7 @@ func (a *Allocator) doNetworkInit(ctx context.Context) (err error) {
 		return errors.Wrap(err, "error listing all networks in store while trying to allocate during init")
 	}
 
+	var allocatedNetworks []*api.Network
 	for _, n := range networks {
 		if na.IsAllocated(n) {
 			continue
@@ -164,7 +165,20 @@ func (a *Allocator) doNetworkInit(ctx context.Context) (err error) {
 
 		if err := a.allocateNetwork(ctx, n); err != nil {
 			log.G(ctx).WithError(err).Errorf("failed allocating network %s during init", n.ID)
+			continue
+		}
+		allocatedNetworks = append(allocatedNetworks, n)
+	}
+
+	if _, err := a.store.Batch(func(batch *store.Batch) error {
+		for _, n := range allocatedNetworks {
+			if err := a.commitAllocatedNetwork(ctx, batch, n); err != nil {
+				log.G(ctx).WithError(err).Errorf("failed committing allocation of network %s during init", n.ID)
+			}
 		}
+		return nil
+	}); err != nil {
+		log.G(ctx).WithError(err).Error("failed committing allocation of networks during init")
 	}
 
 	// Allocate nodes in the store so far before we process watched events.
@@ -176,6 +190,7 @@ func (a *Allocator) doNetworkInit(ctx context.Context) (err error) {
 		return errors.Wrap(err, "error listing all nodes in store while trying to allocate during init")
 	}
 
+	var allocatedNodes []*api.Node
 	for _, node := range nodes {
 		if na.IsNodeAllocated(node) {
 			continue
@@ -188,7 +203,21 @@ func (a *Allocator) doNetworkInit(ctx context.Context) (err error) {
 		node.Attachment.Network = nc.ingressNetwork.Copy()
 		if err := a.allocateNode(ctx, node); err != nil {
 			log.G(ctx).WithError(err).Errorf("Failed to allocate network resources for node %s during init", node.ID)
+			continue
+		}
+
+		allocatedNodes = append(allocatedNodes, node)
+	}
+
+	if _, err := a.store.Batch(func(batch *store.Batch) error {
+		for _, node := range allocatedNodes {
+			if err := a.commitAllocatedNode(ctx, batch, node); err != nil {
+				log.G(ctx).WithError(err).Errorf("Failed to commit allocation of network resources for node %s during init", node.ID)
+			}
 		}
+		return nil
+	}); err != nil {
+		log.G(ctx).WithError(err).Error("Failed to commit allocation of network resources for nodes during init")
 	}
 
 	// Allocate services in the store so far before we process watched events.
@@ -200,6 +229,7 @@ func (a *Allocator) doNetworkInit(ctx context.Context) (err error) {
 		return errors.Wrap(err, "error listing all services in store while trying to allocate during init")
 	}
 
+	var allocatedServices []*api.Service
 	for _, s := range services {
 		if nc.nwkAllocator.IsServiceAllocated(s) {
 			continue
@@ -207,11 +237,27 @@ func (a *Allocator) doNetworkInit(ctx context.Context) (err error) {
 
 		if err := a.allocateService(ctx, s); err != nil {
 			log.G(ctx).WithError(err).Errorf("failed allocating service %s during init", s.ID)
+			continue
+		}
+		allocatedServices = append(allocatedServices, s)
+	}
+
+	if _, err := a.store.Batch(func(batch *store.Batch) error {
+		for _, s := range allocatedServices {
+			if err := a.commitAllocatedService(ctx, batch, s); err != nil {
+				log.G(ctx).WithError(err).Errorf("failed committing allocation of service %s during init", s.ID)
+			}
 		}
+		return nil
+	}); err != nil {
+		log.G(ctx).WithError(err).Error("failed committing allocation of services during init")
 	}
 
 	// Allocate tasks in the store so far before we started watching.
-	var tasks []*api.Task
+	var (
+		tasks          []*api.Task
+		allocatedTasks []*api.Task
+	)
 	a.store.View(func(tx store.ReadTx) {
 		tasks, err = store.FindTasks(tx, store.All)
 	})
@@ -219,66 +265,56 @@ func (a *Allocator) doNetworkInit(ctx context.Context) (err error) {
 		return errors.Wrap(err, "error listing all tasks in store while trying to allocate during init")
 	}
 
-	if _, err := a.store.Batch(func(batch *store.Batch) error {
-		for _, t := range tasks {
-			if taskDead(t) {
-				continue
-			}
-
-			var s *api.Service
-			if t.ServiceID != "" {
-				a.store.View(func(tx store.ReadTx) {
-					s = store.GetService(tx, t.ServiceID)
-				})
-			}
+	for _, t := range tasks {
+		if taskDead(t) {
+			continue
+		}
 
-			// Populate network attachments in the task
-			// based on service spec.
-			a.taskCreateNetworkAttachments(t, s)
+		var s *api.Service
+		if t.ServiceID != "" {
+			a.store.View(func(tx store.ReadTx) {
+				s = store.GetService(tx, t.ServiceID)
+			})
+		}
 
-			if taskReadyForNetworkVote(t, s, nc) {
-				if t.Status.State >= api.TaskStateAllocated {
-					continue
-				}
+		// Populate network attachments in the task
+		// based on service spec.
+		a.taskCreateNetworkAttachments(t, s)
 
-				if a.taskAllocateVote(networkVoter, t.ID) {
-					// If the task is not attached to any network, network
-					// allocators job is done. Immediately cast a vote so
-					// that the task can be moved to ALLOCATED state as
-					// soon as possible.
-					if err := batch.Update(func(tx store.Tx) error {
-						storeT := store.GetTask(tx, t.ID)
-						if storeT == nil {
-							return fmt.Errorf("task %s not found while trying to update state", t.ID)
-						}
-
-						updateTaskStatus(storeT, api.TaskStateAllocated, "allocated")
-
-						if err := store.UpdateTask(tx, storeT); err != nil {
-							return errors.Wrapf(err, "failed updating state in store transaction for task %s", storeT.ID)
-						}
-
-						return nil
-					}); err != nil {
-						log.G(ctx).WithError(err).Error("error updating task network")
-					}
-				}
+		if taskReadyForNetworkVote(t, s, nc) {
+			if t.Status.State >= api.TaskStatePending {
 				continue
 			}
 
-			err := batch.Update(func(tx store.Tx) error {
-				_, err := a.allocateTask(ctx, tx, t)
-				return err
-			})
-			if err != nil {
-				log.G(ctx).WithError(err).Errorf("failed allocating task %s during init", t.ID)
-				nc.unallocatedTasks[t.ID] = t
+			if a.taskAllocateVote(networkVoter, t.ID) {
+				// If the task is not attached to any network, network
+				// allocators job is done. Immediately cast a vote so
+				// that the task can be moved to ALLOCATED state as
+				// soon as possible.
+				allocatedTasks = append(allocatedTasks, t)
+			}
+			continue
+		}
+
+		err := a.allocateTask(ctx, t)
+		if err == nil {
+			allocatedTasks = append(allocatedTasks, t)
+		} else if err != errNoChanges {
+			log.G(ctx).WithError(err).Errorf("failed allocating task %s during init", t.ID)
+			nc.unallocatedTasks[t.ID] = t
+		}
+	}
+
+	if _, err := a.store.Batch(func(batch *store.Batch) error {
+		for _, t := range allocatedTasks {
+			if err := a.commitAllocatedTask(ctx, batch, t); err != nil {
+				log.G(ctx).WithError(err).Errorf("failed committing allocation of task %s during init", t.ID)
 			}
 		}
 
 		return nil
 	}); err != nil {
-		return err
+		log.G(ctx).WithError(err).Error("failed committing allocation of tasks during init")
 	}
 
 	return nil
@@ -298,6 +334,12 @@ func (a *Allocator) doNetworkAlloc(ctx context.Context, ev events.Event) {
 			log.G(ctx).WithError(err).Errorf("Failed allocation for network %s", n.ID)
 			break
 		}
+
+		if _, err := a.store.Batch(func(batch *store.Batch) error {
+			return a.commitAllocatedNetwork(ctx, batch, n)
+		}); err != nil {
+			log.G(ctx).WithError(err).Errorf("Failed to commit allocation for network %s", n.ID)
+		}
 	case state.EventDeleteNetwork:
 		n := v.Network.Copy()
 
@@ -319,6 +361,12 @@ func (a *Allocator) doNetworkAlloc(ctx context.Context, ev events.Event) {
 			log.G(ctx).WithError(err).Errorf("Failed allocation for service %s", s.ID)
 			break
 		}
+
+		if _, err := a.store.Batch(func(batch *store.Batch) error {
+			return a.commitAllocatedService(ctx, batch, s)
+		}); err != nil {
+			log.G(ctx).WithError(err).Errorf("Failed to commit allocation for service %s", s.ID)
+		}
 	case state.EventUpdateService:
 		s := v.Service.Copy()
 
@@ -330,6 +378,12 @@ func (a *Allocator) doNetworkAlloc(ctx context.Context, ev events.Event) {
 			log.G(ctx).WithError(err).Errorf("Failed allocation during update of service %s", s.ID)
 			break
 		}
+
+		if _, err := a.store.Batch(func(batch *store.Batch) error {
+			return a.commitAllocatedService(ctx, batch, s)
+		}); err != nil {
+			log.G(ctx).WithError(err).Errorf("Failed to commit allocation during update for service %s", s.ID)
+		}
 	case state.EventDeleteService:
 		s := v.Service.Copy()
 
@@ -387,6 +441,13 @@ func (a *Allocator) doNodeAlloc(ctx context.Context, ev events.Event) {
 		node.Attachment.Network = nc.ingressNetwork.Copy()
 		if err := a.allocateNode(ctx, node); err != nil {
 			log.G(ctx).WithError(err).Errorf("Failed to allocate network resources for node %s", node.ID)
+			return
+		}
+
+		if _, err := a.store.Batch(func(batch *store.Batch) error {
+			return a.commitAllocatedNode(ctx, batch, node)
+		}); err != nil {
+			log.G(ctx).WithError(err).Errorf("Failed to commit allocation of network resources for node %s", node.ID)
 		}
 	}
 }
@@ -503,7 +564,7 @@ func (a *Allocator) doTaskAlloc(ctx context.Context, ev events.Event) {
 
 	// If we are already in allocated state, there is
 	// absolutely nothing else to do.
-	if t.Status.State >= api.TaskStateAllocated {
+	if t.Status.State >= api.TaskStatePending {
 		delete(nc.unallocatedTasks, t.ID)
 		return
 	}
@@ -537,31 +598,22 @@ func (a *Allocator) doTaskAlloc(ctx context.Context, ev events.Event) {
 }
 
 func (a *Allocator) allocateNode(ctx context.Context, node *api.Node) error {
-	nc := a.netCtx
-
-	if err := nc.nwkAllocator.AllocateNode(node); err != nil {
-		return err
-	}
-
-	if err := a.store.Update(func(tx store.Tx) error {
-		for {
-			err := store.UpdateNode(tx, node)
-			if err != nil && err != store.ErrSequenceConflict {
-				return errors.Wrapf(err, "failed updating state in store transaction for node %s", node.ID)
-			}
+	return a.netCtx.nwkAllocator.AllocateNode(node)
+}
 
-			if err == store.ErrSequenceConflict {
-				storeNode := store.GetNode(tx, node.ID)
-				storeNode.Attachment = node.Attachment.Copy()
-				node = storeNode
-				continue
-			}
+func (a *Allocator) commitAllocatedNode(ctx context.Context, batch *store.Batch, node *api.Node) error {
+	if err := batch.Update(func(tx store.Tx) error {
+		err := store.UpdateNode(tx, node)
 
-			break
+		if err == store.ErrSequenceConflict {
+			storeNode := store.GetNode(tx, node.ID)
+			storeNode.Attachment = node.Attachment.Copy()
+			err = store.UpdateNode(tx, storeNode)
 		}
-		return nil
+
+		return errors.Wrapf(err, "failed updating state in store transaction for node %s", node.ID)
 	}); err != nil {
-		if err := nc.nwkAllocator.DeallocateNode(node); err != nil {
+		if err := a.netCtx.nwkAllocator.DeallocateNode(node); err != nil {
 			log.G(ctx).WithError(err).Errorf("failed rolling back allocation of node %s", node.ID)
 		}
 
@@ -628,27 +680,22 @@ func (a *Allocator) allocateService(ctx context.Context, s *api.Service) error {
 			}
 		}
 	}
+	return nil
+}
 
-	if err := a.store.Update(func(tx store.Tx) error {
-		for {
-			err := store.UpdateService(tx, s)
-
-			if err != nil && err != store.ErrSequenceConflict {
-				return errors.Wrapf(err, "failed updating state in store transaction for service %s", s.ID)
-			}
-
-			if err == store.ErrSequenceConflict {
-				storeService := store.GetService(tx, s.ID)
-				storeService.Endpoint = s.Endpoint
-				s = storeService
-				continue
-			}
+func (a *Allocator) commitAllocatedService(ctx context.Context, batch *store.Batch, s *api.Service) error {
+	if err := batch.Update(func(tx store.Tx) error {
+		err := store.UpdateService(tx, s)
 
-			break
+		if err == store.ErrSequenceConflict {
+			storeService := store.GetService(tx, s.ID)
+			storeService.Endpoint = s.Endpoint
+			err = store.UpdateService(tx, storeService)
 		}
-		return nil
+
+		return errors.Wrapf(err, "failed updating state in store transaction for service %s", s.ID)
 	}); err != nil {
-		if err := nc.nwkAllocator.ServiceDeallocate(s); err != nil {
+		if err := a.netCtx.nwkAllocator.ServiceDeallocate(s); err != nil {
 			log.G(ctx).WithError(err).Errorf("failed rolling back allocation of service %s", s.ID)
 		}
 
@@ -666,13 +713,17 @@ func (a *Allocator) allocateNetwork(ctx context.Context, n *api.Network) error {
 		return errors.Wrapf(err, "failed during network allocation for network %s", n.ID)
 	}
 
-	if err := a.store.Update(func(tx store.Tx) error {
+	return nil
+}
+
+func (a *Allocator) commitAllocatedNetwork(ctx context.Context, batch *store.Batch, n *api.Network) error {
+	if err := batch.Update(func(tx store.Tx) error {
 		if err := store.UpdateNetwork(tx, n); err != nil {
 			return errors.Wrapf(err, "failed updating state in store transaction for network %s", n.ID)
 		}
 		return nil
 	}); err != nil {
-		if err := nc.nwkAllocator.Deallocate(n); err != nil {
+		if err := a.netCtx.nwkAllocator.Deallocate(n); err != nil {
 			log.G(ctx).WithError(err).Errorf("failed rolling back allocation of network %s", n.ID)
 		}
 
@@ -682,15 +733,8 @@ func (a *Allocator) allocateNetwork(ctx context.Context, n *api.Network) error {
 	return nil
 }
 
-func (a *Allocator) allocateTask(ctx context.Context, tx store.Tx, t *api.Task) (*api.Task, error) {
+func (a *Allocator) allocateTask(ctx context.Context, t *api.Task) (err error) {
 	taskUpdated := false
-
-	// Get the latest task state from the store before updating.
-	storeT := store.GetTask(tx, t.ID)
-	if storeT == nil {
-		return nil, fmt.Errorf("could not find task %s while trying to update network allocation", t.ID)
-	}
-
 	nc := a.netCtx
 
 	// We might be here even if a task allocation has already
@@ -698,163 +742,191 @@ func (a *Allocator) allocateTask(ctx context.Context, tx store.Tx, t *api.Task)
 	// cases skip allocation and go straight ahead to updating the
 	// store.
 	if !nc.nwkAllocator.IsTaskAllocated(t) {
-		if t.ServiceID != "" {
-			s := store.GetService(tx, t.ServiceID)
-			if s == nil {
-				return nil, fmt.Errorf("could not find service %s", t.ServiceID)
-			}
+		a.store.View(func(tx store.ReadTx) {
+			if t.ServiceID != "" {
+				s := store.GetService(tx, t.ServiceID)
+				if s == nil {
+					err = fmt.Errorf("could not find service %s", t.ServiceID)
+					return
+				}
 
-			if !nc.nwkAllocator.IsServiceAllocated(s) {
-				return nil, fmt.Errorf("service %s to which this task %s belongs has pending allocations", s.ID, t.ID)
+				if !nc.nwkAllocator.IsServiceAllocated(s) {
+					err = fmt.Errorf("service %s to which this task %s belongs has pending allocations", s.ID, t.ID)
+					return
+				}
+
+				taskUpdateEndpoint(t, s.Endpoint)
 			}
 
-			taskUpdateEndpoint(t, s.Endpoint)
-		}
+			for _, na := range t.Networks {
+				n := store.GetNetwork(tx, na.Network.ID)
+				if n == nil {
+					err = fmt.Errorf("failed to retrieve network %s while allocating task %s", na.Network.ID, t.ID)
+					return
+				}
 
-		for _, na := range t.Networks {
-			n := store.GetNetwork(tx, na.Network.ID)
-			if n == nil {
-				return nil, fmt.Errorf("failed to retrieve network %s while allocating task %s", na.Network.ID, t.ID)
-			}
+				if !nc.nwkAllocator.IsAllocated(n) {
+					err = fmt.Errorf("network %s attached to task %s not allocated yet", n.ID, t.ID)
+					return
+				}
 
-			if !nc.nwkAllocator.IsAllocated(n) {
-				return nil, fmt.Errorf("network %s attached to task %s not allocated yet", n.ID, t.ID)
+				na.Network = n
 			}
 
-			na.Network = n
-		}
-
-		if err := nc.nwkAllocator.AllocateTask(t); err != nil {
-			return nil, errors.Wrapf(err, "failed during networktask allocation for task %s", t.ID)
-		}
-		if nc.nwkAllocator.IsTaskAllocated(t) {
-			taskUpdateNetworks(storeT, t.Networks)
-			taskUpdateEndpoint(storeT, t.Endpoint)
-			taskUpdated = true
+			if err = nc.nwkAllocator.AllocateTask(t); err != nil {
+				err = errors.Wrapf(err, "failed during networktask allocation for task %s", t.ID)
+				return
+			}
+			if nc.nwkAllocator.IsTaskAllocated(t) {
+				taskUpdated = true
+			}
+		})
+		if err != nil {
+			return err
 		}
 	}
 
 	// Update the network allocations and moving to
-	// ALLOCATED state on top of the latest store state.
+	// PENDING state on top of the latest store state.
 	if a.taskAllocateVote(networkVoter, t.ID) {
-		if storeT.Status.State < api.TaskStateAllocated {
-			updateTaskStatus(storeT, api.TaskStateAllocated, "allocated")
+		if t.Status.State < api.TaskStatePending {
+			updateTaskStatus(t, api.TaskStatePending, allocatedStatusMessage)
 			taskUpdated = true
 		}
 	}
 
-	if taskUpdated {
-		if err := store.UpdateTask(tx, storeT); err != nil {
-			return nil, errors.Wrapf(err, "failed updating state in store transaction for task %s", storeT.ID)
-		}
+	if !taskUpdated {
+		return errNoChanges
 	}
 
-	return storeT, nil
+	return nil
+}
+
+func (a *Allocator) commitAllocatedTask(ctx context.Context, batch *store.Batch, t *api.Task) error {
+	return batch.Update(func(tx store.Tx) error {
+		err := store.UpdateTask(tx, t)
+
+		if err == store.ErrSequenceConflict {
+			storeTask := store.GetTask(tx, t.ID)
+			taskUpdateNetworks(storeTask, t.Networks)
+			taskUpdateEndpoint(storeTask, t.Endpoint)
+			if storeTask.Status.State < api.TaskStatePending {
+				storeTask.Status = t.Status
+			}
+			err = store.UpdateTask(tx, storeTask)
+		}
+
+		return errors.Wrapf(err, "failed updating state in store transaction for task %s", t.ID)
+	})
 }
 
 func (a *Allocator) procUnallocatedNetworks(ctx context.Context) {
 	nc := a.netCtx
+	var allocatedNetworks []*api.Network
 	for _, n := range nc.unallocatedNetworks {
 		if !nc.nwkAllocator.IsAllocated(n) {
 			if err := a.allocateNetwork(ctx, n); err != nil {
-				log.G(ctx).Debugf("Failed allocation of unallocated network %s: %v", n.ID, err)
+				log.G(ctx).WithError(err).Debugf("Failed allocation of unallocated network %s", n.ID)
 				continue
 			}
+			allocatedNetworks = append(allocatedNetworks, n)
 		}
+	}
+
+	if len(allocatedNetworks) == 0 {
+		return
+	}
 
+	committed, err := a.store.Batch(func(batch *store.Batch) error {
+		for _, n := range allocatedNetworks {
+			if err := a.commitAllocatedNetwork(ctx, batch, n); err != nil {
+				log.G(ctx).WithError(err).Debugf("Failed to commit allocation of unallocated network %s", n.ID)
+				continue
+			}
+		}
+		return nil
+	})
+
+	if err != nil {
+		log.G(ctx).WithError(err).Error("Failed to commit allocation of unallocated networks")
+	}
+
+	for _, n := range allocatedNetworks[:committed] {
 		delete(nc.unallocatedNetworks, n.ID)
 	}
 }
 
 func (a *Allocator) procUnallocatedServices(ctx context.Context) {
 	nc := a.netCtx
+	var allocatedServices []*api.Service
 	for _, s := range nc.unallocatedServices {
 		if !nc.nwkAllocator.IsServiceAllocated(s) {
 			if err := a.allocateService(ctx, s); err != nil {
-				log.G(ctx).Debugf("Failed allocation of unallocated service %s: %v", s.ID, err)
+				log.G(ctx).WithError(err).Debugf("Failed allocation of unallocated service %s", s.ID)
 				continue
 			}
+			allocatedServices = append(allocatedServices, s)
 		}
-
-		delete(nc.unallocatedServices, s.ID)
 	}
-}
 
-func (a *Allocator) procUnallocatedTasksNetwork(ctx context.Context) {
-	nc := a.netCtx
-	tasks := make([]*api.Task, 0, len(nc.unallocatedTasks))
+	if len(allocatedServices) == 0 {
+		return
+	}
 
 	committed, err := a.store.Batch(func(batch *store.Batch) error {
-		for _, t := range nc.unallocatedTasks {
-			var allocatedT *api.Task
-			err := batch.Update(func(tx store.Tx) error {
-				var err error
-				allocatedT, err = a.allocateTask(ctx, tx, t)
-				return err
-			})
-
-			if err != nil {
-				log.G(ctx).WithError(err).Error("task allocation failure")
+		for _, s := range allocatedServices {
+			if err := a.commitAllocatedService(ctx, batch, s); err != nil {
+				log.G(ctx).WithError(err).Debugf("Failed to commit allocation of unallocated service %s", s.ID)
 				continue
 			}
-
-			tasks = append(tasks, allocatedT)
 		}
-
 		return nil
 	})
 
 	if err != nil {
-		log.G(ctx).WithError(err).Error("failed a store batch operation while processing unallocated tasks")
+		log.G(ctx).WithError(err).Error("Failed to commit allocation of unallocated services")
 	}
 
-	var retryCnt int
-	for len(tasks) != 0 {
-		var err error
+	for _, s := range allocatedServices[:committed] {
+		delete(nc.unallocatedServices, s.ID)
+	}
+}
 
-		for _, t := range tasks[:committed] {
-			delete(nc.unallocatedTasks, t.ID)
-		}
+func (a *Allocator) procUnallocatedTasksNetwork(ctx context.Context) {
+	nc := a.netCtx
+	allocatedTasks := make([]*api.Task, 0, len(nc.unallocatedTasks))
 
-		tasks = tasks[committed:]
-		if len(tasks) == 0 {
-			break
+	for _, t := range nc.unallocatedTasks {
+		if err := a.allocateTask(ctx, t); err == nil {
+			allocatedTasks = append(allocatedTasks, t)
+		} else if err != errNoChanges {
+			log.G(ctx).WithError(err).Error("task allocation failure")
 		}
+	}
 
-		updatedTasks := make([]*api.Task, 0, len(tasks))
-		committed, err = a.store.Batch(func(batch *store.Batch) error {
-			for _, t := range tasks {
-				err := batch.Update(func(tx store.Tx) error {
-					return store.UpdateTask(tx, t)
-				})
+	if len(allocatedTasks) == 0 {
+		return
+	}
 
-				if err != nil {
-					log.G(ctx).WithError(err).Error("allocated task store update failure")
-					continue
-				}
+	committed, err := a.store.Batch(func(batch *store.Batch) error {
+		for _, t := range allocatedTasks {
+			err := a.commitAllocatedTask(ctx, batch, t)
 
-				updatedTasks = append(updatedTasks, t)
+			if err != nil {
+				log.G(ctx).WithError(err).Error("task allocation commit failure")
+				continue
 			}
-
-			return nil
-		})
-		if err != nil {
-			log.G(ctx).WithError(err).Error("failed a store batch operation while processing unallocated tasks")
 		}
 
-		tasks = updatedTasks
+		return nil
+	})
 
-		select {
-		case <-ctx.Done():
-			return
-		default:
-		}
+	if err != nil {
+		log.G(ctx).WithError(err).Error("failed a store batch operation while processing unallocated tasks")
+	}
 
-		retryCnt++
-		if retryCnt >= 3 {
-			log.G(ctx).Error("failed to complete batch update of allocated tasks after 3 retries")
-			break
-		}
+	for _, t := range allocatedTasks[:committed] {
+		delete(nc.unallocatedTasks, t.ID)
 	}
 }
 

+ 20 - 0
vendor/src/github.com/docker/swarmkit/manager/constraint/constraint.go

@@ -125,6 +125,26 @@ func NodeMatches(constraints []Constraint, n *api.Node) bool {
 			if !constraint.Match(n.Spec.Role.String()) {
 				return false
 			}
+		case strings.EqualFold(constraint.key, "node.platform.os"):
+			if n.Description == nil || n.Description.Platform == nil {
+				if !constraint.Match("") {
+					return false
+				}
+				continue
+			}
+			if !constraint.Match(n.Description.Platform.OS) {
+				return false
+			}
+		case strings.EqualFold(constraint.key, "node.platform.arch"):
+			if n.Description == nil || n.Description.Platform == nil {
+				if !constraint.Match("") {
+					return false
+				}
+				continue
+			}
+			if !constraint.Match(n.Description.Platform.Architecture) {
+				return false
+			}
 
 		// node labels constraint in form like 'node.labels.key==value'
 		case len(constraint.key) > len(nodeLabelPrefix) && strings.EqualFold(constraint.key[:len(nodeLabelPrefix)], nodeLabelPrefix):

+ 25 - 1
vendor/src/github.com/docker/swarmkit/manager/controlapi/cluster.go

@@ -2,6 +2,7 @@ package controlapi
 
 import (
 	"strings"
+	"time"
 
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/ca"
@@ -12,6 +13,12 @@ import (
 	"google.golang.org/grpc/codes"
 )
 
+const (
+	// expiredCertGrace is the amount of time to keep a node in the
+	// blacklist beyond its certificate expiration timestamp.
+	expiredCertGrace = 24 * time.Hour * 7
+)
+
 func validateClusterSpec(spec *api.ClusterSpec) error {
 	if spec == nil {
 		return grpc.Errorf(codes.InvalidArgument, errInvalidArgument.Error())
@@ -98,6 +105,8 @@ func (s *Server) UpdateCluster(ctx context.Context, request *api.UpdateClusterRe
 		cluster.Meta.Version = *request.ClusterVersion
 		cluster.Spec = *request.Spec.Copy()
 
+		expireBlacklistedCerts(cluster)
+
 		if request.Rotation.RotateWorkerToken {
 			cluster.RootCA.JoinTokens.Worker = ca.GenerateJoinToken(s.rootCA)
 		}
@@ -202,7 +211,7 @@ func redactClusters(clusters []*api.Cluster) []*api.Cluster {
 				CACertHash: cluster.RootCA.CACertHash,
 				JoinTokens: cluster.RootCA.JoinTokens,
 			},
-			RemovedNodes: cluster.RemovedNodes,
+			BlacklistedCertificates: cluster.BlacklistedCertificates,
 		}
 
 		redactedClusters = append(redactedClusters, newCluster)
@@ -210,3 +219,18 @@ func redactClusters(clusters []*api.Cluster) []*api.Cluster {
 
 	return redactedClusters
 }
+
+func expireBlacklistedCerts(cluster *api.Cluster) {
+	nowMinusGrace := time.Now().Add(-expiredCertGrace)
+
+	for cn, blacklistedCert := range cluster.BlacklistedCertificates {
+		if blacklistedCert.Expiry == nil {
+			continue
+		}
+
+		expiry, err := ptypes.Timestamp(blacklistedCert.Expiry)
+		if err == nil && nowMinusGrace.After(expiry) {
+			delete(cluster.BlacklistedCertificates, cn)
+		}
+	}
+}

+ 8 - 3
vendor/src/github.com/docker/swarmkit/manager/controlapi/node.go

@@ -301,7 +301,7 @@ func (s *Server) RemoveNode(ctx context.Context, request *api.RemoveNodeRequest)
 		}
 		cluster := clusters[0]
 
-		removedNode := &api.RemovedNode{ID: node.ID}
+		blacklistedCert := &api.BlacklistedCertificate{}
 
 		// Set an expiry time for this RemovedNode if a certificate
 		// exists and can be parsed.
@@ -312,13 +312,18 @@ func (s *Server) RemoveNode(ctx context.Context, request *api.RemoveNodeRequest)
 				if err == nil && !X509Cert.NotAfter.IsZero() {
 					expiry, err := ptypes.TimestampProto(X509Cert.NotAfter)
 					if err == nil {
-						removedNode.Expiry = expiry
+						blacklistedCert.Expiry = expiry
 					}
 				}
 			}
 		}
 
-		cluster.RemovedNodes = append(cluster.RemovedNodes, removedNode)
+		if cluster.BlacklistedCertificates == nil {
+			cluster.BlacklistedCertificates = make(map[string]*api.BlacklistedCertificate)
+		}
+		cluster.BlacklistedCertificates[node.ID] = blacklistedCert
+
+		expireBlacklistedCerts(cluster)
 
 		if err := store.UpdateCluster(tx, cluster); err != nil {
 			return err

+ 41 - 0
vendor/src/github.com/docker/swarmkit/manager/controlapi/secret.go

@@ -48,9 +48,50 @@ func (s *Server) GetSecret(ctx context.Context, request *api.GetSecretRequest) (
 		return nil, grpc.Errorf(codes.NotFound, "secret %s not found", request.SecretID)
 	}
 
+	secret.Spec.Data = nil // clean the actual secret data so it's never returned
 	return &api.GetSecretResponse{Secret: secret}, nil
 }
 
+// UpdateSecret updates a Secret referenced by SecretID with the given SecretSpec.
+// - Returns `NotFound` if the Secret is not found.
+// - Returns `InvalidArgument` if the SecretSpec is malformed or anything other than Labels is changed
+// - Returns an error if the update fails.
+func (s *Server) UpdateSecret(ctx context.Context, request *api.UpdateSecretRequest) (*api.UpdateSecretResponse, error) {
+	if request.SecretID == "" || request.SecretVersion == nil {
+		return nil, grpc.Errorf(codes.InvalidArgument, errInvalidArgument.Error())
+	}
+
+	var secret *api.Secret
+	err := s.store.Update(func(tx store.Tx) error {
+		secret = store.GetSecret(tx, request.SecretID)
+		if secret == nil {
+			return nil
+		}
+
+		if secret.Spec.Annotations.Name != request.Spec.Annotations.Name || request.Spec.Data != nil {
+			return grpc.Errorf(codes.InvalidArgument, "only updates to Labels are allowed")
+		}
+
+		// We only allow updating Labels
+		secret.Meta.Version = *request.SecretVersion
+		secret.Spec.Annotations.Labels = request.Spec.Annotations.Labels
+
+		return store.UpdateSecret(tx, secret)
+	})
+	if err != nil {
+		return nil, err
+	}
+	if secret == nil {
+		return nil, grpc.Errorf(codes.NotFound, "secret %s not found", request.SecretID)
+	}
+
+	// WARN: we should never return the actual secret data here. We need to redact the private fields first.
+	secret.Spec.Data = nil
+	return &api.UpdateSecretResponse{
+		Secret: secret,
+	}, nil
+}
+
 // ListSecrets returns a `ListSecretResponse` with a list all non-internal `Secret`s being
 // managed, or all secrets matching any name in `ListSecretsRequest.Names`, any
 // name prefix in `ListSecretsRequest.NamePrefixes`, any id in

+ 76 - 19
vendor/src/github.com/docker/swarmkit/manager/controlapi/service.go

@@ -3,6 +3,7 @@ package controlapi
 import (
 	"errors"
 	"reflect"
+	"regexp"
 	"strconv"
 
 	"github.com/docker/distribution/reference"
@@ -18,9 +19,13 @@ import (
 
 var (
 	errNetworkUpdateNotSupported = errors.New("changing network in service is not supported")
+	errRenameNotSupported        = errors.New("renaming services is not supported")
 	errModeChangeNotAllowed      = errors.New("service mode change is not allowed")
 )
 
+// Regexp pattern for hostname to conform RFC 1123
+var hostnamePattern = regexp.MustCompile("^(([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])\\.)*([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])$")
+
 func validateResources(r *api.Resources) error {
 	if r == nil {
 		return nil
@@ -102,6 +107,43 @@ func validateUpdate(uc *api.UpdateConfig) error {
 	return nil
 }
 
+func validateContainerSpec(container *api.ContainerSpec) error {
+	if container == nil {
+		return grpc.Errorf(codes.InvalidArgument, "ContainerSpec: missing in service spec")
+	}
+
+	if err := validateHostname(container.Hostname); err != nil {
+		return err
+	}
+
+	if container.Image == "" {
+		return grpc.Errorf(codes.InvalidArgument, "ContainerSpec: image reference must be provided")
+	}
+
+	if _, err := reference.ParseNamed(container.Image); err != nil {
+		return grpc.Errorf(codes.InvalidArgument, "ContainerSpec: %q is not a valid repository/tag", container.Image)
+	}
+
+	mountMap := make(map[string]bool)
+	for _, mount := range container.Mounts {
+		if _, exists := mountMap[mount.Target]; exists {
+			return grpc.Errorf(codes.InvalidArgument, "ContainerSpec: duplicate mount point: %s", mount.Target)
+		}
+		mountMap[mount.Target] = true
+	}
+
+	return nil
+}
+
+func validateHostname(hostname string) error {
+	if hostname != "" {
+		if len(hostname) > 63 || !hostnamePattern.MatchString(hostname) {
+			return grpc.Errorf(codes.InvalidArgument, "ContainerSpec: %s is not valid hostname", hostname)
+		}
+	}
+	return nil
+}
+
 func validateTask(taskSpec api.TaskSpec) error {
 	if err := validateResourceRequirements(taskSpec.Resources); err != nil {
 		return err
@@ -124,25 +166,8 @@ func validateTask(taskSpec api.TaskSpec) error {
 		return grpc.Errorf(codes.Unimplemented, "RuntimeSpec: unimplemented runtime in service spec")
 	}
 
-	container := taskSpec.GetContainer()
-	if container == nil {
-		return grpc.Errorf(codes.InvalidArgument, "ContainerSpec: missing in service spec")
-	}
-
-	if container.Image == "" {
-		return grpc.Errorf(codes.InvalidArgument, "ContainerSpec: image reference must be provided")
-	}
-
-	if _, err := reference.ParseNamed(container.Image); err != nil {
-		return grpc.Errorf(codes.InvalidArgument, "ContainerSpec: %q is not a valid repository/tag", container.Image)
-	}
-
-	mountMap := make(map[string]bool)
-	for _, mount := range container.Mounts {
-		if _, exists := mountMap[mount.Target]; exists {
-			return grpc.Errorf(codes.InvalidArgument, "ContainerSpec: duplicate mount point: %s", mount.Target)
-		}
-		mountMap[mount.Target] = true
+	if err := validateContainerSpec(taskSpec.GetContainer()); err != nil {
+		return err
 	}
 
 	return nil
@@ -279,6 +304,25 @@ func (s *Server) checkPortConflicts(spec *api.ServiceSpec, serviceID string) err
 	return nil
 }
 
+// checkSecretConflicts finds if the passed in spec has secrets with conflicting targets.
+func (s *Server) checkSecretConflicts(spec *api.ServiceSpec) error {
+	container := spec.Task.GetContainer()
+	if container == nil {
+		return nil
+	}
+
+	existingTargets := make(map[string]string)
+	for _, secretRef := range container.Secrets {
+		if prevSecretName, ok := existingTargets[secretRef.Target]; ok {
+			return grpc.Errorf(codes.InvalidArgument, "secret references '%s' and '%s' have a conflicting target: '%s'", prevSecretName, secretRef.SecretName, secretRef.Target)
+		}
+
+		existingTargets[secretRef.Target] = secretRef.SecretName
+	}
+
+	return nil
+}
+
 // CreateService creates and return a Service based on the provided ServiceSpec.
 // - Returns `InvalidArgument` if the ServiceSpec is malformed.
 // - Returns `Unimplemented` if the ServiceSpec references unimplemented features.
@@ -297,6 +341,10 @@ func (s *Server) CreateService(ctx context.Context, request *api.CreateServiceRe
 		return nil, err
 	}
 
+	if err := s.checkSecretConflicts(request.Spec); err != nil {
+		return nil, err
+	}
+
 	// TODO(aluzzardi): Consider using `Name` as a primary key to handle
 	// duplicate creations. See #65
 	service := &api.Service{
@@ -364,6 +412,10 @@ func (s *Server) UpdateService(ctx context.Context, request *api.UpdateServiceRe
 		}
 	}
 
+	if err := s.checkSecretConflicts(request.Spec); err != nil {
+		return nil, err
+	}
+
 	err := s.store.Update(func(tx store.Tx) error {
 		service = store.GetService(tx, request.ServiceID)
 		if service == nil {
@@ -390,6 +442,11 @@ func (s *Server) UpdateService(ctx context.Context, request *api.UpdateServiceRe
 		if reflect.TypeOf(service.Spec.Mode) != reflect.TypeOf(request.Spec.Mode) {
 			return errModeChangeNotAllowed
 		}
+
+		if service.Spec.Annotations.Name != request.Spec.Annotations.Name {
+			return errRenameNotSupported
+		}
+
 		service.Meta.Version = *request.ServiceVersion
 		service.PreviousSpec = service.Spec.Copy()
 		service.Spec = *request.Spec.Copy()

+ 3 - 2
vendor/src/github.com/docker/swarmkit/manager/controlapi/task.go

@@ -2,6 +2,7 @@ package controlapi
 
 import (
 	"github.com/docker/swarmkit/api"
+	"github.com/docker/swarmkit/api/naming"
 	"github.com/docker/swarmkit/manager/state/store"
 	"golang.org/x/net/context"
 	"google.golang.org/grpc"
@@ -104,10 +105,10 @@ func (s *Server) ListTasks(ctx context.Context, request *api.ListTasksRequest) (
 	if request.Filters != nil {
 		tasks = filterTasks(tasks,
 			func(e *api.Task) bool {
-				return filterContains(store.TaskName(e), request.Filters.Names)
+				return filterContains(naming.Task(e), request.Filters.Names)
 			},
 			func(e *api.Task) bool {
-				return filterContainsPrefix(store.TaskName(e), request.Filters.NamePrefixes)
+				return filterContainsPrefix(naming.Task(e), request.Filters.NamePrefixes)
 			},
 			func(e *api.Task) bool {
 				return filterContainsPrefix(e.ID, request.Filters.IDPrefixes)

+ 21 - 18
vendor/src/github.com/docker/swarmkit/manager/manager.go

@@ -21,7 +21,10 @@ import (
 	"github.com/docker/swarmkit/manager/dispatcher"
 	"github.com/docker/swarmkit/manager/health"
 	"github.com/docker/swarmkit/manager/keymanager"
-	"github.com/docker/swarmkit/manager/orchestrator"
+	"github.com/docker/swarmkit/manager/orchestrator/constraintenforcer"
+	"github.com/docker/swarmkit/manager/orchestrator/global"
+	"github.com/docker/swarmkit/manager/orchestrator/replicated"
+	"github.com/docker/swarmkit/manager/orchestrator/taskreaper"
 	"github.com/docker/swarmkit/manager/resourceapi"
 	"github.com/docker/swarmkit/manager/scheduler"
 	"github.com/docker/swarmkit/manager/state/raft"
@@ -82,10 +85,10 @@ type Manager struct {
 
 	caserver               *ca.Server
 	dispatcher             *dispatcher.Dispatcher
-	replicatedOrchestrator *orchestrator.ReplicatedOrchestrator
-	globalOrchestrator     *orchestrator.GlobalOrchestrator
-	taskReaper             *orchestrator.TaskReaper
-	constraintEnforcer     *orchestrator.ConstraintEnforcer
+	replicatedOrchestrator *replicated.Orchestrator
+	globalOrchestrator     *global.Orchestrator
+	taskReaper             *taskreaper.TaskReaper
+	constraintEnforcer     *constraintenforcer.ConstraintEnforcer
 	scheduler              *scheduler.Scheduler
 	allocator              *allocator.Allocator
 	keyManager             *keymanager.KeyManager
@@ -263,9 +266,9 @@ func (m *Manager) Run(parent context.Context) error {
 
 	authorize := func(ctx context.Context, roles []string) error {
 		var (
-			removedNodes []*api.RemovedNode
-			clusters     []*api.Cluster
-			err          error
+			blacklistedCerts map[string]*api.BlacklistedCertificate
+			clusters         []*api.Cluster
+			err              error
 		)
 
 		m.raftNode.MemoryStore().View(func(readTx store.ReadTx) {
@@ -276,11 +279,11 @@ func (m *Manager) Run(parent context.Context) error {
 		// Not having a cluster object yet means we can't check
 		// the blacklist.
 		if err == nil && len(clusters) == 1 {
-			removedNodes = clusters[0].RemovedNodes
+			blacklistedCerts = clusters[0].BlacklistedCertificates
 		}
 
 		// Authorize the remote roles, ensure they can only be forwarded by managers
-		_, err = ca.AuthorizeForwardedRoleAndOrg(ctx, roles, []string{ca.ManagerRole}, m.config.SecurityConfig.ClientTLSCreds.Organization(), removedNodes)
+		_, err = ca.AuthorizeForwardedRoleAndOrg(ctx, roles, []string{ca.ManagerRole}, m.config.SecurityConfig.ClientTLSCreds.Organization(), blacklistedCerts)
 		return err
 	}
 
@@ -651,10 +654,10 @@ func (m *Manager) becomeLeader(ctx context.Context) {
 		log.G(ctx).WithError(err).Error("root key-encrypting-key rotation failed")
 	}
 
-	m.replicatedOrchestrator = orchestrator.NewReplicatedOrchestrator(s)
-	m.constraintEnforcer = orchestrator.NewConstraintEnforcer(s)
-	m.globalOrchestrator = orchestrator.NewGlobalOrchestrator(s)
-	m.taskReaper = orchestrator.NewTaskReaper(s)
+	m.replicatedOrchestrator = replicated.NewReplicatedOrchestrator(s)
+	m.constraintEnforcer = constraintenforcer.New(s)
+	m.globalOrchestrator = global.NewGlobalOrchestrator(s)
+	m.taskReaper = taskreaper.New(s)
 	m.scheduler = scheduler.New(s)
 	m.keyManager = keymanager.New(s, keymanager.DefaultConfig())
 
@@ -706,21 +709,21 @@ func (m *Manager) becomeLeader(ctx context.Context) {
 		}
 	}(m.scheduler)
 
-	go func(constraintEnforcer *orchestrator.ConstraintEnforcer) {
+	go func(constraintEnforcer *constraintenforcer.ConstraintEnforcer) {
 		constraintEnforcer.Run()
 	}(m.constraintEnforcer)
 
-	go func(taskReaper *orchestrator.TaskReaper) {
+	go func(taskReaper *taskreaper.TaskReaper) {
 		taskReaper.Run()
 	}(m.taskReaper)
 
-	go func(orchestrator *orchestrator.ReplicatedOrchestrator) {
+	go func(orchestrator *replicated.Orchestrator) {
 		if err := orchestrator.Run(ctx); err != nil {
 			log.G(ctx).WithError(err).Error("replicated orchestrator exited with an error")
 		}
 	}(m.replicatedOrchestrator)
 
-	go func(globalOrchestrator *orchestrator.GlobalOrchestrator) {
+	go func(globalOrchestrator *global.Orchestrator) {
 		if err := globalOrchestrator.Run(ctx); err != nil {
 			log.G(ctx).WithError(err).Error("global orchestrator exited with an error")
 		}

+ 3 - 3
vendor/src/github.com/docker/swarmkit/manager/orchestrator/constraint_enforcer.go → vendor/src/github.com/docker/swarmkit/manager/orchestrator/constraintenforcer/constraint_enforcer.go

@@ -1,4 +1,4 @@
-package orchestrator
+package constraintenforcer
 
 import (
 	"github.com/docker/swarmkit/api"
@@ -16,8 +16,8 @@ type ConstraintEnforcer struct {
 	doneChan chan struct{}
 }
 
-// NewConstraintEnforcer creates a new ConstraintEnforcer.
-func NewConstraintEnforcer(store *store.MemoryStore) *ConstraintEnforcer {
+// New creates a new ConstraintEnforcer.
+func New(store *store.MemoryStore) *ConstraintEnforcer {
 	return &ConstraintEnforcer{
 		store:    store,
 		stopChan: make(chan struct{}),

+ 38 - 43
vendor/src/github.com/docker/swarmkit/manager/orchestrator/global.go → vendor/src/github.com/docker/swarmkit/manager/orchestrator/global/global.go

@@ -1,9 +1,12 @@
-package orchestrator
+package global
 
 import (
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/log"
 	"github.com/docker/swarmkit/manager/constraint"
+	"github.com/docker/swarmkit/manager/orchestrator"
+	"github.com/docker/swarmkit/manager/orchestrator/restart"
+	"github.com/docker/swarmkit/manager/orchestrator/update"
 	"github.com/docker/swarmkit/manager/state"
 	"github.com/docker/swarmkit/manager/state/store"
 	"golang.org/x/net/context"
@@ -16,9 +19,9 @@ type globalService struct {
 	constraints []constraint.Constraint
 }
 
-// GlobalOrchestrator runs a reconciliation loop to create and destroy
-// tasks as necessary for global services.
-type GlobalOrchestrator struct {
+// Orchestrator runs a reconciliation loop to create and destroy tasks as
+// necessary for global services.
+type Orchestrator struct {
 	store *store.MemoryStore
 	// nodes is the set of non-drained nodes in the cluster, indexed by node ID
 	nodes map[string]*api.Node
@@ -30,17 +33,17 @@ type GlobalOrchestrator struct {
 	// doneChan is closed when the state machine terminates.
 	doneChan chan struct{}
 
-	updater  *UpdateSupervisor
-	restarts *RestartSupervisor
+	updater  *update.Supervisor
+	restarts *restart.Supervisor
 
 	cluster *api.Cluster // local instance of the cluster
 }
 
-// NewGlobalOrchestrator creates a new GlobalOrchestrator
-func NewGlobalOrchestrator(store *store.MemoryStore) *GlobalOrchestrator {
-	restartSupervisor := NewRestartSupervisor(store)
-	updater := NewUpdateSupervisor(store, restartSupervisor)
-	return &GlobalOrchestrator{
+// NewGlobalOrchestrator creates a new global Orchestrator
+func NewGlobalOrchestrator(store *store.MemoryStore) *Orchestrator {
+	restartSupervisor := restart.NewSupervisor(store)
+	updater := update.NewSupervisor(store, restartSupervisor)
+	return &Orchestrator{
 		store:          store,
 		nodes:          make(map[string]*api.Node),
 		globalServices: make(map[string]globalService),
@@ -51,8 +54,8 @@ func NewGlobalOrchestrator(store *store.MemoryStore) *GlobalOrchestrator {
 	}
 }
 
-// Run contains the GlobalOrchestrator event loop
-func (g *GlobalOrchestrator) Run(ctx context.Context) error {
+// Run contains the global orchestrator event loop
+func (g *Orchestrator) Run(ctx context.Context) error {
 	defer close(g.doneChan)
 
 	// Watch changes to services and tasks
@@ -98,7 +101,7 @@ func (g *GlobalOrchestrator) Run(ctx context.Context) error {
 
 	var reconcileServiceIDs []string
 	for _, s := range existingServices {
-		if isGlobalService(s) {
+		if orchestrator.IsGlobalService(s) {
 			g.updateService(s)
 			reconcileServiceIDs = append(reconcileServiceIDs, s.ID)
 		}
@@ -113,22 +116,22 @@ func (g *GlobalOrchestrator) Run(ctx context.Context) error {
 			case state.EventUpdateCluster:
 				g.cluster = v.Cluster
 			case state.EventCreateService:
-				if !isGlobalService(v.Service) {
+				if !orchestrator.IsGlobalService(v.Service) {
 					continue
 				}
 				g.updateService(v.Service)
 				g.reconcileServices(ctx, []string{v.Service.ID})
 			case state.EventUpdateService:
-				if !isGlobalService(v.Service) {
+				if !orchestrator.IsGlobalService(v.Service) {
 					continue
 				}
 				g.updateService(v.Service)
 				g.reconcileServices(ctx, []string{v.Service.ID})
 			case state.EventDeleteService:
-				if !isGlobalService(v.Service) {
+				if !orchestrator.IsGlobalService(v.Service) {
 					continue
 				}
-				deleteServiceTasks(ctx, g.store, v.Service)
+				orchestrator.DeleteServiceTasks(ctx, g.store, v.Service)
 				// delete the service from service map
 				delete(g.globalServices, v.Service.ID)
 				g.restarts.ClearServiceHistory(v.Service.ID)
@@ -172,14 +175,14 @@ func (g *GlobalOrchestrator) Run(ctx context.Context) error {
 }
 
 // Stop stops the orchestrator.
-func (g *GlobalOrchestrator) Stop() {
+func (g *Orchestrator) Stop() {
 	close(g.stopChan)
 	<-g.doneChan
 	g.updater.CancelAll()
 	g.restarts.CancelAll()
 }
 
-func (g *GlobalOrchestrator) removeTasksFromNode(ctx context.Context, node *api.Node) {
+func (g *Orchestrator) removeTasksFromNode(ctx context.Context, node *api.Node) {
 	var (
 		tasks []*api.Task
 		err   error
@@ -194,7 +197,7 @@ func (g *GlobalOrchestrator) removeTasksFromNode(ctx context.Context, node *api.
 
 	_, err = g.store.Batch(func(batch *store.Batch) error {
 		for _, t := range tasks {
-			// GlobalOrchestrator only removes tasks from globalServices
+			// Global orchestrator only removes tasks from globalServices
 			if _, exists := g.globalServices[t.ServiceID]; exists {
 				g.removeTask(ctx, batch, t)
 			}
@@ -206,7 +209,7 @@ func (g *GlobalOrchestrator) removeTasksFromNode(ctx context.Context, node *api.
 	}
 }
 
-func (g *GlobalOrchestrator) reconcileServices(ctx context.Context, serviceIDs []string) {
+func (g *Orchestrator) reconcileServices(ctx context.Context, serviceIDs []string) {
 	nodeCompleted := make(map[string]map[string]struct{})
 	nodeTasks := make(map[string]map[string][]*api.Task)
 
@@ -229,7 +232,7 @@ func (g *GlobalOrchestrator) reconcileServices(ctx context.Context, serviceIDs [
 					nodeTasks[serviceID][t.NodeID] = append(nodeTasks[serviceID][t.NodeID], t)
 				} else {
 					// for finished tasks, check restartPolicy
-					if isTaskCompleted(t, restartCondition(t)) {
+					if isTaskCompleted(t, orchestrator.RestartCondition(t)) {
 						nodeCompleted[serviceID][t.NodeID] = struct{}{}
 					}
 				}
@@ -238,7 +241,7 @@ func (g *GlobalOrchestrator) reconcileServices(ctx context.Context, serviceIDs [
 	})
 
 	_, err := g.store.Batch(func(batch *store.Batch) error {
-		var updateTasks []slot
+		var updateTasks []orchestrator.Slot
 		for _, serviceID := range serviceIDs {
 			if _, exists := nodeTasks[serviceID]; !exists {
 				continue
@@ -290,7 +293,7 @@ func (g *GlobalOrchestrator) reconcileServices(ctx context.Context, serviceIDs [
 }
 
 // updateNode updates g.nodes based on the current node value
-func (g *GlobalOrchestrator) updateNode(node *api.Node) {
+func (g *Orchestrator) updateNode(node *api.Node) {
 	if node.Spec.Availability == api.NodeAvailabilityDrain {
 		delete(g.nodes, node.ID)
 	} else {
@@ -299,7 +302,7 @@ func (g *GlobalOrchestrator) updateNode(node *api.Node) {
 }
 
 // updateService updates g.globalServices based on the current service value
-func (g *GlobalOrchestrator) updateService(service *api.Service) {
+func (g *Orchestrator) updateService(service *api.Service) {
 	var constraints []constraint.Constraint
 
 	if service.Spec.Task.Placement != nil && len(service.Spec.Task.Placement.Constraints) != 0 {
@@ -313,7 +316,7 @@ func (g *GlobalOrchestrator) updateService(service *api.Service) {
 }
 
 // reconcileOneNode checks all global services on one node
-func (g *GlobalOrchestrator) reconcileOneNode(ctx context.Context, node *api.Node) {
+func (g *Orchestrator) reconcileOneNode(ctx context.Context, node *api.Node) {
 	if node.Spec.Availability == api.NodeAvailabilityDrain {
 		log.G(ctx).Debugf("global orchestrator: node %s in drain state, removing tasks from it", node.ID)
 		g.removeTasksFromNode(ctx, node)
@@ -328,7 +331,7 @@ func (g *GlobalOrchestrator) reconcileOneNode(ctx context.Context, node *api.Nod
 }
 
 // reconcileServicesOneNode checks the specified services on one node
-func (g *GlobalOrchestrator) reconcileServicesOneNode(ctx context.Context, serviceIDs []string, nodeID string) {
+func (g *Orchestrator) reconcileServicesOneNode(ctx context.Context, serviceIDs []string, nodeID string) {
 	node, exists := g.nodes[nodeID]
 	if !exists {
 		return
@@ -360,7 +363,7 @@ func (g *GlobalOrchestrator) reconcileServicesOneNode(ctx context.Context, servi
 			if isTaskRunning(t) {
 				tasks[serviceID] = append(tasks[serviceID], t)
 			} else {
-				if isTaskCompleted(t, restartCondition(t)) {
+				if isTaskCompleted(t, orchestrator.RestartCondition(t)) {
 					completed[serviceID] = true
 				}
 			}
@@ -413,7 +416,7 @@ func (g *GlobalOrchestrator) reconcileServicesOneNode(ctx context.Context, servi
 				)
 
 				for _, t := range tasks[serviceID] {
-					if isTaskDirty(service.Service, t) {
+					if orchestrator.IsTaskDirty(service.Service, t) {
 						dirtyTasks = append(dirtyTasks, t)
 					} else {
 						cleanTasks = append(cleanTasks, t)
@@ -438,7 +441,7 @@ func (g *GlobalOrchestrator) reconcileServicesOneNode(ctx context.Context, servi
 // restartTask calls the restart supervisor's Restart function, which
 // sets a task's desired state to shutdown and restarts it if the restart
 // policy calls for it to be restarted.
-func (g *GlobalOrchestrator) restartTask(ctx context.Context, taskID string, serviceID string) {
+func (g *Orchestrator) restartTask(ctx context.Context, taskID string, serviceID string) {
 	err := g.store.Update(func(tx store.Tx) error {
 		t := store.GetTask(tx, taskID)
 		if t == nil || t.DesiredState > api.TaskStateRunning {
@@ -455,7 +458,7 @@ func (g *GlobalOrchestrator) restartTask(ctx context.Context, taskID string, ser
 	}
 }
 
-func (g *GlobalOrchestrator) removeTask(ctx context.Context, batch *store.Batch, t *api.Task) {
+func (g *Orchestrator) removeTask(ctx context.Context, batch *store.Batch, t *api.Task) {
 	// set existing task DesiredState to TaskStateShutdown
 	// TODO(aaronl): optimistic update?
 	err := batch.Update(func(tx store.Tx) error {
@@ -471,8 +474,8 @@ func (g *GlobalOrchestrator) removeTask(ctx context.Context, batch *store.Batch,
 	}
 }
 
-func (g *GlobalOrchestrator) addTask(ctx context.Context, batch *store.Batch, service *api.Service, nodeID string) {
-	task := newTask(g.cluster, service, 0, nodeID)
+func (g *Orchestrator) addTask(ctx context.Context, batch *store.Batch, service *api.Service, nodeID string) {
+	task := orchestrator.NewTask(g.cluster, service, 0, nodeID)
 
 	err := batch.Update(func(tx store.Tx) error {
 		return store.CreateTask(tx, task)
@@ -482,7 +485,7 @@ func (g *GlobalOrchestrator) addTask(ctx context.Context, batch *store.Batch, se
 	}
 }
 
-func (g *GlobalOrchestrator) removeTasks(ctx context.Context, batch *store.Batch, tasks []*api.Task) {
+func (g *Orchestrator) removeTasks(ctx context.Context, batch *store.Batch, tasks []*api.Task) {
 	for _, t := range tasks {
 		g.removeTask(ctx, batch, t)
 	}
@@ -503,11 +506,3 @@ func isTaskCompleted(t *api.Task, restartPolicy api.RestartPolicy_RestartConditi
 func isTaskTerminated(t *api.Task) bool {
 	return t != nil && t.Status.State > api.TaskStateRunning
 }
-
-func isGlobalService(service *api.Service) bool {
-	if service == nil {
-		return false
-	}
-	_, ok := service.Spec.GetMode().(*api.ServiceSpec_Global)
-	return ok
-}

+ 0 - 203
vendor/src/github.com/docker/swarmkit/manager/orchestrator/replicated.go

@@ -1,203 +0,0 @@
-package orchestrator
-
-import (
-	"time"
-
-	"github.com/docker/swarmkit/api"
-	"github.com/docker/swarmkit/identity"
-	"github.com/docker/swarmkit/log"
-	"github.com/docker/swarmkit/manager/state"
-	"github.com/docker/swarmkit/manager/state/store"
-	"github.com/docker/swarmkit/protobuf/ptypes"
-	"golang.org/x/net/context"
-)
-
-// A ReplicatedOrchestrator runs a reconciliation loop to create and destroy
-// tasks as necessary for the replicated services.
-type ReplicatedOrchestrator struct {
-	store *store.MemoryStore
-
-	reconcileServices map[string]*api.Service
-	restartTasks      map[string]struct{}
-
-	// stopChan signals to the state machine to stop running.
-	stopChan chan struct{}
-	// doneChan is closed when the state machine terminates.
-	doneChan chan struct{}
-
-	updater  *UpdateSupervisor
-	restarts *RestartSupervisor
-
-	cluster *api.Cluster // local cluster instance
-}
-
-// NewReplicatedOrchestrator creates a new ReplicatedOrchestrator.
-func NewReplicatedOrchestrator(store *store.MemoryStore) *ReplicatedOrchestrator {
-	restartSupervisor := NewRestartSupervisor(store)
-	updater := NewUpdateSupervisor(store, restartSupervisor)
-	return &ReplicatedOrchestrator{
-		store:             store,
-		stopChan:          make(chan struct{}),
-		doneChan:          make(chan struct{}),
-		reconcileServices: make(map[string]*api.Service),
-		restartTasks:      make(map[string]struct{}),
-		updater:           updater,
-		restarts:          restartSupervisor,
-	}
-}
-
-// Run contains the orchestrator event loop. It runs until Stop is called.
-func (r *ReplicatedOrchestrator) Run(ctx context.Context) error {
-	defer close(r.doneChan)
-
-	// Watch changes to services and tasks
-	queue := r.store.WatchQueue()
-	watcher, cancel := queue.Watch()
-	defer cancel()
-
-	// Balance existing services and drain initial tasks attached to invalid
-	// nodes
-	var err error
-	r.store.View(func(readTx store.ReadTx) {
-		if err = r.initTasks(ctx, readTx); err != nil {
-			return
-		}
-
-		if err = r.initServices(readTx); err != nil {
-			return
-		}
-
-		if err = r.initCluster(readTx); err != nil {
-			return
-		}
-	})
-	if err != nil {
-		return err
-	}
-
-	r.tick(ctx)
-
-	for {
-		select {
-		case event := <-watcher:
-			// TODO(stevvooe): Use ctx to limit running time of operation.
-			r.handleTaskEvent(ctx, event)
-			r.handleServiceEvent(ctx, event)
-			switch v := event.(type) {
-			case state.EventCommit:
-				r.tick(ctx)
-			case state.EventUpdateCluster:
-				r.cluster = v.Cluster
-			}
-		case <-r.stopChan:
-			return nil
-		}
-	}
-}
-
-// Stop stops the orchestrator.
-func (r *ReplicatedOrchestrator) Stop() {
-	close(r.stopChan)
-	<-r.doneChan
-	r.updater.CancelAll()
-	r.restarts.CancelAll()
-}
-
-func (r *ReplicatedOrchestrator) tick(ctx context.Context) {
-	// tickTasks must be called first, so we respond to task-level changes
-	// before performing service reconcillation.
-	r.tickTasks(ctx)
-	r.tickServices(ctx)
-}
-
-func newTask(cluster *api.Cluster, service *api.Service, slot uint64, nodeID string) *api.Task {
-	var logDriver *api.Driver
-	if service.Spec.Task.LogDriver != nil {
-		// use the log driver specific to the task, if we have it.
-		logDriver = service.Spec.Task.LogDriver
-	} else if cluster != nil {
-		// pick up the cluster default, if available.
-		logDriver = cluster.Spec.TaskDefaults.LogDriver // nil is okay here.
-	}
-
-	taskID := identity.NewID()
-	task := api.Task{
-		ID:                 taskID,
-		ServiceAnnotations: service.Spec.Annotations,
-		Spec:               service.Spec.Task,
-		ServiceID:          service.ID,
-		Slot:               slot,
-		Status: api.TaskStatus{
-			State:     api.TaskStateNew,
-			Timestamp: ptypes.MustTimestampProto(time.Now()),
-			Message:   "created",
-		},
-		Endpoint: &api.Endpoint{
-			Spec: service.Spec.Endpoint.Copy(),
-		},
-		DesiredState: api.TaskStateRunning,
-		LogDriver:    logDriver,
-	}
-
-	// In global mode we also set the NodeID
-	if nodeID != "" {
-		task.NodeID = nodeID
-	}
-
-	// Assign name based on task name schema
-	name := store.TaskName(&task)
-	task.Annotations = api.Annotations{Name: name}
-
-	return &task
-}
-
-// isReplicatedService checks if a service is a replicated service
-func isReplicatedService(service *api.Service) bool {
-	// service nil validation is required as there are scenarios
-	// where service is removed from store
-	if service == nil {
-		return false
-	}
-	_, ok := service.Spec.GetMode().(*api.ServiceSpec_Replicated)
-	return ok
-}
-
-func deleteServiceTasks(ctx context.Context, s *store.MemoryStore, service *api.Service) {
-	var (
-		tasks []*api.Task
-		err   error
-	)
-	s.View(func(tx store.ReadTx) {
-		tasks, err = store.FindTasks(tx, store.ByServiceID(service.ID))
-	})
-	if err != nil {
-		log.G(ctx).WithError(err).Errorf("failed to list tasks")
-		return
-	}
-
-	_, err = s.Batch(func(batch *store.Batch) error {
-		for _, t := range tasks {
-			err := batch.Update(func(tx store.Tx) error {
-				if err := store.DeleteTask(tx, t.ID); err != nil {
-					log.G(ctx).WithError(err).Errorf("failed to delete task")
-				}
-				return nil
-			})
-			if err != nil {
-				return err
-			}
-		}
-		return nil
-	})
-	if err != nil {
-		log.G(ctx).WithError(err).Errorf("task search transaction failed")
-	}
-}
-
-func restartCondition(task *api.Task) api.RestartPolicy_RestartCondition {
-	restartCondition := api.RestartOnAny
-	if task.Spec.Restart != nil {
-		restartCondition = task.Spec.Restart.Condition
-	}
-	return restartCondition
-}

+ 108 - 0
vendor/src/github.com/docker/swarmkit/manager/orchestrator/replicated/replicated.go

@@ -0,0 +1,108 @@
+package replicated
+
+import (
+	"github.com/docker/swarmkit/api"
+	"github.com/docker/swarmkit/manager/orchestrator/restart"
+	"github.com/docker/swarmkit/manager/orchestrator/update"
+	"github.com/docker/swarmkit/manager/state"
+	"github.com/docker/swarmkit/manager/state/store"
+	"golang.org/x/net/context"
+)
+
+// An Orchestrator runs a reconciliation loop to create and destroy
+// tasks as necessary for the replicated services.
+type Orchestrator struct {
+	store *store.MemoryStore
+
+	reconcileServices map[string]*api.Service
+	restartTasks      map[string]struct{}
+
+	// stopChan signals to the state machine to stop running.
+	stopChan chan struct{}
+	// doneChan is closed when the state machine terminates.
+	doneChan chan struct{}
+
+	updater  *update.Supervisor
+	restarts *restart.Supervisor
+
+	cluster *api.Cluster // local cluster instance
+}
+
+// NewReplicatedOrchestrator creates a new replicated Orchestrator.
+func NewReplicatedOrchestrator(store *store.MemoryStore) *Orchestrator {
+	restartSupervisor := restart.NewSupervisor(store)
+	updater := update.NewSupervisor(store, restartSupervisor)
+	return &Orchestrator{
+		store:             store,
+		stopChan:          make(chan struct{}),
+		doneChan:          make(chan struct{}),
+		reconcileServices: make(map[string]*api.Service),
+		restartTasks:      make(map[string]struct{}),
+		updater:           updater,
+		restarts:          restartSupervisor,
+	}
+}
+
+// Run contains the orchestrator event loop. It runs until Stop is called.
+func (r *Orchestrator) Run(ctx context.Context) error {
+	defer close(r.doneChan)
+
+	// Watch changes to services and tasks
+	queue := r.store.WatchQueue()
+	watcher, cancel := queue.Watch()
+	defer cancel()
+
+	// Balance existing services and drain initial tasks attached to invalid
+	// nodes
+	var err error
+	r.store.View(func(readTx store.ReadTx) {
+		if err = r.initTasks(ctx, readTx); err != nil {
+			return
+		}
+
+		if err = r.initServices(readTx); err != nil {
+			return
+		}
+
+		if err = r.initCluster(readTx); err != nil {
+			return
+		}
+	})
+	if err != nil {
+		return err
+	}
+
+	r.tick(ctx)
+
+	for {
+		select {
+		case event := <-watcher:
+			// TODO(stevvooe): Use ctx to limit running time of operation.
+			r.handleTaskEvent(ctx, event)
+			r.handleServiceEvent(ctx, event)
+			switch v := event.(type) {
+			case state.EventCommit:
+				r.tick(ctx)
+			case state.EventUpdateCluster:
+				r.cluster = v.Cluster
+			}
+		case <-r.stopChan:
+			return nil
+		}
+	}
+}
+
+// Stop stops the orchestrator.
+func (r *Orchestrator) Stop() {
+	close(r.stopChan)
+	<-r.doneChan
+	r.updater.CancelAll()
+	r.restarts.CancelAll()
+}
+
+func (r *Orchestrator) tick(ctx context.Context) {
+	// tickTasks must be called first, so we respond to task-level changes
+	// before performing service reconcillation.
+	r.tickTasks(ctx)
+	r.tickServices(ctx)
+}

+ 21 - 53
vendor/src/github.com/docker/swarmkit/manager/orchestrator/services.go → vendor/src/github.com/docker/swarmkit/manager/orchestrator/replicated/services.go

@@ -1,4 +1,4 @@
-package orchestrator
+package replicated
 
 import (
 	"sort"
@@ -6,6 +6,7 @@ import (
 	"github.com/docker/go-events"
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/log"
+	"github.com/docker/swarmkit/manager/orchestrator"
 	"github.com/docker/swarmkit/manager/state"
 	"github.com/docker/swarmkit/manager/state/store"
 	"golang.org/x/net/context"
@@ -16,7 +17,7 @@ import (
 // specifications. This is different from task-level orchestration, which
 // responds to changes in individual tasks (or nodes which run them).
 
-func (r *ReplicatedOrchestrator) initCluster(readTx store.ReadTx) error {
+func (r *Orchestrator) initCluster(readTx store.ReadTx) error {
 	clusters, err := store.FindClusters(readTx, store.ByName("default"))
 	if err != nil {
 		return err
@@ -31,41 +32,41 @@ func (r *ReplicatedOrchestrator) initCluster(readTx store.ReadTx) error {
 	return nil
 }
 
-func (r *ReplicatedOrchestrator) initServices(readTx store.ReadTx) error {
+func (r *Orchestrator) initServices(readTx store.ReadTx) error {
 	services, err := store.FindServices(readTx, store.All)
 	if err != nil {
 		return err
 	}
 	for _, s := range services {
-		if isReplicatedService(s) {
+		if orchestrator.IsReplicatedService(s) {
 			r.reconcileServices[s.ID] = s
 		}
 	}
 	return nil
 }
 
-func (r *ReplicatedOrchestrator) handleServiceEvent(ctx context.Context, event events.Event) {
+func (r *Orchestrator) handleServiceEvent(ctx context.Context, event events.Event) {
 	switch v := event.(type) {
 	case state.EventDeleteService:
-		if !isReplicatedService(v.Service) {
+		if !orchestrator.IsReplicatedService(v.Service) {
 			return
 		}
-		deleteServiceTasks(ctx, r.store, v.Service)
+		orchestrator.DeleteServiceTasks(ctx, r.store, v.Service)
 		r.restarts.ClearServiceHistory(v.Service.ID)
 	case state.EventCreateService:
-		if !isReplicatedService(v.Service) {
+		if !orchestrator.IsReplicatedService(v.Service) {
 			return
 		}
 		r.reconcileServices[v.Service.ID] = v.Service
 	case state.EventUpdateService:
-		if !isReplicatedService(v.Service) {
+		if !orchestrator.IsReplicatedService(v.Service) {
 			return
 		}
 		r.reconcileServices[v.Service.ID] = v.Service
 	}
 }
 
-func (r *ReplicatedOrchestrator) tickServices(ctx context.Context) {
+func (r *Orchestrator) tickServices(ctx context.Context) {
 	if len(r.reconcileServices) > 0 {
 		for _, s := range r.reconcileServices {
 			r.reconcile(ctx, s)
@@ -74,7 +75,7 @@ func (r *ReplicatedOrchestrator) tickServices(ctx context.Context) {
 	}
 }
 
-func (r *ReplicatedOrchestrator) resolveService(ctx context.Context, task *api.Task) *api.Service {
+func (r *Orchestrator) resolveService(ctx context.Context, task *api.Task) *api.Service {
 	if task.ServiceID == "" {
 		return nil
 	}
@@ -85,8 +86,8 @@ func (r *ReplicatedOrchestrator) resolveService(ctx context.Context, task *api.T
 	return service
 }
 
-func (r *ReplicatedOrchestrator) reconcile(ctx context.Context, service *api.Service) {
-	runningSlots, deadSlots, err := getRunnableAndDeadSlots(r.store, service.ID)
+func (r *Orchestrator) reconcile(ctx context.Context, service *api.Service) {
+	runningSlots, deadSlots, err := orchestrator.GetRunnableAndDeadSlots(r.store, service.ID)
 	if err != nil {
 		log.G(ctx).WithError(err).Errorf("reconcile failed finding tasks")
 		return
@@ -94,7 +95,7 @@ func (r *ReplicatedOrchestrator) reconcile(ctx context.Context, service *api.Ser
 
 	numSlots := len(runningSlots)
 
-	slotsSlice := make([]slot, 0, numSlots)
+	slotsSlice := make([]orchestrator.Slot, 0, numSlots)
 	for _, slot := range runningSlots {
 		slotsSlice = append(slotsSlice, slot)
 	}
@@ -148,7 +149,7 @@ func (r *ReplicatedOrchestrator) reconcile(ctx context.Context, service *api.Ser
 
 		sort.Sort(slotsWithIndices)
 
-		sortedSlots := make([]slot, 0, numSlots)
+		sortedSlots := make([]orchestrator.Slot, 0, numSlots)
 		for _, slot := range slotsWithIndices {
 			sortedSlots = append(sortedSlots, slot.slot)
 		}
@@ -176,7 +177,7 @@ func (r *ReplicatedOrchestrator) reconcile(ctx context.Context, service *api.Ser
 	}
 }
 
-func (r *ReplicatedOrchestrator) addTasks(ctx context.Context, batch *store.Batch, service *api.Service, runningSlots map[uint64]slot, deadSlots map[uint64]slot, count int) {
+func (r *Orchestrator) addTasks(ctx context.Context, batch *store.Batch, service *api.Service, runningSlots map[uint64]orchestrator.Slot, deadSlots map[uint64]orchestrator.Slot, count int) {
 	slot := uint64(0)
 	for i := 0; i < count; i++ {
 		// Find an slot number that is missing a running task
@@ -189,7 +190,7 @@ func (r *ReplicatedOrchestrator) addTasks(ctx context.Context, batch *store.Batc
 
 		delete(deadSlots, slot)
 		err := batch.Update(func(tx store.Tx) error {
-			return store.CreateTask(tx, newTask(r.cluster, service, slot, ""))
+			return store.CreateTask(tx, orchestrator.NewTask(r.cluster, service, slot, ""))
 		})
 		if err != nil {
 			log.G(ctx).Errorf("Failed to create task: %v", err)
@@ -197,7 +198,7 @@ func (r *ReplicatedOrchestrator) addTasks(ctx context.Context, batch *store.Batc
 	}
 }
 
-func (r *ReplicatedOrchestrator) deleteTasks(ctx context.Context, batch *store.Batch, slots []slot) {
+func (r *Orchestrator) deleteTasks(ctx context.Context, batch *store.Batch, slots []orchestrator.Slot) {
 	for _, slot := range slots {
 		for _, t := range slot {
 			r.deleteTask(ctx, batch, t)
@@ -205,7 +206,7 @@ func (r *ReplicatedOrchestrator) deleteTasks(ctx context.Context, batch *store.B
 	}
 }
 
-func (r *ReplicatedOrchestrator) deleteTasksMap(ctx context.Context, batch *store.Batch, slots map[uint64]slot) {
+func (r *Orchestrator) deleteTasksMap(ctx context.Context, batch *store.Batch, slots map[uint64]orchestrator.Slot) {
 	for _, slot := range slots {
 		for _, t := range slot {
 			r.deleteTask(ctx, batch, t)
@@ -213,7 +214,7 @@ func (r *ReplicatedOrchestrator) deleteTasksMap(ctx context.Context, batch *stor
 	}
 }
 
-func (r *ReplicatedOrchestrator) deleteTask(ctx context.Context, batch *store.Batch, t *api.Task) {
+func (r *Orchestrator) deleteTask(ctx context.Context, batch *store.Batch, t *api.Task) {
 	err := batch.Update(func(tx store.Tx) error {
 		return store.DeleteTask(tx, t.ID)
 	})
@@ -221,36 +222,3 @@ func (r *ReplicatedOrchestrator) deleteTask(ctx context.Context, batch *store.Ba
 		log.G(ctx).WithError(err).Errorf("deleting task %s failed", t.ID)
 	}
 }
-
-// getRunnableAndDeadSlots returns two maps of slots. The first contains slots
-// that have at least one task with a desired state above NEW and lesser or
-// equal to RUNNING. The second is for slots that only contain tasks with a
-// desired state above RUNNING.
-func getRunnableAndDeadSlots(s *store.MemoryStore, serviceID string) (map[uint64]slot, map[uint64]slot, error) {
-	var (
-		tasks []*api.Task
-		err   error
-	)
-	s.View(func(tx store.ReadTx) {
-		tasks, err = store.FindTasks(tx, store.ByServiceID(serviceID))
-	})
-	if err != nil {
-		return nil, nil, err
-	}
-
-	runningSlots := make(map[uint64]slot)
-	for _, t := range tasks {
-		if t.DesiredState <= api.TaskStateRunning {
-			runningSlots[t.Slot] = append(runningSlots[t.Slot], t)
-		}
-	}
-
-	deadSlots := make(map[uint64]slot)
-	for _, t := range tasks {
-		if _, exists := runningSlots[t.Slot]; !exists {
-			deadSlots[t.Slot] = append(deadSlots[t.Slot], t)
-		}
-	}
-
-	return runningSlots, deadSlots, nil
-}

+ 55 - 0
vendor/src/github.com/docker/swarmkit/manager/orchestrator/replicated/slot.go

@@ -0,0 +1,55 @@
+package replicated
+
+import (
+	"github.com/docker/swarmkit/api"
+	"github.com/docker/swarmkit/manager/orchestrator"
+)
+
+type slotsByRunningState []orchestrator.Slot
+
+func (is slotsByRunningState) Len() int      { return len(is) }
+func (is slotsByRunningState) Swap(i, j int) { is[i], is[j] = is[j], is[i] }
+
+func (is slotsByRunningState) Less(i, j int) bool {
+	iRunning := false
+	jRunning := false
+
+	for _, ii := range is[i] {
+		if ii.Status.State == api.TaskStateRunning {
+			iRunning = true
+			break
+		}
+	}
+	for _, ij := range is[j] {
+		if ij.Status.State == api.TaskStateRunning {
+			jRunning = true
+			break
+		}
+	}
+
+	return iRunning && !jRunning
+}
+
+type slotWithIndex struct {
+	slot orchestrator.Slot
+
+	// index is a counter that counts this task as the nth instance of
+	// the service on its node. This is used for sorting the tasks so that
+	// when scaling down we leave tasks more evenly balanced.
+	index int
+}
+
+type slotsByIndex []slotWithIndex
+
+func (is slotsByIndex) Len() int      { return len(is) }
+func (is slotsByIndex) Swap(i, j int) { is[i], is[j] = is[j], is[i] }
+
+func (is slotsByIndex) Less(i, j int) bool {
+	if is[i].index < 0 && is[j].index >= 0 {
+		return false
+	}
+	if is[j].index < 0 && is[i].index >= 0 {
+		return true
+	}
+	return is[i].index < is[j].index
+}

+ 16 - 15
vendor/src/github.com/docker/swarmkit/manager/orchestrator/tasks.go → vendor/src/github.com/docker/swarmkit/manager/orchestrator/replicated/tasks.go

@@ -1,4 +1,4 @@
-package orchestrator
+package replicated
 
 import (
 	"time"
@@ -6,6 +6,7 @@ import (
 	"github.com/docker/go-events"
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/log"
+	"github.com/docker/swarmkit/manager/orchestrator"
 	"github.com/docker/swarmkit/manager/state"
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/docker/swarmkit/protobuf/ptypes"
@@ -23,7 +24,7 @@ func invalidNode(n *api.Node) bool {
 		n.Spec.Availability == api.NodeAvailabilityDrain
 }
 
-func (r *ReplicatedOrchestrator) initTasks(ctx context.Context, readTx store.ReadTx) error {
+func (r *Orchestrator) initTasks(ctx context.Context, readTx store.ReadTx) error {
 	tasks, err := store.FindTasks(readTx, store.All)
 	if err != nil {
 		return err
@@ -56,16 +57,16 @@ func (r *ReplicatedOrchestrator) initTasks(ctx context.Context, readTx store.Rea
 				continue
 			}
 			// TODO(aluzzardi): This is shady. We should have a more generic condition.
-			if t.DesiredState != api.TaskStateReady || !isReplicatedService(service) {
+			if t.DesiredState != api.TaskStateReady || !orchestrator.IsReplicatedService(service) {
 				continue
 			}
-			restartDelay := defaultRestartDelay
+			restartDelay := orchestrator.DefaultRestartDelay
 			if t.Spec.Restart != nil && t.Spec.Restart.Delay != nil {
 				var err error
 				restartDelay, err = ptypes.Duration(t.Spec.Restart.Delay)
 				if err != nil {
 					log.G(ctx).WithError(err).Error("invalid restart delay")
-					restartDelay = defaultRestartDelay
+					restartDelay = orchestrator.DefaultRestartDelay
 				}
 			}
 			if restartDelay != 0 {
@@ -107,7 +108,7 @@ func (r *ReplicatedOrchestrator) initTasks(ctx context.Context, readTx store.Rea
 	return err
 }
 
-func (r *ReplicatedOrchestrator) handleTaskEvent(ctx context.Context, event events.Event) {
+func (r *Orchestrator) handleTaskEvent(ctx context.Context, event events.Event) {
 	switch v := event.(type) {
 	case state.EventDeleteNode:
 		r.restartTasksByNodeID(ctx, v.Node.ID)
@@ -118,7 +119,7 @@ func (r *ReplicatedOrchestrator) handleTaskEvent(ctx context.Context, event even
 	case state.EventDeleteTask:
 		if v.Task.DesiredState <= api.TaskStateRunning {
 			service := r.resolveService(ctx, v.Task)
-			if !isReplicatedService(service) {
+			if !orchestrator.IsReplicatedService(service) {
 				return
 			}
 			r.reconcileServices[service.ID] = service
@@ -131,7 +132,7 @@ func (r *ReplicatedOrchestrator) handleTaskEvent(ctx context.Context, event even
 	}
 }
 
-func (r *ReplicatedOrchestrator) tickTasks(ctx context.Context) {
+func (r *Orchestrator) tickTasks(ctx context.Context) {
 	if len(r.restartTasks) > 0 {
 		_, err := r.store.Batch(func(batch *store.Batch) error {
 			for taskID := range r.restartTasks {
@@ -144,7 +145,7 @@ func (r *ReplicatedOrchestrator) tickTasks(ctx context.Context) {
 						}
 
 						service := store.GetService(tx, t.ServiceID)
-						if !isReplicatedService(service) {
+						if !orchestrator.IsReplicatedService(service) {
 							return nil
 						}
 
@@ -156,7 +157,7 @@ func (r *ReplicatedOrchestrator) tickTasks(ctx context.Context) {
 					return nil
 				})
 				if err != nil {
-					log.G(ctx).WithError(err).Errorf("ReplicatedOrchestrator task reaping transaction failed")
+					log.G(ctx).WithError(err).Errorf("Orchestrator task reaping transaction failed")
 				}
 			}
 			return nil
@@ -170,7 +171,7 @@ func (r *ReplicatedOrchestrator) tickTasks(ctx context.Context) {
 	}
 }
 
-func (r *ReplicatedOrchestrator) restartTasksByNodeID(ctx context.Context, nodeID string) {
+func (r *Orchestrator) restartTasksByNodeID(ctx context.Context, nodeID string) {
 	var err error
 	r.store.View(func(tx store.ReadTx) {
 		var tasks []*api.Task
@@ -184,7 +185,7 @@ func (r *ReplicatedOrchestrator) restartTasksByNodeID(ctx context.Context, nodeI
 				continue
 			}
 			service := store.GetService(tx, t.ServiceID)
-			if isReplicatedService(service) {
+			if orchestrator.IsReplicatedService(service) {
 				r.restartTasks[t.ID] = struct{}{}
 			}
 		}
@@ -194,7 +195,7 @@ func (r *ReplicatedOrchestrator) restartTasksByNodeID(ctx context.Context, nodeI
 	}
 }
 
-func (r *ReplicatedOrchestrator) handleNodeChange(ctx context.Context, n *api.Node) {
+func (r *Orchestrator) handleNodeChange(ctx context.Context, n *api.Node) {
 	if !invalidNode(n) {
 		return
 	}
@@ -202,7 +203,7 @@ func (r *ReplicatedOrchestrator) handleNodeChange(ctx context.Context, n *api.No
 	r.restartTasksByNodeID(ctx, n.ID)
 }
 
-func (r *ReplicatedOrchestrator) handleTaskChange(ctx context.Context, t *api.Task) {
+func (r *Orchestrator) handleTaskChange(ctx context.Context, t *api.Task) {
 	// If we already set the desired state past TaskStateRunning, there is no
 	// further action necessary.
 	if t.DesiredState > api.TaskStateRunning {
@@ -222,7 +223,7 @@ func (r *ReplicatedOrchestrator) handleTaskChange(ctx context.Context, t *api.Ta
 		}
 	})
 
-	if !isReplicatedService(service) {
+	if !orchestrator.IsReplicatedService(service) {
 		return
 	}
 

+ 33 - 27
vendor/src/github.com/docker/swarmkit/manager/orchestrator/restart.go → vendor/src/github.com/docker/swarmkit/manager/orchestrator/restart/restart.go

@@ -1,4 +1,4 @@
-package orchestrator
+package restart
 
 import (
 	"container/list"
@@ -9,6 +9,7 @@ import (
 	"github.com/docker/go-events"
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/log"
+	"github.com/docker/swarmkit/manager/orchestrator"
 	"github.com/docker/swarmkit/manager/state"
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/docker/swarmkit/protobuf/ptypes"
@@ -16,7 +17,6 @@ import (
 )
 
 const defaultOldTaskTimeout = time.Minute
-const defaultRestartDelay = 5 * time.Second
 
 type restartedInstance struct {
 	timestamp time.Time
@@ -41,29 +41,35 @@ type delayedStart struct {
 	waiter bool
 }
 
-// RestartSupervisor initiates and manages restarts. It's responsible for
+type instanceTuple struct {
+	instance  uint64 // unset for global tasks
+	serviceID string
+	nodeID    string // unset for replicated tasks
+}
+
+// Supervisor initiates and manages restarts. It's responsible for
 // delaying restarts when applicable.
-type RestartSupervisor struct {
+type Supervisor struct {
 	mu               sync.Mutex
 	store            *store.MemoryStore
 	delays           map[string]*delayedStart
 	history          map[instanceTuple]*instanceRestartInfo
 	historyByService map[string]map[instanceTuple]struct{}
-	taskTimeout      time.Duration
+	TaskTimeout      time.Duration
 }
 
-// NewRestartSupervisor creates a new RestartSupervisor.
-func NewRestartSupervisor(store *store.MemoryStore) *RestartSupervisor {
-	return &RestartSupervisor{
+// NewSupervisor creates a new RestartSupervisor.
+func NewSupervisor(store *store.MemoryStore) *Supervisor {
+	return &Supervisor{
 		store:            store,
 		delays:           make(map[string]*delayedStart),
 		history:          make(map[instanceTuple]*instanceRestartInfo),
 		historyByService: make(map[string]map[instanceTuple]struct{}),
-		taskTimeout:      defaultOldTaskTimeout,
+		TaskTimeout:      defaultOldTaskTimeout,
 	}
 }
 
-func (r *RestartSupervisor) waitRestart(ctx context.Context, oldDelay *delayedStart, cluster *api.Cluster, taskID string) {
+func (r *Supervisor) waitRestart(ctx context.Context, oldDelay *delayedStart, cluster *api.Cluster, taskID string) {
 	// Wait for the last restart delay to elapse.
 	select {
 	case <-oldDelay.doneCh:
@@ -94,7 +100,7 @@ func (r *RestartSupervisor) waitRestart(ctx context.Context, oldDelay *delayedSt
 
 // Restart initiates a new task to replace t if appropriate under the service's
 // restart policy.
-func (r *RestartSupervisor) Restart(ctx context.Context, tx store.Tx, cluster *api.Cluster, service *api.Service, t api.Task) error {
+func (r *Supervisor) Restart(ctx context.Context, tx store.Tx, cluster *api.Cluster, service *api.Service, t api.Task) error {
 	// TODO(aluzzardi): This function should not depend on `service`.
 
 	// Is the old task still in the process of restarting? If so, wait for
@@ -132,10 +138,10 @@ func (r *RestartSupervisor) Restart(ctx context.Context, tx store.Tx, cluster *a
 
 	var restartTask *api.Task
 
-	if isReplicatedService(service) {
-		restartTask = newTask(cluster, service, t.Slot, "")
-	} else if isGlobalService(service) {
-		restartTask = newTask(cluster, service, 0, t.NodeID)
+	if orchestrator.IsReplicatedService(service) {
+		restartTask = orchestrator.NewTask(cluster, service, t.Slot, "")
+	} else if orchestrator.IsGlobalService(service) {
+		restartTask = orchestrator.NewTask(cluster, service, 0, t.NodeID)
 	} else {
 		log.G(ctx).Error("service not supported by restart supervisor")
 		return nil
@@ -153,10 +159,10 @@ func (r *RestartSupervisor) Restart(ctx context.Context, tx store.Tx, cluster *a
 			restartDelay, err = ptypes.Duration(t.Spec.Restart.Delay)
 			if err != nil {
 				log.G(ctx).WithError(err).Error("invalid restart delay; using default")
-				restartDelay = defaultRestartDelay
+				restartDelay = orchestrator.DefaultRestartDelay
 			}
 		} else {
-			restartDelay = defaultRestartDelay
+			restartDelay = orchestrator.DefaultRestartDelay
 		}
 	}
 
@@ -179,10 +185,10 @@ func (r *RestartSupervisor) Restart(ctx context.Context, tx store.Tx, cluster *a
 	return nil
 }
 
-func (r *RestartSupervisor) shouldRestart(ctx context.Context, t *api.Task, service *api.Service) bool {
+func (r *Supervisor) shouldRestart(ctx context.Context, t *api.Task, service *api.Service) bool {
 	// TODO(aluzzardi): This function should not depend on `service`.
 
-	condition := restartCondition(t)
+	condition := orchestrator.RestartCondition(t)
 
 	if condition != api.RestartOnAny &&
 		(condition != api.RestartOnFailure || t.Status.State == api.TaskStateCompleted) {
@@ -200,7 +206,7 @@ func (r *RestartSupervisor) shouldRestart(ctx context.Context, t *api.Task, serv
 
 	// Instance is not meaningful for "global" tasks, so they need to be
 	// indexed by NodeID.
-	if isGlobalService(service) {
+	if orchestrator.IsGlobalService(service) {
 		instanceTuple.nodeID = t.NodeID
 	}
 
@@ -246,7 +252,7 @@ func (r *RestartSupervisor) shouldRestart(ctx context.Context, t *api.Task, serv
 	return numRestarts < t.Spec.Restart.MaxAttempts
 }
 
-func (r *RestartSupervisor) recordRestartHistory(restartTask *api.Task) {
+func (r *Supervisor) recordRestartHistory(restartTask *api.Task) {
 	if restartTask.Spec.Restart == nil || restartTask.Spec.Restart.MaxAttempts == 0 {
 		// No limit on the number of restarts, so no need to record
 		// history.
@@ -292,7 +298,7 @@ func (r *RestartSupervisor) recordRestartHistory(restartTask *api.Task) {
 // It must be called during an Update transaction to ensure that it does not
 // miss events. The purpose of the store.Tx argument is to avoid accidental
 // calls outside an Update transaction.
-func (r *RestartSupervisor) DelayStart(ctx context.Context, _ store.Tx, oldTask *api.Task, newTaskID string, delay time.Duration, waitStop bool) <-chan struct{} {
+func (r *Supervisor) DelayStart(ctx context.Context, _ store.Tx, oldTask *api.Task, newTaskID string, delay time.Duration, waitStop bool) <-chan struct{} {
 	ctx, cancel := context.WithCancel(context.Background())
 	doneCh := make(chan struct{})
 
@@ -345,7 +351,7 @@ func (r *RestartSupervisor) DelayStart(ctx context.Context, _ store.Tx, oldTask
 			close(doneCh)
 		}()
 
-		oldTaskTimer := time.NewTimer(r.taskTimeout)
+		oldTaskTimer := time.NewTimer(r.TaskTimeout)
 		defer oldTaskTimer.Stop()
 
 		// Wait for the delay to elapse, if one is specified.
@@ -383,7 +389,7 @@ func (r *RestartSupervisor) DelayStart(ctx context.Context, _ store.Tx, oldTask
 
 // StartNow moves the task into the RUNNING state so it will proceed to start
 // up.
-func (r *RestartSupervisor) StartNow(tx store.Tx, taskID string) error {
+func (r *Supervisor) StartNow(tx store.Tx, taskID string) error {
 	t := store.GetTask(tx, taskID)
 	if t == nil || t.DesiredState >= api.TaskStateRunning {
 		return nil
@@ -393,7 +399,7 @@ func (r *RestartSupervisor) StartNow(tx store.Tx, taskID string) error {
 }
 
 // Cancel cancels a pending restart.
-func (r *RestartSupervisor) Cancel(taskID string) {
+func (r *Supervisor) Cancel(taskID string) {
 	r.mu.Lock()
 	delay, ok := r.delays[taskID]
 	r.mu.Unlock()
@@ -408,7 +414,7 @@ func (r *RestartSupervisor) Cancel(taskID string) {
 
 // CancelAll aborts all pending restarts and waits for any instances of
 // StartNow that have already triggered to complete.
-func (r *RestartSupervisor) CancelAll() {
+func (r *Supervisor) CancelAll() {
 	var cancelled []delayedStart
 
 	r.mu.Lock()
@@ -423,7 +429,7 @@ func (r *RestartSupervisor) CancelAll() {
 }
 
 // ClearServiceHistory forgets restart history related to a given service ID.
-func (r *RestartSupervisor) ClearServiceHistory(serviceID string) {
+func (r *Supervisor) ClearServiceHistory(serviceID string) {
 	r.mu.Lock()
 	defer r.mu.Unlock()
 

+ 61 - 0
vendor/src/github.com/docker/swarmkit/manager/orchestrator/service.go

@@ -0,0 +1,61 @@
+package orchestrator
+
+import (
+	"github.com/docker/swarmkit/api"
+	"github.com/docker/swarmkit/log"
+	"github.com/docker/swarmkit/manager/state/store"
+	"golang.org/x/net/context"
+)
+
+// IsReplicatedService checks if a service is a replicated service.
+func IsReplicatedService(service *api.Service) bool {
+	// service nil validation is required as there are scenarios
+	// where service is removed from store
+	if service == nil {
+		return false
+	}
+	_, ok := service.Spec.GetMode().(*api.ServiceSpec_Replicated)
+	return ok
+}
+
+// IsGlobalService checks if the service is a global service.
+func IsGlobalService(service *api.Service) bool {
+	if service == nil {
+		return false
+	}
+	_, ok := service.Spec.GetMode().(*api.ServiceSpec_Global)
+	return ok
+}
+
+// DeleteServiceTasks deletes the tasks associated with a service.
+func DeleteServiceTasks(ctx context.Context, s *store.MemoryStore, service *api.Service) {
+	var (
+		tasks []*api.Task
+		err   error
+	)
+	s.View(func(tx store.ReadTx) {
+		tasks, err = store.FindTasks(tx, store.ByServiceID(service.ID))
+	})
+	if err != nil {
+		log.G(ctx).WithError(err).Errorf("failed to list tasks")
+		return
+	}
+
+	_, err = s.Batch(func(batch *store.Batch) error {
+		for _, t := range tasks {
+			err := batch.Update(func(tx store.Tx) error {
+				if err := store.DeleteTask(tx, t.ID); err != nil {
+					log.G(ctx).WithError(err).Errorf("failed to delete task")
+				}
+				return nil
+			})
+			if err != nil {
+				return err
+			}
+		}
+		return nil
+	})
+	if err != nil {
+		log.G(ctx).WithError(err).Errorf("task search transaction failed")
+	}
+}

+ 29 - 44
vendor/src/github.com/docker/swarmkit/manager/orchestrator/slot.go

@@ -2,60 +2,45 @@ package orchestrator
 
 import (
 	"github.com/docker/swarmkit/api"
+	"github.com/docker/swarmkit/manager/state/store"
 )
 
-// slot is a list of the running tasks occupying a certain slot. Generally this
+// Slot is a list of the running tasks occupying a certain slot. Generally this
 // will only be one task, but some rolling update situations involve
 // temporarily having two running tasks in the same slot. Note that this use of
 // "slot" is more generic than the Slot number for replicated services - a node
 // is also considered a slot for global services.
-type slot []*api.Task
-
-type slotsByRunningState []slot
-
-func (is slotsByRunningState) Len() int      { return len(is) }
-func (is slotsByRunningState) Swap(i, j int) { is[i], is[j] = is[j], is[i] }
-
-func (is slotsByRunningState) Less(i, j int) bool {
-	iRunning := false
-	jRunning := false
+type Slot []*api.Task
+
+// GetRunnableAndDeadSlots returns two maps of slots. The first contains slots
+// that have at least one task with a desired state above NEW and lesser or
+// equal to RUNNING. The second is for slots that only contain tasks with a
+// desired state above RUNNING.
+func GetRunnableAndDeadSlots(s *store.MemoryStore, serviceID string) (map[uint64]Slot, map[uint64]Slot, error) {
+	var (
+		tasks []*api.Task
+		err   error
+	)
+	s.View(func(tx store.ReadTx) {
+		tasks, err = store.FindTasks(tx, store.ByServiceID(serviceID))
+	})
+	if err != nil {
+		return nil, nil, err
+	}
 
-	for _, ii := range is[i] {
-		if ii.Status.State == api.TaskStateRunning {
-			iRunning = true
-			break
+	runningSlots := make(map[uint64]Slot)
+	for _, t := range tasks {
+		if t.DesiredState <= api.TaskStateRunning {
+			runningSlots[t.Slot] = append(runningSlots[t.Slot], t)
 		}
 	}
-	for _, ij := range is[j] {
-		if ij.Status.State == api.TaskStateRunning {
-			jRunning = true
-			break
+
+	deadSlots := make(map[uint64]Slot)
+	for _, t := range tasks {
+		if _, exists := runningSlots[t.Slot]; !exists {
+			deadSlots[t.Slot] = append(deadSlots[t.Slot], t)
 		}
 	}
 
-	return iRunning && !jRunning
-}
-
-type slotWithIndex struct {
-	slot slot
-
-	// index is a counter that counts this task as the nth instance of
-	// the service on its node. This is used for sorting the tasks so that
-	// when scaling down we leave tasks more evenly balanced.
-	index int
-}
-
-type slotsByIndex []slotWithIndex
-
-func (is slotsByIndex) Len() int      { return len(is) }
-func (is slotsByIndex) Swap(i, j int) { is[i], is[j] = is[j], is[i] }
-
-func (is slotsByIndex) Less(i, j int) bool {
-	if is[i].index < 0 && is[j].index >= 0 {
-		return false
-	}
-	if is[j].index < 0 && is[i].index >= 0 {
-		return true
-	}
-	return is[i].index < is[j].index
+	return runningSlots, deadSlots, nil
 }

+ 67 - 0
vendor/src/github.com/docker/swarmkit/manager/orchestrator/task.go

@@ -0,0 +1,67 @@
+package orchestrator
+
+import (
+	"reflect"
+	"time"
+
+	"github.com/docker/swarmkit/api"
+	"github.com/docker/swarmkit/identity"
+	"github.com/docker/swarmkit/protobuf/ptypes"
+)
+
+// DefaultRestartDelay is the restart delay value to use when none is
+// specified.
+const DefaultRestartDelay = 5 * time.Second
+
+// NewTask creates a new task.
+func NewTask(cluster *api.Cluster, service *api.Service, slot uint64, nodeID string) *api.Task {
+	var logDriver *api.Driver
+	if service.Spec.Task.LogDriver != nil {
+		// use the log driver specific to the task, if we have it.
+		logDriver = service.Spec.Task.LogDriver
+	} else if cluster != nil {
+		// pick up the cluster default, if available.
+		logDriver = cluster.Spec.TaskDefaults.LogDriver // nil is okay here.
+	}
+
+	taskID := identity.NewID()
+	task := api.Task{
+		ID:                 taskID,
+		ServiceAnnotations: service.Spec.Annotations,
+		Spec:               service.Spec.Task,
+		ServiceID:          service.ID,
+		Slot:               slot,
+		Status: api.TaskStatus{
+			State:     api.TaskStateNew,
+			Timestamp: ptypes.MustTimestampProto(time.Now()),
+			Message:   "created",
+		},
+		Endpoint: &api.Endpoint{
+			Spec: service.Spec.Endpoint.Copy(),
+		},
+		DesiredState: api.TaskStateRunning,
+		LogDriver:    logDriver,
+	}
+
+	// In global mode we also set the NodeID
+	if nodeID != "" {
+		task.NodeID = nodeID
+	}
+
+	return &task
+}
+
+// RestartCondition returns the restart condition to apply to this task.
+func RestartCondition(task *api.Task) api.RestartPolicy_RestartCondition {
+	restartCondition := api.RestartOnAny
+	if task.Spec.Restart != nil {
+		restartCondition = task.Spec.Restart.Condition
+	}
+	return restartCondition
+}
+
+// IsTaskDirty determines whether a task matches the given service's spec.
+func IsTaskDirty(s *api.Service, t *api.Task) bool {
+	return !reflect.DeepEqual(s.Spec.Task, t.Spec) ||
+		(t.Endpoint != nil && !reflect.DeepEqual(s.Spec.Endpoint, t.Endpoint.Spec))
+}

+ 3 - 3
vendor/src/github.com/docker/swarmkit/manager/orchestrator/task_reaper.go → vendor/src/github.com/docker/swarmkit/manager/orchestrator/taskreaper/task_reaper.go

@@ -1,4 +1,4 @@
-package orchestrator
+package taskreaper
 
 import (
 	"sort"
@@ -36,8 +36,8 @@ type TaskReaper struct {
 	doneChan    chan struct{}
 }
 
-// NewTaskReaper creates a new TaskReaper.
-func NewTaskReaper(store *store.MemoryStore) *TaskReaper {
+// New creates a new TaskReaper.
+func New(store *store.MemoryStore) *TaskReaper {
 	watcher, cancel := state.Watch(store.WatchQueue(), state.EventCreateTask{}, state.EventUpdateCluster{})
 
 	return &TaskReaper{

+ 24 - 27
vendor/src/github.com/docker/swarmkit/manager/orchestrator/updater.go → vendor/src/github.com/docker/swarmkit/manager/orchestrator/update/updater.go

@@ -1,4 +1,4 @@
-package orchestrator
+package update
 
 import (
 	"errors"
@@ -12,6 +12,8 @@ import (
 	"github.com/docker/go-events"
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/log"
+	"github.com/docker/swarmkit/manager/orchestrator"
+	"github.com/docker/swarmkit/manager/orchestrator/restart"
 	"github.com/docker/swarmkit/manager/state"
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/docker/swarmkit/manager/state/watch"
@@ -20,18 +22,18 @@ import (
 
 const defaultMonitor = 30 * time.Second
 
-// UpdateSupervisor supervises a set of updates. It's responsible for keeping track of updates,
+// Supervisor supervises a set of updates. It's responsible for keeping track of updates,
 // shutting them down and replacing them.
-type UpdateSupervisor struct {
+type Supervisor struct {
 	store    *store.MemoryStore
-	restarts *RestartSupervisor
+	restarts *restart.Supervisor
 	updates  map[string]*Updater
 	l        sync.Mutex
 }
 
-// NewUpdateSupervisor creates a new UpdateSupervisor.
-func NewUpdateSupervisor(store *store.MemoryStore, restartSupervisor *RestartSupervisor) *UpdateSupervisor {
-	return &UpdateSupervisor{
+// NewSupervisor creates a new UpdateSupervisor.
+func NewSupervisor(store *store.MemoryStore, restartSupervisor *restart.Supervisor) *Supervisor {
+	return &Supervisor{
 		store:    store,
 		updates:  make(map[string]*Updater),
 		restarts: restartSupervisor,
@@ -45,7 +47,7 @@ func NewUpdateSupervisor(store *store.MemoryStore, restartSupervisor *RestartSup
 // and the new task was started before the old one was shut down. If an update
 // for that service was already in progress, it will be cancelled before the
 // new one starts.
-func (u *UpdateSupervisor) Update(ctx context.Context, cluster *api.Cluster, service *api.Service, slots []slot) {
+func (u *Supervisor) Update(ctx context.Context, cluster *api.Cluster, service *api.Service, slots []orchestrator.Slot) {
 	u.l.Lock()
 	defer u.l.Unlock()
 
@@ -72,7 +74,7 @@ func (u *UpdateSupervisor) Update(ctx context.Context, cluster *api.Cluster, ser
 }
 
 // CancelAll cancels all current updates.
-func (u *UpdateSupervisor) CancelAll() {
+func (u *Supervisor) CancelAll() {
 	u.l.Lock()
 	defer u.l.Unlock()
 
@@ -85,7 +87,7 @@ func (u *UpdateSupervisor) CancelAll() {
 type Updater struct {
 	store      *store.MemoryStore
 	watchQueue *watch.Queue
-	restarts   *RestartSupervisor
+	restarts   *restart.Supervisor
 
 	cluster    *api.Cluster
 	newService *api.Service
@@ -100,7 +102,7 @@ type Updater struct {
 }
 
 // NewUpdater creates a new Updater.
-func NewUpdater(store *store.MemoryStore, restartSupervisor *RestartSupervisor, cluster *api.Cluster, newService *api.Service) *Updater {
+func NewUpdater(store *store.MemoryStore, restartSupervisor *restart.Supervisor, cluster *api.Cluster, newService *api.Service) *Updater {
 	return &Updater{
 		store:        store,
 		watchQueue:   store.WatchQueue(),
@@ -120,7 +122,7 @@ func (u *Updater) Cancel() {
 }
 
 // Run starts the update and returns only once its complete or cancelled.
-func (u *Updater) Run(ctx context.Context, slots []slot) {
+func (u *Updater) Run(ctx context.Context, slots []orchestrator.Slot) {
 	defer close(u.doneChan)
 
 	service := u.newService
@@ -132,7 +134,7 @@ func (u *Updater) Run(ctx context.Context, slots []slot) {
 		return
 	}
 
-	var dirtySlots []slot
+	var dirtySlots []orchestrator.Slot
 	for _, slot := range slots {
 		if u.isSlotDirty(slot) {
 			dirtySlots = append(dirtySlots, slot)
@@ -164,7 +166,7 @@ func (u *Updater) Run(ctx context.Context, slots []slot) {
 	}
 
 	// Start the workers.
-	slotQueue := make(chan slot)
+	slotQueue := make(chan orchestrator.Slot)
 	wg := sync.WaitGroup{}
 	wg.Add(parallelism)
 	for i := 0; i < parallelism; i++ {
@@ -300,7 +302,7 @@ slotsLoop:
 	}
 }
 
-func (u *Updater) worker(ctx context.Context, queue <-chan slot) {
+func (u *Updater) worker(ctx context.Context, queue <-chan orchestrator.Slot) {
 	for slot := range queue {
 		// Do we have a task with the new spec in desired state = RUNNING?
 		// If so, all we have to do to complete the update is remove the
@@ -331,9 +333,9 @@ func (u *Updater) worker(ctx context.Context, queue <-chan slot) {
 				log.G(ctx).WithError(err).Error("update failed")
 			}
 		} else {
-			updated := newTask(u.cluster, u.newService, slot[0].Slot, "")
-			if isGlobalService(u.newService) {
-				updated = newTask(u.cluster, u.newService, slot[0].Slot, slot[0].NodeID)
+			updated := orchestrator.NewTask(u.cluster, u.newService, slot[0].Slot, "")
+			if orchestrator.IsGlobalService(u.newService) {
+				updated = orchestrator.NewTask(u.cluster, u.newService, slot[0].Slot, slot[0].NodeID)
 			}
 			updated.DesiredState = api.TaskStateReady
 
@@ -357,7 +359,7 @@ func (u *Updater) worker(ctx context.Context, queue <-chan slot) {
 	}
 }
 
-func (u *Updater) updateTask(ctx context.Context, slot slot, updated *api.Task) error {
+func (u *Updater) updateTask(ctx context.Context, slot orchestrator.Slot, updated *api.Task) error {
 	// Kick off the watch before even creating the updated task. This is in order to avoid missing any event.
 	taskUpdates, cancel := state.Watch(u.watchQueue, state.EventUpdateTask{
 		Task:   &api.Task{ID: updated.ID},
@@ -421,7 +423,7 @@ func (u *Updater) updateTask(ctx context.Context, slot slot, updated *api.Task)
 	}
 }
 
-func (u *Updater) useExistingTask(ctx context.Context, slot slot, existing *api.Task) error {
+func (u *Updater) useExistingTask(ctx context.Context, slot orchestrator.Slot, existing *api.Task) error {
 	var removeTasks []*api.Task
 	for _, t := range slot {
 		if t != existing {
@@ -489,16 +491,11 @@ func (u *Updater) removeOldTasks(ctx context.Context, batch *store.Batch, remove
 	return removedTask, nil
 }
 
-func isTaskDirty(s *api.Service, t *api.Task) bool {
-	return !reflect.DeepEqual(s.Spec.Task, t.Spec) ||
-		(t.Endpoint != nil && !reflect.DeepEqual(s.Spec.Endpoint, t.Endpoint.Spec))
-}
-
 func (u *Updater) isTaskDirty(t *api.Task) bool {
-	return isTaskDirty(u.newService, t)
+	return orchestrator.IsTaskDirty(u.newService, t)
 }
 
-func (u *Updater) isSlotDirty(slot slot) bool {
+func (u *Updater) isSlotDirty(slot orchestrator.Slot) bool {
 	return len(slot) > 1 || (len(slot) == 1 && u.isTaskDirty(slot[0]))
 }
 

+ 47 - 11
vendor/src/github.com/docker/swarmkit/manager/scheduler/nodeinfo.go

@@ -1,6 +1,12 @@
 package scheduler
 
-import "github.com/docker/swarmkit/api"
+import (
+	"time"
+
+	"github.com/docker/swarmkit/api"
+	"github.com/docker/swarmkit/log"
+	"golang.org/x/net/context"
+)
 
 // NodeInfo contains a node and some additional metadata.
 type NodeInfo struct {
@@ -9,6 +15,13 @@ type NodeInfo struct {
 	DesiredRunningTasksCount          int
 	DesiredRunningTasksCountByService map[string]int
 	AvailableResources                api.Resources
+
+	// recentFailures is a map from service ID to the timestamps of the
+	// most recent failures the node has experienced from replicas of that
+	// service.
+	// TODO(aaronl): When spec versioning is supported, this should track
+	// the version of the spec that failed.
+	recentFailures map[string][]time.Time
 }
 
 func newNodeInfo(n *api.Node, tasks map[string]*api.Task, availableResources api.Resources) NodeInfo {
@@ -17,6 +30,7 @@ func newNodeInfo(n *api.Node, tasks map[string]*api.Task, availableResources api
 		Tasks: make(map[string]*api.Task),
 		DesiredRunningTasksCountByService: make(map[string]int),
 		AvailableResources:                availableResources,
+		recentFailures:                    make(map[string][]time.Time),
 	}
 
 	for _, t := range tasks {
@@ -28,9 +42,6 @@ func newNodeInfo(n *api.Node, tasks map[string]*api.Task, availableResources api
 // addTask removes a task from nodeInfo if it's tracked there, and returns true
 // if nodeInfo was modified.
 func (nodeInfo *NodeInfo) removeTask(t *api.Task) bool {
-	if nodeInfo.Tasks == nil {
-		return false
-	}
 	oldTask, ok := nodeInfo.Tasks[t.ID]
 	if !ok {
 		return false
@@ -52,13 +63,6 @@ func (nodeInfo *NodeInfo) removeTask(t *api.Task) bool {
 // addTask adds or updates a task on nodeInfo, and returns true if nodeInfo was
 // modified.
 func (nodeInfo *NodeInfo) addTask(t *api.Task) bool {
-	if nodeInfo.Tasks == nil {
-		nodeInfo.Tasks = make(map[string]*api.Task)
-	}
-	if nodeInfo.DesiredRunningTasksCountByService == nil {
-		nodeInfo.DesiredRunningTasksCountByService = make(map[string]int)
-	}
-
 	oldTask, ok := nodeInfo.Tasks[t.ID]
 	if ok {
 		if t.DesiredState == api.TaskStateRunning && oldTask.DesiredState != api.TaskStateRunning {
@@ -94,3 +98,35 @@ func taskReservations(spec api.TaskSpec) (reservations api.Resources) {
 	}
 	return
 }
+
+// taskFailed records a task failure from a given service.
+func (nodeInfo *NodeInfo) taskFailed(ctx context.Context, serviceID string) {
+	expired := 0
+	now := time.Now()
+	for _, timestamp := range nodeInfo.recentFailures[serviceID] {
+		if now.Sub(timestamp) < monitorFailures {
+			break
+		}
+		expired++
+	}
+
+	if len(nodeInfo.recentFailures[serviceID])-expired == maxFailures-1 {
+		log.G(ctx).Warnf("underweighting node %s for service %s because it experienced %d failures or rejections within %s", nodeInfo.ID, serviceID, maxFailures, monitorFailures.String())
+	}
+
+	nodeInfo.recentFailures[serviceID] = append(nodeInfo.recentFailures[serviceID][expired:], now)
+}
+
+// countRecentFailures returns the number of times the service has failed on
+// this node within the lookback window monitorFailures.
+func (nodeInfo *NodeInfo) countRecentFailures(now time.Time, serviceID string) int {
+	recentFailureCount := len(nodeInfo.recentFailures[serviceID])
+	for i := recentFailureCount - 1; i >= 0; i-- {
+		if now.Sub(nodeInfo.recentFailures[serviceID][i]) > monitorFailures {
+			recentFailureCount -= i + 1
+			break
+		}
+	}
+
+	return recentFailureCount
+}

+ 13 - 0
vendor/src/github.com/docker/swarmkit/manager/scheduler/nodeset.go

@@ -3,6 +3,9 @@ package scheduler
 import (
 	"container/heap"
 	"errors"
+	"time"
+
+	"github.com/docker/swarmkit/api"
 )
 
 var errNodeNotFound = errors.New("node not found in scheduler dataset")
@@ -27,6 +30,16 @@ func (ns *nodeSet) nodeInfo(nodeID string) (NodeInfo, error) {
 // addOrUpdateNode sets the number of tasks for a given node. It adds the node
 // to the set if it wasn't already tracked.
 func (ns *nodeSet) addOrUpdateNode(n NodeInfo) {
+	if n.Tasks == nil {
+		n.Tasks = make(map[string]*api.Task)
+	}
+	if n.DesiredRunningTasksCountByService == nil {
+		n.DesiredRunningTasksCountByService = make(map[string]int)
+	}
+	if n.recentFailures == nil {
+		n.recentFailures = make(map[string][]time.Time)
+	}
+
 	ns.nodes[n.ID] = n
 }
 

+ 46 - 11
vendor/src/github.com/docker/swarmkit/manager/scheduler/scheduler.go

@@ -12,6 +12,16 @@ import (
 	"golang.org/x/net/context"
 )
 
+const (
+	// monitorFailures is the lookback period for counting failures of
+	// a task to determine if a node is faulty for a particular service.
+	monitorFailures = 5 * time.Minute
+
+	// maxFailures is the number of failures within monitorFailures that
+	// triggers downweighting of a node in the sorting function.
+	maxFailures = 5
+)
+
 type schedulingDecision struct {
 	old *api.Task
 	new *api.Task
@@ -54,9 +64,9 @@ func (s *Scheduler) setupTasksList(tx store.ReadTx) error {
 
 	tasksByNode := make(map[string]map[string]*api.Task)
 	for _, t := range tasks {
-		// Ignore all tasks that have not reached ALLOCATED
+		// Ignore all tasks that have not reached PENDING
 		// state and tasks that no longer consume resources.
-		if t.Status.State < api.TaskStateAllocated || t.Status.State > api.TaskStateRunning {
+		if t.Status.State < api.TaskStatePending || t.Status.State > api.TaskStateRunning {
 			continue
 		}
 
@@ -66,7 +76,7 @@ func (s *Scheduler) setupTasksList(tx store.ReadTx) error {
 			continue
 		}
 		// preassigned tasks need to validate resource requirement on corresponding node
-		if t.Status.State == api.TaskStateAllocated {
+		if t.Status.State == api.TaskStatePending {
 			s.preassignedTasks[t.ID] = t
 			continue
 		}
@@ -185,9 +195,9 @@ func (s *Scheduler) enqueue(t *api.Task) {
 }
 
 func (s *Scheduler) createTask(ctx context.Context, t *api.Task) int {
-	// Ignore all tasks that have not reached ALLOCATED
+	// Ignore all tasks that have not reached PENDING
 	// state, and tasks that no longer consume resources.
-	if t.Status.State < api.TaskStateAllocated || t.Status.State > api.TaskStateRunning {
+	if t.Status.State < api.TaskStatePending || t.Status.State > api.TaskStateRunning {
 		return 0
 	}
 
@@ -198,7 +208,7 @@ func (s *Scheduler) createTask(ctx context.Context, t *api.Task) int {
 		return 1
 	}
 
-	if t.Status.State == api.TaskStateAllocated {
+	if t.Status.State == api.TaskStatePending {
 		s.preassignedTasks[t.ID] = t
 		// preassigned tasks do not contribute to running tasks count
 		return 0
@@ -213,9 +223,9 @@ func (s *Scheduler) createTask(ctx context.Context, t *api.Task) int {
 }
 
 func (s *Scheduler) updateTask(ctx context.Context, t *api.Task) int {
-	// Ignore all tasks that have not reached ALLOCATED
+	// Ignore all tasks that have not reached PENDING
 	// state.
-	if t.Status.State < api.TaskStateAllocated {
+	if t.Status.State < api.TaskStatePending {
 		return 0
 	}
 
@@ -224,8 +234,17 @@ func (s *Scheduler) updateTask(ctx context.Context, t *api.Task) int {
 	// Ignore all tasks that have not reached ALLOCATED
 	// state, and tasks that no longer consume resources.
 	if t.Status.State > api.TaskStateRunning {
-		if oldTask != nil {
-			s.deleteTask(ctx, oldTask)
+		if oldTask == nil {
+			return 1
+		}
+		s.deleteTask(ctx, oldTask)
+		if t.Status.State != oldTask.Status.State &&
+			(t.Status.State == api.TaskStateFailed || t.Status.State == api.TaskStateRejected) {
+			nodeInfo, err := s.nodeSet.nodeInfo(t.NodeID)
+			if err == nil {
+				nodeInfo.taskFailed(ctx, t.ServiceID)
+				s.nodeSet.updateNode(nodeInfo)
+			}
 		}
 		return 1
 	}
@@ -240,7 +259,7 @@ func (s *Scheduler) updateTask(ctx context.Context, t *api.Task) int {
 		return 1
 	}
 
-	if t.Status.State == api.TaskStateAllocated {
+	if t.Status.State == api.TaskStatePending {
 		if oldTask != nil {
 			s.deleteTask(ctx, oldTask)
 		}
@@ -481,7 +500,23 @@ func (s *Scheduler) scheduleTaskGroup(ctx context.Context, taskGroup map[string]
 
 	s.pipeline.SetTask(t)
 
+	now := time.Now()
+
 	nodeLess := func(a *NodeInfo, b *NodeInfo) bool {
+		// If either node has at least maxFailures recent failures,
+		// that's the deciding factor.
+		recentFailuresA := a.countRecentFailures(now, t.ServiceID)
+		recentFailuresB := b.countRecentFailures(now, t.ServiceID)
+
+		if recentFailuresA >= maxFailures || recentFailuresB >= maxFailures {
+			if recentFailuresA > recentFailuresB {
+				return false
+			}
+			if recentFailuresB > recentFailuresA {
+				return true
+			}
+		}
+
 		tasksByServiceA := a.DesiredRunningTasksCountByService[t.ServiceID]
 		tasksByServiceB := b.DesiredRunningTasksCountByService[t.ServiceID]
 

+ 25 - 20
vendor/src/github.com/docker/swarmkit/manager/state/raft/raft.go

@@ -755,6 +755,9 @@ func (n *Node) Leave(ctx context.Context, req *api.LeaveRequest) (*api.LeaveResp
 		return nil, err
 	}
 
+	ctx, cancel := n.WithContext(ctx)
+	defer cancel()
+
 	fields := logrus.Fields{
 		"node.id": nodeInfo.NodeID,
 		"method":  "(*Node).Leave",
@@ -765,20 +768,7 @@ func (n *Node) Leave(ctx context.Context, req *api.LeaveRequest) (*api.LeaveResp
 	}
 	log.G(ctx).WithFields(fields).Debug("")
 
-	// can't stop the raft node while an async RPC is in progress
-	n.stopMu.RLock()
-	defer n.stopMu.RUnlock()
-
-	if !n.IsMember() {
-		return nil, ErrNoRaftMember
-	}
-
-	if !n.isLeader() {
-		return nil, ErrLostLeadership
-	}
-
-	err = n.RemoveMember(ctx, req.Node.RaftID)
-	if err != nil {
+	if err := n.removeMember(ctx, req.Node.RaftID); err != nil {
 		return nil, err
 	}
 
@@ -791,12 +781,21 @@ func (n *Node) CanRemoveMember(id uint64) bool {
 	return n.cluster.CanRemoveMember(n.Config.ID, id)
 }
 
-// RemoveMember submits a configuration change to remove a member from the raft cluster
-// after checking if the operation would not result in a loss of quorum.
-func (n *Node) RemoveMember(ctx context.Context, id uint64) error {
+func (n *Node) removeMember(ctx context.Context, id uint64) error {
+	// can't stop the raft node while an async RPC is in progress
+	n.stopMu.RLock()
+	defer n.stopMu.RUnlock()
+
+	if !n.IsMember() {
+		return ErrNoRaftMember
+	}
+
+	if !n.isLeader() {
+		return ErrLostLeadership
+	}
+
 	n.membershipLock.Lock()
 	defer n.membershipLock.Unlock()
-
 	if n.cluster.CanRemoveMember(n.Config.ID, id) {
 		cc := raftpb.ConfChange{
 			ID:      id,
@@ -804,15 +803,21 @@ func (n *Node) RemoveMember(ctx context.Context, id uint64) error {
 			NodeID:  id,
 			Context: []byte(""),
 		}
-		ctx, cancel := n.WithContext(ctx)
 		err := n.configure(ctx, cc)
-		cancel()
 		return err
 	}
 
 	return ErrCannotRemoveMember
 }
 
+// RemoveMember submits a configuration change to remove a member from the raft cluster
+// after checking if the operation would not result in a loss of quorum.
+func (n *Node) RemoveMember(ctx context.Context, id uint64) error {
+	ctx, cancel := n.WithContext(ctx)
+	defer cancel()
+	return n.removeMember(ctx, id)
+}
+
 // ProcessRaftMessage calls 'Step' which advances the
 // raft state machine with the provided message on the
 // receiving node

+ 2 - 2
vendor/src/github.com/docker/swarmkit/manager/state/store/memory.go

@@ -240,7 +240,7 @@ func (s *MemoryStore) update(proposer state.Proposer, cb func(Tx) error) error {
 			sa, err = tx.changelistStoreActions()
 
 			if err == nil {
-				if sa != nil {
+				if len(sa) != 0 {
 					err = proposer.ProposeValue(context.Background(), sa, func() {
 						memDBTx.Commit()
 					})
@@ -350,7 +350,7 @@ func (batch *Batch) commit() error {
 		sa, batch.err = batch.tx.changelistStoreActions()
 
 		if batch.err == nil {
-			if sa != nil {
+			if len(sa) != 0 {
 				batch.err = batch.store.proposer.ProposeValue(context.Background(), sa, func() {
 					batch.tx.memDBTx.Commit()
 				})

+ 2 - 22
vendor/src/github.com/docker/swarmkit/manager/state/store/tasks.go

@@ -1,11 +1,11 @@
 package store
 
 import (
-	"fmt"
 	"strconv"
 	"strings"
 
 	"github.com/docker/swarmkit/api"
+	"github.com/docker/swarmkit/api/naming"
 	"github.com/docker/swarmkit/manager/state"
 	memdb "github.com/hashicorp/go-memdb"
 )
@@ -112,26 +112,6 @@ func init() {
 	})
 }
 
-// TaskName returns the task name from Annotations.Name,
-// and, in case Annotations.Name is missing, fallback
-// to construct the name from othere information.
-func TaskName(t *api.Task) string {
-	name := t.Annotations.Name
-	if name == "" {
-		// If Task name is not assigned then calculated name is used like before.
-		// This might be removed in the future.
-		// We use the following scheme for Task name:
-		// Name := <ServiceAnnotations.Name>.<Slot>.<TaskID> (replicated mode)
-		//      := <ServiceAnnotations.Name>.<NodeID>.<TaskID> (global mode)
-		if t.Slot != 0 {
-			name = fmt.Sprintf("%v.%v.%v", t.ServiceAnnotations.Name, t.Slot, t.ID)
-		} else {
-			name = fmt.Sprintf("%v.%v.%v", t.ServiceAnnotations.Name, t.NodeID, t.ID)
-		}
-	}
-	return name
-}
-
 type taskEntry struct {
 	*api.Task
 }
@@ -245,7 +225,7 @@ func (ti taskIndexerByName) FromObject(obj interface{}) (bool, []byte, error) {
 		panic("unexpected type passed to FromObject")
 	}
 
-	name := TaskName(t.Task)
+	name := naming.Task(t.Task)
 
 	// Add the null character as a terminator
 	return true, []byte(strings.ToLower(name) + "\x00"), nil

+ 7 - 2
vendor/src/github.com/docker/swarmkit/manager/state/watch.go

@@ -563,12 +563,17 @@ func Watch(queue *watch.Queue, specifiers ...Event) (eventq chan events.Event, c
 	if len(specifiers) == 0 {
 		return queue.Watch()
 	}
-	return queue.CallbackWatch(events.MatcherFunc(func(event events.Event) bool {
+	return queue.CallbackWatch(Matcher(specifiers...))
+}
+
+// Matcher returns an events.Matcher that matches the specifiers with OR logic.
+func Matcher(specifiers ...Event) events.MatcherFunc {
+	return events.MatcherFunc(func(event events.Event) bool {
 		for _, s := range specifiers {
 			if s.matches(event) {
 				return true
 			}
 		}
 		return false
-	}))
+	})
 }

+ 19 - 10
vendor/src/github.com/docker/swarmkit/node/node.go

@@ -104,7 +104,7 @@ type Node struct {
 	err                  error
 	agent                *agent.Agent
 	manager              *manager.Manager
-	roleChangeReq        chan api.NodeRole // used to send role updates from the dispatcher api on promotion/demotion
+	notifyNodeChange     chan *api.Node // used to send role updates from the dispatcher api on promotion/demotion
 }
 
 // RemoteAPIAddr returns address on which remote manager api listens.
@@ -148,7 +148,7 @@ func New(c *Config) (*Node, error) {
 		closed:               make(chan struct{}),
 		ready:                make(chan struct{}),
 		certificateRequested: make(chan struct{}),
-		roleChangeReq:        make(chan api.NodeRole, 1),
+		notifyNodeChange:     make(chan *api.Node, 1),
 	}
 	n.roleCond = sync.NewCond(n.RLocker())
 	n.connCond = sync.NewCond(n.RLocker())
@@ -248,16 +248,29 @@ func (n *Node) run(ctx context.Context) (err error) {
 	}
 
 	forceCertRenewal := make(chan struct{})
+	renewCert := func() {
+		select {
+		case forceCertRenewal <- struct{}{}:
+		case <-ctx.Done():
+		}
+	}
+
 	go func() {
 		for {
 			select {
 			case <-ctx.Done():
 				return
-			case apirole := <-n.roleChangeReq:
+			case node := <-n.notifyNodeChange:
+				// If the server is sending us a ForceRenewal State, renew
+				if node.Certificate.Status.State == api.IssuanceStateRotate {
+					renewCert()
+					continue
+				}
 				n.Lock()
+				// If we got a role change, renew
 				lastRole := n.role
 				role := ca.WorkerRole
-				if apirole == api.NodeRoleManager {
+				if node.Spec.Role == api.NodeRoleManager {
 					role = ca.ManagerRole
 				}
 				if lastRole == role {
@@ -270,11 +283,7 @@ func (n *Node) run(ctx context.Context) (err error) {
 					n.roleCond.Broadcast()
 				}
 				n.Unlock()
-				select {
-				case forceCertRenewal <- struct{}{}:
-				case <-ctx.Done():
-					return
-				}
+				renewCert()
 			}
 		}
 	}()
@@ -380,7 +389,7 @@ func (n *Node) runAgent(ctx context.Context, db *bolt.DB, creds credentials.Tran
 		Managers:         n.remotes,
 		Executor:         n.config.Executor,
 		DB:               db,
-		NotifyRoleChange: n.roleChangeReq,
+		NotifyNodeChange: n.notifyNodeChange,
 		Credentials:      creds,
 	})
 	if err != nil {

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

@@ -1,3 +1,3 @@
 package plugin
 
-//go:generate protoc -I.:/usr/local --gogoswarm_out=import_path=github.com/docker/swarmkit/protobuf/plugin,Mgoogle/protobuf/descriptor.proto=github.com/gogo/protobuf/protoc-gen-gogo/descriptor:. plugin.proto
+//go:generate protoc -I.:../../vendor/github.com/gogo/protobuf/protobuf --gogoswarm_out=import_path=github.com/docker/swarmkit/protobuf/plugin,Mgoogle/protobuf/descriptor.proto=github.com/gogo/protobuf/protoc-gen-gogo/descriptor:. plugin.proto