task.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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.NodeIDs) > 0:
  81. tasks, err = store.FindTasks(tx, buildFilters(store.ByNodeID, request.Filters.NodeIDs))
  82. case request.Filters != nil && len(request.Filters.DesiredStates) > 0:
  83. filters := make([]store.By, 0, len(request.Filters.DesiredStates))
  84. for _, v := range request.Filters.DesiredStates {
  85. filters = append(filters, store.ByDesiredState(v))
  86. }
  87. tasks, err = store.FindTasks(tx, store.Or(filters...))
  88. default:
  89. tasks, err = store.FindTasks(tx, store.All)
  90. }
  91. if err != nil || request.Filters == nil {
  92. return
  93. }
  94. tasks = filterTasks(tasks,
  95. func(e *api.Task) bool {
  96. return filterContains(naming.Task(e), request.Filters.Names)
  97. },
  98. func(e *api.Task) bool {
  99. return filterContainsPrefix(naming.Task(e), request.Filters.NamePrefixes)
  100. },
  101. func(e *api.Task) bool {
  102. return filterContainsPrefix(e.ID, request.Filters.IDPrefixes)
  103. },
  104. func(e *api.Task) bool {
  105. return filterMatchLabels(e.ServiceAnnotations.Labels, request.Filters.Labels)
  106. },
  107. func(e *api.Task) bool {
  108. return filterContains(e.ServiceID, request.Filters.ServiceIDs)
  109. },
  110. func(e *api.Task) bool {
  111. return filterContains(e.NodeID, request.Filters.NodeIDs)
  112. },
  113. func(e *api.Task) bool {
  114. if len(request.Filters.DesiredStates) == 0 {
  115. return true
  116. }
  117. for _, c := range request.Filters.DesiredStates {
  118. if c == e.DesiredState {
  119. return true
  120. }
  121. }
  122. return false
  123. },
  124. func(e *api.Task) bool {
  125. if !request.Filters.UpToDate {
  126. return true
  127. }
  128. service := store.GetService(tx, e.ServiceID)
  129. if service == nil {
  130. return false
  131. }
  132. return !orchestrator.IsTaskDirty(service, e)
  133. },
  134. )
  135. })
  136. if err != nil {
  137. return nil, err
  138. }
  139. return &api.ListTasksResponse{
  140. Tasks: tasks,
  141. }, nil
  142. }