package orchestrator import ( "reflect" "time" "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/api/defaults" "github.com/docker/swarmkit/identity" "github.com/docker/swarmkit/protobuf/ptypes" ) // NewTask creates a new task. func NewTask(cluster *api.Cluster, service *api.Service, slot uint64, nodeID string) *api.Task { var logDriver *api.Driver if service.Spec.Task.LogDriver != nil { // use the log driver specific to the task, if we have it. logDriver = service.Spec.Task.LogDriver } else if cluster != nil { // pick up the cluster default, if available. logDriver = cluster.Spec.TaskDefaults.LogDriver // nil is okay here. } taskID := identity.NewID() task := api.Task{ ID: taskID, ServiceAnnotations: service.Spec.Annotations, Spec: service.Spec.Task, SpecVersion: service.SpecVersion, ServiceID: service.ID, Slot: slot, Status: api.TaskStatus{ State: api.TaskStateNew, Timestamp: ptypes.MustTimestampProto(time.Now()), Message: "created", }, Endpoint: &api.Endpoint{ Spec: service.Spec.Endpoint.Copy(), }, DesiredState: api.TaskStateRunning, LogDriver: logDriver, } // In global mode we also set the NodeID if nodeID != "" { task.NodeID = nodeID } return &task } // RestartCondition returns the restart condition to apply to this task. func RestartCondition(task *api.Task) api.RestartPolicy_RestartCondition { restartCondition := defaults.Service.Task.Restart.Condition if task.Spec.Restart != nil { restartCondition = task.Spec.Restart.Condition } return restartCondition } // IsTaskDirty determines whether a task matches the given service's spec. func IsTaskDirty(s *api.Service, t *api.Task) bool { // If the spec version matches, we know the task is not dirty. However, // if it does not match, that doesn't mean the task is dirty, since // only a portion of the spec is included in the comparison. if t.SpecVersion != nil && *s.SpecVersion == *t.SpecVersion { return false } return !reflect.DeepEqual(s.Spec.Task, t.Spec) || (t.Endpoint != nil && !reflect.DeepEqual(s.Spec.Endpoint, t.Endpoint.Spec)) } // InvalidNode is true if the node is nil, down, or drained func InvalidNode(n *api.Node) bool { return n == nil || n.Status.State == api.NodeStatus_DOWN || n.Spec.Availability == api.NodeAvailabilityDrain }