Browse Source

Update SwarmKit to 6bc357e9c5f0ac2cdf801898a43d08c260b4d5d0

This fix tries to update the SwarmKit from
ed384f3b3957f65e3111bd020f9815f3d4296fa2
to
6bc357e9c5f0ac2cdf801898a43d08c260b4d5d0

The following is the list of docker related changes:
1. Took long time for Docker Swarm service turn desired state from Ready to Running (Issue #28291)
2. Native Swarm in 1.12 - panic: runtime error: index out of range (Issue #25608)
3. Global mode target replicas keep increasing (Issue #30854)
4. Creating service with publish mode=host and without published port crashes swarm manager (Issue #30938)
5. Define signals used to stop containers for updates (Issue #25696) (PR #30754)

This fix fixes #28291, #25608, #30854, #30938.
This fix is required by PR #30754.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
Yong Tang 8 years ago
parent
commit
ec860ca252
33 changed files with 879 additions and 519 deletions
  1. 1 1
      vendor.conf
  2. 5 5
      vendor/github.com/docker/swarmkit/agent/agent.go
  3. 2 4
      vendor/github.com/docker/swarmkit/agent/exec/errors.go
  4. 4 4
      vendor/github.com/docker/swarmkit/agent/secrets/secrets.go
  5. 4 1
      vendor/github.com/docker/swarmkit/agent/worker.go
  6. 176 113
      vendor/github.com/docker/swarmkit/api/control.pb.go
  7. 15 0
      vendor/github.com/docker/swarmkit/api/control.proto
  8. 1 1
      vendor/github.com/docker/swarmkit/api/naming/naming.go
  9. 257 157
      vendor/github.com/docker/swarmkit/api/specs.pb.go
  10. 7 1
      vendor/github.com/docker/swarmkit/api/specs.proto
  11. 0 11
      vendor/github.com/docker/swarmkit/api/types.pb.go
  12. 0 11
      vendor/github.com/docker/swarmkit/api/types.proto
  13. 30 28
      vendor/github.com/docker/swarmkit/ca/certificates.go
  14. 1 2
      vendor/github.com/docker/swarmkit/ca/external.go
  15. 1 1
      vendor/github.com/docker/swarmkit/ca/keyreadwriter.go
  16. 3 2
      vendor/github.com/docker/swarmkit/manager/allocator/network.go
  17. 1 1
      vendor/github.com/docker/swarmkit/manager/allocator/networkallocator/networkallocator.go
  18. 2 1
      vendor/github.com/docker/swarmkit/manager/allocator/networkallocator/portallocator.go
  19. 1 1
      vendor/github.com/docker/swarmkit/manager/controlapi/secret.go
  20. 48 13
      vendor/github.com/docker/swarmkit/manager/controlapi/service.go
  21. 1 1
      vendor/github.com/docker/swarmkit/manager/encryption/nacl.go
  22. 0 2
      vendor/github.com/docker/swarmkit/manager/keymanager/keymanager.go
  23. 16 4
      vendor/github.com/docker/swarmkit/manager/orchestrator/constraintenforcer/constraint_enforcer.go
  24. 104 31
      vendor/github.com/docker/swarmkit/manager/orchestrator/global/global.go
  25. 5 0
      vendor/github.com/docker/swarmkit/manager/orchestrator/replicated/services.go
  26. 39 92
      vendor/github.com/docker/swarmkit/manager/orchestrator/replicated/tasks.go
  27. 7 0
      vendor/github.com/docker/swarmkit/manager/orchestrator/task.go
  28. 103 0
      vendor/github.com/docker/swarmkit/manager/orchestrator/taskinit/init.go
  29. 12 5
      vendor/github.com/docker/swarmkit/manager/orchestrator/taskreaper/task_reaper.go
  30. 30 23
      vendor/github.com/docker/swarmkit/manager/orchestrator/update/updater.go
  31. 1 1
      vendor/github.com/docker/swarmkit/manager/state/doc.go
  32. 1 1
      vendor/github.com/docker/swarmkit/manager/state/raft/storage/snapwrap.go
  33. 1 1
      vendor/github.com/docker/swarmkit/manager/state/raft/storage/walwrap.go

+ 1 - 1
vendor.conf

@@ -103,7 +103,7 @@ github.com/docker/containerd 78fb8f45890a601e0fd9051cf9f9f74923e950fd
 github.com/tonistiigi/fifo 1405643975692217d6720f8b54aeee1bf2cd5cf4
 github.com/tonistiigi/fifo 1405643975692217d6720f8b54aeee1bf2cd5cf4
 
 
 # cluster
 # cluster
-github.com/docker/swarmkit ed384f3b3957f65e3111bd020f9815f3d4296fa2
+github.com/docker/swarmkit 6bc357e9c5f0ac2cdf801898a43d08c260b4d5d0
 github.com/golang/mock bd3c8e81be01eef76d4b503f5e687d2d1354d2d9
 github.com/golang/mock bd3c8e81be01eef76d4b503f5e687d2d1354d2d9
 github.com/gogo/protobuf 8d70fb3182befc465c4a1eac8ad4d38ff49778e2
 github.com/gogo/protobuf 8d70fb3182befc465c4a1eac8ad4d38ff49778e2
 github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a
 github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a

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

@@ -179,13 +179,13 @@ func (a *Agent) run(ctx context.Context) {
 
 
 	ctx = log.WithModule(ctx, "agent")
 	ctx = log.WithModule(ctx, "agent")
 
 
-	log.G(ctx).Debugf("(*Agent).run")
-	defer log.G(ctx).Debugf("(*Agent).run exited")
+	log.G(ctx).Debug("(*Agent).run")
+	defer log.G(ctx).Debug("(*Agent).run exited")
 
 
 	// get the node description
 	// get the node description
 	nodeDescription, err := a.nodeDescriptionWithHostname(ctx)
 	nodeDescription, err := a.nodeDescriptionWithHostname(ctx)
 	if err != nil {
 	if err != nil {
-		log.G(ctx).WithError(err).WithField("agent", a.config.Executor).Errorf("agent: node description unavailable")
+		log.G(ctx).WithError(err).WithField("agent", a.config.Executor).Error("agent: node description unavailable")
 	}
 	}
 	// nodeUpdateTicker is used to periodically check for updates to node description
 	// nodeUpdateTicker is used to periodically check for updates to node description
 	nodeUpdateTicker := time.NewTicker(nodeUpdatePeriod)
 	nodeUpdateTicker := time.NewTicker(nodeUpdatePeriod)
@@ -312,7 +312,7 @@ func (a *Agent) run(ctx context.Context) {
 			// get the current node description
 			// get the current node description
 			newNodeDescription, err := a.nodeDescriptionWithHostname(ctx)
 			newNodeDescription, err := a.nodeDescriptionWithHostname(ctx)
 			if err != nil {
 			if err != nil {
-				log.G(ctx).WithError(err).WithField("agent", a.config.Executor).Errorf("agent: updated node description unavailable")
+				log.G(ctx).WithError(err).WithField("agent", a.config.Executor).Error("agent: updated node description unavailable")
 			}
 			}
 
 
 			// if newNodeDescription is nil, it will cause a panic when
 			// if newNodeDescription is nil, it will cause a panic when
@@ -431,7 +431,7 @@ func (a *Agent) withSession(ctx context.Context, fn func(session *session) error
 //
 //
 // If an error is returned, the operation should be retried.
 // If an error is returned, the operation should be retried.
 func (a *Agent) UpdateTaskStatus(ctx context.Context, taskID string, status *api.TaskStatus) error {
 func (a *Agent) UpdateTaskStatus(ctx context.Context, taskID string, status *api.TaskStatus) error {
-	log.G(ctx).WithField("task.id", taskID).Debugf("(*Agent).UpdateTaskStatus")
+	log.G(ctx).WithField("task.id", taskID).Debug("(*Agent).UpdateTaskStatus")
 	ctx, cancel := context.WithCancel(ctx)
 	ctx, cancel := context.WithCancel(ctx)
 	defer cancel()
 	defer cancel()
 
 

+ 2 - 4
vendor/github.com/docker/swarmkit/agent/exec/errors.go

@@ -66,10 +66,8 @@ func (t temporary) Temporary() bool { return true }
 // temporary.
 // temporary.
 func IsTemporary(err error) bool {
 func IsTemporary(err error) bool {
 	for err != nil {
 	for err != nil {
-		if tmp, ok := err.(Temporary); ok {
-			if tmp.Temporary() {
-				return true
-			}
+		if tmp, ok := err.(Temporary); ok && tmp.Temporary() {
+			return true
 		}
 		}
 
 
 		cause := errors.Cause(err)
 		cause := errors.Cause(err)

+ 4 - 4
vendor/github.com/docker/swarmkit/agent/secrets/secrets.go

@@ -8,7 +8,7 @@ import (
 )
 )
 
 
 // secrets is a map that keeps all the currently available secrets to the agent
 // secrets is a map that keeps all the currently available secrets to the agent
-// mapped by secret ID
+// mapped by secret ID.
 type secrets struct {
 type secrets struct {
 	mu sync.RWMutex
 	mu sync.RWMutex
 	m  map[string]*api.Secret
 	m  map[string]*api.Secret
@@ -31,7 +31,7 @@ func (s *secrets) Get(secretID string) *api.Secret {
 	return nil
 	return nil
 }
 }
 
 
-// add adds one or more secrets to the secret map
+// Add adds one or more secrets to the secret map.
 func (s *secrets) Add(secrets ...api.Secret) {
 func (s *secrets) Add(secrets ...api.Secret) {
 	s.mu.Lock()
 	s.mu.Lock()
 	defer s.mu.Unlock()
 	defer s.mu.Unlock()
@@ -40,7 +40,7 @@ func (s *secrets) Add(secrets ...api.Secret) {
 	}
 	}
 }
 }
 
 
-// remove removes one or more secrets by ID from the secret map.  Succeeds
+// Remove removes one or more secrets by ID from the secret map.  Succeeds
 // whether or not the given IDs are in the map.
 // whether or not the given IDs are in the map.
 func (s *secrets) Remove(secrets []string) {
 func (s *secrets) Remove(secrets []string) {
 	s.mu.Lock()
 	s.mu.Lock()
@@ -50,7 +50,7 @@ func (s *secrets) Remove(secrets []string) {
 	}
 	}
 }
 }
 
 
-// reset removes all the secrets
+// Reset removes all the secrets.
 func (s *secrets) Reset() {
 func (s *secrets) Reset() {
 	s.mu.Lock()
 	s.mu.Lock()
 	defer s.mu.Unlock()
 	defer s.mu.Unlock()

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

@@ -396,7 +396,10 @@ func (w *worker) taskManager(ctx context.Context, tx *bolt.Tx, task *api.Task) (
 }
 }
 
 
 func (w *worker) newTaskManager(ctx context.Context, tx *bolt.Tx, task *api.Task) (*taskManager, error) {
 func (w *worker) newTaskManager(ctx context.Context, tx *bolt.Tx, task *api.Task) (*taskManager, error) {
-	ctx = log.WithLogger(ctx, log.G(ctx).WithField("task.id", task.ID))
+	ctx = log.WithLogger(ctx, log.G(ctx).WithFields(logrus.Fields{
+		"task.id":    task.ID,
+		"service.id": task.ServiceID,
+	}))
 
 
 	ctlr, status, err := exec.Resolve(ctx, task, w.executor)
 	ctlr, status, err := exec.Resolve(ctx, task, w.executor)
 	if err := w.updateTaskStatus(ctx, tx, task.ID, status); err != nil {
 	if err := w.updateTaskStatus(ctx, tx, task.ID, status); err != nil {

+ 176 - 113
vendor/github.com/docker/swarmkit/api/control.pb.go

@@ -34,6 +34,33 @@ var _ = proto.Marshal
 var _ = fmt.Errorf
 var _ = fmt.Errorf
 var _ = math.Inf
 var _ = math.Inf
 
 
+type UpdateServiceRequest_Rollback int32
+
+const (
+	// This is not a rollback. The spec field of the request will
+	// be honored.
+	UpdateServiceRequest_NONE UpdateServiceRequest_Rollback = 0
+	// Roll back the service - get spec from the service's
+	// previous_spec.
+	UpdateServiceRequest_PREVIOUS UpdateServiceRequest_Rollback = 1
+)
+
+var UpdateServiceRequest_Rollback_name = map[int32]string{
+	0: "NONE",
+	1: "PREVIOUS",
+}
+var UpdateServiceRequest_Rollback_value = map[string]int32{
+	"NONE":     0,
+	"PREVIOUS": 1,
+}
+
+func (x UpdateServiceRequest_Rollback) String() string {
+	return proto.EnumName(UpdateServiceRequest_Rollback_name, int32(x))
+}
+func (UpdateServiceRequest_Rollback) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptorControl, []int{18, 0}
+}
+
 type GetNodeRequest struct {
 type GetNodeRequest struct {
 	NodeID string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"`
 	NodeID string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"`
 }
 }
@@ -220,6 +247,10 @@ type UpdateServiceRequest struct {
 	ServiceID      string       `protobuf:"bytes,1,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"`
 	ServiceID      string       `protobuf:"bytes,1,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"`
 	ServiceVersion *Version     `protobuf:"bytes,2,opt,name=service_version,json=serviceVersion" json:"service_version,omitempty"`
 	ServiceVersion *Version     `protobuf:"bytes,2,opt,name=service_version,json=serviceVersion" json:"service_version,omitempty"`
 	Spec           *ServiceSpec `protobuf:"bytes,3,opt,name=spec" json:"spec,omitempty"`
 	Spec           *ServiceSpec `protobuf:"bytes,3,opt,name=spec" json:"spec,omitempty"`
+	// Rollback may be set to PREVIOUS to request a rollback (the service's
+	// spec will be set to the value of its previous_spec field). In this
+	// case, the spec field of this request is ignored.
+	Rollback UpdateServiceRequest_Rollback `protobuf:"varint,4,opt,name=rollback,proto3,enum=docker.swarmkit.v1.UpdateServiceRequest_Rollback" json:"rollback,omitempty"`
 }
 }
 
 
 func (m *UpdateServiceRequest) Reset()                    { *m = UpdateServiceRequest{} }
 func (m *UpdateServiceRequest) Reset()                    { *m = UpdateServiceRequest{} }
@@ -614,6 +645,7 @@ func init() {
 	proto.RegisterType((*CreateSecretResponse)(nil), "docker.swarmkit.v1.CreateSecretResponse")
 	proto.RegisterType((*CreateSecretResponse)(nil), "docker.swarmkit.v1.CreateSecretResponse")
 	proto.RegisterType((*RemoveSecretRequest)(nil), "docker.swarmkit.v1.RemoveSecretRequest")
 	proto.RegisterType((*RemoveSecretRequest)(nil), "docker.swarmkit.v1.RemoveSecretRequest")
 	proto.RegisterType((*RemoveSecretResponse)(nil), "docker.swarmkit.v1.RemoveSecretResponse")
 	proto.RegisterType((*RemoveSecretResponse)(nil), "docker.swarmkit.v1.RemoveSecretResponse")
+	proto.RegisterEnum("docker.swarmkit.v1.UpdateServiceRequest_Rollback", UpdateServiceRequest_Rollback_name, UpdateServiceRequest_Rollback_value)
 }
 }
 
 
 type authenticatedWrapperControlServer struct {
 type authenticatedWrapperControlServer struct {
@@ -3602,6 +3634,11 @@ func (m *UpdateServiceRequest) MarshalTo(dAtA []byte) (int, error) {
 		}
 		}
 		i += n18
 		i += n18
 	}
 	}
+	if m.Rollback != 0 {
+		dAtA[i] = 0x20
+		i++
+		i = encodeVarintControl(dAtA, i, uint64(m.Rollback))
+	}
 	return i, nil
 	return i, nil
 }
 }
 
 
@@ -6030,6 +6067,9 @@ func (m *UpdateServiceRequest) Size() (n int) {
 		l = m.Spec.Size()
 		l = m.Spec.Size()
 		n += 1 + l + sovControl(uint64(l))
 		n += 1 + l + sovControl(uint64(l))
 	}
 	}
+	if m.Rollback != 0 {
+		n += 1 + sovControl(uint64(m.Rollback))
+	}
 	return n
 	return n
 }
 }
 
 
@@ -6741,6 +6781,7 @@ func (this *UpdateServiceRequest) String() string {
 		`ServiceID:` + fmt.Sprintf("%v", this.ServiceID) + `,`,
 		`ServiceID:` + fmt.Sprintf("%v", this.ServiceID) + `,`,
 		`ServiceVersion:` + strings.Replace(fmt.Sprintf("%v", this.ServiceVersion), "Version", "Version", 1) + `,`,
 		`ServiceVersion:` + strings.Replace(fmt.Sprintf("%v", this.ServiceVersion), "Version", "Version", 1) + `,`,
 		`Spec:` + strings.Replace(fmt.Sprintf("%v", this.Spec), "ServiceSpec", "ServiceSpec", 1) + `,`,
 		`Spec:` + strings.Replace(fmt.Sprintf("%v", this.Spec), "ServiceSpec", "ServiceSpec", 1) + `,`,
+		`Rollback:` + fmt.Sprintf("%v", this.Rollback) + `,`,
 		`}`,
 		`}`,
 	}, "")
 	}, "")
 	return s
 	return s
@@ -9511,6 +9552,25 @@ func (m *UpdateServiceRequest) Unmarshal(dAtA []byte) error {
 				return err
 				return err
 			}
 			}
 			iNdEx = postIndex
 			iNdEx = postIndex
+		case 4:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Rollback", wireType)
+			}
+			m.Rollback = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowControl
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Rollback |= (UpdateServiceRequest_Rollback(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
 		default:
 		default:
 			iNdEx = preIndex
 			iNdEx = preIndex
 			skippy, err := skipControl(dAtA[iNdEx:])
 			skippy, err := skipControl(dAtA[iNdEx:])
@@ -13250,117 +13310,120 @@ var (
 func init() { proto.RegisterFile("control.proto", fileDescriptorControl) }
 func init() { proto.RegisterFile("control.proto", fileDescriptorControl) }
 
 
 var fileDescriptorControl = []byte{
 var fileDescriptorControl = []byte{
-	// 1781 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x5a, 0xdd, 0x6f, 0x1b, 0xc5,
-	0x16, 0xaf, 0xed, 0x24, 0x4e, 0x8e, 0xe3, 0x7c, 0x4c, 0xdc, 0x5e, 0xcb, 0xed, 0x4d, 0xaa, 0xed,
-	0x6d, 0xea, 0x5c, 0xe5, 0x3a, 0x17, 0x97, 0x8a, 0x52, 0xc4, 0x47, 0x93, 0xd0, 0xe2, 0xa6, 0x84,
-	0x6a, 0xd3, 0x22, 0xde, 0x22, 0xc7, 0x9e, 0x86, 0xad, 0x1d, 0xaf, 0xd9, 0xdd, 0xa4, 0x8d, 0x78,
-	0x01, 0x04, 0x7f, 0x02, 0x12, 0xaf, 0xbc, 0x82, 0xc4, 0x33, 0x6f, 0xbc, 0x56, 0x3c, 0xf1, 0xc8,
-	0x53, 0x44, 0x2d, 0x21, 0xf1, 0xc4, 0x9f, 0x80, 0xd0, 0xcc, 0x9c, 0xd9, 0x2f, 0xcf, 0xee, 0xda,
-	0x49, 0x50, 0xfa, 0x14, 0xef, 0xec, 0xef, 0xcc, 0x39, 0x33, 0xe7, 0x37, 0xbf, 0x3d, 0x73, 0x14,
-	0xc8, 0x37, 0xcc, 0x8e, 0x63, 0x99, 0xed, 0x4a, 0xd7, 0x32, 0x1d, 0x93, 0x90, 0xa6, 0xd9, 0x68,
-	0x51, 0xab, 0x62, 0x3f, 0xad, 0x5b, 0x7b, 0x2d, 0xc3, 0xa9, 0x1c, 0xbc, 0x52, 0xca, 0xd9, 0x5d,
-	0xda, 0xb0, 0x05, 0xa0, 0x94, 0x37, 0x77, 0x9e, 0xd0, 0x86, 0x23, 0x1f, 0x73, 0xce, 0x61, 0x97,
-	0xca, 0x87, 0xc2, 0xae, 0xb9, 0x6b, 0xf2, 0x9f, 0x2b, 0xec, 0x17, 0x8e, 0xce, 0x75, 0xdb, 0xfb,
-	0xbb, 0x46, 0x67, 0x45, 0xfc, 0x11, 0x83, 0xda, 0x0d, 0x98, 0xba, 0x4b, 0x9d, 0x4d, 0xb3, 0x49,
-	0x75, 0xfa, 0xc9, 0x3e, 0xb5, 0x1d, 0x72, 0x05, 0xb2, 0x1d, 0xb3, 0x49, 0xb7, 0x8d, 0x66, 0x31,
-	0x75, 0x39, 0x55, 0x9e, 0x58, 0x85, 0xde, 0xd1, 0xc2, 0x18, 0x43, 0xd4, 0xd6, 0xf5, 0x31, 0xf6,
-	0xaa, 0xd6, 0xd4, 0xde, 0x86, 0x69, 0xd7, 0xcc, 0xee, 0x9a, 0x1d, 0x9b, 0x92, 0x65, 0x18, 0x61,
-	0x2f, 0xb9, 0x51, 0xae, 0x5a, 0xac, 0xf4, 0x2f, 0xa0, 0xc2, 0xf1, 0x1c, 0xa5, 0x1d, 0x65, 0x60,
-	0xe6, 0xbe, 0x61, 0xf3, 0x29, 0x6c, 0xe9, 0xfa, 0x0e, 0x64, 0x1f, 0x1b, 0x6d, 0x87, 0x5a, 0x36,
-	0xce, 0xb2, 0xac, 0x9a, 0x25, 0x6c, 0x56, 0xb9, 0x23, 0x6c, 0x74, 0x69, 0x5c, 0xfa, 0x3c, 0x03,
-	0x59, 0x1c, 0x24, 0x05, 0x18, 0xed, 0xd4, 0xf7, 0x28, 0x9b, 0x31, 0x53, 0x9e, 0xd0, 0xc5, 0x03,
-	0x59, 0x81, 0x9c, 0xd1, 0xdc, 0xee, 0x5a, 0xf4, 0xb1, 0xf1, 0x8c, 0xda, 0xc5, 0x34, 0x7b, 0xb7,
-	0x3a, 0xd5, 0x3b, 0x5a, 0x80, 0xda, 0xfa, 0x03, 0x1c, 0xd5, 0xc1, 0x68, 0xca, 0xdf, 0xe4, 0x01,
-	0x8c, 0xb5, 0xeb, 0x3b, 0xb4, 0x6d, 0x17, 0x33, 0x97, 0x33, 0xe5, 0x5c, 0xf5, 0xe6, 0x30, 0x91,
-	0x55, 0xee, 0x73, 0xd3, 0x77, 0x3b, 0x8e, 0x75, 0xa8, 0xe3, 0x3c, 0xa4, 0x06, 0xb9, 0x3d, 0xba,
-	0xb7, 0x43, 0x2d, 0xfb, 0x63, 0xa3, 0x6b, 0x17, 0x47, 0x2e, 0x67, 0xca, 0x53, 0xd5, 0x6b, 0x51,
-	0xdb, 0xb6, 0xd5, 0xa5, 0x8d, 0xca, 0xfb, 0x2e, 0x5e, 0xf7, 0xdb, 0x92, 0x2a, 0x8c, 0x5a, 0x66,
-	0x9b, 0xda, 0xc5, 0x51, 0x3e, 0xc9, 0xa5, 0xc8, 0xbd, 0x37, 0xdb, 0x54, 0x17, 0x50, 0x72, 0x05,
-	0xf2, 0x6c, 0x2b, 0xbc, 0x3d, 0x18, 0xe3, 0xfb, 0x33, 0xc9, 0x06, 0xe5, 0xaa, 0x4b, 0xaf, 0x43,
-	0xce, 0x17, 0x3a, 0x99, 0x81, 0x4c, 0x8b, 0x1e, 0x0a, 0x5a, 0xe8, 0xec, 0x27, 0xdb, 0xdd, 0x83,
-	0x7a, 0x7b, 0x9f, 0x16, 0xd3, 0x7c, 0x4c, 0x3c, 0xdc, 0x4a, 0xdf, 0x4c, 0x69, 0x6b, 0x30, 0xeb,
-	0xdb, 0x0e, 0xe4, 0x48, 0x05, 0x46, 0x59, 0xf6, 0x45, 0x32, 0xe2, 0x48, 0x22, 0x60, 0xda, 0x77,
-	0x29, 0x98, 0x7d, 0xd4, 0x6d, 0xd6, 0x1d, 0x3a, 0x2c, 0x43, 0xc9, 0x5b, 0x30, 0xc9, 0x41, 0x07,
-	0xd4, 0xb2, 0x0d, 0xb3, 0xc3, 0x03, 0xcc, 0x55, 0x2f, 0xaa, 0x3c, 0x7e, 0x28, 0x20, 0x7a, 0x8e,
-	0x19, 0xe0, 0x03, 0xf9, 0x3f, 0x8c, 0xb0, 0xe3, 0x56, 0xcc, 0x70, 0xbb, 0x4b, 0x71, 0x79, 0xd1,
-	0x39, 0x52, 0x5b, 0x05, 0xe2, 0x8f, 0xf5, 0x58, 0xc7, 0x62, 0x13, 0x66, 0x75, 0xba, 0x67, 0x1e,
-	0x0c, 0xbf, 0xde, 0x02, 0x8c, 0x3e, 0x36, 0xad, 0x86, 0xc8, 0xc4, 0xb8, 0x2e, 0x1e, 0xb4, 0x02,
-	0x10, 0xff, 0x7c, 0x22, 0x26, 0x3c, 0xf4, 0x0f, 0xeb, 0x76, 0xcb, 0xe7, 0xc2, 0xa9, 0xdb, 0xad,
-	0x90, 0x0b, 0x86, 0x60, 0x2e, 0xd8, 0x2b, 0xf7, 0xd0, 0x0b, 0x33, 0x6f, 0x75, 0xec, 0x65, 0xdc,
-	0xea, 0x38, 0x9e, 0xa3, 0xb4, 0x9b, 0x72, 0x75, 0x43, 0xbb, 0x76, 0xd7, 0xe1, 0xf7, 0xae, 0xfd,
-	0x85, 0x22, 0xc2, 0x06, 0x8f, 0x21, 0x22, 0x7e, 0xb3, 0x7e, 0x11, 0xf9, 0xf6, 0x0c, 0x45, 0x44,
-	0x15, 0x99, 0x52, 0x44, 0x56, 0x20, 0x67, 0x53, 0xeb, 0xc0, 0x68, 0x30, 0x76, 0x08, 0x11, 0xc1,
-	0x10, 0xb6, 0xc4, 0x70, 0x6d, 0xdd, 0xd6, 0x01, 0x21, 0xb5, 0xa6, 0x4d, 0x16, 0x61, 0x1c, 0xb9,
-	0x24, 0xd4, 0x62, 0x62, 0x35, 0xd7, 0x3b, 0x5a, 0xc8, 0x0a, 0x32, 0xd9, 0x7a, 0x56, 0xb0, 0xc9,
-	0x26, 0xeb, 0x30, 0xd5, 0xa4, 0xb6, 0x61, 0xd1, 0xe6, 0xb6, 0xed, 0xd4, 0x1d, 0xd4, 0x87, 0xa9,
-	0xea, 0xbf, 0xa3, 0x52, 0xbc, 0xc5, 0x50, 0x7a, 0x1e, 0x8d, 0xf8, 0x93, 0x42, 0x64, 0xb2, 0xff,
-	0x88, 0xc8, 0xe0, 0x76, 0x79, 0x22, 0xc3, 0x58, 0x13, 0x2b, 0x32, 0x9c, 0x46, 0x02, 0xa6, 0x6d,
-	0x40, 0x61, 0xcd, 0xa2, 0x75, 0x87, 0xe2, 0x96, 0x49, 0x22, 0x5d, 0x47, 0x05, 0x10, 0x2c, 0x5a,
-	0x50, 0x4d, 0x83, 0x16, 0x3e, 0x11, 0xd8, 0x84, 0xf3, 0xa1, 0xc9, 0x30, 0xaa, 0x1b, 0x90, 0xc5,
-	0x34, 0xe0, 0x84, 0x17, 0x63, 0x26, 0xd4, 0x25, 0x56, 0xbb, 0x0d, 0xb3, 0x77, 0xa9, 0x13, 0x8a,
-	0x6c, 0x19, 0xc0, 0xcb, 0x3a, 0x9e, 0x9a, 0x7c, 0xef, 0x68, 0x61, 0xc2, 0x4d, 0xba, 0x3e, 0xe1,
-	0xe6, 0x5c, 0xdb, 0x00, 0xe2, 0x9f, 0xe2, 0x64, 0xf1, 0xfc, 0x94, 0x82, 0x82, 0x50, 0xb9, 0x93,
-	0xc4, 0x44, 0xd6, 0x61, 0x5a, 0xa2, 0x87, 0x10, 0xe8, 0x29, 0xb4, 0x91, 0x1a, 0x7d, 0x3d, 0xa0,
-	0xd1, 0x83, 0x67, 0x28, 0xb4, 0x80, 0x93, 0xed, 0xc8, 0x3a, 0x14, 0x84, 0x34, 0x9d, 0x28, 0x49,
-	0xff, 0x82, 0xf3, 0xa1, 0x59, 0x50, 0xe3, 0xfe, 0x48, 0xc3, 0x1c, 0xe3, 0x38, 0x8e, 0xbb, 0x32,
-	0x57, 0x0b, 0xcb, 0xdc, 0x4a, 0x94, 0x98, 0x84, 0x2c, 0xfb, 0x95, 0xee, 0xab, 0xf4, 0xa9, 0x2b,
-	0xdd, 0x56, 0x48, 0xe9, 0xde, 0x18, 0x32, 0x38, 0xa5, 0xd8, 0xf5, 0xa9, 0xc9, 0xc8, 0xe9, 0xaa,
-	0xc9, 0x07, 0x50, 0x08, 0x86, 0x84, 0xc4, 0x78, 0x0d, 0xc6, 0x31, 0x51, 0x52, 0x53, 0x62, 0x99,
-	0xe1, 0x82, 0x3d, 0x65, 0xd9, 0xa4, 0xce, 0x53, 0xd3, 0x6a, 0x0d, 0xa1, 0x2c, 0x68, 0xa1, 0x52,
-	0x16, 0x77, 0x32, 0x8f, 0xb7, 0x1d, 0x31, 0x14, 0xc7, 0x5b, 0x69, 0x25, 0xb1, 0xda, 0x23, 0xae,
-	0x2c, 0xa1, 0xc8, 0x08, 0x8c, 0xb0, 0xdd, 0xc4, 0xfd, 0xe2, 0xbf, 0x19, 0x91, 0xd1, 0x86, 0x11,
-	0x39, 0xed, 0x11, 0x19, 0x6d, 0x19, 0x91, 0x11, 0xe0, 0xaa, 0xcd, 0x29, 0xc5, 0xf8, 0x91, 0x3c,
-	0x5b, 0xa7, 0x1e, 0xa6, 0x7b, 0xde, 0x42, 0x91, 0xba, 0xe7, 0x0d, 0xc7, 0x8f, 0x71, 0xde, 0x42,
-	0x96, 0x2f, 0xd7, 0x79, 0x8b, 0x08, 0xee, 0x2c, 0xcf, 0x9b, 0x17, 0x92, 0x77, 0xde, 0x30, 0x51,
-	0xb1, 0xe7, 0x4d, 0x66, 0xce, 0x05, 0xe3, 0xc7, 0x72, 0xad, 0xbd, 0x6f, 0x3b, 0xd4, 0xf2, 0xe9,
-	0x70, 0x43, 0x8c, 0x84, 0x74, 0x18, 0x71, 0x8c, 0x17, 0x08, 0x70, 0xe9, 0xeb, 0x4e, 0xe1, 0xd1,
-	0x17, 0x21, 0x71, 0xf4, 0x95, 0x56, 0x12, 0xeb, 0x72, 0x09, 0x5f, 0x1c, 0x83, 0x4b, 0x21, 0xcb,
-	0x97, 0x8b, 0x4b, 0x11, 0xc1, 0x9d, 0x25, 0x97, 0xbc, 0x90, 0x3c, 0x2e, 0x61, 0x36, 0x62, 0xb9,
-	0x24, 0x53, 0xe7, 0x82, 0xb5, 0xaf, 0x53, 0x90, 0xdb, 0xa0, 0x87, 0xba, 0xe9, 0xd4, 0x1d, 0x56,
-	0x6b, 0xfc, 0x17, 0x66, 0x19, 0xc9, 0xa8, 0xb5, 0xfd, 0xc4, 0x34, 0x3a, 0xdb, 0x8e, 0xd9, 0xa2,
-	0x1d, 0x1e, 0xda, 0xb8, 0x3e, 0x2d, 0x5e, 0xdc, 0x33, 0x8d, 0xce, 0x43, 0x36, 0x4c, 0x96, 0x81,
-	0xec, 0xd5, 0x3b, 0xf5, 0xdd, 0x20, 0x58, 0x5c, 0xcc, 0x66, 0xf0, 0x8d, 0x12, 0xbd, 0xdf, 0x69,
-	0x9b, 0x8d, 0xd6, 0x36, 0x5b, 0x75, 0x26, 0x80, 0x7e, 0xc4, 0x5f, 0x6c, 0xd0, 0x43, 0xed, 0x8b,
-	0xb4, 0x2c, 0xc0, 0x4e, 0xc2, 0x73, 0x56, 0x80, 0x49, 0xf4, 0x30, 0x05, 0x18, 0xda, 0x0c, 0x51,
-	0x80, 0xa1, 0x77, 0xef, 0x43, 0x46, 0x6e, 0xc3, 0xb8, 0x85, 0xbb, 0x5a, 0x1c, 0x89, 0x36, 0xf4,
-	0x6d, 0xfe, 0xea, 0xc8, 0xf3, 0xa3, 0x85, 0x73, 0xba, 0x6b, 0xe6, 0xd5, 0x70, 0xa7, 0x74, 0x50,
-	0xdf, 0x84, 0x19, 0x5e, 0x22, 0x37, 0x2c, 0xea, 0xc8, 0xfd, 0x5c, 0x82, 0x09, 0x9b, 0x0f, 0x78,
-	0xdb, 0x39, 0xd9, 0x3b, 0x5a, 0x18, 0x17, 0xa8, 0xda, 0x3a, 0xfb, 0xce, 0xf3, 0x5f, 0x4d, 0xed,
-	0x2e, 0x16, 0xe9, 0xc2, 0x1c, 0x43, 0xa9, 0xc2, 0x98, 0x00, 0x60, 0x24, 0x25, 0x75, 0xcd, 0xc0,
-	0x6d, 0x10, 0xa9, 0xfd, 0x98, 0x82, 0x39, 0x59, 0x9c, 0x1e, 0x2f, 0x16, 0xb2, 0x0a, 0x53, 0x08,
-	0x1d, 0x22, 0xaf, 0x79, 0x61, 0x22, 0xd3, 0x5a, 0x0d, 0xa4, 0x75, 0x3e, 0x3a, 0x70, 0x5f, 0x79,
-	0x72, 0xcf, 0xbb, 0x17, 0x9c, 0x78, 0x1b, 0x7e, 0x4f, 0x03, 0x11, 0x95, 0x18, 0x7b, 0x74, 0x65,
-	0xf3, 0xbd, 0xb0, 0x6c, 0x56, 0xa2, 0xab, 0x4a, 0xbf, 0x61, 0xbf, 0x6a, 0x7e, 0x79, 0xfa, 0xaa,
-	0xa9, 0x87, 0x54, 0xf3, 0xd6, 0x70, 0xb1, 0x9d, 0x89, 0x68, 0x6e, 0xc8, 0xab, 0x05, 0x46, 0x84,
-	0x29, 0x7b, 0x95, 0x5d, 0x84, 0xf8, 0x10, 0x4a, 0x66, 0x5c, 0xce, 0x24, 0x54, 0xab, 0xc1, 0x9c,
-	0xbc, 0xf9, 0xfa, 0xa9, 0x5b, 0x0d, 0xd4, 0xba, 0x03, 0x73, 0x29, 0x38, 0xd5, 0x09, 0xb8, 0xf4,
-	0x0e, 0xcc, 0xc9, 0x8b, 0xd5, 0x31, 0x4f, 0xf7, 0x05, 0xef, 0x82, 0xe7, 0x8f, 0xa6, 0xfa, 0xfd,
-	0x05, 0xc8, 0xae, 0x89, 0xa6, 0x3d, 0x31, 0x20, 0x8b, 0xfd, 0x70, 0xa2, 0xa9, 0x82, 0x0a, 0xf6,
-	0xd8, 0x4b, 0x57, 0x62, 0x31, 0x58, 0x89, 0x9e, 0xff, 0xf9, 0x87, 0x3f, 0xbf, 0x49, 0x4f, 0x43,
-	0x9e, 0x83, 0xfe, 0x87, 0x5f, 0x02, 0x62, 0xc2, 0x84, 0xdb, 0x58, 0x25, 0xff, 0x19, 0xa4, 0x0d,
-	0x5d, 0xba, 0x9a, 0x80, 0x8a, 0x77, 0x68, 0x01, 0x78, 0x7d, 0x4d, 0xa2, 0x9c, 0xab, 0xaf, 0x47,
-	0x5b, 0x5a, 0x4c, 0x82, 0x25, 0xfa, 0xf4, 0xfa, 0x96, 0x6a, 0x9f, 0x7d, 0x7d, 0x52, 0xb5, 0x4f,
-	0x45, 0xfb, 0x33, 0xc2, 0xa7, 0xc8, 0xe1, 0xc3, 0xba, 0xdd, 0x8a, 0xcc, 0xa1, 0xaf, 0x6f, 0x19,
-	0x99, 0xc3, 0x40, 0x87, 0x32, 0x3e, 0x87, 0xbc, 0x6f, 0x15, 0x9d, 0x43, 0x7f, 0x17, 0x30, 0x3a,
-	0x87, 0x81, 0xe6, 0x57, 0xe2, 0x7e, 0xf2, 0xe5, 0xc5, 0xec, 0xa7, 0x7f, 0x85, 0x8b, 0x49, 0xb0,
-	0x44, 0x9f, 0x5e, 0xdf, 0x49, 0xed, 0xb3, 0xaf, 0xb5, 0xa5, 0xf6, 0xd9, 0xdf, 0xbe, 0x8a, 0xf2,
-	0xf9, 0x0c, 0x26, 0xfd, 0x57, 0x78, 0x72, 0x6d, 0xc0, 0xbe, 0x43, 0xa9, 0x9c, 0x0c, 0x8c, 0xf7,
-	0xfc, 0x29, 0xe4, 0x03, 0x8d, 0x3f, 0xa2, 0x9c, 0x51, 0xd5, 0x68, 0x2c, 0x2d, 0x0d, 0x80, 0x4c,
-	0x74, 0x1e, 0xe8, 0x69, 0xa9, 0x9d, 0xab, 0xfa, 0x76, 0x6a, 0xe7, 0xca, 0x06, 0x59, 0x8c, 0xf3,
-	0x40, 0xeb, 0x4a, 0xed, 0x5c, 0xd5, 0x23, 0x53, 0x3b, 0x57, 0xf7, 0xc1, 0x62, 0x49, 0x86, 0x57,
-	0xc1, 0x48, 0x92, 0x05, 0xdb, 0x07, 0x91, 0x24, 0x0b, 0xf7, 0x02, 0xe2, 0x49, 0x26, 0xef, 0xad,
-	0xd1, 0x24, 0x0b, 0x5d, 0xb6, 0xa3, 0x49, 0x16, 0xbe, 0x02, 0x27, 0x92, 0x4c, 0x2e, 0x38, 0x86,
-	0x64, 0xa1, 0x35, 0x2f, 0x0d, 0x80, 0x1c, 0x30, 0xcf, 0xb1, 0xce, 0x55, 0xfd, 0x9a, 0xb8, 0x3c,
-	0x0f, 0xe8, 0x5c, 0xe4, 0x19, 0x0b, 0xf7, 0xc8, 0x3c, 0x07, 0xaf, 0x44, 0x91, 0x79, 0x0e, 0xdd,
-	0x1a, 0x12, 0xf2, 0x2c, 0xef, 0x94, 0xd1, 0x79, 0x0e, 0x5d, 0x84, 0xa3, 0xf3, 0x1c, 0xbe, 0x9e,
-	0x26, 0x9e, 0x67, 0xb9, 0xe0, 0x98, 0xf3, 0x1c, 0x5a, 0xf3, 0xd2, 0x00, 0xc8, 0xc4, 0x8f, 0x93,
-	0x7b, 0x9b, 0x51, 0x7f, 0x9c, 0xc2, 0x77, 0xa5, 0xd2, 0xd5, 0x04, 0x54, 0xe2, 0x3e, 0xfb, 0xaf,
-	0x0e, 0xea, 0x7d, 0x56, 0x5c, 0x8b, 0x4a, 0xe5, 0x64, 0x60, 0xbc, 0xe7, 0x7d, 0xc8, 0xf9, 0x0a,
-	0x60, 0xb2, 0x38, 0x58, 0xcd, 0x5e, 0xba, 0x96, 0x88, 0x4b, 0x5c, 0xb0, 0xbf, 0xbe, 0x55, 0x2f,
-	0x58, 0x51, 0x4c, 0x97, 0xca, 0xc9, 0xc0, 0x44, 0xcf, 0xfe, 0x5a, 0x56, 0xed, 0x59, 0x51, 0x2f,
-	0x97, 0xca, 0xc9, 0xc0, 0x58, 0xcf, 0xab, 0xc5, 0xe7, 0x2f, 0xe6, 0xcf, 0xfd, 0xfa, 0x62, 0xfe,
-	0xdc, 0x67, 0xbd, 0xf9, 0xd4, 0xf3, 0xde, 0x7c, 0xea, 0x97, 0xde, 0x7c, 0xea, 0xb7, 0xde, 0x7c,
-	0x6a, 0x67, 0x8c, 0xff, 0x27, 0xca, 0xf5, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xb2, 0xa1, 0x31,
-	0x8d, 0x02, 0x23, 0x00, 0x00,
+	// 1838 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x5a, 0x4d, 0x4f, 0x1b, 0x57,
+	0x17, 0xc6, 0x1f, 0x60, 0x73, 0x8c, 0x0d, 0x5c, 0x9c, 0xbc, 0x96, 0x93, 0x17, 0xd0, 0xe4, 0x0d,
+	0x31, 0xaf, 0xa8, 0x69, 0x9c, 0x46, 0x4d, 0x53, 0xf5, 0x23, 0x40, 0x92, 0x3a, 0x24, 0x24, 0x1a,
+	0x42, 0xd4, 0x1d, 0x1a, 0xec, 0x1b, 0x3a, 0xb1, 0xf1, 0xb8, 0x33, 0x03, 0x09, 0xea, 0xa6, 0xad,
+	0xda, 0x9f, 0x50, 0xa9, 0xdb, 0x6e, 0x5b, 0xa9, 0x8b, 0xae, 0xfa, 0x13, 0xa2, 0xae, 0xba, 0xec,
+	0x0a, 0x35, 0x96, 0x2a, 0x75, 0xd5, 0x9f, 0x50, 0x55, 0xf7, 0x6b, 0xbe, 0x7c, 0x67, 0xc6, 0x06,
+	0x2a, 0xb2, 0xca, 0xcc, 0x9d, 0xe7, 0xdc, 0x73, 0xee, 0x3d, 0xcf, 0x7d, 0x7c, 0xee, 0x09, 0x90,
+	0x6f, 0x18, 0x1d, 0xdb, 0x34, 0xda, 0xd5, 0xae, 0x69, 0xd8, 0x06, 0x42, 0x4d, 0xa3, 0xd1, 0xc2,
+	0x66, 0xd5, 0x7a, 0xae, 0x99, 0x7b, 0x2d, 0xdd, 0xae, 0x1e, 0x5c, 0x2d, 0xe7, 0xac, 0x2e, 0x6e,
+	0x58, 0x0c, 0x50, 0xce, 0x1b, 0x3b, 0xcf, 0x70, 0xc3, 0x16, 0xaf, 0x39, 0xfb, 0xb0, 0x8b, 0xc5,
+	0x4b, 0x71, 0xd7, 0xd8, 0x35, 0xe8, 0xe3, 0x32, 0x79, 0xe2, 0xa3, 0x33, 0xdd, 0xf6, 0xfe, 0xae,
+	0xde, 0x59, 0x66, 0xff, 0xb0, 0x41, 0xe5, 0x3a, 0x14, 0xee, 0x62, 0x7b, 0xc3, 0x68, 0x62, 0x15,
+	0x7f, 0xba, 0x8f, 0x2d, 0x1b, 0x5d, 0x82, 0x4c, 0xc7, 0x68, 0xe2, 0x6d, 0xbd, 0x59, 0x4a, 0xcc,
+	0x27, 0x2a, 0xe3, 0x2b, 0xd0, 0x3b, 0x9a, 0x1b, 0x23, 0x88, 0xfa, 0x9a, 0x3a, 0x46, 0x3e, 0xd5,
+	0x9b, 0xca, 0x07, 0x30, 0xe9, 0x98, 0x59, 0x5d, 0xa3, 0x63, 0x61, 0xb4, 0x04, 0x69, 0xf2, 0x91,
+	0x1a, 0xe5, 0x6a, 0xa5, 0x6a, 0xff, 0x02, 0xaa, 0x14, 0x4f, 0x51, 0xca, 0x51, 0x0a, 0xa6, 0xee,
+	0xeb, 0x16, 0x9d, 0xc2, 0x12, 0xae, 0xef, 0x40, 0xe6, 0xa9, 0xde, 0xb6, 0xb1, 0x69, 0xf1, 0x59,
+	0x96, 0x64, 0xb3, 0x04, 0xcd, 0xaa, 0x77, 0x98, 0x8d, 0x2a, 0x8c, 0xcb, 0x5f, 0xa4, 0x20, 0xc3,
+	0x07, 0x51, 0x11, 0x46, 0x3b, 0xda, 0x1e, 0x26, 0x33, 0xa6, 0x2a, 0xe3, 0x2a, 0x7b, 0x41, 0xcb,
+	0x90, 0xd3, 0x9b, 0xdb, 0x5d, 0x13, 0x3f, 0xd5, 0x5f, 0x60, 0xab, 0x94, 0x24, 0xdf, 0x56, 0x0a,
+	0xbd, 0xa3, 0x39, 0xa8, 0xaf, 0x3d, 0xe2, 0xa3, 0x2a, 0xe8, 0x4d, 0xf1, 0x8c, 0x1e, 0xc1, 0x58,
+	0x5b, 0xdb, 0xc1, 0x6d, 0xab, 0x94, 0x9a, 0x4f, 0x55, 0x72, 0xb5, 0x1b, 0xc3, 0x44, 0x56, 0xbd,
+	0x4f, 0x4d, 0x6f, 0x77, 0x6c, 0xf3, 0x50, 0xe5, 0xf3, 0xa0, 0x3a, 0xe4, 0xf6, 0xf0, 0xde, 0x0e,
+	0x36, 0xad, 0x4f, 0xf4, 0xae, 0x55, 0x4a, 0xcf, 0xa7, 0x2a, 0x85, 0xda, 0x95, 0xb0, 0x6d, 0xdb,
+	0xec, 0xe2, 0x46, 0xf5, 0x81, 0x83, 0x57, 0xbd, 0xb6, 0xa8, 0x06, 0xa3, 0xa6, 0xd1, 0xc6, 0x56,
+	0x69, 0x94, 0x4e, 0x72, 0x31, 0x74, 0xef, 0x8d, 0x36, 0x56, 0x19, 0x14, 0x5d, 0x82, 0x3c, 0xd9,
+	0x0a, 0x77, 0x0f, 0xc6, 0xe8, 0xfe, 0x4c, 0x90, 0x41, 0xb1, 0xea, 0xf2, 0x3b, 0x90, 0xf3, 0x84,
+	0x8e, 0xa6, 0x20, 0xd5, 0xc2, 0x87, 0x8c, 0x16, 0x2a, 0x79, 0x24, 0xbb, 0x7b, 0xa0, 0xb5, 0xf7,
+	0x71, 0x29, 0x49, 0xc7, 0xd8, 0xcb, 0xcd, 0xe4, 0x8d, 0x84, 0xb2, 0x0a, 0xd3, 0x9e, 0xed, 0xe0,
+	0x1c, 0xa9, 0xc2, 0x28, 0xc9, 0x3e, 0x4b, 0x46, 0x14, 0x49, 0x18, 0x4c, 0xf9, 0x3e, 0x01, 0xd3,
+	0x5b, 0xdd, 0xa6, 0x66, 0xe3, 0x61, 0x19, 0x8a, 0xde, 0x87, 0x09, 0x0a, 0x3a, 0xc0, 0xa6, 0xa5,
+	0x1b, 0x1d, 0x1a, 0x60, 0xae, 0x76, 0x41, 0xe6, 0xf1, 0x09, 0x83, 0xa8, 0x39, 0x62, 0xc0, 0x5f,
+	0xd0, 0x9b, 0x90, 0x26, 0xc7, 0xad, 0x94, 0xa2, 0x76, 0x17, 0xa3, 0xf2, 0xa2, 0x52, 0xa4, 0xb2,
+	0x02, 0xc8, 0x1b, 0xeb, 0xb1, 0x8e, 0xc5, 0x06, 0x4c, 0xab, 0x78, 0xcf, 0x38, 0x18, 0x7e, 0xbd,
+	0x45, 0x18, 0x7d, 0x6a, 0x98, 0x0d, 0x96, 0x89, 0xac, 0xca, 0x5e, 0x94, 0x22, 0x20, 0xef, 0x7c,
+	0x2c, 0x26, 0x7e, 0xe8, 0x1f, 0x6b, 0x56, 0xcb, 0xe3, 0xc2, 0xd6, 0xac, 0x56, 0xc0, 0x05, 0x41,
+	0x10, 0x17, 0xe4, 0x93, 0x73, 0xe8, 0x99, 0x99, 0xbb, 0x3a, 0xf2, 0x31, 0x6a, 0x75, 0x14, 0x4f,
+	0x51, 0xca, 0x0d, 0xb1, 0xba, 0xa1, 0x5d, 0x3b, 0xeb, 0xf0, 0x7a, 0x57, 0xfe, 0xe6, 0x22, 0x42,
+	0x06, 0x8f, 0x21, 0x22, 0x5e, 0xb3, 0x7e, 0x11, 0xf9, 0xee, 0x0c, 0x45, 0x44, 0x16, 0x99, 0x54,
+	0x44, 0x96, 0x21, 0x67, 0x61, 0xf3, 0x40, 0x6f, 0x10, 0x76, 0x30, 0x11, 0xe1, 0x21, 0x6c, 0xb2,
+	0xe1, 0xfa, 0x9a, 0xa5, 0x02, 0x87, 0xd4, 0x9b, 0x16, 0x5a, 0x80, 0x2c, 0xe7, 0x12, 0x53, 0x8b,
+	0xf1, 0x95, 0x5c, 0xef, 0x68, 0x2e, 0xc3, 0xc8, 0x64, 0xa9, 0x19, 0xc6, 0x26, 0x0b, 0xad, 0x41,
+	0xa1, 0x89, 0x2d, 0xdd, 0xc4, 0xcd, 0x6d, 0xcb, 0xd6, 0x6c, 0xae, 0x0f, 0x85, 0xda, 0x7f, 0xc3,
+	0x52, 0xbc, 0x49, 0x50, 0x6a, 0x9e, 0x1b, 0xd1, 0x37, 0x89, 0xc8, 0x64, 0xfe, 0x15, 0x91, 0xe1,
+	0xdb, 0xe5, 0x8a, 0x0c, 0x61, 0x4d, 0xa4, 0xc8, 0x50, 0x1a, 0x31, 0x98, 0xb2, 0x0e, 0xc5, 0x55,
+	0x13, 0x6b, 0x36, 0xe6, 0x5b, 0x26, 0x88, 0x74, 0x8d, 0x2b, 0x00, 0x63, 0xd1, 0x9c, 0x6c, 0x1a,
+	0x6e, 0xe1, 0x11, 0x81, 0x0d, 0x38, 0x17, 0x98, 0x8c, 0x47, 0x75, 0x1d, 0x32, 0x3c, 0x0d, 0x7c,
+	0xc2, 0x0b, 0x11, 0x13, 0xaa, 0x02, 0xab, 0xdc, 0x82, 0xe9, 0xbb, 0xd8, 0x0e, 0x44, 0xb6, 0x04,
+	0xe0, 0x66, 0x9d, 0x9f, 0x9a, 0x7c, 0xef, 0x68, 0x6e, 0xdc, 0x49, 0xba, 0x3a, 0xee, 0xe4, 0x5c,
+	0x59, 0x07, 0xe4, 0x9d, 0xe2, 0x64, 0xf1, 0xfc, 0x94, 0x84, 0x22, 0x53, 0xb9, 0x93, 0xc4, 0x84,
+	0xd6, 0x60, 0x52, 0xa0, 0x87, 0x10, 0xe8, 0x02, 0xb7, 0x11, 0x1a, 0x7d, 0xcd, 0xa7, 0xd1, 0x83,
+	0x65, 0x08, 0x3d, 0x80, 0xac, 0x69, 0xb4, 0xdb, 0x3b, 0x5a, 0xa3, 0x55, 0x4a, 0xcf, 0x27, 0x2a,
+	0x85, 0xda, 0x55, 0x99, 0xa1, 0x6c, 0x91, 0x55, 0x95, 0x1b, 0xaa, 0xce, 0x14, 0x8a, 0x02, 0x59,
+	0x31, 0x8a, 0xb2, 0x90, 0xde, 0x78, 0xb8, 0x71, 0x7b, 0x6a, 0x04, 0x4d, 0x40, 0xf6, 0x91, 0x7a,
+	0xfb, 0x49, 0xfd, 0xe1, 0xd6, 0xe6, 0x54, 0x82, 0x90, 0x22, 0x30, 0xdd, 0xc9, 0x92, 0xb0, 0x06,
+	0x45, 0xa6, 0x86, 0x27, 0xe2, 0xc5, 0x7f, 0xe0, 0x5c, 0x60, 0x16, 0x2e, 0xab, 0x7f, 0x26, 0x61,
+	0x86, 0x1c, 0x2b, 0x3e, 0xee, 0x28, 0x6b, 0x3d, 0xa8, 0xac, 0xcb, 0x61, 0xfa, 0x15, 0xb0, 0xec,
+	0x17, 0xd7, 0xaf, 0x93, 0xa7, 0x2e, 0xae, 0x9b, 0x01, 0x71, 0x7d, 0x77, 0xc8, 0xe0, 0xa4, 0xfa,
+	0xda, 0x27, 0x60, 0xe9, 0xd3, 0x15, 0xb0, 0x87, 0x50, 0xf4, 0x87, 0xc4, 0x89, 0xf1, 0x36, 0x64,
+	0x79, 0xa2, 0x84, 0x8c, 0x45, 0x32, 0xc3, 0x01, 0xbb, 0x62, 0xb6, 0x81, 0xed, 0xe7, 0x86, 0xd9,
+	0x1a, 0x42, 0xcc, 0xb8, 0x85, 0x4c, 0xcc, 0x9c, 0xc9, 0x5c, 0xde, 0x76, 0xd8, 0x50, 0x14, 0x6f,
+	0x85, 0x95, 0xc0, 0x2a, 0x5b, 0x54, 0xcc, 0x02, 0x91, 0x21, 0x48, 0x93, 0xdd, 0xe4, 0xfb, 0x45,
+	0x9f, 0x09, 0x91, 0xb9, 0x0d, 0x21, 0x72, 0xd2, 0x25, 0x32, 0xb7, 0x25, 0x44, 0xe6, 0x00, 0x47,
+	0xe0, 0x4e, 0x29, 0xc6, 0x8f, 0xc5, 0xd9, 0x3a, 0xf5, 0x30, 0x9d, 0xf3, 0x16, 0x88, 0xd4, 0x39,
+	0x6f, 0x7c, 0xfc, 0x18, 0xe7, 0x2d, 0x60, 0xf9, 0x7a, 0x9d, 0xb7, 0x90, 0xe0, 0xce, 0xf2, 0xbc,
+	0xb9, 0x21, 0xb9, 0xe7, 0x8d, 0x27, 0x2a, 0xf2, 0xbc, 0x89, 0xcc, 0x39, 0x60, 0xfe, 0xfb, 0xbc,
+	0xda, 0xde, 0xb7, 0x6c, 0x6c, 0x7a, 0x74, 0xb8, 0xc1, 0x46, 0x02, 0x3a, 0xcc, 0x71, 0x84, 0x17,
+	0x1c, 0xe0, 0xd0, 0xd7, 0x99, 0xc2, 0xa5, 0x2f, 0x87, 0x44, 0xd1, 0x57, 0x58, 0x09, 0xac, 0xc3,
+	0x25, 0xfe, 0xe1, 0x18, 0x5c, 0x0a, 0x58, 0xbe, 0x5e, 0x5c, 0x0a, 0x09, 0xee, 0x2c, 0xb9, 0xe4,
+	0x86, 0xe4, 0x72, 0x89, 0x67, 0x23, 0x92, 0x4b, 0x22, 0x75, 0x0e, 0x58, 0xf9, 0x26, 0x01, 0xb9,
+	0x75, 0x7c, 0xa8, 0x1a, 0xb6, 0x66, 0x93, 0xf2, 0xe6, 0xff, 0x30, 0x4d, 0x48, 0x86, 0xcd, 0xed,
+	0x67, 0x86, 0xde, 0xd9, 0xb6, 0x8d, 0x16, 0xee, 0xd0, 0xd0, 0xb2, 0xea, 0x24, 0xfb, 0x70, 0xcf,
+	0xd0, 0x3b, 0x8f, 0xc9, 0x30, 0x5a, 0x02, 0xb4, 0xa7, 0x75, 0xb4, 0x5d, 0x3f, 0x98, 0xdd, 0x05,
+	0xa7, 0xf8, 0x17, 0x29, 0x7a, 0xbf, 0xd3, 0x36, 0x1a, 0xad, 0x6d, 0xb2, 0xea, 0x94, 0x0f, 0xbd,
+	0x45, 0x3f, 0xac, 0xe3, 0x43, 0xe5, 0x4b, 0xa7, 0xe6, 0x3b, 0x09, 0xcf, 0x49, 0xcd, 0x27, 0xd0,
+	0xc3, 0xd4, 0x7c, 0xdc, 0x66, 0x88, 0x9a, 0x8f, 0x7b, 0xf7, 0xd4, 0x7c, 0xb7, 0x48, 0xcd, 0xc7,
+	0x76, 0x95, 0xd6, 0x7c, 0x21, 0x86, 0x9e, 0xcd, 0x5f, 0x49, 0xbf, 0x3c, 0x9a, 0x1b, 0x51, 0x1d,
+	0x33, 0xb7, 0x86, 0x3b, 0xa5, 0x83, 0xfa, 0x1e, 0x4c, 0xd1, 0xaa, 0xbc, 0x61, 0x62, 0x5b, 0xec,
+	0xe7, 0x22, 0x8c, 0x5b, 0x74, 0xc0, 0xdd, 0xce, 0x89, 0xde, 0xd1, 0x5c, 0x96, 0xa1, 0xea, 0x6b,
+	0xe4, 0x77, 0x9e, 0x3e, 0x35, 0x95, 0xbb, 0xfc, 0x5e, 0xc0, 0xcc, 0x79, 0x28, 0x35, 0x18, 0x63,
+	0x00, 0x1e, 0x49, 0x59, 0x5e, 0x33, 0x50, 0x1b, 0x8e, 0x54, 0x7e, 0x4e, 0xc0, 0x8c, 0x28, 0x4e,
+	0x8f, 0x17, 0x0b, 0x5a, 0x81, 0x02, 0x87, 0x0e, 0x91, 0xd7, 0x3c, 0x33, 0x11, 0x69, 0xad, 0xf9,
+	0xd2, 0x3a, 0x1b, 0x1e, 0xb8, 0xa7, 0x3c, 0xb9, 0xe7, 0x5e, 0x45, 0x4e, 0xbc, 0x0d, 0x7f, 0x24,
+	0x01, 0xb1, 0x4a, 0x8c, 0xbc, 0x3a, 0xb2, 0xf9, 0x51, 0x50, 0x36, 0xab, 0xe1, 0x55, 0xa5, 0xd7,
+	0xb0, 0x5f, 0x35, 0xbf, 0x3a, 0x7d, 0xd5, 0x54, 0x03, 0xaa, 0x79, 0x73, 0xb8, 0xd8, 0xce, 0x44,
+	0x34, 0xd7, 0xc5, 0xd5, 0x82, 0x47, 0xc4, 0x53, 0xf6, 0x16, 0xb9, 0x08, 0xd1, 0x21, 0x2e, 0x99,
+	0x51, 0x39, 0x13, 0x50, 0xa5, 0x0e, 0x33, 0xe2, 0xb2, 0xed, 0xa5, 0x6e, 0xcd, 0x57, 0xeb, 0x0e,
+	0xcc, 0x25, 0xff, 0x54, 0x27, 0xe0, 0xd2, 0x87, 0x30, 0x23, 0x2e, 0x56, 0xc7, 0x3c, 0xdd, 0xe7,
+	0xdd, 0x0b, 0x9e, 0x37, 0x9a, 0xda, 0x0f, 0xe7, 0x21, 0xb3, 0xca, 0xfe, 0x9f, 0x00, 0xe9, 0x90,
+	0xe1, 0x2d, 0x78, 0xa4, 0xc8, 0x82, 0xf2, 0xb7, 0xf5, 0xcb, 0x97, 0x22, 0x31, 0xbc, 0x12, 0x3d,
+	0xf7, 0xcb, 0x8f, 0x7f, 0x7d, 0x9b, 0x9c, 0x84, 0x3c, 0x05, 0xbd, 0xc1, 0x7f, 0x09, 0x90, 0x01,
+	0xe3, 0x4e, 0x2f, 0x17, 0xfd, 0x6f, 0x90, 0xce, 0x77, 0xf9, 0x72, 0x0c, 0x2a, 0xda, 0xa1, 0x09,
+	0xe0, 0xb6, 0x52, 0xd1, 0xe5, 0xf0, 0xfb, 0xb9, 0x77, 0x85, 0x0b, 0x71, 0xb0, 0x58, 0x9f, 0x6e,
+	0xab, 0x54, 0xee, 0xb3, 0xaf, 0x35, 0x2b, 0xf7, 0x29, 0xe9, 0xb8, 0x86, 0xf8, 0x64, 0x39, 0x7c,
+	0xac, 0x59, 0xad, 0xd0, 0x1c, 0x7a, 0x5a, 0xa5, 0xa1, 0x39, 0xf4, 0x35, 0x45, 0xa3, 0x73, 0x48,
+	0x5b, 0x65, 0xe1, 0x39, 0xf4, 0x36, 0x1e, 0xc3, 0x73, 0xe8, 0xeb, 0xb7, 0xc5, 0xee, 0x27, 0x5d,
+	0x5e, 0xc4, 0x7e, 0x7a, 0x57, 0xb8, 0x10, 0x07, 0x8b, 0xf5, 0xe9, 0xb6, 0xba, 0xe4, 0x3e, 0xfb,
+	0xba, 0x69, 0x72, 0x9f, 0xfd, 0x1d, 0xb3, 0x30, 0x9f, 0x2f, 0x60, 0xc2, 0x7b, 0x85, 0x47, 0x57,
+	0x06, 0xec, 0x3b, 0x94, 0x2b, 0xf1, 0xc0, 0x68, 0xcf, 0x9f, 0x41, 0xde, 0xd7, 0x6b, 0x44, 0xd2,
+	0x19, 0x65, 0xbd, 0xcd, 0xf2, 0xe2, 0x00, 0xc8, 0x58, 0xe7, 0xbe, 0x9e, 0x96, 0xdc, 0xb9, 0xac,
+	0x8b, 0x26, 0x77, 0x2e, 0x6d, 0x90, 0x45, 0x38, 0xf7, 0xb5, 0xae, 0xe4, 0xce, 0x65, 0x3d, 0x32,
+	0xb9, 0x73, 0x79, 0x1f, 0x2c, 0x92, 0x64, 0xfc, 0x2a, 0x18, 0x4a, 0x32, 0x7f, 0xfb, 0x20, 0x94,
+	0x64, 0xc1, 0x5e, 0x40, 0x34, 0xc9, 0xc4, 0xbd, 0x35, 0x9c, 0x64, 0x81, 0xcb, 0x76, 0x38, 0xc9,
+	0x82, 0x57, 0xe0, 0x58, 0x92, 0x89, 0x05, 0x47, 0x90, 0x2c, 0xb0, 0xe6, 0xc5, 0x01, 0x90, 0x03,
+	0xe6, 0x39, 0xd2, 0xb9, 0xac, 0x5f, 0x13, 0x95, 0xe7, 0x01, 0x9d, 0xb3, 0x3c, 0xf3, 0xc2, 0x3d,
+	0x34, 0xcf, 0xfe, 0x2b, 0x51, 0x68, 0x9e, 0x03, 0xb7, 0x86, 0x98, 0x3c, 0x8b, 0x3b, 0x65, 0x78,
+	0x9e, 0x03, 0x17, 0xe1, 0xf0, 0x3c, 0x07, 0xaf, 0xa7, 0xb1, 0xe7, 0x59, 0x2c, 0x38, 0xe2, 0x3c,
+	0x07, 0xd6, 0xbc, 0x38, 0x00, 0x32, 0xf6, 0xc7, 0xc9, 0xb9, 0xcd, 0xc8, 0x7f, 0x9c, 0x82, 0x77,
+	0xa5, 0xf2, 0xe5, 0x18, 0x54, 0xec, 0x3e, 0x7b, 0xaf, 0x0e, 0xf2, 0x7d, 0x96, 0x5c, 0x8b, 0xca,
+	0x95, 0x78, 0x60, 0xb4, 0xe7, 0x7d, 0xc8, 0x79, 0x0a, 0x60, 0xb4, 0x30, 0x58, 0xcd, 0x5e, 0xbe,
+	0x12, 0x8b, 0x8b, 0x5d, 0xb0, 0xb7, 0xbe, 0x95, 0x2f, 0x58, 0x52, 0x4c, 0x97, 0x2b, 0xf1, 0xc0,
+	0x58, 0xcf, 0xde, 0x5a, 0x56, 0xee, 0x59, 0x52, 0x2f, 0x97, 0x2b, 0xf1, 0xc0, 0x48, 0xcf, 0x2b,
+	0xa5, 0x97, 0xaf, 0x66, 0x47, 0x7e, 0x7b, 0x35, 0x3b, 0xf2, 0x79, 0x6f, 0x36, 0xf1, 0xb2, 0x37,
+	0x9b, 0xf8, 0xb5, 0x37, 0x9b, 0xf8, 0xbd, 0x37, 0x9b, 0xd8, 0x19, 0xa3, 0x7f, 0xfc, 0x72, 0xed,
+	0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf7, 0xd5, 0x67, 0xd5, 0x75, 0x23, 0x00, 0x00,
 }
 }

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

@@ -220,6 +220,21 @@ message UpdateServiceRequest {
 	string service_id = 1;
 	string service_id = 1;
 	Version service_version = 2;
 	Version service_version = 2;
 	ServiceSpec spec = 3;
 	ServiceSpec spec = 3;
+
+	enum Rollback {
+		// This is not a rollback. The spec field of the request will
+		// be honored.
+		NONE = 0;
+
+		// Roll back the service - get spec from the service's
+		// previous_spec.
+		PREVIOUS = 1;
+	}
+
+	// Rollback may be set to PREVIOUS to request a rollback (the service's
+	// spec will be set to the value of its previous_spec field). In this
+	// case, the spec field of this request is ignored.
+	Rollback rollback = 4;
 }
 }
 
 
 message UpdateServiceResponse {
 message UpdateServiceResponse {

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

@@ -9,7 +9,7 @@ import (
 
 
 // Task returns the task name from Annotations.Name,
 // Task returns the task name from Annotations.Name,
 // and, in case Annotations.Name is missing, fallback
 // and, in case Annotations.Name is missing, fallback
-// to construct the name from othere information.
+// to construct the name from other information.
 func Task(t *api.Task) string {
 func Task(t *api.Task) string {
 	if t.Annotations.Name != "" {
 	if t.Annotations.Name != "" {
 		// if set, use the container Annotations.Name field, set in the orchestrator.
 		// if set, use the container Annotations.Name field, set in the orchestrator.

+ 257 - 157
vendor/github.com/docker/swarmkit/api/specs.pb.go

@@ -138,8 +138,10 @@ type ServiceSpec struct {
 	//	*ServiceSpec_Replicated
 	//	*ServiceSpec_Replicated
 	//	*ServiceSpec_Global
 	//	*ServiceSpec_Global
 	Mode isServiceSpec_Mode `protobuf_oneof:"mode"`
 	Mode isServiceSpec_Mode `protobuf_oneof:"mode"`
-	// UpdateConfig controls the rate and policy of updates.
+	// Update contains settings which affect updates.
 	Update *UpdateConfig `protobuf:"bytes,6,opt,name=update" json:"update,omitempty"`
 	Update *UpdateConfig `protobuf:"bytes,6,opt,name=update" json:"update,omitempty"`
+	// Rollback contains settings which affect rollbacks of updates.
+	Rollback *UpdateConfig `protobuf:"bytes,9,opt,name=rollback" json:"rollback,omitempty"`
 	// ServiceSpec.Networks has been deprecated and is replaced by
 	// ServiceSpec.Networks has been deprecated and is replaced by
 	// Networks field in Task (TaskSpec.Networks).
 	// Networks field in Task (TaskSpec.Networks).
 	// This field (ServiceSpec.Networks) is kept for compatibility.
 	// This field (ServiceSpec.Networks) is kept for compatibility.
@@ -488,8 +490,10 @@ type ContainerSpec struct {
 	// This only impacts the root filesystem, not additional mounts (including
 	// This only impacts the root filesystem, not additional mounts (including
 	// tmpfs). For additional mounts that are not part of the initial rootfs,
 	// tmpfs). For additional mounts that are not part of the initial rootfs,
 	// they will be decided by the modes passed in the mount definition.
 	// they will be decided by the modes passed in the mount definition.
-	ReadOnly bool    `protobuf:"varint,19,opt,name=read_only,json=readOnly,proto3" json:"read_only,omitempty"`
-	Mounts   []Mount `protobuf:"bytes,8,rep,name=mounts" json:"mounts"`
+	ReadOnly bool `protobuf:"varint,19,opt,name=read_only,json=readOnly,proto3" json:"read_only,omitempty"`
+	// StopSignal defines the signal to stop the container.
+	StopSignal string  `protobuf:"bytes,20,opt,name=stop_signal,json=stopSignal,proto3" json:"stop_signal,omitempty"`
+	Mounts     []Mount `protobuf:"bytes,8,rep,name=mounts" json:"mounts"`
 	// StopGracePeriod the grace period for stopping the container before
 	// StopGracePeriod the grace period for stopping the container before
 	// forcefully killing the container.
 	// forcefully killing the container.
 	// Note: Can't use stdduration here because this needs to be nullable.
 	// Note: Can't use stdduration here because this needs to be nullable.
@@ -683,6 +687,10 @@ func (m *ServiceSpec) CopyFrom(src interface{}) {
 		m.Update = &UpdateConfig{}
 		m.Update = &UpdateConfig{}
 		github_com_docker_swarmkit_api_deepcopy.Copy(m.Update, o.Update)
 		github_com_docker_swarmkit_api_deepcopy.Copy(m.Update, o.Update)
 	}
 	}
+	if o.Rollback != nil {
+		m.Rollback = &UpdateConfig{}
+		github_com_docker_swarmkit_api_deepcopy.Copy(m.Rollback, o.Rollback)
+	}
 	if o.Networks != nil {
 	if o.Networks != nil {
 		m.Networks = make([]*NetworkAttachmentConfig, len(o.Networks))
 		m.Networks = make([]*NetworkAttachmentConfig, len(o.Networks))
 		for i := range m.Networks {
 		for i := range m.Networks {
@@ -1130,6 +1138,16 @@ func (m *ServiceSpec) MarshalTo(dAtA []byte) (int, error) {
 		}
 		}
 		i += n6
 		i += n6
 	}
 	}
+	if m.Rollback != nil {
+		dAtA[i] = 0x4a
+		i++
+		i = encodeVarintSpecs(dAtA, i, uint64(m.Rollback.Size()))
+		n7, err := m.Rollback.MarshalTo(dAtA[i:])
+		if err != nil {
+			return 0, err
+		}
+		i += n7
+	}
 	return i, nil
 	return i, nil
 }
 }
 
 
@@ -1139,11 +1157,11 @@ func (m *ServiceSpec_Replicated) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0x1a
 		dAtA[i] = 0x1a
 		i++
 		i++
 		i = encodeVarintSpecs(dAtA, i, uint64(m.Replicated.Size()))
 		i = encodeVarintSpecs(dAtA, i, uint64(m.Replicated.Size()))
-		n7, err := m.Replicated.MarshalTo(dAtA[i:])
+		n8, err := m.Replicated.MarshalTo(dAtA[i:])
 		if err != nil {
 		if err != nil {
 			return 0, err
 			return 0, err
 		}
 		}
-		i += n7
+		i += n8
 	}
 	}
 	return i, nil
 	return i, nil
 }
 }
@@ -1153,11 +1171,11 @@ func (m *ServiceSpec_Global) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0x22
 		dAtA[i] = 0x22
 		i++
 		i++
 		i = encodeVarintSpecs(dAtA, i, uint64(m.Global.Size()))
 		i = encodeVarintSpecs(dAtA, i, uint64(m.Global.Size()))
-		n8, err := m.Global.MarshalTo(dAtA[i:])
+		n9, err := m.Global.MarshalTo(dAtA[i:])
 		if err != nil {
 		if err != nil {
 			return 0, err
 			return 0, err
 		}
 		}
-		i += n8
+		i += n9
 	}
 	}
 	return i, nil
 	return i, nil
 }
 }
@@ -1218,51 +1236,51 @@ func (m *TaskSpec) MarshalTo(dAtA []byte) (int, error) {
 	var l int
 	var l int
 	_ = l
 	_ = l
 	if m.Runtime != nil {
 	if m.Runtime != nil {
-		nn9, err := m.Runtime.MarshalTo(dAtA[i:])
+		nn10, err := m.Runtime.MarshalTo(dAtA[i:])
 		if err != nil {
 		if err != nil {
 			return 0, err
 			return 0, err
 		}
 		}
-		i += nn9
+		i += nn10
 	}
 	}
 	if m.Resources != nil {
 	if m.Resources != nil {
 		dAtA[i] = 0x12
 		dAtA[i] = 0x12
 		i++
 		i++
 		i = encodeVarintSpecs(dAtA, i, uint64(m.Resources.Size()))
 		i = encodeVarintSpecs(dAtA, i, uint64(m.Resources.Size()))
-		n10, err := m.Resources.MarshalTo(dAtA[i:])
+		n11, err := m.Resources.MarshalTo(dAtA[i:])
 		if err != nil {
 		if err != nil {
 			return 0, err
 			return 0, err
 		}
 		}
-		i += n10
+		i += n11
 	}
 	}
 	if m.Restart != nil {
 	if m.Restart != nil {
 		dAtA[i] = 0x22
 		dAtA[i] = 0x22
 		i++
 		i++
 		i = encodeVarintSpecs(dAtA, i, uint64(m.Restart.Size()))
 		i = encodeVarintSpecs(dAtA, i, uint64(m.Restart.Size()))
-		n11, err := m.Restart.MarshalTo(dAtA[i:])
+		n12, err := m.Restart.MarshalTo(dAtA[i:])
 		if err != nil {
 		if err != nil {
 			return 0, err
 			return 0, err
 		}
 		}
-		i += n11
+		i += n12
 	}
 	}
 	if m.Placement != nil {
 	if m.Placement != nil {
 		dAtA[i] = 0x2a
 		dAtA[i] = 0x2a
 		i++
 		i++
 		i = encodeVarintSpecs(dAtA, i, uint64(m.Placement.Size()))
 		i = encodeVarintSpecs(dAtA, i, uint64(m.Placement.Size()))
-		n12, err := m.Placement.MarshalTo(dAtA[i:])
+		n13, err := m.Placement.MarshalTo(dAtA[i:])
 		if err != nil {
 		if err != nil {
 			return 0, err
 			return 0, err
 		}
 		}
-		i += n12
+		i += n13
 	}
 	}
 	if m.LogDriver != nil {
 	if m.LogDriver != nil {
 		dAtA[i] = 0x32
 		dAtA[i] = 0x32
 		i++
 		i++
 		i = encodeVarintSpecs(dAtA, i, uint64(m.LogDriver.Size()))
 		i = encodeVarintSpecs(dAtA, i, uint64(m.LogDriver.Size()))
-		n13, err := m.LogDriver.MarshalTo(dAtA[i:])
+		n14, err := m.LogDriver.MarshalTo(dAtA[i:])
 		if err != nil {
 		if err != nil {
 			return 0, err
 			return 0, err
 		}
 		}
-		i += n13
+		i += n14
 	}
 	}
 	if len(m.Networks) > 0 {
 	if len(m.Networks) > 0 {
 		for _, msg := range m.Networks {
 		for _, msg := range m.Networks {
@@ -1290,11 +1308,11 @@ func (m *TaskSpec_Container) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0xa
 		dAtA[i] = 0xa
 		i++
 		i++
 		i = encodeVarintSpecs(dAtA, i, uint64(m.Container.Size()))
 		i = encodeVarintSpecs(dAtA, i, uint64(m.Container.Size()))
-		n14, err := m.Container.MarshalTo(dAtA[i:])
+		n15, err := m.Container.MarshalTo(dAtA[i:])
 		if err != nil {
 		if err != nil {
 			return 0, err
 			return 0, err
 		}
 		}
-		i += n14
+		i += n15
 	}
 	}
 	return i, nil
 	return i, nil
 }
 }
@@ -1304,11 +1322,11 @@ func (m *TaskSpec_Attachment) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0x42
 		dAtA[i] = 0x42
 		i++
 		i++
 		i = encodeVarintSpecs(dAtA, i, uint64(m.Attachment.Size()))
 		i = encodeVarintSpecs(dAtA, i, uint64(m.Attachment.Size()))
-		n15, err := m.Attachment.MarshalTo(dAtA[i:])
+		n16, err := m.Attachment.MarshalTo(dAtA[i:])
 		if err != nil {
 		if err != nil {
 			return 0, err
 			return 0, err
 		}
 		}
-		i += n15
+		i += n16
 	}
 	}
 	return i, nil
 	return i, nil
 }
 }
@@ -1447,21 +1465,21 @@ func (m *ContainerSpec) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0x4a
 		dAtA[i] = 0x4a
 		i++
 		i++
 		i = encodeVarintSpecs(dAtA, i, uint64(m.StopGracePeriod.Size()))
 		i = encodeVarintSpecs(dAtA, i, uint64(m.StopGracePeriod.Size()))
-		n16, err := m.StopGracePeriod.MarshalTo(dAtA[i:])
+		n17, err := m.StopGracePeriod.MarshalTo(dAtA[i:])
 		if err != nil {
 		if err != nil {
 			return 0, err
 			return 0, err
 		}
 		}
-		i += n16
+		i += n17
 	}
 	}
 	if m.PullOptions != nil {
 	if m.PullOptions != nil {
 		dAtA[i] = 0x52
 		dAtA[i] = 0x52
 		i++
 		i++
 		i = encodeVarintSpecs(dAtA, i, uint64(m.PullOptions.Size()))
 		i = encodeVarintSpecs(dAtA, i, uint64(m.PullOptions.Size()))
-		n17, err := m.PullOptions.MarshalTo(dAtA[i:])
+		n18, err := m.PullOptions.MarshalTo(dAtA[i:])
 		if err != nil {
 		if err != nil {
 			return 0, err
 			return 0, err
 		}
 		}
-		i += n17
+		i += n18
 	}
 	}
 	if len(m.Groups) > 0 {
 	if len(m.Groups) > 0 {
 		for _, s := range m.Groups {
 		for _, s := range m.Groups {
@@ -1510,11 +1528,11 @@ func (m *ContainerSpec) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0x7a
 		dAtA[i] = 0x7a
 		i++
 		i++
 		i = encodeVarintSpecs(dAtA, i, uint64(m.DNSConfig.Size()))
 		i = encodeVarintSpecs(dAtA, i, uint64(m.DNSConfig.Size()))
-		n18, err := m.DNSConfig.MarshalTo(dAtA[i:])
+		n19, err := m.DNSConfig.MarshalTo(dAtA[i:])
 		if err != nil {
 		if err != nil {
 			return 0, err
 			return 0, err
 		}
 		}
-		i += n18
+		i += n19
 	}
 	}
 	if m.Healthcheck != nil {
 	if m.Healthcheck != nil {
 		dAtA[i] = 0x82
 		dAtA[i] = 0x82
@@ -1522,11 +1540,11 @@ func (m *ContainerSpec) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0x1
 		dAtA[i] = 0x1
 		i++
 		i++
 		i = encodeVarintSpecs(dAtA, i, uint64(m.Healthcheck.Size()))
 		i = encodeVarintSpecs(dAtA, i, uint64(m.Healthcheck.Size()))
-		n19, err := m.Healthcheck.MarshalTo(dAtA[i:])
+		n20, err := m.Healthcheck.MarshalTo(dAtA[i:])
 		if err != nil {
 		if err != nil {
 			return 0, err
 			return 0, err
 		}
 		}
-		i += n19
+		i += n20
 	}
 	}
 	if len(m.Hosts) > 0 {
 	if len(m.Hosts) > 0 {
 		for _, s := range m.Hosts {
 		for _, s := range m.Hosts {
@@ -1569,6 +1587,14 @@ func (m *ContainerSpec) MarshalTo(dAtA []byte) (int, error) {
 		}
 		}
 		i++
 		i++
 	}
 	}
+	if len(m.StopSignal) > 0 {
+		dAtA[i] = 0xa2
+		i++
+		dAtA[i] = 0x1
+		i++
+		i = encodeVarintSpecs(dAtA, i, uint64(len(m.StopSignal)))
+		i += copy(dAtA[i:], m.StopSignal)
+	}
 	return i, nil
 	return i, nil
 }
 }
 
 
@@ -1714,20 +1740,20 @@ func (m *NetworkSpec) MarshalTo(dAtA []byte) (int, error) {
 	dAtA[i] = 0xa
 	dAtA[i] = 0xa
 	i++
 	i++
 	i = encodeVarintSpecs(dAtA, i, uint64(m.Annotations.Size()))
 	i = encodeVarintSpecs(dAtA, i, uint64(m.Annotations.Size()))
-	n20, err := m.Annotations.MarshalTo(dAtA[i:])
+	n21, err := m.Annotations.MarshalTo(dAtA[i:])
 	if err != nil {
 	if err != nil {
 		return 0, err
 		return 0, err
 	}
 	}
-	i += n20
+	i += n21
 	if m.DriverConfig != nil {
 	if m.DriverConfig != nil {
 		dAtA[i] = 0x12
 		dAtA[i] = 0x12
 		i++
 		i++
 		i = encodeVarintSpecs(dAtA, i, uint64(m.DriverConfig.Size()))
 		i = encodeVarintSpecs(dAtA, i, uint64(m.DriverConfig.Size()))
-		n21, err := m.DriverConfig.MarshalTo(dAtA[i:])
+		n22, err := m.DriverConfig.MarshalTo(dAtA[i:])
 		if err != nil {
 		if err != nil {
 			return 0, err
 			return 0, err
 		}
 		}
-		i += n21
+		i += n22
 	}
 	}
 	if m.Ipv6Enabled {
 	if m.Ipv6Enabled {
 		dAtA[i] = 0x18
 		dAtA[i] = 0x18
@@ -1753,11 +1779,11 @@ func (m *NetworkSpec) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0x2a
 		dAtA[i] = 0x2a
 		i++
 		i++
 		i = encodeVarintSpecs(dAtA, i, uint64(m.IPAM.Size()))
 		i = encodeVarintSpecs(dAtA, i, uint64(m.IPAM.Size()))
-		n22, err := m.IPAM.MarshalTo(dAtA[i:])
+		n23, err := m.IPAM.MarshalTo(dAtA[i:])
 		if err != nil {
 		if err != nil {
 			return 0, err
 			return 0, err
 		}
 		}
-		i += n22
+		i += n23
 	}
 	}
 	if m.Attachable {
 	if m.Attachable {
 		dAtA[i] = 0x30
 		dAtA[i] = 0x30
@@ -1790,67 +1816,67 @@ func (m *ClusterSpec) MarshalTo(dAtA []byte) (int, error) {
 	dAtA[i] = 0xa
 	dAtA[i] = 0xa
 	i++
 	i++
 	i = encodeVarintSpecs(dAtA, i, uint64(m.Annotations.Size()))
 	i = encodeVarintSpecs(dAtA, i, uint64(m.Annotations.Size()))
-	n23, err := m.Annotations.MarshalTo(dAtA[i:])
+	n24, err := m.Annotations.MarshalTo(dAtA[i:])
 	if err != nil {
 	if err != nil {
 		return 0, err
 		return 0, err
 	}
 	}
-	i += n23
+	i += n24
 	dAtA[i] = 0x12
 	dAtA[i] = 0x12
 	i++
 	i++
 	i = encodeVarintSpecs(dAtA, i, uint64(m.AcceptancePolicy.Size()))
 	i = encodeVarintSpecs(dAtA, i, uint64(m.AcceptancePolicy.Size()))
-	n24, err := m.AcceptancePolicy.MarshalTo(dAtA[i:])
+	n25, err := m.AcceptancePolicy.MarshalTo(dAtA[i:])
 	if err != nil {
 	if err != nil {
 		return 0, err
 		return 0, err
 	}
 	}
-	i += n24
+	i += n25
 	dAtA[i] = 0x1a
 	dAtA[i] = 0x1a
 	i++
 	i++
 	i = encodeVarintSpecs(dAtA, i, uint64(m.Orchestration.Size()))
 	i = encodeVarintSpecs(dAtA, i, uint64(m.Orchestration.Size()))
-	n25, err := m.Orchestration.MarshalTo(dAtA[i:])
+	n26, err := m.Orchestration.MarshalTo(dAtA[i:])
 	if err != nil {
 	if err != nil {
 		return 0, err
 		return 0, err
 	}
 	}
-	i += n25
+	i += n26
 	dAtA[i] = 0x22
 	dAtA[i] = 0x22
 	i++
 	i++
 	i = encodeVarintSpecs(dAtA, i, uint64(m.Raft.Size()))
 	i = encodeVarintSpecs(dAtA, i, uint64(m.Raft.Size()))
-	n26, err := m.Raft.MarshalTo(dAtA[i:])
+	n27, err := m.Raft.MarshalTo(dAtA[i:])
 	if err != nil {
 	if err != nil {
 		return 0, err
 		return 0, err
 	}
 	}
-	i += n26
+	i += n27
 	dAtA[i] = 0x2a
 	dAtA[i] = 0x2a
 	i++
 	i++
 	i = encodeVarintSpecs(dAtA, i, uint64(m.Dispatcher.Size()))
 	i = encodeVarintSpecs(dAtA, i, uint64(m.Dispatcher.Size()))
-	n27, err := m.Dispatcher.MarshalTo(dAtA[i:])
+	n28, err := m.Dispatcher.MarshalTo(dAtA[i:])
 	if err != nil {
 	if err != nil {
 		return 0, err
 		return 0, err
 	}
 	}
-	i += n27
+	i += n28
 	dAtA[i] = 0x32
 	dAtA[i] = 0x32
 	i++
 	i++
 	i = encodeVarintSpecs(dAtA, i, uint64(m.CAConfig.Size()))
 	i = encodeVarintSpecs(dAtA, i, uint64(m.CAConfig.Size()))
-	n28, err := m.CAConfig.MarshalTo(dAtA[i:])
+	n29, err := m.CAConfig.MarshalTo(dAtA[i:])
 	if err != nil {
 	if err != nil {
 		return 0, err
 		return 0, err
 	}
 	}
-	i += n28
+	i += n29
 	dAtA[i] = 0x3a
 	dAtA[i] = 0x3a
 	i++
 	i++
 	i = encodeVarintSpecs(dAtA, i, uint64(m.TaskDefaults.Size()))
 	i = encodeVarintSpecs(dAtA, i, uint64(m.TaskDefaults.Size()))
-	n29, err := m.TaskDefaults.MarshalTo(dAtA[i:])
+	n30, err := m.TaskDefaults.MarshalTo(dAtA[i:])
 	if err != nil {
 	if err != nil {
 		return 0, err
 		return 0, err
 	}
 	}
-	i += n29
+	i += n30
 	dAtA[i] = 0x42
 	dAtA[i] = 0x42
 	i++
 	i++
 	i = encodeVarintSpecs(dAtA, i, uint64(m.EncryptionConfig.Size()))
 	i = encodeVarintSpecs(dAtA, i, uint64(m.EncryptionConfig.Size()))
-	n30, err := m.EncryptionConfig.MarshalTo(dAtA[i:])
+	n31, err := m.EncryptionConfig.MarshalTo(dAtA[i:])
 	if err != nil {
 	if err != nil {
 		return 0, err
 		return 0, err
 	}
 	}
-	i += n30
+	i += n31
 	return i, nil
 	return i, nil
 }
 }
 
 
@@ -1872,11 +1898,11 @@ func (m *SecretSpec) MarshalTo(dAtA []byte) (int, error) {
 	dAtA[i] = 0xa
 	dAtA[i] = 0xa
 	i++
 	i++
 	i = encodeVarintSpecs(dAtA, i, uint64(m.Annotations.Size()))
 	i = encodeVarintSpecs(dAtA, i, uint64(m.Annotations.Size()))
-	n31, err := m.Annotations.MarshalTo(dAtA[i:])
+	n32, err := m.Annotations.MarshalTo(dAtA[i:])
 	if err != nil {
 	if err != nil {
 		return 0, err
 		return 0, err
 	}
 	}
-	i += n31
+	i += n32
 	if len(m.Data) > 0 {
 	if len(m.Data) > 0 {
 		dAtA[i] = 0x12
 		dAtA[i] = 0x12
 		i++
 		i++
@@ -1955,6 +1981,10 @@ func (m *ServiceSpec) Size() (n int) {
 		l = m.Endpoint.Size()
 		l = m.Endpoint.Size()
 		n += 1 + l + sovSpecs(uint64(l))
 		n += 1 + l + sovSpecs(uint64(l))
 	}
 	}
+	if m.Rollback != nil {
+		l = m.Rollback.Size()
+		n += 1 + l + sovSpecs(uint64(l))
+	}
 	return n
 	return n
 }
 }
 
 
@@ -2147,6 +2177,10 @@ func (m *ContainerSpec) Size() (n int) {
 	if m.ReadOnly {
 	if m.ReadOnly {
 		n += 3
 		n += 3
 	}
 	}
+	l = len(m.StopSignal)
+	if l > 0 {
+		n += 2 + l + sovSpecs(uint64(l))
+	}
 	return n
 	return n
 }
 }
 
 
@@ -2295,6 +2329,7 @@ func (this *ServiceSpec) String() string {
 		`Update:` + strings.Replace(fmt.Sprintf("%v", this.Update), "UpdateConfig", "UpdateConfig", 1) + `,`,
 		`Update:` + strings.Replace(fmt.Sprintf("%v", this.Update), "UpdateConfig", "UpdateConfig", 1) + `,`,
 		`Networks:` + strings.Replace(fmt.Sprintf("%v", this.Networks), "NetworkAttachmentConfig", "NetworkAttachmentConfig", 1) + `,`,
 		`Networks:` + strings.Replace(fmt.Sprintf("%v", this.Networks), "NetworkAttachmentConfig", "NetworkAttachmentConfig", 1) + `,`,
 		`Endpoint:` + strings.Replace(fmt.Sprintf("%v", this.Endpoint), "EndpointSpec", "EndpointSpec", 1) + `,`,
 		`Endpoint:` + strings.Replace(fmt.Sprintf("%v", this.Endpoint), "EndpointSpec", "EndpointSpec", 1) + `,`,
+		`Rollback:` + strings.Replace(fmt.Sprintf("%v", this.Rollback), "UpdateConfig", "UpdateConfig", 1) + `,`,
 		`}`,
 		`}`,
 	}, "")
 	}, "")
 	return s
 	return s
