Show task output, fix event time precision

This commit is contained in:
Matej Kramny 2016-04-17 19:01:51 +01:00
parent cf75b1caf1
commit 4dd8335273
12 changed files with 185 additions and 55 deletions

View File

@ -3,7 +3,7 @@ CREATE TABLE `event` (
`object_id` int(11) DEFAULT NULL,
`object_type` varchar(20) DEFAULT '',
`description` text,
`created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`created` datetime(6) NOT NULL,
KEY `project_id` (`project_id`),
KEY `object_id` (`object_id`),
KEY `created` (`created`)

View File

@ -18,7 +18,7 @@ type Event struct {
}
func (evt Event) Insert() error {
_, err := database.Mysql.Exec("insert into event set project_id=?, object_id=?, object_type=?, description=?, created=NOW()", evt.ProjectID, evt.ObjectID, evt.ObjectType, evt.Description)
_, err := database.Mysql.Exec("insert into event set project_id=?, object_id=?, object_type=?, description=?, created=NOW(6)", evt.ProjectID, evt.ObjectID, evt.ObjectType, evt.Description)
return err
}

View File

@ -21,6 +21,7 @@ type Task struct {
type TaskOutput struct {
TaskID int `db:"task_id" json:"task_id"`
Task string `db:"task" json:"task"`
Time time.Time `db:"time" json:"time"`
Output string `db:"output" json:"output"`
}

View File

@ -11,14 +11,17 @@
.col-sm-5
h4.no-top-margin Task history
ul.list-group
li.list-group-item(ng-repeat="task in tasks"): a(ng-click="openTask()" href="#")
li.list-group-item(ng-repeat="task in tasks"): a(ng-click="openTask(task)" href="#")
i.fa.fa-fw.fa-clock-o.text-warning(ng-if="task.status == 'waiting'")
i.fa.fa-fw.fa-times.text-danger(ng-if="task.status == 'error'")
i.fa.fa-fw.fa-times.text-success(ng-if="task.status == 'success'")
i.fa.fa-fw.fa-check.text-success(ng-if="task.status == 'success'")
i.fa.fa-fw.fa-play.text-warning(ng-if="task.status == 'running'")
|  
span(ng-if="task.playbook.length == 0") {{ task.tpl_playbook }}
span(ng-if="task.playbook.length > 0") {{ task.playbook }}
span.pull-right {{ task.created | date:'short' }}
span.pull-right(ng-if="task.status == 'waiting'") {{ task.created | date:'short' }}
span.pull-right(ng-if="task.status != 'waiting'") {{ task.start | date:'short' }}
br
i Duration
span Duration
span.pull-right {{ task.duration }}

View File

@ -1,7 +1,16 @@
.modal-header
h4.modal-title Task Log
.modal-body
pre: code Hello!
dl.dl-horizontal
dt Status
dd {{ task.status }}
dt Started
dd {{ task.start | date:'short' }}
dt Ended
dd {{ task.end | date:'short' }}
dt Created
dd {{ task.created | date:'short' }}
pre: code {{ output_formatted }}
.modal-footer
button.btn.btn-default.pull-left(ng-click="$dismiss()") Dismiss

View File

@ -24,7 +24,8 @@ define(['controllers/projects/taskRunner'], function () {
$modal.open({
templateUrl: '/tpl/projects/taskModal.html',
controller: 'TaskCtrl',
scope: scope
scope: scope,
size: 'lg'
});
}
}]);

View File

@ -14,5 +14,14 @@ define(function () {
}]);
app.registerController('TaskCtrl', ['$scope', '$http', function ($scope, $http) {
$http.get($scope.project.getURL() + '/tasks/' + $scope.task.id + '/output')
.success(function (output) {
var out = [];
output.forEach(function (o) {
out.push(moment(o.time).format('HH:mm:ss') + ': ' + o.output);
});
$scope.output_formatted = out.join('\n');
});
}]);
});

View File

@ -89,6 +89,7 @@ func Route(r *gin.Engine) {
api.GET("/tasks", tasks.GetAll)
api.POST("/tasks", tasks.AddTask)
api.GET("/tasks/:task_id/output", tasks.GetTaskMiddleware, tasks.GetTaskOutput)
}(api.Group("/project/:project_id"))
}

95
routes/tasks/http.go Normal file
View File

@ -0,0 +1,95 @@
package tasks
import (
"strconv"
"time"
"github.com/ansible-semaphore/semaphore/util"
"github.com/ansible-semaphore/semaphore/database"
"github.com/ansible-semaphore/semaphore/models"
"github.com/gin-gonic/gin"
"github.com/masterminds/squirrel"
)
func AddTask(c *gin.Context) {
project := c.MustGet("project").(models.Project)
var taskObj models.Task
if err := c.Bind(&taskObj); err != nil {
return
}
taskObj.Created = time.Now()
taskObj.Status = "waiting"
if err := database.Mysql.Insert(&taskObj); err != nil {
panic(err)
}
pool.register <- &task{
task: taskObj,
projectID: project.ID,
}
objType := "task"
desc := "Task ID " + strconv.Itoa(taskObj.ID) + " queued for running"
if err := (models.Event{
ProjectID: &project.ID,
ObjectType: &objType,
ObjectID: &taskObj.ID,
Description: &desc,
}.Insert()); err != nil {
panic(err)
}
c.JSON(201, taskObj)
}
func GetAll(c *gin.Context) {
project := c.MustGet("project").(models.Project)
query, args, _ := squirrel.Select("task.*, tpl.playbook as tpl_playbook").
From("task").
Join("project__template as tpl on task.template_id=tpl.id").
Where("tpl.project_id=?", project.ID).
OrderBy("task.created desc").
ToSql()
var tasks []struct {
models.Task
TemplatePlaybook string `db:"tpl_playbook" json:"tpl_playbook"`
}
if _, err := database.Mysql.Select(&tasks, query, args...); err != nil {
panic(err)
}
c.JSON(200, tasks)
}
func GetTaskMiddleware(c *gin.Context) {
taskID, err := util.GetIntParam("task_id", c)
if err != nil {
panic(err)
}
var task models.Task
if err := database.Mysql.SelectOne(&task, "select * from task where id=?", taskID); err != nil {
panic(err)
}
c.Set("task", task)
c.Next()
}
func GetTaskOutput(c *gin.Context) {
task := c.MustGet("task").(models.Task)
var output []models.TaskOutput
if _, err := database.Mysql.Select(&output, "select * from task__output where task_id=? order by time desc", task.ID); err != nil {
panic(err)
}
c.JSON(200, output)
}

View File

@ -3,11 +3,6 @@ package tasks
import (
"fmt"
"time"
"github.com/ansible-semaphore/semaphore/database"
"github.com/ansible-semaphore/semaphore/models"
"github.com/gin-gonic/gin"
"github.com/masterminds/squirrel"
)
type taskPool struct {
@ -54,45 +49,3 @@ func (p *taskPool) run() {
func StartRunner() {
pool.run()
}
func AddTask(c *gin.Context) {
var taskObj models.Task
if err := c.Bind(&taskObj); err != nil {
return
}
taskObj.Created = time.Now()
taskObj.Status = "waiting"
if err := database.Mysql.Insert(&taskObj); err != nil {
panic(err)
}
pool.register <- &task{
task: taskObj,
}
c.JSON(201, taskObj)
}
func GetAll(c *gin.Context) {
project := c.MustGet("project").(models.Project)
query, args, _ := squirrel.Select("task.*, tpl.playbook as tpl_playbook").
From("task").
Join("project__template as tpl on task.template_id=tpl.id").
Where("tpl.project_id=?", project.ID).
OrderBy("task.created desc").
ToSql()
var tasks []struct {
models.Task
TemplatePlaybook string `db:"tpl_playbook" json:"tpl_playbook"`
}
if _, err := database.Mysql.Select(&tasks, query, args...); err != nil {
panic(err)
}
c.JSON(200, tasks)
}

View File

@ -23,6 +23,7 @@ type task struct {
repository models.Repository
environment models.Environment
users []int
projectID int
}
func (t *task) fail() {
@ -44,6 +45,18 @@ func (t *task) run() {
t.log("Fatal error with database!")
panic(err)
}
objType := "task"
desc := "Task ID " + strconv.Itoa(t.task.ID) + " finished"
if err := (models.Event{
ProjectID: &t.projectID,
ObjectType: &objType,
ObjectID: &t.task.ID,
Description: &desc,
}.Insert()); err != nil {
t.log("Fatal error inserting an event")
panic(err)
}
}()
if _, err := database.Mysql.Exec("update task set status='running', start=NOW() where id=?", t.task.ID); err != nil {
@ -52,6 +65,18 @@ func (t *task) run() {
panic(err)
}
objType := "task"
desc := "Task ID " + strconv.Itoa(t.task.ID) + " is running"
if err := (models.Event{
ProjectID: &t.projectID,
ObjectType: &objType,
ObjectID: &t.task.ID,
Description: &desc,
}.Insert()); err != nil {
t.log("Fatal error inserting an event")
panic(err)
}
t.log("Started: " + strconv.Itoa(t.task.ID) + "\n")
if err := t.populateDetails(); err != nil {

View File

@ -148,6 +148,18 @@ definitions:
type: string
environment:
type: string
Task:
type: object
properties:
task_id:
type: integer
task:
type: string
time:
type: string
format: date-time
output:
type: string
Template:
type: object
properties:
@ -234,6 +246,12 @@ parameters:
in: path
type: integer
required: true
task_id:
name: task_id
description: task ID
in: path
type: integer
required: true
paths:
/ping:
@ -749,6 +767,21 @@ paths:
description: Task queued
schema:
$ref: "#/definitions/Task"
/project/{project_id}/tasks/{task_id}/output:
parameters:
- $ref: '#/parameters/project_id'
- $ref: '#/parameters/task_id'
get:
tags:
- project
summary: Get task output
responses:
200:
description: output
schema:
type: array
items:
$ref: "#/definitions/TaskOutput"
# users
/users: