func createTaskInfo(task eremetic.Task, offer *mesosproto.Offer) (eremetic.Task, *mesosproto.TaskInfo) { task.FrameworkID = *offer.FrameworkId.Value task.SlaveID = *offer.SlaveId.Value task.Hostname = *offer.Hostname task.AgentIP = offer.GetUrl().GetAddress().GetIp() task.AgentPort = offer.GetUrl().GetAddress().GetPort() portMapping, portResources := buildPorts(task, offer) env := buildEnvironment(task, portMapping) taskInfo := &mesosproto.TaskInfo{ TaskId: &mesosproto.TaskID{Value: proto.String(task.ID)}, SlaveId: offer.SlaveId, Name: proto.String(task.Name), Command: buildCommandInfo(task, env), Container: &mesosproto.ContainerInfo{ Type: mesosproto.ContainerInfo_DOCKER.Enum(), Docker: &mesosproto.ContainerInfo_DockerInfo{ Image: proto.String(task.Image), ForcePullImage: proto.Bool(task.ForcePullImage), PortMappings: portMapping, Network: mesosproto.ContainerInfo_DockerInfo_BRIDGE.Enum(), }, Volumes: buildVolumes(task), }, Resources: []*mesosproto.Resource{ mesosutil.NewScalarResource("cpus", task.TaskCPUs), mesosutil.NewScalarResource("mem", task.TaskMem), mesosutil.NewRangesResource("ports", portResources), }, } return task, taskInfo }
func makeMap(task eremetic.Task) map[string]interface{} { data := make(map[string]interface{}) data["TaskID"] = task.ID data["CommandEnv"] = task.Environment data["CommandUser"] = task.User data["Command"] = task.Command // TODO: Support more than docker? data["ContainerImage"] = task.Image data["FrameworkID"] = task.FrameworkID data["Hostname"] = task.Hostname data["Name"] = task.Name data["SlaveID"] = task.SlaveID data["SlaveConstraints"] = task.SlaveConstraints data["Status"] = task.Status data["CPU"] = fmt.Sprintf("%.2f", task.TaskCPUs) data["Memory"] = fmt.Sprintf("%.2f", task.TaskMem) data["Terminated"] = task.IsTerminated() return data }
// ListNonTerminalTasks returns a list of tasks that are not yet finished in one // way or another. func (db *TaskDB) ListNonTerminalTasks() ([]*eremetic.Task, error) { tasks := []*eremetic.Task{} err := db.conn.View(func(tx *bolt.Tx) error { b := tx.Bucket([]byte("tasks")) if b == nil { return bolt.ErrBucketNotFound } b.ForEach(func(_, v []byte) error { var task eremetic.Task json.Unmarshal(v, &task) if !task.IsTerminated() { eremetic.ApplyMask(&task) tasks = append(tasks, &task) } return nil }) return nil }) return tasks, err }
func TestTask(t *testing.T) { status := []eremetic.Status{ eremetic.Status{ Status: eremetic.TaskRunning, Time: time.Now().Unix(), }, } Convey("createTaskInfo", t, func() { eremeticTask := eremetic.Task{ TaskCPUs: 0.2, TaskMem: 0.5, Command: "echo hello", Image: "busybox", Status: status, ID: "eremetic-task.1234", Name: "Eremetic task 17", } portres := "ports" offer := mesosproto.Offer{ FrameworkId: &mesosproto.FrameworkID{ Value: proto.String("framework-id"), }, SlaveId: &mesosproto.SlaveID{ Value: proto.String("slave-id"), }, Hostname: proto.String("hostname"), Resources: []*mesosproto.Resource{&mesosproto.Resource{ Name: &portres, Type: mesosproto.Value_RANGES.Enum(), Ranges: &mesosproto.Value_Ranges{ Range: []*mesosproto.Value_Range{ mesosutil.NewValueRange(31000, 31010), }, }, }}, } Convey("No volume or environment specified", func() { net, taskInfo := createTaskInfo(eremeticTask, &offer) So(taskInfo.TaskId.GetValue(), ShouldEqual, eremeticTask.ID) So(taskInfo.GetName(), ShouldEqual, eremeticTask.Name) So(taskInfo.GetResources()[0].GetScalar().GetValue(), ShouldEqual, eremeticTask.TaskCPUs) So(taskInfo.GetResources()[1].GetScalar().GetValue(), ShouldEqual, eremeticTask.TaskMem) So(taskInfo.Container.GetType().String(), ShouldEqual, "DOCKER") So(taskInfo.Container.Docker.GetImage(), ShouldEqual, "busybox") So(net.SlaveID, ShouldEqual, "slave-id") So(taskInfo.Container.Docker.GetForcePullImage(), ShouldBeFalse) }) Convey("Given no Command", func() { eremeticTask.Command = "" _, taskInfo := createTaskInfo(eremeticTask, &offer) So(taskInfo.Command.GetValue(), ShouldBeEmpty) So(taskInfo.Command.GetShell(), ShouldBeFalse) }) Convey("Given a volume and environment", func() { volumes := []eremetic.Volume{{ ContainerPath: "/var/www", HostPath: "/var/www", }} environment := make(map[string]string) environment["foo"] = "bar" eremeticTask.Environment = environment eremeticTask.Volumes = volumes _, taskInfo := createTaskInfo(eremeticTask, &offer) So(taskInfo.TaskId.GetValue(), ShouldEqual, eremeticTask.ID) So(taskInfo.Container.Volumes[0].GetContainerPath(), ShouldEqual, volumes[0].ContainerPath) So(taskInfo.Container.Volumes[0].GetHostPath(), ShouldEqual, volumes[0].HostPath) So(taskInfo.Command.Environment.Variables[0].GetName(), ShouldEqual, "foo") So(taskInfo.Command.Environment.Variables[0].GetValue(), ShouldEqual, "bar") So(taskInfo.Command.Environment.Variables[1].GetName(), ShouldEqual, "MESOS_TASK_ID") So(taskInfo.Command.Environment.Variables[1].GetValue(), ShouldEqual, eremeticTask.ID) }) Convey("Given a port", func() { var ports []eremetic.Port ports = append(ports, eremetic.Port{ ContainerPort: 80, Protocol: "tcp", }, ) eremeticTask.Ports = ports _, taskInfo := createTaskInfo(eremeticTask, &offer) So(len(taskInfo.Container.Docker.PortMappings), ShouldEqual, 1) So(taskInfo.Container.Docker.GetPortMappings()[0].GetContainerPort(), ShouldEqual, ports[0].ContainerPort) So(taskInfo.GetResources()[2].GetName(), ShouldEqual, "ports") expectedRange := mesosutil.NewValueRange(31000, 31001) So(taskInfo.GetResources()[2].GetRanges().GetRange()[0].GetBegin(), ShouldEqual, expectedRange.GetBegin()) So(taskInfo.GetResources()[2].GetRanges().GetRange()[0].GetEnd(), ShouldEqual, expectedRange.GetEnd()) vars := taskInfo.GetCommand().GetEnvironment().GetVariables() var foundPortVar, foundPort0Var bool for _, v := range vars { switch v.GetName() { case "PORT": So(v.GetValue(), ShouldEqual, "31000") foundPortVar = true case "PORT0": So(v.GetValue(), ShouldEqual, "31000") foundPort0Var = true } } So(foundPortVar, ShouldBeTrue) So(foundPort0Var, ShouldBeTrue) }) Convey("Given unspecified port", func() { var ports []eremetic.Port ports = append(ports, eremetic.Port{ ContainerPort: 0, Protocol: "tcp", }, ) eremeticTask.Ports = ports _, taskInfo := createTaskInfo(eremeticTask, &offer) So(len(taskInfo.Container.Docker.PortMappings), ShouldEqual, 1) So(taskInfo.Container.Docker.GetPortMappings()[0].GetContainerPort(), ShouldEqual, 31000) So(taskInfo.GetResources()[2].GetName(), ShouldEqual, "ports") expected_range := mesosutil.NewValueRange(31000, 31001) So(taskInfo.GetResources()[2].GetRanges().GetRange()[0].GetBegin(), ShouldEqual, expected_range.GetBegin()) So(taskInfo.GetResources()[2].GetRanges().GetRange()[0].GetEnd(), ShouldEqual, expected_range.GetEnd()) vars := taskInfo.GetCommand().GetEnvironment().GetVariables() var foundPortVar, foundPort0Var bool for _, v := range vars { switch v.GetName() { case "PORT": So(v.GetValue(), ShouldEqual, "31000") foundPortVar = true case "PORT0": So(v.GetValue(), ShouldEqual, "31000") foundPort0Var = true } } So(foundPortVar, ShouldBeTrue) So(foundPort0Var, ShouldBeTrue) }) Convey("Given archive to fetch", func() { URI := []eremetic.URI{{ URI: "http://foobar.local/cats.zip", Extract: true, }} eremeticTask.FetchURIs = URI _, taskInfo := createTaskInfo(eremeticTask, &offer) So(taskInfo.TaskId.GetValue(), ShouldEqual, eremeticTask.ID) So(taskInfo.Command.Uris, ShouldHaveLength, 1) So(taskInfo.Command.Uris[0].GetValue(), ShouldEqual, eremeticTask.FetchURIs[0].URI) So(taskInfo.Command.Uris[0].GetExecutable(), ShouldBeFalse) So(taskInfo.Command.Uris[0].GetExtract(), ShouldBeTrue) So(taskInfo.Command.Uris[0].GetCache(), ShouldBeFalse) }) Convey("Given archive to fetch and cache", func() { URI := []eremetic.URI{{ URI: "http://foobar.local/cats.zip", Extract: true, Cache: true, }} eremeticTask.FetchURIs = URI _, taskInfo := createTaskInfo(eremeticTask, &offer) So(taskInfo.TaskId.GetValue(), ShouldEqual, eremeticTask.ID) So(taskInfo.Command.Uris, ShouldHaveLength, 1) So(taskInfo.Command.Uris[0].GetValue(), ShouldEqual, eremeticTask.FetchURIs[0].URI) So(taskInfo.Command.Uris[0].GetExecutable(), ShouldBeFalse) So(taskInfo.Command.Uris[0].GetExtract(), ShouldBeTrue) So(taskInfo.Command.Uris[0].GetCache(), ShouldBeTrue) }) Convey("Given image to fetch", func() { URI := []eremetic.URI{{ URI: "http://foobar.local/cats.jpeg", }} eremeticTask.FetchURIs = URI _, taskInfo := createTaskInfo(eremeticTask, &offer) So(taskInfo.TaskId.GetValue(), ShouldEqual, eremeticTask.ID) So(taskInfo.Command.Uris, ShouldHaveLength, 1) So(taskInfo.Command.Uris[0].GetValue(), ShouldEqual, eremeticTask.FetchURIs[0].URI) So(taskInfo.Command.Uris[0].GetExecutable(), ShouldBeFalse) So(taskInfo.Command.Uris[0].GetExtract(), ShouldBeFalse) So(taskInfo.Command.Uris[0].GetCache(), ShouldBeFalse) }) Convey("Given script to fetch", func() { URI := []eremetic.URI{{ URI: "http://foobar.local/cats.sh", Executable: true, }} eremeticTask.FetchURIs = URI _, taskInfo := createTaskInfo(eremeticTask, &offer) So(taskInfo.TaskId.GetValue(), ShouldEqual, eremeticTask.ID) So(taskInfo.Command.Uris, ShouldHaveLength, 1) So(taskInfo.Command.Uris[0].GetValue(), ShouldEqual, eremeticTask.FetchURIs[0].URI) So(taskInfo.Command.Uris[0].GetExecutable(), ShouldBeTrue) So(taskInfo.Command.Uris[0].GetExtract(), ShouldBeFalse) So(taskInfo.Command.Uris[0].GetCache(), ShouldBeFalse) }) Convey("Force pull of docker image", func() { eremeticTask.ForcePullImage = true _, taskInfo := createTaskInfo(eremeticTask, &offer) So(taskInfo.TaskId.GetValue(), ShouldEqual, eremeticTask.ID) So(taskInfo.Container.Docker.GetForcePullImage(), ShouldBeTrue) }) }) }