@@ -2418,6 +2453,7 @@ func (this *ContainerSpec) String() string {
 		`Hosts:` + fmt.Sprintf("%v", this.Hosts) + `,`,
 		`Hosts:` + fmt.Sprintf("%v", this.Hosts) + `,`,
 		`OpenStdin:` + fmt.Sprintf("%v", this.OpenStdin) + `,`,
 		`OpenStdin:` + fmt.Sprintf("%v", this.OpenStdin) + `,`,
 		`ReadOnly:` + fmt.Sprintf("%v", this.ReadOnly) + `,`,
 		`ReadOnly:` + fmt.Sprintf("%v", this.ReadOnly) + `,`,
+		`StopSignal:` + fmt.Sprintf("%v", this.StopSignal) + `,`,
 		`}`,
 		`}`,
 	}, "")
 	}, "")
 	return s
 	return s
@@ -2893,6 +2929,39 @@ func (m *ServiceSpec) Unmarshal(dAtA []byte) error {
 				return err
 				return err
 			}
 			}
 			iNdEx = postIndex
 			iNdEx = postIndex
+		case 9:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Rollback", 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.Rollback == nil {
+				m.Rollback = &UpdateConfig{}
+			}
+			if err := m.Rollback.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
 		default:
 		default:
 			iNdEx = preIndex
 			iNdEx = preIndex
 			skippy, err := skipSpecs(dAtA[iNdEx:])
 			skippy, err := skipSpecs(dAtA[iNdEx:])
@@ -4068,6 +4137,35 @@ func (m *ContainerSpec) Unmarshal(dAtA []byte) error {
 				}
 				}
 			}
 			}
 			m.ReadOnly = bool(v != 0)
 			m.ReadOnly = bool(v != 0)
+		case 20:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field StopSignal", 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.StopSignal = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
 		default:
 		default:
 			iNdEx = preIndex
 			iNdEx = preIndex
 			skippy, err := skipSpecs(dAtA[iNdEx:])
 			skippy, err := skipSpecs(dAtA[iNdEx:])
@@ -5120,110 +5218,112 @@ var (
 func init() { proto.RegisterFile("specs.proto", fileDescriptorSpecs) }
 func init() { proto.RegisterFile("specs.proto", fileDescriptorSpecs) }
 
 
 var fileDescriptorSpecs = []byte{
 var fileDescriptorSpecs = []byte{
-	// 1672 bytes of a gzipped FileDescriptorProto
+	// 1707 bytes of a gzipped FileDescriptorProto
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x57, 0x41, 0x73, 0x1b, 0xb7,
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x57, 0x41, 0x73, 0x1b, 0xb7,
-	0x15, 0x26, 0x25, 0x8a, 0x5c, 0xbe, 0xa5, 0x6c, 0x0a, 0x4d, 0xd2, 0x35, 0xdd, 0x50, 0x34, 0xe3,
+	0x15, 0x26, 0x25, 0x8a, 0x5a, 0xbe, 0xa5, 0x6c, 0x1a, 0x75, 0xd2, 0x35, 0xdd, 0x90, 0x34, 0xe3,
 	0xa6, 0x4a, 0x33, 0xa5, 0xa6, 0x6a, 0x27, 0x75, 0xea, 0x66, 0x5a, 0x52, 0x64, 0x65, 0x55, 0x95,
 	0xa6, 0x4a, 0x33, 0xa5, 0xa6, 0x6a, 0x27, 0x75, 0xea, 0x66, 0x5a, 0x52, 0x64, 0x65, 0x55, 0x95,
-	0xcc, 0x81, 0x14, 0x77, 0x7c, 0xe2, 0x40, 0xbb, 0x10, 0xb9, 0xa3, 0xe5, 0x62, 0x0b, 0x60, 0x99,
-	0xe1, 0xad, 0xc7, 0x8c, 0x0f, 0xfd, 0x07, 0x3a, 0xf5, 0x37, 0xf4, 0x3f, 0xf8, 0xd8, 0x63, 0x4f,
-	0x9a, 0x9a, 0x7f, 0x21, 0x3f, 0xa0, 0x1d, 0x60, 0xb1, 0xe4, 0x32, 0x59, 0xc5, 0x99, 0xa9, 0x6f,
-	0x78, 0x8f, 0xdf, 0xf7, 0x16, 0x78, 0xf8, 0xf0, 0xde, 0x23, 0xd8, 0x22, 0xa2, 0xae, 0xe8, 0x44,
-	0x9c, 0x49, 0x86, 0x90, 0xc7, 0xdc, 0x6b, 0xca, 0x3b, 0xe2, 0x2b, 0xc2, 0xa7, 0xd7, 0xbe, 0xec,
-	0xcc, 0x7e, 0xd9, 0xb0, 0xe5, 0x3c, 0xa2, 0x06, 0xd0, 0x78, 0x6f, 0xcc, 0xc6, 0x4c, 0x2f, 0xf7,
-	0xd5, 0xca, 0x78, 0x9b, 0x63, 0xc6, 0xc6, 0x01, 0xdd, 0xd7, 0xd6, 0x65, 0x7c, 0xb5, 0xef, 0xc5,
-	0x9c, 0x48, 0x9f, 0x85, 0xc9, 0xef, 0xed, 0x9b, 0x12, 0x58, 0x67, 0xcc, 0xa3, 0xe7, 0x11, 0x75,
-	0xd1, 0x11, 0xd8, 0x24, 0x0c, 0x99, 0xd4, 0x00, 0xe1, 0x14, 0x5b, 0xc5, 0x3d, 0xfb, 0x60, 0xb7,
-	0xf3, 0xdd, 0x2f, 0x77, 0xba, 0x2b, 0x58, 0xaf, 0xf4, 0xfa, 0x76, 0xb7, 0x80, 0xb3, 0x4c, 0xf4,
-	0x7b, 0xa8, 0x79, 0x54, 0xf8, 0x9c, 0x7a, 0x23, 0xce, 0x02, 0xea, 0x6c, 0xb4, 0x8a, 0x7b, 0xf7,
-	0x0e, 0x7e, 0x92, 0x17, 0x49, 0x7d, 0x1c, 0xb3, 0x80, 0x62, 0xdb, 0x30, 0x94, 0x81, 0x8e, 0x00,
-	0xa6, 0x74, 0x7a, 0x49, 0xb9, 0x98, 0xf8, 0x91, 0xb3, 0xa9, 0xe9, 0x3f, 0xbb, 0x8b, 0xae, 0xf6,
-	0xde, 0x39, 0x5d, 0xc2, 0x71, 0x86, 0x8a, 0x4e, 0xa1, 0x46, 0x66, 0xc4, 0x0f, 0xc8, 0xa5, 0x1f,
-	0xf8, 0x72, 0xee, 0x94, 0x74, 0xa8, 0x4f, 0xbe, 0x37, 0x54, 0x37, 0x43, 0xc0, 0x6b, 0xf4, 0xb6,
-	0x07, 0xb0, 0xfa, 0x10, 0xfa, 0x18, 0x2a, 0xc3, 0xc1, 0x59, 0xff, 0xf8, 0xec, 0xa8, 0x5e, 0x68,
-	0x3c, 0x78, 0x75, 0xd3, 0x7a, 0x5f, 0xc5, 0x58, 0x01, 0x86, 0x34, 0xf4, 0xfc, 0x70, 0x8c, 0xf6,
-	0xc0, 0xea, 0x1e, 0x1e, 0x0e, 0x86, 0x17, 0x83, 0x7e, 0xbd, 0xd8, 0x68, 0xbc, 0xba, 0x69, 0x7d,
-	0xb0, 0x0e, 0xec, 0xba, 0x2e, 0x8d, 0x24, 0xf5, 0x1a, 0xa5, 0xaf, 0xff, 0xd1, 0x2c, 0xb4, 0xbf,
-	0x2e, 0x42, 0x2d, 0xbb, 0x09, 0xf4, 0x31, 0x94, 0xbb, 0x87, 0x17, 0xc7, 0x2f, 0x06, 0xf5, 0xc2,
-	0x8a, 0x9e, 0x45, 0x74, 0x5d, 0xe9, 0xcf, 0x28, 0x7a, 0x0c, 0x5b, 0xc3, 0xee, 0x97, 0xe7, 0x83,
-	0x7a, 0x71, 0xb5, 0x9d, 0x2c, 0x6c, 0x48, 0x62, 0xa1, 0x51, 0x7d, 0xdc, 0x3d, 0x3e, 0xab, 0x6f,
-	0xe4, 0xa3, 0xfa, 0x9c, 0xf8, 0xa1, 0xd9, 0xca, 0x9b, 0x4d, 0xb0, 0xcf, 0x29, 0x9f, 0xf9, 0xee,
-	0x3b, 0x96, 0xc8, 0x67, 0x50, 0x92, 0x44, 0x5c, 0x6b, 0x69, 0xd8, 0xf9, 0xd2, 0xb8, 0x20, 0xe2,
-	0x5a, 0x7d, 0xd4, 0xd0, 0x35, 0x5e, 0x29, 0x83, 0xd3, 0x28, 0xf0, 0x5d, 0x22, 0xa9, 0xa7, 0x95,
-	0x61, 0x1f, 0xfc, 0x34, 0x8f, 0x8d, 0x97, 0x28, 0xb3, 0xff, 0x67, 0x05, 0x9c, 0xa1, 0xa2, 0xa7,
-	0x50, 0x1e, 0x07, 0xec, 0x92, 0x04, 0x5a, 0x13, 0xf6, 0xc1, 0xa3, 0xbc, 0x20, 0x47, 0x1a, 0xb1,
-	0x0a, 0x60, 0x28, 0xe8, 0x09, 0x94, 0xe3, 0xc8, 0x23, 0x92, 0x3a, 0x65, 0x4d, 0x6e, 0xe5, 0x91,
-	0xbf, 0xd4, 0x88, 0x43, 0x16, 0x5e, 0xf9, 0x63, 0x6c, 0xf0, 0xe8, 0x04, 0xac, 0x90, 0xca, 0xaf,
-	0x18, 0xbf, 0x16, 0x4e, 0xa5, 0xb5, 0xb9, 0x67, 0x1f, 0x7c, 0x9a, 0x2b, 0xc6, 0x04, 0xd3, 0x95,
-	0x92, 0xb8, 0x93, 0x29, 0x0d, 0x65, 0x12, 0xa6, 0xb7, 0xe1, 0x14, 0xf1, 0x32, 0x00, 0xfa, 0x1d,
-	0x58, 0x34, 0xf4, 0x22, 0xe6, 0x87, 0xd2, 0xb1, 0xee, 0xde, 0xc8, 0xc0, 0x60, 0x54, 0x32, 0xf1,
-	0x92, 0xd1, 0x2b, 0x43, 0x69, 0xca, 0x3c, 0xda, 0xde, 0x87, 0x9d, 0xef, 0x24, 0x0b, 0x35, 0xc0,
-	0x32, 0xc9, 0x4a, 0x6e, 0xb9, 0x84, 0x97, 0x76, 0xfb, 0x3e, 0x6c, 0xaf, 0x25, 0xa6, 0xfd, 0xf7,
-	0x12, 0x58, 0xe9, 0x6d, 0xa1, 0x2e, 0x54, 0x5d, 0x16, 0x4a, 0xe2, 0x87, 0x94, 0x1b, 0x81, 0xe4,
-	0xe6, 0xf6, 0x30, 0x05, 0x29, 0xd6, 0xb3, 0x02, 0x5e, 0xb1, 0xd0, 0x1f, 0xa1, 0xca, 0xa9, 0x60,
-	0x31, 0x77, 0xa9, 0x30, 0x0a, 0xd9, 0xcb, 0xbf, 0xe3, 0x04, 0x84, 0xe9, 0x5f, 0x63, 0x9f, 0x53,
-	0x95, 0x27, 0x81, 0x57, 0x54, 0xf4, 0x14, 0x2a, 0x9c, 0x0a, 0x49, 0xb8, 0xfc, 0xbe, 0x4b, 0xc6,
-	0x09, 0x64, 0xc8, 0x02, 0xdf, 0x9d, 0xe3, 0x94, 0x81, 0x9e, 0x42, 0x35, 0x0a, 0x88, 0xab, 0xa3,
-	0x3a, 0x5b, 0x9a, 0xfe, 0x61, 0x1e, 0x7d, 0x98, 0x82, 0xf0, 0x0a, 0x8f, 0x3e, 0x07, 0x08, 0xd8,
-	0x78, 0xe4, 0x71, 0x7f, 0x46, 0xb9, 0x11, 0x49, 0x23, 0x8f, 0xdd, 0xd7, 0x08, 0x5c, 0x0d, 0xd8,
-	0x38, 0x59, 0xa2, 0xa3, 0xff, 0x4b, 0x21, 0x19, 0x75, 0x9c, 0x00, 0x90, 0xe5, 0xaf, 0x46, 0x1f,
-	0x9f, 0xfc, 0xa0, 0x50, 0xe6, 0x46, 0x32, 0x74, 0xf4, 0x08, 0x6a, 0x57, 0x8c, 0xbb, 0x74, 0x64,
-	0x74, 0x5f, 0xd5, 0x9a, 0xb0, 0xb5, 0x2f, 0x11, 0x7a, 0xaf, 0x0a, 0x15, 0x1e, 0x87, 0xd2, 0x9f,
-	0xd2, 0xf6, 0x09, 0xbc, 0x9f, 0x1b, 0x14, 0x1d, 0x40, 0x6d, 0x79, 0xcd, 0x23, 0xdf, 0xd3, 0xfa,
-	0xa8, 0xf6, 0xee, 0x2f, 0x6e, 0x77, 0xed, 0xa5, 0x1e, 0x8e, 0xfb, 0xd8, 0x5e, 0x82, 0x8e, 0xbd,
-	0xf6, 0x37, 0x15, 0xd8, 0x5e, 0x13, 0x0b, 0x7a, 0x0f, 0xb6, 0xfc, 0x29, 0x19, 0xd3, 0x84, 0x8e,
-	0x13, 0x03, 0x0d, 0xa0, 0x1c, 0x90, 0x4b, 0x1a, 0x28, 0xc9, 0xa8, 0xb4, 0xfd, 0xe2, 0xad, 0xaa,
-	0xeb, 0xfc, 0x59, 0xe3, 0x07, 0xa1, 0xe4, 0x73, 0x6c, 0xc8, 0xc8, 0x81, 0x8a, 0xcb, 0xa6, 0x53,
-	0x12, 0xaa, 0xf2, 0xb2, 0xb9, 0x57, 0xc5, 0xa9, 0x89, 0x10, 0x94, 0x08, 0x1f, 0x0b, 0xa7, 0xa4,
-	0xdd, 0x7a, 0x8d, 0xea, 0xb0, 0x49, 0xc3, 0x99, 0xb3, 0xa5, 0x5d, 0x6a, 0xa9, 0x3c, 0x9e, 0x9f,
-	0xdc, 0x79, 0x15, 0xab, 0xa5, 0xe2, 0xc5, 0x82, 0x72, 0xa7, 0xa2, 0x5d, 0x7a, 0x8d, 0x7e, 0x03,
-	0xe5, 0x29, 0x8b, 0x43, 0x29, 0x1c, 0x4b, 0x6f, 0xf6, 0x41, 0xde, 0x66, 0x4f, 0x15, 0xc2, 0x94,
-	0x3f, 0x03, 0x47, 0x03, 0xd8, 0x11, 0x92, 0x45, 0xa3, 0x31, 0x27, 0x2e, 0x1d, 0x45, 0x94, 0xfb,
-	0xcc, 0xd3, 0xb7, 0xa1, 0x62, 0x24, 0xdd, 0xbe, 0x93, 0x76, 0xfb, 0x4e, 0xdf, 0x74, 0x7b, 0x7c,
-	0x5f, 0x71, 0x8e, 0x14, 0x65, 0xa8, 0x19, 0x68, 0x08, 0xb5, 0x28, 0x0e, 0x82, 0x11, 0x8b, 0x92,
-	0x4a, 0x0e, 0x3a, 0xc2, 0x0f, 0x48, 0xd9, 0x30, 0x0e, 0x82, 0xe7, 0x09, 0x09, 0xdb, 0xd1, 0xca,
-	0x40, 0x1f, 0x40, 0x79, 0xcc, 0x59, 0x1c, 0x09, 0xc7, 0xd6, 0xc9, 0x30, 0x16, 0xfa, 0x02, 0x2a,
-	0x82, 0xba, 0x9c, 0x4a, 0xe1, 0xd4, 0xf4, 0x51, 0x3f, 0xca, 0xfb, 0xc8, 0xb9, 0x86, 0x60, 0x7a,
-	0x45, 0x39, 0x0d, 0x5d, 0x8a, 0x53, 0x0e, 0x7a, 0x00, 0x9b, 0x52, 0xce, 0x9d, 0xed, 0x56, 0x71,
-	0xcf, 0xea, 0x55, 0x16, 0xb7, 0xbb, 0x9b, 0x17, 0x17, 0x2f, 0xb1, 0xf2, 0xa9, 0x1a, 0x35, 0x61,
-	0x42, 0x86, 0x64, 0x4a, 0x9d, 0x7b, 0x3a, 0xb7, 0x4b, 0x1b, 0xbd, 0x04, 0xf0, 0x42, 0x31, 0x72,
-	0xf5, 0xa3, 0x70, 0xee, 0xeb, 0xd3, 0x7d, 0xfa, 0xf6, 0xd3, 0xf5, 0xcf, 0xce, 0x4d, 0xa5, 0xdd,
-	0x5e, 0xdc, 0xee, 0x56, 0x97, 0x26, 0xae, 0x7a, 0xa1, 0x48, 0x96, 0xa8, 0x07, 0xf6, 0x84, 0x92,
-	0x40, 0x4e, 0xdc, 0x09, 0x75, 0xaf, 0x9d, 0xfa, 0xdd, 0x85, 0xf7, 0x99, 0x86, 0x99, 0x08, 0x59,
-	0x92, 0x52, 0xb0, 0xda, 0xaa, 0x70, 0x76, 0x74, 0xae, 0x12, 0x03, 0x7d, 0x08, 0xc0, 0x22, 0x1a,
-	0x8e, 0x84, 0xf4, 0xfc, 0xd0, 0x41, 0xea, 0xc8, 0xb8, 0xaa, 0x3c, 0xe7, 0xca, 0x81, 0x1e, 0xaa,
-	0xb2, 0x48, 0xbc, 0x11, 0x0b, 0x83, 0xb9, 0xf3, 0x23, 0xfd, 0xab, 0xa5, 0x1c, 0xcf, 0xc3, 0x60,
-	0xde, 0xf8, 0x1c, 0xec, 0x8c, 0x9a, 0x95, 0x0a, 0xaf, 0xe9, 0xdc, 0x3c, 0x10, 0xb5, 0x54, 0x9f,
-	0x9c, 0x91, 0x20, 0x4e, 0xa6, 0xb1, 0x2a, 0x4e, 0x8c, 0xdf, 0x6e, 0x3c, 0x29, 0x36, 0x0e, 0xc0,
-	0xce, 0xdc, 0x2a, 0xfa, 0x08, 0xb6, 0x39, 0x1d, 0xfb, 0x42, 0xf2, 0xf9, 0x88, 0xc4, 0x72, 0xe2,
-	0xfc, 0x41, 0x13, 0x6a, 0xa9, 0xb3, 0x1b, 0xcb, 0x49, 0x63, 0x04, 0xab, 0xe4, 0xa0, 0x16, 0xd8,
-	0x2a, 0xe9, 0x82, 0xf2, 0x19, 0xe5, 0xaa, 0x5f, 0xa8, 0x33, 0x65, 0x5d, 0x4a, 0x1c, 0x82, 0x12,
-	0xee, 0x4e, 0xf4, 0xdb, 0xac, 0x62, 0x63, 0xa9, 0xc7, 0x96, 0x2a, 0xd0, 0x3c, 0x36, 0x63, 0xb6,
-	0xbf, 0x29, 0x42, 0x2d, 0xdb, 0xb8, 0xd0, 0x61, 0xd2, 0xae, 0xf4, 0x91, 0xee, 0x1d, 0xec, 0xbf,
-	0xad, 0xd1, 0xe9, 0xe6, 0x10, 0xc4, 0x2a, 0xd8, 0xa9, 0x9a, 0x31, 0x35, 0x19, 0xfd, 0x1a, 0xb6,
-	0x22, 0xc6, 0x65, 0x5a, 0x22, 0x9a, 0xb9, 0x05, 0x9d, 0xf1, 0xb4, 0x98, 0x26, 0xe0, 0xf6, 0x04,
-	0xee, 0xad, 0x47, 0x43, 0x8f, 0x61, 0xf3, 0xc5, 0xf1, 0xb0, 0x5e, 0x68, 0x3c, 0x7c, 0x75, 0xd3,
-	0xfa, 0xf1, 0xfa, 0x8f, 0x2f, 0x7c, 0x2e, 0x63, 0x12, 0x1c, 0x0f, 0xd1, 0xcf, 0x61, 0xab, 0x7f,
-	0x76, 0x8e, 0x71, 0xbd, 0xd8, 0xd8, 0x7d, 0x75, 0xd3, 0x7a, 0xb8, 0x8e, 0x53, 0x3f, 0xb1, 0x38,
-	0xf4, 0x30, 0xbb, 0x5c, 0xce, 0x5b, 0xff, 0xdc, 0x00, 0xdb, 0x54, 0xce, 0x77, 0x3d, 0x92, 0x6f,
-	0x27, 0xcd, 0x28, 0x7d, 0x12, 0x1b, 0x6f, 0xed, 0x49, 0xb5, 0x84, 0x60, 0xee, 0xf8, 0x11, 0xd4,
-	0xfc, 0x68, 0xf6, 0xd9, 0x88, 0x86, 0xe4, 0x32, 0x30, 0xa3, 0x97, 0x85, 0x6d, 0xe5, 0x1b, 0x24,
-	0x2e, 0xf5, 0x1e, 0xfd, 0x50, 0x52, 0x1e, 0x9a, 0xa1, 0xca, 0xc2, 0x4b, 0x1b, 0x7d, 0x01, 0x25,
-	0x3f, 0x22, 0x53, 0xd3, 0x48, 0x73, 0x4f, 0x70, 0x3c, 0xec, 0x9e, 0x1a, 0x0d, 0xf6, 0xac, 0xc5,
-	0xed, 0x6e, 0x49, 0x39, 0xb0, 0xa6, 0xa1, 0x66, 0xda, 0xcb, 0xd4, 0x97, 0x74, 0x6d, 0xb5, 0x70,
-	0xc6, 0xd3, 0xfe, 0x6f, 0x09, 0xec, 0xc3, 0x20, 0x16, 0xd2, 0x74, 0x88, 0x77, 0x96, 0xb7, 0x97,
-	0xb0, 0x43, 0xf4, 0x74, 0x4e, 0x42, 0x55, 0x6e, 0xf5, 0x8c, 0x60, 0x72, 0xf7, 0x38, 0x37, 0xdc,
-	0x12, 0x9c, 0xcc, 0x13, 0xbd, 0xb2, 0x8a, 0xe9, 0x14, 0x71, 0x9d, 0x7c, 0xeb, 0x17, 0x74, 0x0e,
-	0xdb, 0x8c, 0xbb, 0x13, 0x2a, 0x64, 0x52, 0xa4, 0xcd, 0x34, 0x9b, 0xfb, 0x3f, 0xe7, 0x79, 0x16,
-	0x68, 0x2a, 0x54, 0xb2, 0xdb, 0xf5, 0x18, 0xe8, 0x09, 0x94, 0x38, 0xb9, 0x4a, 0xe7, 0x9d, 0x5c,
-	0x7d, 0x63, 0x72, 0x25, 0xd7, 0x42, 0x68, 0x06, 0xfa, 0x13, 0x80, 0xe7, 0x8b, 0x88, 0x48, 0x77,
-	0x42, 0xb9, 0xb9, 0xa7, 0xdc, 0x23, 0xf6, 0x97, 0xa8, 0xb5, 0x28, 0x19, 0x36, 0x3a, 0x81, 0xaa,
-	0x4b, 0x52, 0xa5, 0x95, 0xef, 0x1e, 0xf1, 0x0f, 0xbb, 0x26, 0x44, 0x5d, 0x85, 0x58, 0xdc, 0xee,
-	0x5a, 0xa9, 0x07, 0x5b, 0x2e, 0x31, 0xca, 0x3b, 0x81, 0x6d, 0x35, 0xfa, 0x8f, 0x3c, 0x7a, 0x45,
-	0xe2, 0x40, 0x0a, 0xdd, 0x47, 0xef, 0xa8, 0xb8, 0x6a, 0x0a, 0xed, 0x1b, 0x9c, 0xd9, 0x57, 0x4d,
-	0x66, 0x7c, 0xe8, 0x2f, 0xb0, 0x43, 0x43, 0x97, 0xcf, 0xb5, 0xce, 0xd2, 0x1d, 0x5a, 0x77, 0x1f,
-	0x76, 0xb0, 0x04, 0xaf, 0x1d, 0xb6, 0x4e, 0xbf, 0xe5, 0x6f, 0xfb, 0x00, 0x49, 0x0f, 0x7b, 0xb7,
-	0xfa, 0x43, 0x50, 0xf2, 0x88, 0x24, 0x5a, 0x72, 0x35, 0xac, 0xd7, 0x3d, 0xe7, 0xf5, 0x9b, 0x66,
-	0xe1, 0xdf, 0x6f, 0x9a, 0x85, 0xbf, 0x2d, 0x9a, 0xc5, 0xd7, 0x8b, 0x66, 0xf1, 0x5f, 0x8b, 0x66,
-	0xf1, 0x3f, 0x8b, 0x66, 0xf1, 0xb2, 0xac, 0x3b, 0xff, 0xaf, 0xfe, 0x17, 0x00, 0x00, 0xff, 0xff,
-	0xa2, 0xd8, 0xcf, 0x61, 0x3b, 0x10, 0x00, 0x00,
+	0xcc, 0x01, 0x15, 0x77, 0x7c, 0xe2, 0x80, 0xbb, 0x10, 0xb9, 0xa3, 0xe5, 0x62, 0x0b, 0x60, 0x99,
+	0xe1, 0xad, 0xc7, 0x8c, 0x0f, 0x3d, 0xf5, 0xaa, 0xe9, 0xa1, 0xbf, 0xa1, 0xff, 0xc1, 0xc7, 0x1e,
+	0x7b, 0xd2, 0x34, 0xfc, 0x0b, 0xfd, 0x01, 0xed, 0x00, 0x0b, 0x92, 0xcb, 0x64, 0x15, 0x7b, 0x26,
+	0xbe, 0xe1, 0xbd, 0xfd, 0xbe, 0x07, 0xe0, 0xe1, 0xc3, 0xc3, 0x5b, 0xb0, 0x45, 0x44, 0x5d, 0xd1,
+	0x8a, 0x38, 0x93, 0x0c, 0x21, 0x8f, 0xb9, 0x57, 0x94, 0xb7, 0xc4, 0x97, 0x84, 0x4f, 0xaf, 0x7c,
+	0xd9, 0x9a, 0xfd, 0xbc, 0x6a, 0xcb, 0x79, 0x44, 0x0d, 0xa0, 0x7a, 0x7f, 0xcc, 0xc6, 0x4c, 0x0f,
+	0x0f, 0xd4, 0xc8, 0x78, 0x6b, 0x63, 0xc6, 0xc6, 0x01, 0x3d, 0xd0, 0xd6, 0x28, 0xbe, 0x3c, 0xf0,
+	0x62, 0x4e, 0xa4, 0xcf, 0xc2, 0xe4, 0x7b, 0xf3, 0xba, 0x00, 0xd6, 0x39, 0xf3, 0xe8, 0x20, 0xa2,
+	0x2e, 0x3a, 0x06, 0x9b, 0x84, 0x21, 0x93, 0x1a, 0x20, 0x9c, 0x7c, 0x23, 0xbf, 0x6f, 0x1f, 0xd6,
+	0x5b, 0xdf, 0x9e, 0xb9, 0xd5, 0x5e, 0xc3, 0x3a, 0x85, 0xd7, 0x37, 0xf5, 0x1c, 0x4e, 0x33, 0xd1,
+	0x6f, 0xa1, 0xec, 0x51, 0xe1, 0x73, 0xea, 0x0d, 0x39, 0x0b, 0xa8, 0xb3, 0xd5, 0xc8, 0xef, 0xdf,
+	0x39, 0xfc, 0x51, 0x56, 0x24, 0x35, 0x39, 0x66, 0x01, 0xc5, 0xb6, 0x61, 0x28, 0x03, 0x1d, 0x03,
+	0x4c, 0xe9, 0x74, 0x44, 0xb9, 0x98, 0xf8, 0x91, 0xb3, 0xad, 0xe9, 0x3f, 0xb9, 0x8d, 0xae, 0xd6,
+	0xde, 0x3a, 0x5b, 0xc1, 0x71, 0x8a, 0x8a, 0xce, 0xa0, 0x4c, 0x66, 0xc4, 0x0f, 0xc8, 0xc8, 0x0f,
+	0x7c, 0x39, 0x77, 0x0a, 0x3a, 0xd4, 0xc7, 0xdf, 0x19, 0xaa, 0x9d, 0x22, 0xe0, 0x0d, 0x7a, 0xd3,
+	0x03, 0x58, 0x4f, 0x84, 0x3e, 0x82, 0xdd, 0x7e, 0xef, 0xbc, 0x7b, 0x72, 0x7e, 0x5c, 0xc9, 0x55,
+	0x1f, 0xbc, 0xba, 0x6e, 0xbc, 0xa7, 0x62, 0xac, 0x01, 0x7d, 0x1a, 0x7a, 0x7e, 0x38, 0x46, 0xfb,
+	0x60, 0xb5, 0x8f, 0x8e, 0x7a, 0xfd, 0x8b, 0x5e, 0xb7, 0x92, 0xaf, 0x56, 0x5f, 0x5d, 0x37, 0xde,
+	0xdf, 0x04, 0xb6, 0x5d, 0x97, 0x46, 0x92, 0x7a, 0xd5, 0xc2, 0x57, 0xff, 0xa8, 0xe5, 0x9a, 0x5f,
+	0xe5, 0xa1, 0x9c, 0x5e, 0x04, 0xfa, 0x08, 0x8a, 0xed, 0xa3, 0x8b, 0x93, 0x17, 0xbd, 0x4a, 0x6e,
+	0x4d, 0x4f, 0x23, 0xda, 0xae, 0xf4, 0x67, 0x14, 0x3d, 0x86, 0x9d, 0x7e, 0xfb, 0x8b, 0x41, 0xaf,
+	0x92, 0x5f, 0x2f, 0x27, 0x0d, 0xeb, 0x93, 0x58, 0x68, 0x54, 0x17, 0xb7, 0x4f, 0xce, 0x2b, 0x5b,
+	0xd9, 0xa8, 0x2e, 0x27, 0x7e, 0x68, 0x96, 0xf2, 0xf7, 0x02, 0xd8, 0x03, 0xca, 0x67, 0xbe, 0xfb,
+	0x8e, 0x25, 0xf2, 0x29, 0x14, 0x24, 0x11, 0x57, 0x5a, 0x1a, 0x76, 0xb6, 0x34, 0x2e, 0x88, 0xb8,
+	0x52, 0x93, 0x1a, 0xba, 0xc6, 0x2b, 0x65, 0x70, 0x1a, 0x05, 0xbe, 0x4b, 0x24, 0xf5, 0xb4, 0x32,
+	0xec, 0xc3, 0x1f, 0x67, 0xb1, 0xf1, 0x0a, 0x65, 0xd6, 0xff, 0x2c, 0x87, 0x53, 0x54, 0xf4, 0x14,
+	0x8a, 0xe3, 0x80, 0x8d, 0x48, 0xa0, 0x35, 0x61, 0x1f, 0x3e, 0xca, 0x0a, 0x72, 0xac, 0x11, 0xeb,
+	0x00, 0x86, 0x82, 0x9e, 0x40, 0x31, 0x8e, 0x3c, 0x22, 0xa9, 0x53, 0xd4, 0xe4, 0x46, 0x16, 0xf9,
+	0x0b, 0x8d, 0x38, 0x62, 0xe1, 0xa5, 0x3f, 0xc6, 0x06, 0x8f, 0x4e, 0xc1, 0x0a, 0xa9, 0xfc, 0x92,
+	0xf1, 0x2b, 0xe1, 0xec, 0x36, 0xb6, 0xf7, 0xed, 0xc3, 0x4f, 0x32, 0xc5, 0x98, 0x60, 0xda, 0x52,
+	0x12, 0x77, 0x32, 0xa5, 0xa1, 0x4c, 0xc2, 0x74, 0xb6, 0x9c, 0x3c, 0x5e, 0x05, 0x40, 0xbf, 0x01,
+	0x8b, 0x86, 0x5e, 0xc4, 0xfc, 0x50, 0x3a, 0xd6, 0xed, 0x0b, 0xe9, 0x19, 0x8c, 0x4a, 0x26, 0x5e,
+	0x31, 0x14, 0x9b, 0xb3, 0x20, 0x18, 0x11, 0xf7, 0xca, 0x29, 0xbd, 0xe5, 0x36, 0x56, 0x8c, 0x4e,
+	0x11, 0x0a, 0x53, 0xe6, 0xd1, 0xe6, 0x01, 0xdc, 0xfb, 0x56, 0xaa, 0x51, 0x15, 0x2c, 0x93, 0xea,
+	0x44, 0x23, 0x05, 0xbc, 0xb2, 0x9b, 0x77, 0x61, 0x6f, 0x23, 0xad, 0xcd, 0xbf, 0x16, 0xc0, 0x5a,
+	0x9e, 0x35, 0x6a, 0x43, 0xc9, 0x65, 0xa1, 0x24, 0x7e, 0x48, 0xb9, 0x91, 0x57, 0xe6, 0xc9, 0x1c,
+	0x2d, 0x41, 0x8a, 0xf5, 0x2c, 0x87, 0xd7, 0x2c, 0xf4, 0x7b, 0x28, 0x71, 0x2a, 0x58, 0xcc, 0x5d,
+	0x2a, 0x8c, 0xbe, 0xf6, 0xb3, 0x15, 0x92, 0x80, 0x30, 0xfd, 0x73, 0xec, 0x73, 0xaa, 0xb2, 0x2c,
+	0xf0, 0x9a, 0x8a, 0x9e, 0xc2, 0x2e, 0xa7, 0x42, 0x12, 0x2e, 0xbf, 0x4b, 0x22, 0x38, 0x81, 0xf4,
+	0x59, 0xe0, 0xbb, 0x73, 0xbc, 0x64, 0xa0, 0xa7, 0x50, 0x8a, 0x02, 0xe2, 0xea, 0xa8, 0xce, 0x8e,
+	0xa6, 0x7f, 0x90, 0x45, 0xef, 0x2f, 0x41, 0x78, 0x8d, 0x47, 0x9f, 0x01, 0x04, 0x6c, 0x3c, 0xf4,
+	0xb8, 0x3f, 0xa3, 0xdc, 0x48, 0xac, 0x9a, 0xc5, 0xee, 0x6a, 0x04, 0x2e, 0x05, 0x6c, 0x9c, 0x0c,
+	0xd1, 0xf1, 0xf7, 0xd2, 0x57, 0x4a, 0x5b, 0xa7, 0x00, 0x64, 0xf5, 0xd5, 0xa8, 0xeb, 0xe3, 0xb7,
+	0x0a, 0x65, 0x4e, 0x24, 0x45, 0x47, 0x8f, 0xa0, 0x7c, 0xc9, 0xb8, 0x4b, 0x87, 0xe6, 0xd6, 0x94,
+	0xb4, 0x26, 0x6c, 0xed, 0x4b, 0xf4, 0xd5, 0x29, 0xc1, 0x2e, 0x8f, 0x43, 0xe9, 0x4f, 0x69, 0xf3,
+	0x14, 0xde, 0xcb, 0x0c, 0x8a, 0x0e, 0xa1, 0xbc, 0x3a, 0xe6, 0xa1, 0xef, 0x69, 0x7d, 0x94, 0x3a,
+	0x77, 0x17, 0x37, 0x75, 0x7b, 0xa5, 0x87, 0x93, 0x2e, 0xb6, 0x57, 0xa0, 0x13, 0xaf, 0xf9, 0x37,
+	0x0b, 0xf6, 0x36, 0xc4, 0x82, 0xee, 0xc3, 0x8e, 0x3f, 0x25, 0x63, 0x9a, 0xd0, 0x71, 0x62, 0xa0,
+	0x1e, 0x14, 0x03, 0x32, 0xa2, 0x81, 0x92, 0x8c, 0x4a, 0xdb, 0xcf, 0xde, 0xa8, 0xba, 0xd6, 0x1f,
+	0x35, 0xbe, 0x17, 0x4a, 0x3e, 0xc7, 0x86, 0x8c, 0x1c, 0xd8, 0x75, 0xd9, 0x74, 0x4a, 0x42, 0x55,
+	0x9c, 0xb6, 0xf7, 0x4b, 0x78, 0x69, 0x22, 0x04, 0x05, 0xc2, 0xc7, 0xc2, 0x29, 0x68, 0xb7, 0x1e,
+	0xa3, 0x0a, 0x6c, 0xd3, 0x70, 0xe6, 0xec, 0x68, 0x97, 0x1a, 0x2a, 0x8f, 0xe7, 0x27, 0x67, 0x5e,
+	0xc2, 0x6a, 0xa8, 0x78, 0xb1, 0xa0, 0xdc, 0xd9, 0xd5, 0x2e, 0x3d, 0x46, 0xbf, 0x82, 0xe2, 0x94,
+	0xc5, 0xa1, 0x14, 0x8e, 0xa5, 0x17, 0xfb, 0x20, 0x6b, 0xb1, 0x67, 0x0a, 0x61, 0x8a, 0xa7, 0x81,
+	0xa3, 0x1e, 0xdc, 0x13, 0x92, 0x45, 0xc3, 0x31, 0x27, 0x2e, 0x1d, 0x46, 0x94, 0xfb, 0xcc, 0x33,
+	0x97, 0xff, 0x41, 0x2b, 0xe9, 0x15, 0x5a, 0xcb, 0x5e, 0xa1, 0xd5, 0x35, 0xbd, 0x02, 0xbe, 0xab,
+	0x38, 0xc7, 0x8a, 0xd2, 0xd7, 0x0c, 0xd4, 0x87, 0x72, 0x14, 0x07, 0xc1, 0x90, 0x45, 0xc9, 0x3b,
+	0x00, 0x3a, 0xc2, 0x5b, 0xa4, 0xac, 0x1f, 0x07, 0xc1, 0xf3, 0x84, 0x84, 0xed, 0x68, 0x6d, 0xa0,
+	0xf7, 0xa1, 0x38, 0xe6, 0x2c, 0x8e, 0x84, 0x63, 0xeb, 0x64, 0x18, 0x0b, 0x7d, 0x0e, 0xbb, 0x82,
+	0xba, 0x9c, 0x4a, 0xe1, 0x94, 0xf5, 0x56, 0x3f, 0xcc, 0x9a, 0x64, 0xa0, 0x21, 0x98, 0x5e, 0x52,
+	0x4e, 0x43, 0x97, 0xe2, 0x25, 0x07, 0x3d, 0x80, 0x6d, 0x29, 0xe7, 0xce, 0x5e, 0x23, 0xbf, 0x6f,
+	0x75, 0x76, 0x17, 0x37, 0xf5, 0xed, 0x8b, 0x8b, 0x97, 0x58, 0xf9, 0x54, 0x8d, 0x9a, 0x30, 0x21,
+	0x43, 0x32, 0xa5, 0xce, 0x1d, 0x9d, 0xdb, 0x95, 0x8d, 0x5e, 0x02, 0x78, 0xa1, 0x18, 0xba, 0xfa,
+	0x52, 0x38, 0x77, 0xf5, 0xee, 0x3e, 0x79, 0xf3, 0xee, 0xba, 0xe7, 0x03, 0x53, 0xa7, 0xf7, 0x16,
+	0x37, 0xf5, 0xd2, 0xca, 0xc4, 0x25, 0x2f, 0x14, 0xc9, 0x10, 0x75, 0xc0, 0x9e, 0x50, 0x12, 0xc8,
+	0x89, 0x3b, 0xa1, 0xee, 0x95, 0x53, 0xb9, 0xbd, 0xf0, 0x3e, 0xd3, 0x30, 0x13, 0x21, 0x4d, 0x52,
+	0x0a, 0x56, 0x4b, 0x15, 0xce, 0x3d, 0x9d, 0xab, 0xc4, 0x40, 0x1f, 0x00, 0xb0, 0x88, 0x86, 0x43,
+	0x21, 0x3d, 0x3f, 0x74, 0x90, 0xda, 0x32, 0x2e, 0x29, 0xcf, 0x40, 0x39, 0xd0, 0x43, 0x55, 0x16,
+	0x89, 0x37, 0x64, 0x61, 0x30, 0x77, 0x7e, 0xa0, 0xbf, 0x5a, 0xca, 0xf1, 0x3c, 0x0c, 0xe6, 0xa8,
+	0x0e, 0xb6, 0xd6, 0x85, 0xf0, 0xc7, 0x21, 0x09, 0x9c, 0xfb, 0x3a, 0x1f, 0xa0, 0x5c, 0x03, 0xed,
+	0xa9, 0x7e, 0x06, 0x76, 0x4a, 0xee, 0x4a, 0xa6, 0x57, 0x74, 0x6e, 0x6e, 0x90, 0x1a, 0xaa, 0x35,
+	0xcd, 0x48, 0x10, 0x27, 0xcd, 0x5e, 0x09, 0x27, 0xc6, 0xaf, 0xb7, 0x9e, 0xe4, 0xab, 0x87, 0x60,
+	0xa7, 0x8e, 0x1d, 0x7d, 0x08, 0x7b, 0x9c, 0x8e, 0x7d, 0x21, 0xf9, 0x7c, 0x48, 0x62, 0x39, 0x71,
+	0x7e, 0xa7, 0x09, 0xe5, 0xa5, 0xb3, 0x1d, 0xcb, 0x49, 0x75, 0x08, 0xeb, 0xec, 0xa1, 0x06, 0xd8,
+	0xea, 0x54, 0x04, 0xe5, 0x33, 0xca, 0xd5, 0x83, 0xa2, 0x36, 0x9d, 0x76, 0x29, 0xf5, 0x08, 0x4a,
+	0xb8, 0x3b, 0xd1, 0x97, 0xb7, 0x84, 0x8d, 0xa5, 0x6e, 0xe3, 0x52, 0xa2, 0xe6, 0x36, 0x1a, 0xb3,
+	0xf9, 0xdf, 0x3c, 0x94, 0xd3, 0xef, 0x22, 0x3a, 0x4a, 0xde, 0x33, 0xbd, 0xa5, 0x3b, 0x87, 0x07,
+	0x6f, 0x7a, 0x47, 0xf5, 0xeb, 0x11, 0xc4, 0x2a, 0xd8, 0x99, 0x6a, 0x61, 0x35, 0x19, 0xfd, 0x12,
+	0x76, 0x22, 0xc6, 0xe5, 0xb2, 0x86, 0xd4, 0x32, 0x2b, 0x3e, 0xe3, 0xcb, 0x6a, 0x9b, 0x80, 0x9b,
+	0x13, 0xb8, 0xb3, 0x19, 0x0d, 0x3d, 0x86, 0xed, 0x17, 0x27, 0xfd, 0x4a, 0xae, 0xfa, 0xf0, 0xd5,
+	0x75, 0xe3, 0x87, 0x9b, 0x1f, 0x5f, 0xf8, 0x5c, 0xc6, 0x24, 0x38, 0xe9, 0xa3, 0x9f, 0xc2, 0x4e,
+	0xf7, 0x7c, 0x80, 0x71, 0x25, 0x5f, 0xad, 0xbf, 0xba, 0x6e, 0x3c, 0xdc, 0xc4, 0xa9, 0x4f, 0x2c,
+	0x0e, 0x3d, 0xcc, 0x46, 0xab, 0x76, 0xee, 0x9f, 0x5b, 0x60, 0x9b, 0xd2, 0xfa, 0xae, 0x3b, 0xfe,
+	0xbd, 0xe4, 0xb5, 0x5a, 0xde, 0x99, 0xad, 0x37, 0x3e, 0x5a, 0xe5, 0x84, 0x60, 0xce, 0xf8, 0x11,
+	0x94, 0xfd, 0x68, 0xf6, 0xe9, 0x90, 0x86, 0x64, 0x14, 0x98, 0xce, 0xce, 0xc2, 0xb6, 0xf2, 0xf5,
+	0x12, 0x97, 0xba, 0xb0, 0x7e, 0x28, 0x29, 0x0f, 0x4d, 0xcf, 0x66, 0xe1, 0x95, 0x8d, 0x3e, 0x87,
+	0x82, 0x1f, 0x91, 0xa9, 0x79, 0x69, 0x33, 0x77, 0x70, 0xd2, 0x6f, 0x9f, 0x19, 0x0d, 0x76, 0xac,
+	0xc5, 0x4d, 0xbd, 0xa0, 0x1c, 0x58, 0xd3, 0x50, 0x6d, 0xf9, 0xd8, 0xa9, 0x99, 0x74, 0xf1, 0xb5,
+	0x70, 0xca, 0xd3, 0xfc, 0x5f, 0x01, 0xec, 0xa3, 0x20, 0x16, 0xd2, 0x3c, 0x21, 0xef, 0x2c, 0x6f,
+	0x2f, 0xe1, 0x1e, 0xd1, 0xcd, 0x3f, 0x09, 0x55, 0x3d, 0xd6, 0x4d, 0x84, 0xc9, 0xdd, 0xe3, 0xcc,
+	0x70, 0x2b, 0x70, 0xd2, 0x70, 0x74, 0x8a, 0x2a, 0xa6, 0x93, 0xc7, 0x15, 0xf2, 0x8d, 0x2f, 0x68,
+	0x00, 0x7b, 0x8c, 0xbb, 0x13, 0x2a, 0x64, 0x52, 0xc5, 0x4d, 0xb3, 0x9c, 0xf9, 0x1b, 0xf5, 0x3c,
+	0x0d, 0x34, 0x25, 0x2c, 0x59, 0xed, 0x66, 0x0c, 0xf4, 0x04, 0x0a, 0x9c, 0x5c, 0x2e, 0x1b, 0xa2,
+	0x4c, 0x7d, 0x63, 0x72, 0x29, 0x37, 0x42, 0x68, 0x06, 0xfa, 0x03, 0x80, 0xe7, 0x8b, 0x88, 0x48,
+	0x77, 0x42, 0xb9, 0x39, 0xa7, 0xcc, 0x2d, 0x76, 0x57, 0xa8, 0x8d, 0x28, 0x29, 0x36, 0x3a, 0x85,
+	0x92, 0x4b, 0x96, 0x4a, 0x2b, 0xde, 0xfe, 0x07, 0x71, 0xd4, 0x36, 0x21, 0x2a, 0x2a, 0xc4, 0xe2,
+	0xa6, 0x6e, 0x2d, 0x3d, 0xd8, 0x72, 0x89, 0x51, 0xde, 0x29, 0xec, 0xa9, 0x3f, 0x8b, 0xa1, 0x47,
+	0x2f, 0x49, 0x1c, 0x48, 0xa1, 0x1f, 0xda, 0x5b, 0x4a, 0xb2, 0x6a, 0x53, 0xbb, 0x06, 0x67, 0xd6,
+	0x55, 0x96, 0x29, 0x1f, 0xfa, 0x13, 0xdc, 0xa3, 0xa1, 0xcb, 0xe7, 0x5a, 0x67, 0xcb, 0x15, 0x5a,
+	0xb7, 0x6f, 0xb6, 0xb7, 0x02, 0x6f, 0x6c, 0xb6, 0x42, 0xbf, 0xe1, 0x6f, 0xfa, 0x00, 0xc9, 0x23,
+	0xf7, 0x6e, 0xf5, 0x87, 0xa0, 0xe0, 0x11, 0x49, 0xb4, 0xe4, 0xca, 0x58, 0x8f, 0x3b, 0xce, 0xeb,
+	0xaf, 0x6b, 0xb9, 0x7f, 0x7f, 0x5d, 0xcb, 0xfd, 0x65, 0x51, 0xcb, 0xbf, 0x5e, 0xd4, 0xf2, 0xff,
+	0x5a, 0xd4, 0xf2, 0xff, 0x59, 0xd4, 0xf2, 0xa3, 0xa2, 0x6e, 0x0d, 0x7e, 0xf1, 0xff, 0x00, 0x00,
+	0x00, 0xff, 0xff, 0xed, 0xbe, 0x26, 0xe6, 0x9a, 0x10, 0x00, 0x00,
 }
 }

+ 7 - 1
vendor/github.com/docker/swarmkit/api/specs.proto

@@ -69,9 +69,12 @@ message ServiceSpec {
 		GlobalService global = 4;
 		GlobalService global = 4;
 	}
 	}
 
 
