func updateTasks(dp api.DemandPayload, tasks *demand.Tasks) (demandChanged bool) { demandChanged = false tasks.Lock() defer tasks.Unlock() for _, taskFromServer := range dp.Demand.Tasks { name := taskFromServer.App if existingTask, err := tasks.GetTask(name); err == nil { if existingTask.Demand != taskFromServer.DemandCount { demandChanged = true } existingTask.Demand = taskFromServer.DemandCount } } return demandChanged }
// CountAllTasks checks how many of each task are running func (c *DockerScheduler) CountAllTasks(running *demand.Tasks) error { // Docker Remote API https://docs.docker.com/reference/api/docker_remote_api_v1.20/ // get /containers/json var err error var containers []docker.APIContainers containers, err = c.client.ListContainers(docker.ListContainersOptions{}) if err != nil { return fmt.Errorf("Failed to list containers: %v", err) } running.Lock() defer running.Unlock() c.Lock() defer c.Unlock() // Reset all the running counts to 0 tasks := running.Tasks for _, t := range tasks { t.Running = 0 for _, cc := range c.taskContainers[t.Name] { cc.updated = false } } var taskName string var present bool for i := range containers { labels := containers[i].Labels taskName, present = labels[labelMap] if present { // Only update tasks that are already in our task map - don't try to manage anything else // log.Debugf("Found a container with labels %v", labels) t, err := running.GetTask(taskName) if err != nil { log.Errorf("Received info about task %s that we're not managing", taskName) } else { newState := statusToState(containers[i].Status) id := containers[i].ID[:12] thisContainer, ok := c.taskContainers[taskName][id] if !ok { log.Infof("We have no previous record of container %s, state %s", id, newState) thisContainer = &dockerContainer{} c.taskContainers[taskName][id] = thisContainer } switch newState { case "running": t.Running++ // We could be moving from starting to running, or it could be a container that's totally new to us if thisContainer.state == "starting" || thisContainer.state == "" { thisContainer.state = newState } case "removing": if thisContainer.state != "removing" { log.Errorf("Container %s is being removed, but we didn't terminate it", id) } case "exited": if thisContainer.state != "stopping" && thisContainer.state != "exited" { log.Errorf("Container %s is being removed, but we didn't terminate it", id) } case "dead": if thisContainer.state != "dead" { log.Errorf("Container %s is dead", id) } thisContainer.state = newState } thisContainer.updated = true } } } for _, task := range tasks { log.Debugf(" %s: internally running %d, requested %d", task.Name, task.Running, task.Requested) for id, cc := range c.taskContainers[task.Name] { log.Debugf(" %s - %s", id, cc.state) if !cc.updated { if cc.state == "removing" || cc.state == "exited" { log.Debugf(" Deleting %s", id) delete(c.taskContainers[task.Name], id) } else if cc.state != "created" && cc.state != "starting" && cc.state != "stopping" { log.Errorf("Bad state for container %s: %s", id, cc.state) } } } } return err }