task.go 2.3 KB

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