-	// UpdateConfig controls the rate and policy of updates.
+	// Update contains settings which affect updates.
 	UpdateConfig update = 6;
 	UpdateConfig update = 6;
 
 
+	// Rollback contains settings which affect rollbacks of updates.
+	UpdateConfig rollback = 9;
+
 	// ServiceSpec.Networks has been deprecated and is replaced by
 	// ServiceSpec.Networks has been deprecated and is replaced by
 	// Networks field in Task (TaskSpec.Networks).
 	// Networks field in Task (TaskSpec.Networks).
 	// This field (ServiceSpec.Networks) is kept for compatibility.
 	// This field (ServiceSpec.Networks) is kept for compatibility.
@@ -200,6 +203,9 @@ message ContainerSpec {
 	// they will be decided by the modes passed in the mount definition.
 	// they will be decided by the modes passed in the mount definition.
 	bool read_only = 19;
 	bool read_only = 19;
 
 
+	// StopSignal defines the signal to stop the container.
+	string stop_signal = 20;
+
 	repeated Mount mounts = 8 [(gogoproto.nullable) = false];
 	repeated Mount mounts = 8 [(gogoproto.nullable) = false];
 
 
 	// StopGracePeriod the grace period for stopping the container before
 	// StopGracePeriod the grace period for stopping the container before

+ 0 - 11
vendor/github.com/docker/swarmkit/api/types.pb.go

@@ -449,12 +449,6 @@ type UpdateConfig_FailureAction int32
 const (
 const (
 	UpdateConfig_PAUSE    UpdateConfig_FailureAction = 0
 	UpdateConfig_PAUSE    UpdateConfig_FailureAction = 0
 	UpdateConfig_CONTINUE UpdateConfig_FailureAction = 1
 	UpdateConfig_CONTINUE UpdateConfig_FailureAction = 1
-	// NOTE: Automated rollback triggered as a failure action is an
-	// experimental feature that is not yet exposed to the end
-	// user. Currently, rollbacks must be initiated manually
-	// through the API by setting Spec to PreviousSpec. We may
-	// decide to expose automatic rollback in the future based on
-	// user feedback, or remove this feature otherwise.
 	UpdateConfig_ROLLBACK UpdateConfig_FailureAction = 2
 	UpdateConfig_ROLLBACK UpdateConfig_FailureAction = 2
 )
 )
 
 
@@ -951,11 +945,6 @@ type UpdateConfig struct {
 	// If the failure action is ROLLBACK, the orchestrator will attempt to
 	// If the failure action is ROLLBACK, the orchestrator will attempt to
 	// roll back to the previous service spec. If the MaxFailureRatio
 	// roll back to the previous service spec. If the MaxFailureRatio
 	// threshold is hit during the rollback, the rollback will pause.
 	// threshold is hit during the rollback, the rollback will pause.
-	//
-	// TODO(aaronl): Should there be a separate failure threshold for
-	// rollbacks? Should there be a failure action for rollbacks (to allow
-	// them to do something other than pause when the rollback encounters
-	// errors)?
 	MaxFailureRatio float32 `protobuf:"fixed32,5,opt,name=max_failure_ratio,json=maxFailureRatio,proto3" json:"max_failure_ratio,omitempty"`
 	MaxFailureRatio float32 `protobuf:"fixed32,5,opt,name=max_failure_ratio,json=maxFailureRatio,proto3" json:"max_failure_ratio,omitempty"`
 }
 }
 
 

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

