| package controlapi |
| |
| import ( |
| "github.com/docker/swarmkit/api" |
| "github.com/docker/swarmkit/api/naming" |
| "github.com/docker/swarmkit/manager/orchestrator" |
| "github.com/docker/swarmkit/manager/state/store" |
| "golang.org/x/net/context" |
| "google.golang.org/grpc" |
| "google.golang.org/grpc/codes" |
| ) |
| |
| // GetTask returns a Task given a TaskID. |
| // - Returns `InvalidArgument` if TaskID is not provided. |
| // - Returns `NotFound` if the Task is not found. |
| func (s *Server) GetTask(ctx context.Context, request *api.GetTaskRequest) (*api.GetTaskResponse, error) { |
| if request.TaskID == "" { |
| return nil, grpc.Errorf(codes.InvalidArgument, errInvalidArgument.Error()) |
| } |
| |
| var task *api.Task |
| s.store.View(func(tx store.ReadTx) { |
| task = store.GetTask(tx, request.TaskID) |
| }) |
| if task == nil { |
| return nil, grpc.Errorf(codes.NotFound, "task %s not found", request.TaskID) |
| } |
| return &api.GetTaskResponse{ |
| Task: task, |
| }, nil |
| } |
| |
| // RemoveTask removes a Task referenced by TaskID. |
| // - Returns `InvalidArgument` if TaskID is not provided. |
| // - Returns `NotFound` if the Task is not found. |
| // - Returns an error if the deletion fails. |
| func (s *Server) RemoveTask(ctx context.Context, request *api.RemoveTaskRequest) (*api.RemoveTaskResponse, error) { |
| if request.TaskID == "" { |
| return nil, grpc.Errorf(codes.InvalidArgument, errInvalidArgument.Error()) |
| } |
| |
| err := s.store.Update(func(tx store.Tx) error { |
| return store.DeleteTask(tx, request.TaskID) |
| }) |
| if err != nil { |
| if err == store.ErrNotExist { |
| return nil, grpc.Errorf(codes.NotFound, "task %s not found", request.TaskID) |
| } |
| return nil, err |
| } |
| return &api.RemoveTaskResponse{}, nil |
| } |
| |
| func filterTasks(candidates []*api.Task, filters ...func(*api.Task) bool) []*api.Task { |
| result := []*api.Task{} |
| |
| for _, c := range candidates { |
| match := true |
| for _, f := range filters { |
| if !f(c) { |
| match = false |
| break |
| } |
| } |
| if match { |
| result = append(result, c) |
| } |
| } |
| |
| return result |
| } |
| |
| // ListTasks returns a list of all tasks. |
| func (s *Server) ListTasks(ctx context.Context, request *api.ListTasksRequest) (*api.ListTasksResponse, error) { |
| var ( |
| tasks []*api.Task |
| err error |
| ) |
| |
| s.store.View(func(tx store.ReadTx) { |
| switch { |
| case request.Filters != nil && len(request.Filters.Names) > 0: |
| tasks, err = store.FindTasks(tx, buildFilters(store.ByName, request.Filters.Names)) |
| case request.Filters != nil && len(request.Filters.NamePrefixes) > 0: |
| tasks, err = store.FindTasks(tx, buildFilters(store.ByNamePrefix, request.Filters.NamePrefixes)) |
| case request.Filters != nil && len(request.Filters.IDPrefixes) > 0: |
| tasks, err = store.FindTasks(tx, buildFilters(store.ByIDPrefix, request.Filters.IDPrefixes)) |
| case request.Filters != nil && len(request.Filters.ServiceIDs) > 0: |
| tasks, err = store.FindTasks(tx, buildFilters(store.ByServiceID, request.Filters.ServiceIDs)) |
| case request.Filters != nil && len(request.Filters.Runtimes) > 0: |
| tasks, err = store.FindTasks(tx, buildFilters(store.ByRuntime, request.Filters.Runtimes)) |
| case request.Filters != nil && len(request.Filters.NodeIDs) > 0: |
| tasks, err = store.FindTasks(tx, buildFilters(store.ByNodeID, request.Filters.NodeIDs)) |
| case request.Filters != nil && len(request.Filters.DesiredStates) > 0: |
| filters := make([]store.By, 0, len(request.Filters.DesiredStates)) |
| for _, v := range request.Filters.DesiredStates { |
| filters = append(filters, store.ByDesiredState(v)) |
| } |
| tasks, err = store.FindTasks(tx, store.Or(filters...)) |
| default: |
| tasks, err = store.FindTasks(tx, store.All) |
| } |
| |
| if err != nil || request.Filters == nil { |
| return |
| } |
| |
| tasks = filterTasks(tasks, |
| func(e *api.Task) bool { |
| return filterContains(naming.Task(e), request.Filters.Names) |
| }, |
| func(e *api.Task) bool { |
| return filterContainsPrefix(naming.Task(e), request.Filters.NamePrefixes) |
| }, |
| func(e *api.Task) bool { |
| return filterContainsPrefix(e.ID, request.Filters.IDPrefixes) |
| }, |
| func(e *api.Task) bool { |
| return filterMatchLabels(e.ServiceAnnotations.Labels, request.Filters.Labels) |
| }, |
| func(e *api.Task) bool { |
| return filterContains(e.ServiceID, request.Filters.ServiceIDs) |
| }, |
| func(e *api.Task) bool { |
| return filterContains(e.NodeID, request.Filters.NodeIDs) |
| }, |
| func(e *api.Task) bool { |
| if len(request.Filters.Runtimes) == 0 { |
| return true |
| } |
| r, err := naming.Runtime(e.Spec) |
| if err != nil { |
| return false |
| } |
| return filterContains(r, request.Filters.Runtimes) |
| }, |
| func(e *api.Task) bool { |
| if len(request.Filters.DesiredStates) == 0 { |
| return true |
| } |
| for _, c := range request.Filters.DesiredStates { |
| if c == e.DesiredState { |
| return true |
| } |
| } |
| return false |
| }, |
| func(e *api.Task) bool { |
| if !request.Filters.UpToDate { |
| return true |
| } |
| |
| service := store.GetService(tx, e.ServiceID) |
| if service == nil { |
| return false |
| } |
| |
| return !orchestrator.IsTaskDirty(service, e) |
| }, |
| ) |
| }) |
| |
| if err != nil { |
| return nil, err |
| } |
| |
| return &api.ListTasksResponse{ |
| Tasks: tasks, |
| }, nil |
| } |