task.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. package controlapi
  2. import (
  3. "github.com/docker/swarmkit/api"
  4. "github.com/docker/swarmkit/api/naming"
  5. "github.com/docker/swarmkit/manager/orchestrator"
  6. "github.com/docker/swarmkit/manager/state/store"
  7. "golang.org/x/net/context"
  8. "google.golang.org/grpc"
  9. "google.golang.org/grpc/codes"
  10. )
  11. // GetTask returns a Task given a TaskID.
  12. // - Returns `InvalidArgument` if TaskID is not provided.
  13. // - Returns `NotFound` if the Task is not found.
  14. func (s *Server) GetTask(ctx context.Context, request *api.GetTaskRequest) (*api.GetTaskResponse, error) {
  15. if request.TaskID == "" {
  16. return nil, grpc.Errorf(codes.InvalidArgument, errInvalidArgument.Error())
  17. }
  18. var task *api.Task
  19. s.store.View(func(tx store.ReadTx) {
  20. task = store.GetTask(tx, request.TaskID)
  21. })
  22. if task == nil {
  23. return nil, grpc.Errorf(codes.NotFound, "task %s not found", request.TaskID)
  24. }
  25. return &api.GetTaskResponse{
  26. Task: task,
  27. }, nil
  28. }
  29. // RemoveTask removes a Task referenced by TaskID.
  30. // - Returns `InvalidArgument` if TaskID is not provided.
  31. // - Returns `NotFound` if the Task is not found.
  32. // - Returns an error if the deletion fails.
  33. func (s *Server) RemoveTask(ctx context.Context, request *api.RemoveTaskRequest) (*api.RemoveTaskResponse, error) {
  34. if request.TaskID == "" {
  35. return nil, grpc.Errorf(codes.InvalidArgument, errInvalidArgument.Error())
  36. }
  37. err := s.store.Update(func(tx store.Tx) error {
  38. return store.DeleteTask(tx, request.TaskID)
  39. })
  40. if err != nil {
  41. if err == store.ErrNotExist {
  42. return nil, grpc.Errorf(codes.NotFound, "task %s not found", request.TaskID)
  43. }
  44. return nil, err
  45. }
  46. return &api.RemoveTaskResponse{}, nil
  47. }
  48. func filterTasks(candidates []*api.Task, filters ...func(*api.Task) bool) []*api.Task {
  49. result := []*api.Task{}
  50. for _, c := range candidates {
  51. match := true
  52. for _, f := range filters {
  53. if !f(c) {
  54. match = false
  55. break
  56. }
  57. }
  58. if match {
  59. result = append(result, c)
  60. }
  61. }
  62. return result
  63. }
  64. // ListTasks returns a list of all tasks.
  65. func (s *Server) ListTasks(ctx context.Context, request *api.ListTasksRequest) (*api.ListTasksResponse, error) {
  66. var (
  67. tasks []*api.Task
  68. err error
  69. )
  70. s.store.View(func(tx store.ReadTx) {
  71. switch {
  72. case request.Filters != nil && len(request.Filters.Names) > 0:
  73. tasks, err = store.FindTasks(tx, buildFilters(store.ByName, request.Filters.Names))
  74. case request.Filters != nil && len(request.Filters.NamePrefixes) > 0:
  75. tasks, err = store.FindTasks(tx, buildFilters(store.ByNamePrefix, request.Filters.NamePrefixes))
  76. case request.Filters != nil && len(request.Filters.IDPrefixes) > 0:
  77. tasks, err = store.FindTasks(tx, buildFilters(store.ByIDPrefix, request.Filters.IDPrefixes))
  78. case request.Filters != nil && len(request.Filters.ServiceIDs) > 0:
  79. tasks, err = store.FindTasks(tx, buildFilters(store.ByServiceID, request.Filters.ServiceIDs))
  80. case request.Filters != nil && len(request.Filters.Runtimes) > 0:
  81. tasks, err = store.FindTasks(tx, buildFilters(store.ByRuntime, request.Filters.Runtimes))
  82. case request.Filters != nil && len(request.Filters.NodeIDs) > 0:
  83. tasks, err = store.FindTasks(tx, buildFilters(store.ByNodeID, request.Filters.NodeIDs))
  84. case request.Filters != nil && len(request.Filters.DesiredStates) > 0:
  85. filters := make([]store.By, 0, len(request.Filters.DesiredStates))
  86. for _, v := range request.Filters.DesiredStates {
  87. filters = append(filters, store.ByDesiredState(v))
  88. }
  89. tasks, err = store.FindTasks(tx, store.Or(filters...))
  90. default:
  91. tasks, err = store.FindTasks(tx, store.All)
  92. }
  93. if err != nil || request.Filters == nil {
  94. return
  95. }
  96. tasks = filterTasks(tasks,
  97. func(e *api.Task) bool {
  98. return filterContains(naming.Task(e), request.Filters.Names)
  99. },
  100. func(e *api.Task) bool {
  101. return filterContainsPrefix(naming.Task(e), request.Filters.NamePrefixes)
  102. },
  103. func(e *api.Task) bool {
  104. return filterContainsPrefix(e.ID, request.Filters.IDPrefixes)
  105. },
  106. func(e *api.Task) bool {
  107. return filterMatchLabels(e.ServiceAnnotations.Labels, request.Filters.Labels)
  108. },
  109. func(e *api.Task) bool {
  110. return filterContains(e.ServiceID, request.Filters.ServiceIDs)
  111. },
  112. func(e *api.Task) bool {
  113. return filterContains(e.NodeID, request.Filters.NodeIDs)
  114. },
  115. func(e *api.Task) bool {
  116. if len(request.Filters.Runtimes) == 0 {
  117. return true
  118. }
  119. r, err := naming.Runtime(e.Spec)
  120. if err != nil {
  121. return false
  122. }
  123. return filterContains(r, request.Filters.Runtimes)
  124. },
  125. func(e *api.Task) bool {
  126. if len(request.Filters.DesiredStates) == 0 {
  127. return true
  128. }
  129. for _, c := range request.Filters.DesiredStates {
  130. if c == e.DesiredState {
  131. return true
  132. }
  133. }
  134. return false
  135. },
  136. func(e *api.Task) bool {
  137. if !request.Filters.UpToDate {
  138. return true
  139. }
  140. service := store.GetService(tx, e.ServiceID)
  141. if service == nil {
  142. return false
  143. }
  144. return !orchestrator.IsTaskDirty(service, e)
  145. },
  146. )
  147. })
  148. if err != nil {
  149. return nil, err
  150. }
  151. return &api.ListTasksResponse{
  152. Tasks: tasks,
  153. }, nil
  154. }