@@ -285,12 +285,6 @@ message UpdateConfig {
 	enum FailureAction {
 	enum FailureAction {
 		PAUSE = 0;
 		PAUSE = 0;
 		CONTINUE = 1;
 		CONTINUE = 1;
-		// NOTE: Automated rollback triggered as a failure action is an
-		// experimental feature that is not yet exposed to the end
-		// user. Currently, rollbacks must be initiated manually
-		// through the API by setting Spec to PreviousSpec. We may
-		// decide to expose automatic rollback in the future based on
-		// user feedback, or remove this feature otherwise.
 		ROLLBACK = 2;
 		ROLLBACK = 2;
 	}
 	}
 
 
@@ -320,11 +314,6 @@ message UpdateConfig {
 	// If the failure action is ROLLBACK, the orchestrator will attempt to
 	// If the failure action is ROLLBACK, the orchestrator will attempt to
 	// roll back to the previous service spec. If the MaxFailureRatio
 	// roll back to the previous service spec. If the MaxFailureRatio
 	// threshold is hit during the rollback, the rollback will pause.
 	// threshold is hit during the rollback, the rollback will pause.
-	//
-	// TODO(aaronl): Should there be a separate failure threshold for
-	// rollbacks? Should there be a failure action for rollbacks (to allow
-	// them to do something other than pause when the rollback encounters
-	// errors)?
 	float max_failure_ratio = 5;
 	float max_failure_ratio = 5;
 }
 }
 
 

