mirror of
https://github.com/semaphoreui/semaphore.git
synced 2024-11-23 12:30:41 +01:00
Show task output, fix event time precision
This commit is contained in:
parent
cf75b1caf1
commit
4dd8335273
@ -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`)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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"`
|
||||
}
|
||||
|
@ -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 }}
|
||||
|
@ -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
|
||||
|
@ -24,7 +24,8 @@ define(['controllers/projects/taskRunner'], function () {
|
||||
$modal.open({
|
||||
templateUrl: '/tpl/projects/taskModal.html',
|
||||
controller: 'TaskCtrl',
|
||||
scope: scope
|
||||
scope: scope,
|
||||
size: 'lg'
|
||||
});
|
||||
}
|
||||
}]);
|
||||
|
@ -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');
|
||||
});
|
||||
}]);
|
||||
});
|
@ -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
95
routes/tasks/http.go
Normal 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)
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
33
swagger.yml
33
swagger.yml
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user