task.go 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. package orchestrator
  2. import (
  3. "reflect"
  4. "time"
  5. "github.com/docker/swarmkit/api"
  6. "github.com/docker/swarmkit/identity"
  7. "github.com/docker/swarmkit/protobuf/ptypes"
  8. )
  9. // DefaultRestartDelay is the restart delay value to use when none is
  10. // specified.
  11. const DefaultRestartDelay = 5 * time.Second
  12. // NewTask creates a new task.
  13. func NewTask(cluster *api.Cluster, service *api.Service, slot uint64, nodeID string) *api.Task {
  14. var logDriver *api.Driver
  15. if service.Spec.Task.LogDriver != nil {
  16. // use the log driver specific to the task, if we have it.
  17. logDriver = service.Spec.Task.LogDriver
  18. } else if cluster != nil {
  19. // pick up the cluster default, if available.
  20. logDriver = cluster.Spec.TaskDefaults.LogDriver // nil is okay here.
  21. }
  22. taskID := identity.NewID()
  23. task := api.Task{
  24. ID: taskID,
  25. ServiceAnnotations: service.Spec.Annotations,
  26. Spec: service.Spec.Task,
  27. SpecVersion: service.SpecVersion,
  28. ServiceID: service.ID,
  29. Slot: slot,
  30. Status: api.TaskStatus{
  31. State: api.TaskStateNew,
  32. Timestamp: ptypes.MustTimestampProto(time.Now()),
  33. Message: "created",
  34. },
  35. Endpoint: &api.Endpoint{
  36. Spec: service.Spec.Endpoint.Copy(),
  37. },
  38. DesiredState: api.TaskStateRunning,
  39. LogDriver: logDriver,
  40. }
  41. // In global mode we also set the NodeID
  42. if nodeID != "" {
  43. task.NodeID = nodeID
  44. }
  45. return &task
  46. }
  47. // RestartCondition returns the restart condition to apply to this task.
  48. func RestartCondition(task *api.Task) api.RestartPolicy_RestartCondition {
  49. restartCondition := api.RestartOnAny
  50. if task.Spec.Restart != nil {
  51. restartCondition = task.Spec.Restart.Condition
  52. }
  53. return restartCondition
  54. }
  55. // IsTaskDirty determines whether a task matches the given service's spec.
  56. func IsTaskDirty(s *api.Service, t *api.Task) bool {
  57. // If the spec version matches, we know the task is not dirty. However,
  58. // if it does not match, that doesn't mean the task is dirty, since
  59. // only a portion of the spec is included in the comparison.
  60. if t.SpecVersion != nil && *s.SpecVersion == *t.SpecVersion {
  61. return false
  62. }
  63. return !reflect.DeepEqual(s.Spec.Task, t.Spec) ||
  64. (t.Endpoint != nil && !reflect.DeepEqual(s.Spec.Endpoint, t.Endpoint.Spec))
  65. }
  66. // InvalidNode is true if the node is nil, down, or drained
  67. func InvalidNode(n *api.Node) bool {
  68. return n == nil ||
  69. n.Status.State == api.NodeStatus_DOWN ||
  70. n.Spec.Availability == api.NodeAvailabilityDrain
  71. }