+ 30 - 28
vendor/github.com/docker/swarmkit/ca/certificates.go

@@ -4,10 +4,13 @@ import (
 	"bytes"
 	"bytes"
 	"crypto"
 	"crypto"
 	"crypto/ecdsa"
 	"crypto/ecdsa"
+	"crypto/elliptic"
 	"crypto/rand"
 	"crypto/rand"
+	"crypto/rsa"
 	"crypto/tls"
 	"crypto/tls"
 	"crypto/x509"
 	"crypto/x509"
 	"encoding/pem"
 	"encoding/pem"
+	"fmt"
 	"io"
 	"io"
 	"io/ioutil"
 	"io/ioutil"
 	"os"
 	"os"
@@ -52,7 +55,7 @@ const (
 	// root CA private key material encryption key. It can be used for seamless
 	// root CA private key material encryption key. It can be used for seamless
 	// KEK rotations.
 	// KEK rotations.
 	PassphraseENVVarPrev = "SWARM_ROOT_CA_PASSPHRASE_PREV"
 	PassphraseENVVarPrev = "SWARM_ROOT_CA_PASSPHRASE_PREV"
-	// RootCAExpiration represents the expiration for the root CA in seconds (20 years)
+	// RootCAExpiration represents the default expiration for the root CA in seconds (20 years)
 	RootCAExpiration = "630720000s"
 	RootCAExpiration = "630720000s"
 	// DefaultNodeCertExpiration represents the default expiration for node certificates (3 months)
 	// DefaultNodeCertExpiration represents the default expiration for node certificates (3 months)
 	DefaultNodeCertExpiration = 2160 * time.Hour
 	DefaultNodeCertExpiration = 2160 * time.Hour
@@ -317,31 +320,7 @@ func (rca *RootCA) ParseValidateAndSignCSR(csrBytes []byte, cn, ou, org string)
 		return nil, errors.Wrap(err, "failed to sign node certificate")
 		return nil, errors.Wrap(err, "failed to sign node certificate")
 	}
 	}
 
 
-	return rca.AppendFirstRootPEM(cert)
-}
-
-// AppendFirstRootPEM appends the first certificate from this RootCA's cert
-// bundle to the given cert bundle (which should already be encoded as a series
-// of PEM-encoded certificate blocks).
-func (rca *RootCA) AppendFirstRootPEM(cert []byte) ([]byte, error) {
-	// Append the first root CA Cert to the certificate, to create a valid chain
-	// Get the first Root CA Cert on the bundle
-	firstRootCA, _, err := helpers.ParseOneCertificateFromPEM(rca.Cert)
-	if err != nil {
-		return nil, err
-	}
-	if len(firstRootCA) < 1 {
-		return nil, errors.New("no valid Root CA certificates found")
-	}
-	// Convert the first root CA back to PEM
-	firstRootCAPEM := helpers.EncodeCertificatePEM(firstRootCA[0])
-	if firstRootCAPEM == nil {
-		return nil, errors.New("error while encoding the Root CA certificate")
-	}
-	// Append this Root CA to the certificate to make [Cert PEM]\n[Root PEM][EOF]
-	certChain := append(cert, firstRootCAPEM...)
-
-	return certChain, nil
+	return cert, nil
 }
 }
 
 
 // NewRootCA creates a new RootCA object from unparsed PEM cert bundle and key byte
 // NewRootCA creates a new RootCA object from unparsed PEM cert bundle and key byte
