oc-catalog/controllers/workflow.go

338 lines
10 KiB
Go

package controllers
import (
"time"
"cloud.o-forge.io/core/oc-catalog/models"
"github.com/beego/beego/v2/core/logs"
beego "github.com/beego/beego/v2/server/web"
"github.com/vk496/cron"
)
type WorkflowController struct {
beego.Controller
}
// @Title Create a new workflow
// @Description Create a name for the new workflow
// @Param workflowName query string true "Name of the workflow"
// @Success 200 {string} Workflow created succeful
// @Failure 403 Authentication issue
// @Failure 400 {string} Other error
// // @Security jwtAPIToken
// @router / [post]
func (u *WorkflowController) CreateWorkflow(workflowName string) {
// token := u.Ctx.Input.GetData("jwtAPIToken").(string)
// //TODO: Implement as swagger security definition (api key?)
// username, err := GetUsernameFromToken(token)
// if err != nil {
// u.Data["json"] = "No valid token"
// u.Ctx.Output.Status = 403
// u.ServeJSON()
// return
// }
username := "asd"
if err := models.CreateWorkflow(username, workflowName); err != nil {
u.Data["json"] = err.Error()
u.Ctx.Output.Status = 400
u.ServeJSON()
return
}
}
// @Title List workflows
// @Description List available workflows
// @Success 200 []string List of workflows
// @Failure 403 Authentication issue
// @Failure 400 {string} Other error
// // @Security jwtAPIToken
// @router / [get]
func (u *WorkflowController) ListWorkflows() {
// token := u.Ctx.Input.GetData("jwtAPIToken").(string)
username := "asd"
w := models.GetWorkspace(username)
if w == nil {
// No username
u.Data["json"] = "Workspace doesn't exist"
u.Ctx.Output.Status = 400
u.ServeJSON()
}
u.Data["json"] = w.GetWorkflows()
u.ServeJSON()
}
// @Title Get Workflow
// @Description Get a workflow by name
// @Param workflowName path string true "Workflow Name"
// @Success 200 {object} models.Workflow
// @Failure 403 Authentication issue
// @Failure 400 {string} Other error
// // @Security jwtAPIToken
// @router /:workflowName [get]
func (u *WorkflowController) GetWorkflow(workflowName string) {
// token := u.Ctx.Input.GetData("jwtAPIToken").(string)
username := "asd"
proj, err := models.GetWorkflow(username, workflowName)
if err != nil {
u.SetData(err.Error())
u.Ctx.Output.Status = 400
u.ServeJSON()
return
}
u.Data["json"] = proj
u.ServeJSON()
}
// @Title Add new object to a Workflow
// @Description Create a Rtype object from already added resources to the workspace
// @Param workflowName path string true "workflow Name"
// @Param rID query string true "rID of already existing item in Workspace"
// @Success 200 {string} ID of the new object (rObjID)
// @Failure 403 Authentication issue
// @Failure 400 {string} Other error
// // @Security jwtAPIToken
// @router /:workflowName/add [post]
func (u *WorkflowController) AddElementWorkflow(workflowName, rID string) {
username := "asd"
rObjID, err := models.CreateObjectInWorkflow(username, workflowName, rID)
if err != nil {
logs.Debug(err.Error())
u.Data["json"] = err.Error()
u.Ctx.Output.Status = 400
u.ServeJSON()
return
}
u.Data["json"] = rObjID
u.ServeJSON()
return
}
// @Title Parse mxGraph
// @Description If we use this aproach to transofrm mxgraph representation in our representation, we should not use other API calls for modify the project structure or we'll have inconsistencies.
// @Param workflowName path string true "Workflow Name"
// @Param xmlData body string true "Xml representation of the workflow"
// @Success 200 The xmlgraph consumed correctly
// @Success 201 The xmlgraph consumed with issues
// @Failure 403 Authentication issue
// @Failure 400 {string} Other error
// @router /:workflowName/mxGraphParser [post]
func (u *WorkflowController) MxGraphParser(workflowName, xmlData string) {
username := "asd"
err, mxissues := models.ParseMxGraph(username, workflowName, xmlData)
if err != nil {
logs.Debug(err.Error())
u.CustomAbort(400, err.Error())
}
if len(mxissues) > 0 {
strErrors := make([]string, len(mxissues))
for i, err := range mxissues {
strErrors[i] = err.Error()
}
u.Data["json"] = strErrors
u.Ctx.Output.Status = 201
u.ServeJSON()
return
}
}
// @Title Get mxGraph last status
// @Description Obtain the last mxgraph XML status from the workflow
// @Param workflowName path string true "Workflow Name"
// @Success 200 The xmlgraph
// @Success 201 Empty workflow
// @Failure 403 Authentication issue
// @Failure 400 {string} Other error
// @router /:workflowName/mxGraphParser [get]
func (u *WorkflowController) MxGraphParserConsume(workflowName string) {
username := "asd"
xmlData, err := models.GetMxGraph(username, workflowName)
if err != nil {
logs.Debug(err.Error())
u.Data["json"] = err.Error()
u.Ctx.Output.Status = 400
u.ServeJSON()
return
}
if xmlData == nil {
u.Ctx.Output.Status = 201
} else {
u.Ctx.Output.Status = 200
u.Ctx.Output.Body([]byte(*xmlData))
u.ServeXML()
}
return
}
// @Title Create a realtionship between two Robjects
// @Description Create a Rtype object from already added resources to the workspace
// @Param workflowName path string true "Workflow Name"
// @Param rObjIDsource query string true "Robject source. Usually Data"
// @Param isInput query bool true "If the operation is for input (true) linkage or output (false)"
// @Param rObjIDtarger query string true "Robject where will be written the association"
// @Success 200 {string} ID of the new object (rObjID)
// @Failure 403 Authentication issue
// @Failure 400 {string} Other error
// // @Security jwtAPIToken
// @router /:workflowName/link [post]
func (u *WorkflowController) LinkElementsWorkflow(workflowName, rObjIDsource, rObjIDtarger string, isInput bool) {
username := "asd"
err := models.LinkObjectsInWorkspace(username, workflowName, rObjIDsource, isInput, rObjIDtarger)
if err != nil {
logs.Debug(err.Error())
u.Data["json"] = err.Error()
u.Ctx.Output.Status = 400
u.ServeJSON()
return
}
}
// @Title Get Schedule
// @Description Obtain the desired schedule of this workflow
// @Param workflowName path string true "Workflow Name"
// @Success 200 {object} models.ScheduleTime
// @Failure 403 Authentication issue
// @Failure 400 Workflow doesn't exist
// @Failure 401 Other error
// @router /:workflowName/schedule [get]
func (u *WorkflowController) GetWorkflowSchedule(workflowName string) {
username := "asd"
sched, err := models.GetWorkflowSchedule(username, workflowName)
// Some error
if err != nil {
u.CustomAbort(401, err.Error())
}
// No workflow
if sched == nil {
u.Ctx.Output.Status = 400
return
}
u.Ctx.Output.Status = 200
u.Data["json"] = sched
u.ServeJSON()
}
// @Title Set Schedule
// @Description Set desired schedule by the user. No other effects a part of saving the user input
// @Param workflowName path string true "Workflow Name"
// @Param isService query bool true "True: Service, False: Task"
// @Param startDate query time.Time true "RFC3339 time for startDate"
// @Param stopDate query time.Time true "RFC3339 time for stopDate"
// @Param events query string false "List of events separated by comma"
// @Param cronString query string false "Cron string"
// @Param duration query uint false "Duration in seconds"
// @Success 200 {object} models.ScheduleInfo
// @Failure 403 Authentication issue
// @Failure 400 Workflow doesn't exist
// @Failure 401 Other error
// @Failure 402 Bad user input
// @router /:workflowName/schedule [put]
func (u *WorkflowController) SetWorkflowSchedule(workflowName, cronString, events string, isService bool, startDate, stopDate time.Time, duration uint) {
username := "asd"
// Check Dates
if startDate.After(stopDate) || startDate.Equal(stopDate) {
u.CustomAbort(402, "startDate must be before stopDate")
}
if startDate.Before(time.Now().UTC()) {
u.CustomAbort(402, "Current server time ("+time.Now().UTC().String()+") is after the startDate ("+startDate.String()+")")
}
// Tasks must have cron and duration
if !isService {
if cronString == "" {
u.CustomAbort(402, "Tasks cronString must not be empty")
}
if duration == 0 {
u.CustomAbort(402, "Tasks duration musn't be 0")
}
_, err := cron.Parse(cronString)
// Check cron
if err != nil {
u.CustomAbort(402, "Bad cron message: "+err.Error())
}
}
schedInfo, err := models.SetWorkflowSchedule(username, workflowName, cronString, events, isService, startDate, stopDate, duration)
// Some error
if err != nil {
u.CustomAbort(401, err.Error())
}
// No workflow
if schedInfo == nil {
u.CustomAbort(400, "")
}
u.Ctx.Output.Status = 200
u.Data["json"] = schedInfo
u.ServeJSON()
}
// @Title Check Schedule
// @Description Check if we can schedule the project in other DCs. Must set a desired schedule first!
// @Param workflowName path string true "Workflow Name"
// @Success 200 {object} []models.DCstatus
// @Failure 403 Authentication issue
// @Failure 401 Other error
// @router /:workflowName/schedule/check [get]
func (u *WorkflowController) CheckWorkflowSchedule(workflowName string) {
username := "asd"
data, err := models.CheckAndBookWorkflowSchedule(username, workflowName, false)
if err != nil {
u.CustomAbort(401, err.Error())
}
u.Ctx.Output.Status = 200
u.Data["json"] = data
u.ServeJSON()
return
}
// @Title Book Schedule
// @Description Book a schedule in all DCs of the workflow. Must set a desired schedule first!
// @Param workflowName path string true "Workflow Name"
// @Success 200 {object} []models.DCstatus
// @Failure 403 Authentication issue
// @Failure 401 Other error. Check output
// @router /:workflowName/schedule/book [post]
func (u *WorkflowController) BookWorkflowSchedule(workflowName string) {
username := "asd"
data, err := models.CheckAndBookWorkflowSchedule(username, workflowName, true)
if err != nil {
u.CustomAbort(401, err.Error())
}
u.Ctx.Output.Status = 200
u.Data["json"] = data
u.ServeJSON()
return
}