Semaphore/api/tasks/http.go
2019-07-09 20:45:27 +03:00

163 lines
4.6 KiB
Go

package tasks
import (
"net/http"
"strconv"
"time"
log "github.com/Sirupsen/logrus"
"github.com/ansible-semaphore/semaphore/db"
"github.com/ansible-semaphore/semaphore/util"
"github.com/gorilla/context"
"github.com/masterminds/squirrel"
)
// AddTask inserts a task into the database and returns a header or returns error
func AddTask(w http.ResponseWriter, r *http.Request) {
project := context.Get(r, "project").(db.Project)
user := context.Get(r, "user").(*db.User)
var taskObj db.Task
if err := util.Bind(w, r, &taskObj); err != nil {
return
}
taskObj.Created = time.Now()
taskObj.Status = "waiting"
taskObj.UserID = &user.ID
if err := db.Mysql.Insert(&taskObj); err != nil {
util.LogErrorWithFields(err, log.Fields{"error": "Bad request. Cannot create new task"})
w.WriteHeader(http.StatusBadRequest)
return
}
pool.register <- &task{
task: taskObj,
projectID: project.ID,
}
objType := taskTypeID
desc := "Task ID " + strconv.Itoa(taskObj.ID) + " queued for running"
if err := (db.Event{
ProjectID: &project.ID,
ObjectType: &objType,
ObjectID: &taskObj.ID,
Description: &desc,
}.Insert()); err != nil {
util.LogErrorWithFields(err, log.Fields{"error": "Cannot write new event to database"})
}
util.WriteJSON(w, http.StatusCreated, taskObj)
}
// GetTasksList returns a list of tasks for the current project in desc order to limit or error
func GetTasksList(w http.ResponseWriter, r *http.Request, limit uint64) {
project := context.Get(r, "project").(db.Project)
q := squirrel.Select("task.*, tpl.playbook as tpl_playbook, user.name as user_name, tpl.alias as tpl_alias").
From(taskTypeID).
Join("project__template as tpl on task.template_id=tpl.id").
LeftJoin("user on task.user_id=user.id").
Where("tpl.project_id=?", project.ID).
OrderBy("task.created desc")
if limit > 0 {
q = q.Limit(limit)
}
query, args, _ := q.ToSql()
var tasks []struct {
db.Task
TemplatePlaybook string `db:"tpl_playbook" json:"tpl_playbook"`
TemplateAlias string `db:"tpl_alias" json:"tpl_alias"`
UserName *string `db:"user_name" json:"user_name"`
}
if _, err := db.Mysql.Select(&tasks, query, args...); err != nil {
util.LogErrorWithFields(err, log.Fields{"error": "Bad request. Cannot get tasks list from database"})
w.WriteHeader(http.StatusBadRequest)
return
}
util.WriteJSON(w, http.StatusOK, tasks)
}
// GetAllTasks returns all tasks for the current project
func GetAllTasks(w http.ResponseWriter, r *http.Request) {
GetTasksList(w, r, 0)
}
// GetLastTasks returns the hundred most recent tasks
func GetLastTasks(w http.ResponseWriter, r *http.Request) {
GetTasksList(w, r, 200)
}
// GetTask returns a task based on its id
func GetTask(w http.ResponseWriter, r *http.Request) {
task := context.Get(r, taskTypeID).(db.Task)
util.WriteJSON(w, http.StatusOK, task)
}
// GetTaskMiddleware is middleware that gets a task by id and sets the context to it or panics
func GetTaskMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
taskID, err := util.GetIntParam("task_id", w, r)
if err != nil {
panic(err)
}
var task db.Task
if err := db.Mysql.SelectOne(&task, "select * from task where id=?", taskID); err != nil {
panic(err)
}
context.Set(r, taskTypeID, task)
next.ServeHTTP(w, r)
})
}
// GetTaskOutput returns the logged task output by id and writes it as json or returns error
func GetTaskOutput(w http.ResponseWriter, r *http.Request) {
task := context.Get(r, taskTypeID).(db.Task)
var output []db.TaskOutput
if _, err := db.Mysql.Select(&output, "select task_id, task, time, output from task__output where task_id=? order by time asc", task.ID); err != nil {
util.LogErrorWithFields(err, log.Fields{"error": "Bad request. Cannot get task output from database"})
w.WriteHeader(http.StatusBadRequest)
return
}
util.WriteJSON(w, http.StatusOK, output)
}
// RemoveTask removes a task from the database
func RemoveTask(w http.ResponseWriter, r *http.Request) {
task := context.Get(r, taskTypeID).(db.Task)
editor := context.Get(r, "user").(*db.User)
if !editor.Admin {
log.Warn(editor.Username + " is not permitted to delete task logs")
w.WriteHeader(http.StatusUnauthorized)
return
}
statements := []string{
"delete from task__output where task_id=?",
"delete from task where id=?",
}
for _, statement := range statements {
_, err := db.Mysql.Exec(statement, task.ID)
if err != nil {
util.LogErrorWithFields(err, log.Fields{"error": "Bad request. Cannot delete task from database"})
w.WriteHeader(http.StatusBadRequest)
return
}
}
w.WriteHeader(http.StatusNoContent)
}