@@ -361,8 +340,17 @@ func NewRootCA(certBytes, keyBytes []byte, certExpiry time.Duration) (RootCA, er
 	// Create a Pool with all of the certificates found
 	// Create a Pool with all of the certificates found
 	pool := x509.NewCertPool()
 	pool := x509.NewCertPool()
 	for _, cert := range parsedCerts {
 	for _, cert := range parsedCerts {
+		switch cert.SignatureAlgorithm {
+		case x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA, x509.ECDSAWithSHA256, x509.ECDSAWithSHA384, x509.ECDSAWithSHA512:
+			break
+		default:
+			return RootCA{}, fmt.Errorf("unsupported signature algorithm: %s", cert.SignatureAlgorithm.String())
+		}
+
 		// Check to see if all of the certificates are valid, self-signed root CA certs
 		// Check to see if all of the certificates are valid, self-signed root CA certs
-		if err := cert.CheckSignature(cert.SignatureAlgorithm, cert.RawTBSCertificate, cert.Signature); err != nil {
+		selfpool := x509.NewCertPool()
+		selfpool.AddCert(cert)
+		if _, err := cert.Verify(x509.VerifyOptions{Roots: selfpool}); err != nil {
 			return RootCA{}, errors.Wrap(err, "error while validating Root CA Certificate")
 			return RootCA{}, errors.Wrap(err, "error while validating Root CA Certificate")
 		}
 		}
 		pool.AddCert(cert)
 		pool.AddCert(cert)
@@ -429,8 +417,22 @@ func NewRootCA(certBytes, keyBytes []byte, certExpiry time.Duration) (RootCA, er
 
 
 func ensureCertKeyMatch(cert *x509.Certificate, key crypto.PublicKey) error {
 func ensureCertKeyMatch(cert *x509.Certificate, key crypto.PublicKey) error {
 	switch certPub := cert.PublicKey.(type) {
 	switch certPub := cert.PublicKey.(type) {
-	// TODO: Handle RSA keys.
+	case *rsa.PublicKey:
+		if certPub.N.BitLen() < 2048 || certPub.E == 1 {
+			return errors.New("unsupported RSA key parameters")
+		}
+		rsaKey, ok := key.(*rsa.PublicKey)
+		if ok && certPub.E == rsaKey.E && certPub.N.Cmp(rsaKey.N) == 0 {
+			return nil
+		}
 	case *ecdsa.PublicKey:
 	case *ecdsa.PublicKey:
+		switch certPub.Curve {
+		case elliptic.P256(), elliptic.P384(), elliptic.P521():
+			break
+		default:
+			return errors.New("unsupported ECDSA key parameters")
+		}
+
 		ecKey, ok := key.(*ecdsa.PublicKey)
 		ecKey, ok := key.(*ecdsa.PublicKey)
 		if ok && certPub.X.Cmp(ecKey.X) == 0 && certPub.Y.Cmp(ecKey.Y) == 0 {
 		if ok && certPub.X.Cmp(ecKey.X) == 0 && certPub.Y.Cmp(ecKey.Y) == 0 {
 			return nil
 			return nil

+ 1 - 2
vendor/github.com/docker/swarmkit/ca/external.go

@@ -89,9 +89,8 @@ func (eca *ExternalCA) Sign(ctx context.Context, req signer.SignRequest) (cert [
 	for _, url := range urls {
 	for _, url := range urls {
 		cert, err = makeExternalSignRequest(ctx, client, url, csrJSON)
 		cert, err = makeExternalSignRequest(ctx, client, url, csrJSON)
 		if err == nil {
 		if err == nil {
-			return eca.rootCA.AppendFirstRootPEM(cert)
+			return cert, err
 		}
 		}
-
 		logrus.Debugf("unable to proxy certificate signing request to %s: %s", url, err)
 		logrus.Debugf("unable to proxy certificate signing request to %s: %s", url, err)
 	}
 	}
 
 

+ 1 - 1
vendor/github.com/docker/swarmkit/ca/keyreadwriter.go

@@ -321,7 +321,7 @@ func (k *KeyReadWriter) readKey() (*pem.Block, error) {
 	}
 	}
 
 
 	// If it's encrypted, we can't read without a passphrase (we're assuming
 	// If it's encrypted, we can't read without a passphrase (we're assuming
-	// empty passphrases iare invalid)
+	// empty passphrases are invalid)
 	if k.kekData.KEK == nil {
 	if k.kekData.KEK == nil {
 		return nil, ErrInvalidKEK{Wrapped: x509.IncorrectPasswordError}
 		return nil, ErrInvalidKEK{Wrapped: x509.IncorrectPasswordError}
 	}
 	}

+ 3 - 2
vendor/github.com/docker/swarmkit/manager/allocator/network.go

@@ -289,8 +289,9 @@ func (a *Allocator) doNetworkInit(ctx context.Context) (err error) {
 			if a.taskAllocateVote(networkVoter, t.ID) {
 			if a.taskAllocateVote(networkVoter, t.ID) {
 				// If the task is not attached to any network, network
 				// If the task is not attached to any network, network
 				// allocators job is done. Immediately cast a vote so
 				// allocators job is done. Immediately cast a vote so
-				// that the task can be moved to ALLOCATED state as
+				// that the task can be moved to the PENDING state as
 				// soon as possible.
 				// soon as possible.
+				updateTaskStatus(t, api.TaskStatePending, allocatedStatusMessage)
 				allocatedTasks = append(allocatedTasks, t)
 				allocatedTasks = append(allocatedTasks, t)
 			}
 			}
 			continue
 			continue
@@ -467,7 +468,7 @@ func taskDead(t *api.Task) bool {
 }
 }
 
 
 // taskReadyForNetworkVote checks if the task is ready for a network
 // taskReadyForNetworkVote checks if the task is ready for a network
-// vote to move it to ALLOCATED state.
+// vote to move it to PENDING state.
 func taskReadyForNetworkVote(t *api.Task, s *api.Service, nc *networkContext) bool {
 func taskReadyForNetworkVote(t *api.Task, s *api.Service, nc *networkContext) bool {
 	// Task is ready for vote if the following is true:
 	// Task is ready for vote if the following is true:
 	//
 	//

+ 1 - 1
vendor/github.com/docker/swarmkit/manager/allocator/networkallocator/networkallocator.go

@@ -419,7 +419,7 @@ func (na *NetworkAllocator) releaseEndpoints(networks []*api.NetworkAttachment)
 
 
 		localNet := na.getNetwork(nAttach.Network.ID)
 		localNet := na.getNetwork(nAttach.Network.ID)
 		if localNet == nil {
 		if localNet == nil {
-			return fmt.Errorf("could not find network allocater state for network %s", nAttach.Network.ID)
+			return fmt.Errorf("could not find network allocator state for network %s", nAttach.Network.ID)
 		}
 		}
 
 
 		// Do not fail and bail out if we fail to release IP
 		// Do not fail and bail out if we fail to release IP

+ 2 - 1
vendor/github.com/docker/swarmkit/manager/allocator/networkallocator/portallocator.go

@@ -285,7 +285,8 @@ func (pa *portAllocator) portsAllocatedInHostPublishMode(s *api.Service) bool {
 
 
 	if s.Spec.Endpoint != nil {
 	if s.Spec.Endpoint != nil {
 		for _, portConfig := range s.Spec.Endpoint.Ports {
 		for _, portConfig := range s.Spec.Endpoint.Ports {
-			if portConfig.PublishMode == api.PublishModeHost {
+			if portConfig.PublishMode == api.PublishModeHost &&
+				portConfig.PublishedPort != 0 {
 				if portStates.delState(portConfig) == nil {
 				if portStates.delState(portConfig) == nil {
 					return false
 					return false
 				}
 				}

+ 1 - 1
vendor/github.com/docker/swarmkit/manager/controlapi/secret.go

@@ -156,7 +156,7 @@ func (s *Server) ListSecrets(ctx context.Context, request *api.ListSecretsReques
 	return &api.ListSecretsResponse{Secrets: respSecrets}, nil
 	return &api.ListSecretsResponse{Secrets: respSecrets}, nil
 }
 }
 
 
-// CreateSecret creates and return a `CreateSecretResponse` with a `Secret` based
+// CreateSecret creates and returns a `CreateSecretResponse` with a `Secret` based
 // on the provided `CreateSecretRequest.SecretSpec`.
 // on the provided `CreateSecretRequest.SecretSpec`.
 // - Returns `InvalidArgument` if the `CreateSecretRequest.SecretSpec` is malformed,
 // - Returns `InvalidArgument` if the `CreateSecretRequest.SecretSpec` is malformed,
 //   or if the secret data is too long or contains invalid characters.
 //   or if the secret data is too long or contains invalid characters.

+ 48 - 13
vendor/github.com/docker/swarmkit/manager/controlapi/service.go

@@ -6,12 +6,14 @@ import (
 	"reflect"
 	"reflect"
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
+	"time"
 
 
 	"github.com/docker/distribution/reference"
 	"github.com/docker/distribution/reference"
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/identity"
 	"github.com/docker/swarmkit/identity"
 	"github.com/docker/swarmkit/manager/constraint"
 	"github.com/docker/swarmkit/manager/constraint"
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/docker/swarmkit/manager/state/store"
+	"github.com/docker/swarmkit/protobuf/ptypes"
 	"github.com/docker/swarmkit/template"
 	"github.com/docker/swarmkit/template"
 	gogotypes "github.com/gogo/protobuf/types"
 	gogotypes "github.com/gogo/protobuf/types"
 	"golang.org/x/net/context"
 	"golang.org/x/net/context"
@@ -98,6 +100,20 @@ func validateUpdate(uc *api.UpdateConfig) error {
 		return grpc.Errorf(codes.InvalidArgument, "TaskSpec: update-delay cannot be negative")
 		return grpc.Errorf(codes.InvalidArgument, "TaskSpec: update-delay cannot be negative")
 	}
 	}
 
 
+	if uc.Monitor != nil {
+		monitor, err := gogotypes.DurationFromProto(uc.Monitor)
+		if err != nil {
+			return err
+		}
+		if monitor < 0 {
+			return grpc.Errorf(codes.InvalidArgument, "TaskSpec: update-monitor cannot be negative")
+		}
+	}
+
+	if uc.MaxFailureRatio < 0 || uc.MaxFailureRatio > 1 {
+		return grpc.Errorf(codes.InvalidArgument, "TaskSpec: update-maxfailureratio cannot be less than 0 or bigger than 1")
+	}
+
 	return nil
 	return nil
 }
 }
 
 
@@ -125,7 +141,7 @@ func validateContainerSpec(container *api.ContainerSpec) error {
 	return nil
 	return nil
 }
 }
 
 
-func validateTask(taskSpec api.TaskSpec) error {
+func validateTaskSpec(taskSpec api.TaskSpec) error {
 	if err := validateResourceRequirements(taskSpec.Resources); err != nil {
 	if err := validateResourceRequirements(taskSpec.Resources); err != nil {
 		return err
 		return err
 	}
 	}
@@ -138,6 +154,11 @@ func validateTask(taskSpec api.TaskSpec) error {
 		return err
 		return err
 	}
 	}
 
 
+	// Check to see if the Secret Reference portion of the spec is valid
+	if err := validateSecretRefsSpec(taskSpec); err != nil {
+		return err
+	}
+
 	if taskSpec.GetRuntime() == nil {
 	if taskSpec.GetRuntime() == nil {
 		return grpc.Errorf(codes.InvalidArgument, "TaskSpec: missing runtime")
 		return grpc.Errorf(codes.InvalidArgument, "TaskSpec: missing runtime")
 	}
 	}
@@ -218,8 +239,8 @@ func validateEndpointSpec(epSpec *api.EndpointSpec) error {
 
 
 // validateSecretRefsSpec finds if the secrets passed in spec are valid and have no
 // validateSecretRefsSpec finds if the secrets passed in spec are valid and have no
 // conflicting targets.
 // conflicting targets.
-func validateSecretRefsSpec(spec *api.ServiceSpec) error {
-	container := spec.Task.GetContainer()
+func validateSecretRefsSpec(spec api.TaskSpec) error {
+	container := spec.GetContainer()
 	if container == nil {
 	if container == nil {
 		return nil
 		return nil
 	}
 	}
@@ -257,6 +278,7 @@ func validateSecretRefsSpec(spec *api.ServiceSpec) error {
 
 
 	return nil
 	return nil
 }
 }
+
 func (s *Server) validateNetworks(networks []*api.NetworkAttachmentConfig) error {
 func (s *Server) validateNetworks(networks []*api.NetworkAttachmentConfig) error {
 	for _, na := range networks {
 	for _, na := range networks {
 		var network *api.Network
 		var network *api.Network
@@ -297,7 +319,7 @@ func validateServiceSpec(spec *api.ServiceSpec) error {
 	if err := validateAnnotations(spec.Annotations); err != nil {
 	if err := validateAnnotations(spec.Annotations); err != nil {
 		return err
 		return err
 	}
 	}
-	if err := validateTask(spec.Task); err != nil {
+	if err := validateTaskSpec(spec.Task); err != nil {
 		return err
 		return err
 	}
 	}
 	if err := validateUpdate(spec.Update); err != nil {
 	if err := validateUpdate(spec.Update); err != nil {
@@ -309,10 +331,6 @@ func validateServiceSpec(spec *api.ServiceSpec) error {
 	if err := validateMode(spec); err != nil {
 	if err := validateMode(spec); err != nil {
 		return err
 		return err
 	}
 	}
-	// Check to see if the Secret Reference portion of the spec is valid
-	if err := validateSecretRefsSpec(spec); err != nil {
-		return err
-	}
 
 
 	return nil
 	return nil
 }
 }
@@ -406,7 +424,7 @@ func (s *Server) checkSecretExistence(tx store.Tx, spec *api.ServiceSpec) error
 	return nil
 	return nil
 }
 }
 
 
-// CreateService creates and return a Service based on the provided ServiceSpec.
+// CreateService creates and returns a Service based on the provided ServiceSpec.
 // - Returns `InvalidArgument` if the ServiceSpec is malformed.
 // - Returns `InvalidArgument` if the ServiceSpec is malformed.
 // - Returns `Unimplemented` if the ServiceSpec references unimplemented features.
 // - Returns `Unimplemented` if the ServiceSpec references unimplemented features.
 // - Returns `AlreadyExists` if the ServiceID conflicts.
 // - Returns `AlreadyExists` if the ServiceID conflicts.
@@ -537,11 +555,28 @@ func (s *Server) UpdateService(ctx context.Context, request *api.UpdateServiceRe
 		}
 		}
 
 
 		service.Meta.Version = *request.ServiceVersion
 		service.Meta.Version = *request.ServiceVersion
-		service.PreviousSpec = service.Spec.Copy()
-		service.Spec = *request.Spec.Copy()
 
 
-		// Reset update status
-		service.UpdateStatus = nil
+		if request.Rollback == api.UpdateServiceRequest_PREVIOUS {
+			if service.PreviousSpec == nil {
+				return grpc.Errorf(codes.FailedPrecondition, "service %s does not have a previous spec", request.ServiceID)
+			}
+
+			curSpec := service.Spec.Copy()
+			service.Spec = *service.PreviousSpec.Copy()
+			service.PreviousSpec = curSpec
+
+			service.UpdateStatus = &api.UpdateStatus{
+				State:     api.UpdateStatus_ROLLBACK_STARTED,
+				Message:   "manually requested rollback",
+				StartedAt: ptypes.MustTimestampProto(time.Now()),
+			}
+		} else {
+			service.PreviousSpec = service.Spec.Copy()
+			service.Spec = *request.Spec.Copy()
+
+			// Reset update status
+			service.UpdateStatus = nil
+		}
 
 
 		return store.UpdateService(tx, service)
 		return store.UpdateService(tx, service)
 	})
 	})

+ 1 - 1
vendor/github.com/docker/swarmkit/manager/encryption/nacl.go

@@ -29,7 +29,7 @@ func NewNACLSecretbox(key []byte) NACLSecretbox {
 	return secretbox
 	return secretbox
 }
 }
 
 
-// Algorithm returns the type of algorhtm this is (NACL Secretbox using XSalsa20 and Poly1305)
+// Algorithm returns the type of algorithm this is (NACL Secretbox using XSalsa20 and Poly1305)
 func (n NACLSecretbox) Algorithm() api.MaybeEncryptedRecord_Algorithm {
 func (n NACLSecretbox) Algorithm() api.MaybeEncryptedRecord_Algorithm {
 	return api.MaybeEncryptedRecord_NACLSecretboxSalsa20Poly1305
 	return api.MaybeEncryptedRecord_NACLSecretboxSalsa20Poly1305
 }
 }

+ 0 - 2
vendor/github.com/docker/swarmkit/manager/keymanager/keymanager.go

@@ -200,8 +200,6 @@ func (k *KeyManager) Run(ctx context.Context) error {
 	} else {
 	} else {
 		k.keyRing.lClock = cluster.EncryptionKeyLamportClock
 		k.keyRing.lClock = cluster.EncryptionKeyLamportClock
 		k.keyRing.keys = cluster.NetworkBootstrapKeys
 		k.keyRing.keys = cluster.NetworkBootstrapKeys
-
-		k.rotateKey(ctx)
 	}
 	}
 
 
 	ticker := time.NewTicker(k.config.RotationInterval)
 	ticker := time.NewTicker(k.config.RotationInterval)

+ 16 - 4
vendor/github.com/docker/swarmkit/manager/orchestrator/constraintenforcer/constraint_enforcer.go

@@ -1,11 +1,14 @@
 package constraintenforcer
 package constraintenforcer
 
 
 import (
 import (
+	"time"
+
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/log"
 	"github.com/docker/swarmkit/log"
 	"github.com/docker/swarmkit/manager/constraint"
 	"github.com/docker/swarmkit/manager/constraint"
 	"github.com/docker/swarmkit/manager/state"
 	"github.com/docker/swarmkit/manager/state"
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/docker/swarmkit/manager/state/store"
+	"github.com/docker/swarmkit/protobuf/ptypes"
 )
 )
 
 
 // ConstraintEnforcer watches for updates to nodes and shuts down tasks that no
 // ConstraintEnforcer watches for updates to nodes and shuts down tasks that no
@@ -43,7 +46,7 @@ func (ce *ConstraintEnforcer) Run() {
 		log.L.WithError(err).Error("failed to check nodes for noncompliant tasks")
 		log.L.WithError(err).Error("failed to check nodes for noncompliant tasks")
 	} else {
 	} else {
 		for _, node := range nodes {
 		for _, node := range nodes {
-			ce.shutdownNoncompliantTasks(node)
+			ce.rejectNoncompliantTasks(node)
 		}
 		}
 	}
 	}
 
 
@@ -51,14 +54,14 @@ func (ce *ConstraintEnforcer) Run() {
 		select {
 		select {
 		case event := <-watcher:
 		case event := <-watcher:
 			node := event.(state.EventUpdateNode).Node
 			node := event.(state.EventUpdateNode).Node
-			ce.shutdownNoncompliantTasks(node)
+			ce.rejectNoncompliantTasks(node)
 		case <-ce.stopChan:
 		case <-ce.stopChan:
 			return
 			return
 		}
 		}
 	}
 	}
 }
 }
 
 
-func (ce *ConstraintEnforcer) shutdownNoncompliantTasks(node *api.Node) {
+func (ce *ConstraintEnforcer) rejectNoncompliantTasks(node *api.Node) {
 	// If the availability is "drain", the orchestrator will
 	// If the availability is "drain", the orchestrator will
 	// shut down all tasks.
 	// shut down all tasks.
 	// If the availability is "pause", we shouldn't touch
 	// If the availability is "pause", we shouldn't touch
@@ -134,7 +137,16 @@ func (ce *ConstraintEnforcer) shutdownNoncompliantTasks(node *api.Node) {
 						return nil
 						return nil
 					}
 					}
 
 
-					t.DesiredState = api.TaskStateShutdown
+					// We set the observed state to
+					// REJECTED, rather than the desired
+					// state. Desired state is owned by the
+					// orchestrator, and setting it directly
+					// will bypass actions such as
+					// restarting the task on another node
+					// (if applicable).
+					t.Status.State = api.TaskStateRejected
+					t.Status.Message = "assigned node no longer meets constraints"
+					t.Status.Timestamp = ptypes.MustTimestampProto(time.Now())
 					return store.UpdateTask(tx, t)
 					return store.UpdateTask(tx, t)
 				})
 				})
 				if err != nil {
 				if err != nil {

+ 104 - 31
vendor/github.com/docker/swarmkit/manager/orchestrator/global/global.go

@@ -6,6 +6,7 @@ import (
 	"github.com/docker/swarmkit/manager/constraint"
 	"github.com/docker/swarmkit/manager/constraint"
 	"github.com/docker/swarmkit/manager/orchestrator"
 	"github.com/docker/swarmkit/manager/orchestrator"
 	"github.com/docker/swarmkit/manager/orchestrator/restart"
 	"github.com/docker/swarmkit/manager/orchestrator/restart"
+	"github.com/docker/swarmkit/manager/orchestrator/taskinit"
 	"github.com/docker/swarmkit/manager/orchestrator/update"
 	"github.com/docker/swarmkit/manager/orchestrator/update"
 	"github.com/docker/swarmkit/manager/state"
 	"github.com/docker/swarmkit/manager/state"
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/docker/swarmkit/manager/state/store"
@@ -27,6 +28,7 @@ type Orchestrator struct {
 	nodes map[string]*api.Node
 	nodes map[string]*api.Node
 	// globalServices has all the global services in the cluster, indexed by ServiceID
 	// globalServices has all the global services in the cluster, indexed by ServiceID
 	globalServices map[string]globalService
 	globalServices map[string]globalService
+	restartTasks   map[string]struct{}
 
 
 	// stopChan signals to the state machine to stop running.
 	// stopChan signals to the state machine to stop running.
 	stopChan chan struct{}
 	stopChan chan struct{}
@@ -51,9 +53,14 @@ func NewGlobalOrchestrator(store *store.MemoryStore) *Orchestrator {
 		doneChan:       make(chan struct{}),
 		doneChan:       make(chan struct{}),
 		updater:        updater,
 		updater:        updater,
 		restarts:       restartSupervisor,
 		restarts:       restartSupervisor,
+		restartTasks:   make(map[string]struct{}),
 	}
 	}
 }
 }
 
 
+func (g *Orchestrator) initTasks(ctx context.Context, readTx store.ReadTx) error {
+	return taskinit.CheckTasks(ctx, g.store, readTx, g, g.restarts)
+}
+
 // Run contains the global orchestrator event loop
 // Run contains the global orchestrator event loop
 func (g *Orchestrator) Run(ctx context.Context) error {
 func (g *Orchestrator) Run(ctx context.Context) error {
 	defer close(g.doneChan)
 	defer close(g.doneChan)
@@ -106,6 +113,16 @@ func (g *Orchestrator) Run(ctx context.Context) error {
 			reconcileServiceIDs = append(reconcileServiceIDs, s.ID)
 			reconcileServiceIDs = append(reconcileServiceIDs, s.ID)
 		}
 		}
 	}
 	}
+
+	// fix tasks in store before reconciliation loop
+	g.store.View(func(readTx store.ReadTx) {
+		err = g.initTasks(ctx, readTx)
+	})
+	if err != nil {
+		return err
+	}
+
+	g.tickTasks(ctx)
 	g.reconcileServices(ctx, reconcileServiceIDs)
 	g.reconcileServices(ctx, reconcileServiceIDs)
 
 
 	for {
 	for {
@@ -152,15 +169,7 @@ func (g *Orchestrator) Run(ctx context.Context) error {
 				g.removeTasksFromNode(ctx, v.Node)
 				g.removeTasksFromNode(ctx, v.Node)
 				delete(g.nodes, v.Node.ID)
 				delete(g.nodes, v.Node.ID)
 			case state.EventUpdateTask:
 			case state.EventUpdateTask:
-				if _, exists := g.globalServices[v.Task.ServiceID]; !exists {
-					continue
-				}
-				// global orchestrator needs to inspect when a task has terminated
-				// it should ignore tasks whose DesiredState is past running, which
-				// means the task has been processed
-				if isTaskTerminated(v.Task) {
-					g.restartTask(ctx, v.Task.ID, v.Task.ServiceID)
-				}
+				g.handleTaskChange(ctx, v.Task)
 			case state.EventDeleteTask:
 			case state.EventDeleteTask:
 				// CLI allows deleting task
 				// CLI allows deleting task
 				if _, exists := g.globalServices[v.Task.ServiceID]; !exists {
 				if _, exists := g.globalServices[v.Task.ServiceID]; !exists {
@@ -171,6 +180,52 @@ func (g *Orchestrator) Run(ctx context.Context) error {
 		case <-g.stopChan:
 		case <-g.stopChan:
 			return nil
 			return nil
 		}
 		}
+		g.tickTasks(ctx)
+	}
+}
+
+// FixTask validates a task with the current cluster settings, and takes
+// action to make it conformant to node state and service constraint
+// it's called at orchestrator initialization
+func (g *Orchestrator) FixTask(ctx context.Context, batch *store.Batch, t *api.Task) {
+	if _, exists := g.globalServices[t.ServiceID]; !exists {
+		return
+	}
+	// if a task's DesiredState has past running, the task has been processed
+	if t.DesiredState > api.TaskStateRunning {
+		return
+	}
+
+	var node *api.Node
+	if t.NodeID != "" {
+		node = g.nodes[t.NodeID]
+	}
+	// if the node no longer valid, remove the task
+	if t.NodeID == "" || orchestrator.InvalidNode(node) {
+		g.removeTask(ctx, batch, t)
+		return
+	}
+
+	// restart a task if it fails
+	if t.Status.State > api.TaskStateRunning {
+		g.restartTasks[t.ID] = struct{}{}
+	}
+}
+
+// handleTaskChange defines what orchestrator does when a task is updated by agent
+func (g *Orchestrator) handleTaskChange(ctx context.Context, t *api.Task) {
+	if _, exists := g.globalServices[t.ServiceID]; !exists {
+		return
+	}
+	// if a task's DesiredState has past running, which
+	// means the task has been processed
+	if t.DesiredState > api.TaskStateRunning {
+		return
+	}
+
+	// if a task has passed running, restart it
+	if t.Status.State > api.TaskStateRunning {
+		g.restartTasks[t.ID] = struct{}{}
 	}
 	}
 }
 }
 
 
@@ -227,7 +282,7 @@ func (g *Orchestrator) reconcileServices(ctx context.Context, serviceIDs []strin
 			nodeTasks[serviceID] = make(map[string][]*api.Task)
 			nodeTasks[serviceID] = make(map[string][]*api.Task)
 
 
 			for _, t := range tasks {
 			for _, t := range tasks {
-				if isTaskRunning(t) {
+				if t.DesiredState <= api.TaskStateRunning {
 					// Collect all running instances of this service
 					// Collect all running instances of this service
 					nodeTasks[serviceID][t.NodeID] = append(nodeTasks[serviceID][t.NodeID], t)
 					nodeTasks[serviceID][t.NodeID] = append(nodeTasks[serviceID][t.NodeID], t)
 				} else {
 				} else {
@@ -369,7 +424,7 @@ func (g *Orchestrator) reconcileServicesOneNode(ctx context.Context, serviceIDs
 			if t.ServiceID != serviceID {
 			if t.ServiceID != serviceID {
 				continue
 				continue
 			}
 			}
-			if isTaskRunning(t) {
+			if t.DesiredState <= api.TaskStateRunning {
 				tasks[serviceID] = append(tasks[serviceID], t)
 				tasks[serviceID] = append(tasks[serviceID], t)
 			} else {
 			} else {
 				if isTaskCompleted(t, orchestrator.RestartCondition(t)) {
 				if isTaskCompleted(t, orchestrator.RestartCondition(t)) {
@@ -447,24 +502,45 @@ func (g *Orchestrator) reconcileServicesOneNode(ctx context.Context, serviceIDs
 	}
 	}
 }
 }
 
 
-// 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 *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 {
-			return nil
-		}
-		service := store.GetService(tx, serviceID)
-		if service == nil {
-			return nil
+func (g *Orchestrator) tickTasks(ctx context.Context) {
+	if len(g.restartTasks) == 0 {
+		return
+	}
+	_, err := g.store.Batch(func(batch *store.Batch) error {
+		for taskID := range g.restartTasks {
+			err := batch.Update(func(tx store.Tx) error {
+				t := store.GetTask(tx, taskID)
+				if t == nil || t.DesiredState > api.TaskStateRunning {
+					return nil
+				}
+
+				service := store.GetService(tx, t.ServiceID)
+				if service == nil {
+					return nil
+				}
+
+				node, nodeExists := g.nodes[t.NodeID]
+				serviceEntry, serviceExists := g.globalServices[t.ServiceID]
+				if !nodeExists || !serviceExists {
+					return nil
+				}
+				if !constraint.NodeMatches(serviceEntry.constraints, node) {
+					t.DesiredState = api.TaskStateShutdown
+					return store.UpdateTask(tx, t)
+				}
+
+				return g.restarts.Restart(ctx, tx, g.cluster, service, *t)
+			})
+			if err != nil {
+				log.G(ctx).WithError(err).Errorf("orchestrator restartTask transaction failed")
+			}
 		}
 		}
-		return g.restarts.Restart(ctx, tx, g.cluster, service, *t)
+		return nil
 	})
 	})
 	if err != nil {
 	if err != nil {
 		log.G(ctx).WithError(err).Errorf("global orchestrator: restartTask transaction failed")
 		log.G(ctx).WithError(err).Errorf("global orchestrator: restartTask transaction failed")
 	}
 	}
+	g.restartTasks = make(map[string]struct{})
 }
 }
 
 
 func (g *Orchestrator) removeTask(ctx context.Context, batch *store.Batch, t *api.Task) {
 func (g *Orchestrator) removeTask(ctx context.Context, batch *store.Batch, t *api.Task) {
@@ -503,18 +579,15 @@ func (g *Orchestrator) removeTasks(ctx context.Context, batch *store.Batch, task
 	}
 	}
 }
 }
 
 
-func isTaskRunning(t *api.Task) bool {
-	return t != nil && t.DesiredState <= api.TaskStateRunning && t.Status.State <= api.TaskStateRunning
+// IsRelatedService returns true if the service should be governed by this orchestrator
+func (g *Orchestrator) IsRelatedService(service *api.Service) bool {
+	return orchestrator.IsGlobalService(service)
 }
 }
 
 
 func isTaskCompleted(t *api.Task, restartPolicy api.RestartPolicy_RestartCondition) bool {
 func isTaskCompleted(t *api.Task, restartPolicy api.RestartPolicy_RestartCondition) bool {
-	if t == nil || isTaskRunning(t) {
+	if t == nil || t.DesiredState <= api.TaskStateRunning {
 		return false
 		return false
 	}
 	}
 	return restartPolicy == api.RestartOnNone ||
 	return restartPolicy == api.RestartOnNone ||
 		(restartPolicy == api.RestartOnFailure && t.Status.State == api.TaskStateCompleted)
 		(restartPolicy == api.RestartOnFailure && t.Status.State == api.TaskStateCompleted)
 }
 }
-
-func isTaskTerminated(t *api.Task) bool {
-	return t != nil && t.Status.State > api.TaskStateRunning
-}

+ 5 - 0
vendor/github.com/docker/swarmkit/manager/orchestrator/replicated/services.go

@@ -223,3 +223,8 @@ func (r *Orchestrator) deleteTask(ctx context.Context, batch *store.Batch, t *ap
 		log.G(ctx).WithError(err).Errorf("deleting task %s failed", t.ID)
 		log.G(ctx).WithError(err).Errorf("deleting task %s failed", t.ID)
 	}
 	}
 }
 }
+
+// IsRelatedService returns true if the service should be governed by this orchestrator
+func (r *Orchestrator) IsRelatedService(service *api.Service) bool {
+	return orchestrator.IsReplicatedService(service)
+}

+ 39 - 92
vendor/github.com/docker/swarmkit/manager/orchestrator/replicated/tasks.go

@@ -1,15 +1,13 @@
 package replicated
 package replicated
 
 
 import (
 import (
-	"time"
-
 	"github.com/docker/go-events"
 	"github.com/docker/go-events"
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/log"
 	"github.com/docker/swarmkit/log"
 	"github.com/docker/swarmkit/manager/orchestrator"
 	"github.com/docker/swarmkit/manager/orchestrator"
+	"github.com/docker/swarmkit/manager/orchestrator/taskinit"
 	"github.com/docker/swarmkit/manager/state"
 	"github.com/docker/swarmkit/manager/state"
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/docker/swarmkit/manager/state/store"
-	gogotypes "github.com/gogo/protobuf/types"
 	"golang.org/x/net/context"
 	"golang.org/x/net/context"
 )
 )
 
 
@@ -18,94 +16,8 @@ import (
 // service-level reconciliation, which observes changes to services and creates
 // service-level reconciliation, which observes changes to services and creates
 // and/or kills tasks to match the service definition.
 // and/or kills tasks to match the service definition.
 
 
-func invalidNode(n *api.Node) bool {
-	return n == nil ||
-		n.Status.State == api.NodeStatus_DOWN ||
-		n.Spec.Availability == api.NodeAvailabilityDrain
-}
-
 func (r *Orchestrator) 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
-	}
-	for _, t := range tasks {
-		if t.NodeID != "" {
-			n := store.GetNode(readTx, t.NodeID)
-			if invalidNode(n) && t.Status.State <= api.TaskStateRunning && t.DesiredState <= api.TaskStateRunning {
-				r.restartTasks[t.ID] = struct{}{}
-			}
-		}
-	}
-
-	_, err = r.store.Batch(func(batch *store.Batch) error {
-		for _, t := range tasks {
-			if t.ServiceID == "" {
-				continue
-			}
-
-			// TODO(aluzzardi): We should NOT retrieve the service here.
-			service := store.GetService(readTx, t.ServiceID)
-			if service == nil {
-				// Service was deleted
-				err := batch.Update(func(tx store.Tx) error {
-					return store.DeleteTask(tx, t.ID)
-				})
-				if err != nil {
-					log.G(ctx).WithError(err).Error("failed to set task desired state to dead")
-				}
-				continue
-			}
-			// TODO(aluzzardi): This is shady. We should have a more generic condition.
-			if t.DesiredState != api.TaskStateReady || !orchestrator.IsReplicatedService(service) {
-				continue
-			}
-			restartDelay := orchestrator.DefaultRestartDelay
-			if t.Spec.Restart != nil && t.Spec.Restart.Delay != nil {
-				var err error
-				restartDelay, err = gogotypes.DurationFromProto(t.Spec.Restart.Delay)
-				if err != nil {
-					log.G(ctx).WithError(err).Error("invalid restart delay")
-					restartDelay = orchestrator.DefaultRestartDelay
-				}
-			}
-			if restartDelay != 0 {
-				timestamp, err := gogotypes.TimestampFromProto(t.Status.Timestamp)
-				if err == nil {
-					restartTime := timestamp.Add(restartDelay)
-					calculatedRestartDelay := restartTime.Sub(time.Now())
-					if calculatedRestartDelay < restartDelay {
-						restartDelay = calculatedRestartDelay
-					}
-					if restartDelay > 0 {
-						_ = batch.Update(func(tx store.Tx) error {
-							t := store.GetTask(tx, t.ID)
-							// TODO(aluzzardi): This is shady as well. We should have a more generic condition.
-							if t == nil || t.DesiredState != api.TaskStateReady {
-								return nil
-							}
-							r.restarts.DelayStart(ctx, tx, nil, t.ID, restartDelay, true)
-							return nil
-						})
-						continue
-					}
-				} else {
-					log.G(ctx).WithError(err).Error("invalid status timestamp")
-				}
-			}
-
-			// Start now
-			err := batch.Update(func(tx store.Tx) error {
-				return r.restarts.StartNow(tx, t.ID)
-			})
-			if err != nil {
-				log.G(ctx).WithError(err).WithField("task.id", t.ID).Error("moving task out of delayed state failed")
-			}
-		}
-		return nil
-	})
-
-	return err
+	return taskinit.CheckTasks(ctx, r.store, readTx, r, r.restarts)
 }
 }
 
 
 func (r *Orchestrator) handleTaskEvent(ctx context.Context, event events.Event) {
 func (r *Orchestrator) handleTaskEvent(ctx context.Context, event events.Event) {
@@ -196,13 +108,14 @@ func (r *Orchestrator) restartTasksByNodeID(ctx context.Context, nodeID string)
 }
 }
 
 
 func (r *Orchestrator) handleNodeChange(ctx context.Context, n *api.Node) {
 func (r *Orchestrator) handleNodeChange(ctx context.Context, n *api.Node) {
-	if !invalidNode(n) {
+	if !orchestrator.InvalidNode(n) {
 		return
 		return
 	}
 	}
 
 
 	r.restartTasksByNodeID(ctx, n.ID)
 	r.restartTasksByNodeID(ctx, n.ID)
 }
 }
 
 
+// handleTaskChange defines what orchestrator does when a task is updated by agent.
 func (r *Orchestrator) 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
 	// If we already set the desired state past TaskStateRunning, there is no
 	// further action necessary.
 	// further action necessary.
@@ -228,7 +141,41 @@ func (r *Orchestrator) handleTaskChange(ctx context.Context, t *api.Task) {
 	}
 	}
 
 
 	if t.Status.State > api.TaskStateRunning ||
 	if t.Status.State > api.TaskStateRunning ||
-		(t.NodeID != "" && invalidNode(n)) {
+		(t.NodeID != "" && orchestrator.InvalidNode(n)) {
 		r.restartTasks[t.ID] = struct{}{}
 		r.restartTasks[t.ID] = struct{}{}
 	}
 	}
 }
 }
+
+// FixTask validates a task with the current cluster settings, and takes
+// action to make it conformant. it's called at orchestrator initialization.
+func (r *Orchestrator) FixTask(ctx context.Context, batch *store.Batch, t *api.Task) {
+	// If we already set the desired state past TaskStateRunning, there is no
+	// further action necessary.
+	if t.DesiredState > api.TaskStateRunning {
+		return
+	}
+
+	var (
+		n       *api.Node
+		service *api.Service
+	)
+	batch.Update(func(tx store.Tx) error {
+		if t.NodeID != "" {
+			n = store.GetNode(tx, t.NodeID)
+		}
+		if t.ServiceID != "" {
+			service = store.GetService(tx, t.ServiceID)
+		}
+		return nil
+	})
+
+	if !orchestrator.IsReplicatedService(service) {
+		return
+	}
+
+	if t.Status.State > api.TaskStateRunning ||
+		(t.NodeID != "" && orchestrator.InvalidNode(n)) {
+		r.restartTasks[t.ID] = struct{}{}
+		return
+	}
+}

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

@@ -65,3 +65,10 @@ func IsTaskDirty(s *api.Service, t *api.Task) bool {
 	return !reflect.DeepEqual(s.Spec.Task, t.Spec) ||
 	return !reflect.DeepEqual(s.Spec.Task, t.Spec) ||
 		(t.Endpoint != nil && !reflect.DeepEqual(s.Spec.Endpoint, t.Endpoint.Spec))
 		(t.Endpoint != nil && !reflect.DeepEqual(s.Spec.Endpoint, t.Endpoint.Spec))
 }
 }
+
+// InvalidNode is true if the node is nil, down, or drained
+func InvalidNode(n *api.Node) bool {
+	return n == nil ||
+		n.Status.State == api.NodeStatus_DOWN ||
+		n.Spec.Availability == api.NodeAvailabilityDrain
+}

+ 103 - 0
vendor/github.com/docker/swarmkit/manager/orchestrator/taskinit/init.go

@@ -0,0 +1,103 @@
+package taskinit
+
+import (
+	"time"
+
+	"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/store"
+	gogotypes "github.com/gogo/protobuf/types"
+	"golang.org/x/net/context"
+)
+
+// InitHandler defines orchestrator's action to fix tasks at start.
+type InitHandler interface {
+	IsRelatedService(service *api.Service) bool
+	FixTask(ctx context.Context, batch *store.Batch, t *api.Task)
+}
+
+// CheckTasks fixes tasks in the store before orchestrator runs. The previous leader might
+// not have finished processing their updates and left them in an inconsistent state.
+func CheckTasks(ctx context.Context, s *store.MemoryStore, readTx store.ReadTx, initHandler InitHandler, startSupervisor *restart.Supervisor) error {
+	_, err := s.Batch(func(batch *store.Batch) error {
+		tasks, err := store.FindTasks(readTx, store.All)
+		if err != nil {
+			return err
+		}
+		for _, t := range tasks {
+			if t.ServiceID == "" {
+				continue
+			}
+
+			// TODO(aluzzardi): We should NOT retrieve the service here.
+			service := store.GetService(readTx, t.ServiceID)
+			if service == nil {
+				// Service was deleted
+				err := batch.Update(func(tx store.Tx) error {
+					return store.DeleteTask(tx, t.ID)
+				})
+				if err != nil {
+					log.G(ctx).WithError(err).Error("failed to delete task")
+				}
+				continue
+			}
+			if !initHandler.IsRelatedService(service) {
+				continue
+			}
+
+			// handle task updates from agent which should have been triggered by task update events
+			initHandler.FixTask(ctx, batch, t)
+
+			// desired state ready is a transient state that it should be started.
+			// however previous leader may not have started it, retry start here
+			if t.DesiredState != api.TaskStateReady || t.Status.State > api.TaskStateRunning {
+				continue
+			}
+			restartDelay := orchestrator.DefaultRestartDelay
+			if t.Spec.Restart != nil && t.Spec.Restart.Delay != nil {
+				var err error
+				restartDelay, err = gogotypes.DurationFromProto(t.Spec.Restart.Delay)
+				if err != nil {
+					log.G(ctx).WithError(err).Error("invalid restart delay")
+					restartDelay = orchestrator.DefaultRestartDelay
+				}
+			}
+			if restartDelay != 0 {
+				timestamp, err := gogotypes.TimestampFromProto(t.Status.Timestamp)
+				if err == nil {
+					restartTime := timestamp.Add(restartDelay)
+					calculatedRestartDelay := restartTime.Sub(time.Now())
+					if calculatedRestartDelay < restartDelay {
+						restartDelay = calculatedRestartDelay
+					}
+					if restartDelay > 0 {
+						_ = batch.Update(func(tx store.Tx) error {
+							t := store.GetTask(tx, t.ID)
+							// TODO(aluzzardi): This is shady as well. We should have a more generic condition.
+							if t == nil || t.DesiredState != api.TaskStateReady {
+								return nil
+							}
+							startSupervisor.DelayStart(ctx, tx, nil, t.ID, restartDelay, true)
+							return nil
+						})
+						continue
+					}
+				} else {
+					log.G(ctx).WithError(err).Error("invalid status timestamp")
+				}
+			}
+
+			// Start now
+			err := batch.Update(func(tx store.Tx) error {
+				return startSupervisor.StartNow(tx, t.ID)
+			})
+			if err != nil {
+				log.G(ctx).WithError(err).WithField("task.id", t.ID).Error("moving task out of delayed state failed")
+			}
+		}
+		return nil
+	})
+	return err
+}

+ 12 - 5
vendor/github.com/docker/swarmkit/manager/orchestrator/taskreaper/task_reaper.go

@@ -131,11 +131,13 @@ func (tr *TaskReaper) tick() {
 	}
 	}
 
 
 	defer func() {
 	defer func() {
-		tr.dirty = make(map[instanceTuple]struct{})
 		tr.orphaned = nil
 		tr.orphaned = nil
 	}()
 	}()
 
 
-	deleteTasks := tr.orphaned
+	deleteTasks := make(map[string]struct{})
+	for _, tID := range tr.orphaned {
+		deleteTasks[tID] = struct{}{}
+	}
 	tr.store.View(func(tx store.ReadTx) {
 	tr.store.View(func(tx store.ReadTx) {
 		for dirty := range tr.dirty {
 		for dirty := range tr.dirty {
 			service := store.GetService(tx, dirty.serviceID)
 			service := store.GetService(tx, dirty.serviceID)
@@ -180,13 +182,15 @@ func (tr *TaskReaper) tick() {
 			// instead of sorting the whole slice.
 			// instead of sorting the whole slice.
 			sort.Sort(tasksByTimestamp(historicTasks))
 			sort.Sort(tasksByTimestamp(historicTasks))
 
 
+			runningTasks := 0
 			for _, t := range historicTasks {
 			for _, t := range historicTasks {
-				if t.DesiredState <= api.TaskStateRunning {
+				if t.DesiredState <= api.TaskStateRunning || t.Status.State <= api.TaskStateRunning {
 					// Don't delete running tasks
 					// Don't delete running tasks
+					runningTasks++
 					continue
 					continue
 				}
 				}
 
 
-				deleteTasks = append(deleteTasks, t.ID)
+				deleteTasks[t.ID] = struct{}{}
 
 
 				taskHistory++
 				taskHistory++
 				if int64(len(historicTasks)) <= taskHistory {
 				if int64(len(historicTasks)) <= taskHistory {
@@ -194,12 +198,15 @@ func (tr *TaskReaper) tick() {
 				}
 				}
 			}
 			}
 
 
+			if runningTasks <= 1 {
+				delete(tr.dirty, dirty)
+			}
 		}
 		}
 	})
 	})
 
 
 	if len(deleteTasks) > 0 {
 	if len(deleteTasks) > 0 {
 		tr.store.Batch(func(batch *store.Batch) error {
 		tr.store.Batch(func(batch *store.Batch) error {
-			for _, taskID := range deleteTasks {
+			for taskID := range deleteTasks {
 				batch.Update(func(tx store.Tx) error {
 				batch.Update(func(tx store.Tx) error {
 					return store.DeleteTask(tx, taskID)
 					return store.DeleteTask(tx, taskID)
 				})
 				})

+ 30 - 23
vendor/github.com/docker/swarmkit/manager/orchestrator/update/updater.go

@@ -156,10 +156,34 @@ func (u *Updater) Run(ctx context.Context, slots []orchestrator.Slot) {
 		u.startUpdate(ctx, service.ID)
 		u.startUpdate(ctx, service.ID)
 	}
 	}
 
 
-	parallelism := 0
-	if service.Spec.Update != nil {
-		parallelism = int(service.Spec.Update.Parallelism)
+	var (
+		parallelism            int
+		delay                  time.Duration
+		failureAction          = api.UpdateConfig_PAUSE
+		allowedFailureFraction = float32(0)
+		monitoringPeriod       = defaultMonitor
+	)
+
+	updateConfig := service.Spec.Update
+	if service.UpdateStatus != nil && service.UpdateStatus.State == api.UpdateStatus_ROLLBACK_STARTED {
+		updateConfig = service.Spec.Rollback
+	}
+
+	if updateConfig != nil {
+		failureAction = updateConfig.FailureAction
+		allowedFailureFraction = updateConfig.MaxFailureRatio
+		parallelism = int(updateConfig.Parallelism)
+		delay = updateConfig.Delay
+
+		var err error
+		if updateConfig.Monitor != nil {
+			monitoringPeriod, err = gogotypes.DurationFromProto(updateConfig.Monitor)
+			if err != nil {
+				monitoringPeriod = defaultMonitor
+			}
+		}
 	}
 	}
+
 	if parallelism == 0 {
 	if parallelism == 0 {
 		// TODO(aluzzardi): We could try to optimize unlimited parallelism by performing updates in a single
 		// TODO(aluzzardi): We could try to optimize unlimited parallelism by performing updates in a single
 		// goroutine using a batch transaction.
 		// goroutine using a batch transaction.
@@ -172,28 +196,11 @@ func (u *Updater) Run(ctx context.Context, slots []orchestrator.Slot) {
 	wg.Add(parallelism)
 	wg.Add(parallelism)
 	for i := 0; i < parallelism; i++ {
 	for i := 0; i < parallelism; i++ {
 		go func() {
 		go func() {
-			u.worker(ctx, slotQueue)
+			u.worker(ctx, slotQueue, delay)
 			wg.Done()
 			wg.Done()
 		}()
 		}()
 	}
 	}
 
 
-	failureAction := api.UpdateConfig_PAUSE
-	allowedFailureFraction := float32(0)
-	monitoringPeriod := defaultMonitor
-
-	if service.Spec.Update != nil {
-		failureAction = service.Spec.Update.FailureAction
-		allowedFailureFraction = service.Spec.Update.MaxFailureRatio
-
-		if service.Spec.Update.Monitor != nil {
-			var err error
-			monitoringPeriod, err = gogotypes.DurationFromProto(service.Spec.Update.Monitor)
-			if err != nil {
-				monitoringPeriod = defaultMonitor
-			}
-		}
-	}
-
 	var failedTaskWatch chan events.Event
 	var failedTaskWatch chan events.Event
 
 
 	if failureAction != api.UpdateConfig_CONTINUE {
 	if failureAction != api.UpdateConfig_CONTINUE {
@@ -303,7 +310,7 @@ slotsLoop:
 	}
 	}
 }
 }
 
 
-func (u *Updater) worker(ctx context.Context, queue <-chan orchestrator.Slot) {
+func (u *Updater) worker(ctx context.Context, queue <-chan orchestrator.Slot, delay time.Duration) {
 	for slot := range queue {
 	for slot := range queue {
 		// Do we have a task with the new spec in desired state = RUNNING?
 		// 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
 		// If so, all we have to do to complete the update is remove the
@@ -345,7 +352,7 @@ func (u *Updater) worker(ctx context.Context, queue <-chan orchestrator.Slot) {
 			}
 			}
 		}
 		}
 
 
-		if u.newService.Spec.Update != nil && u.newService.Spec.Update.Delay != 0 {
+		if delay != 0 {
 			select {
 			select {
 			case <-time.After(u.newService.Spec.Update.Delay):
 			case <-time.After(u.newService.Spec.Update.Delay):
 			case <-u.stopChan:
 			case <-u.stopChan:

+ 1 - 1
vendor/github.com/docker/swarmkit/manager/state/doc.go

@@ -12,7 +12,7 @@
 //
 //
 //	err := store.Update(func(tx state.Tx) {
 //	err := store.Update(func(tx state.Tx) {
 //		if err := tx.Nodes().Update(newNode); err != nil {
 //		if err := tx.Nodes().Update(newNode); err != nil {
-//			reutrn err
+//			return err
 //		}
 //		}
 //		return nil
 //		return nil
 //	})
 //	})

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

@@ -100,7 +100,7 @@ func (o originalSnap) New(dirpath string) Snapshotter {
 	return snap.New(dirpath)
 	return snap.New(dirpath)
 }
 }
 
 
-// OriginalSnap is the original `snap` package as an implemntation of the SnapFactory interface
+// OriginalSnap is the original `snap` package as an implementation of the SnapFactory interface
 var OriginalSnap SnapFactory = originalSnap{}
 var OriginalSnap SnapFactory = originalSnap{}
 
 
 // MigrateSnapshot reads the latest existing snapshot from one directory, encoded one way, and writes
 // MigrateSnapshot reads the latest existing snapshot from one directory, encoded one way, and writes

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

@@ -136,7 +136,7 @@ func (o originalWAL) Open(dirpath string, walsnap walpb.Snapshot) (WAL, error) {
 	return wal.Open(dirpath, walsnap)
 	return wal.Open(dirpath, walsnap)
 }
 }
 
 
-// OriginalWAL is the original `wal` package as an implemntation of the WALFactory interface
+// OriginalWAL is the original `wal` package as an implementation of the WALFactory interface
 var OriginalWAL WALFactory = originalWAL{}
 var OriginalWAL WALFactory = originalWAL{}
 
 
 // WALData contains all the data returned by a WAL's ReadAll() function
 // WALData contains all the data returned by a WAL's ReadAll() function