You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
222 lines
5.2 KiB
222 lines
5.2 KiB
/* |
|
------------------------------------------------------------------------------------------------------------------------ |
|
####### dune ####### Copyright (c) 2021-2022 losyme ################################################ MIT License ####### |
|
------------------------------------------------------------------------------------------------------------------------ |
|
*/ |
|
|
|
package model |
|
|
|
import ( |
|
"time" |
|
|
|
"forge.chapril.org/dune/jw" |
|
"forge.chapril.org/losyme/errors" |
|
"forge.chapril.org/losyme/uuid" |
|
) |
|
|
|
func validateID(id *string) error { |
|
if *id == "" { |
|
*id = uuid.New() |
|
} else if !uuid.IsValid(*id) { |
|
return errors.New( ///////////////////////////////////////////////////////////////////////////////////////////// |
|
"this identifier is not a UUID", |
|
"id", *id, |
|
) |
|
} |
|
|
|
return nil |
|
} |
|
|
|
func validatePriority(p *jw.Priority) { |
|
if *p < jw.PriorityNone { |
|
*p = jw.PriorityNone |
|
} else if *p > jw.PriorityCritical { |
|
*p = jw.PriorityCritical |
|
} |
|
} |
|
|
|
func (m *model) validateJob(job *jw.Job) error { |
|
if err := m.cs.Storage().ValidateJob(job); err != nil { |
|
return err |
|
} |
|
|
|
if err := validateID(&job.ID); err != nil { |
|
return err |
|
} |
|
|
|
if job.Name == "" { |
|
job.Name = "?" |
|
} |
|
|
|
if job.Namespace == "" { |
|
return errors.New("namespace must not be empty") /////////////////////////////////////////////////////////////// |
|
} |
|
|
|
if job.Type == "" { |
|
return errors.New("type must not be empty") //////////////////////////////////////////////////////////////////// |
|
} |
|
|
|
if job.Origin == "" { |
|
job.Origin = "?" |
|
} |
|
|
|
validatePriority(&job.Priority) |
|
|
|
// @FIXME: nécessaire ? |
|
if job.Public == nil { |
|
job.Public = make(map[string]interface{}) |
|
} |
|
|
|
// @FIXME: nécessaire ? |
|
if job.Private == nil { |
|
job.Private = make(map[string]interface{}) |
|
} |
|
|
|
if job.MaxAttempts < 0 { |
|
job.MaxAttempts = 0 |
|
} |
|
|
|
if job.MaxOccurrences < 0 { |
|
job.MaxOccurrences = 0 |
|
} |
|
|
|
job.Workflow = nil |
|
job.CreatedAt = time.Now() |
|
job.Status = jw.StatusTodo |
|
job.Attempt = 0 |
|
job.Session = 0 |
|
job.Result = nil |
|
job.FinishedAt = nil |
|
job.TimeReference = job.CreatedAt |
|
job.Weight = 0 |
|
job.ErrorCounter = 0 |
|
job.LastError = nil |
|
|
|
return nil |
|
} |
|
|
|
func validateNext(wf *jw.Workflow, next map[string]interface{}) error { |
|
if next == nil { |
|
return nil |
|
} |
|
|
|
for key, v := range next { |
|
switch value := v.(type) { |
|
case nil: |
|
// ok |
|
case string: |
|
if _, ok := wf.AllSteps[value]; !ok { |
|
return errors.New( ///////////////////////////////////////////////////////////////////////////////////// |
|
"the step associated with this key does not exist", |
|
"key", key, |
|
"step", value, |
|
) |
|
} |
|
case map[string]interface{}: |
|
for k, v := range value { |
|
switch k { |
|
case "data": |
|
// ok |
|
case "step": |
|
s, ok := v.(string) |
|
if !ok { |
|
return errors.New( ///////////////////////////////////////////////////////////////////////////// |
|
"the 'step' key must be a string", |
|
"key", key, |
|
) |
|
} |
|
|
|
if _, ok := wf.AllSteps[s]; !ok { |
|
return errors.New( ///////////////////////////////////////////////////////////////////////////// |
|
"the step associated with these keys does not exist", |
|
"keys", key+"/"+k, |
|
"step", s, |
|
) |
|
} |
|
default: |
|
return errors.New( ///////////////////////////////////////////////////////////////////////////////// |
|
"the last of these keys is not known", |
|
"keys", key+"/"+k, |
|
) |
|
} |
|
} |
|
default: |
|
return errors.New( ///////////////////////////////////////////////////////////////////////////////////////// |
|
"the value associated with this key is not valid", |
|
"key", key, |
|
) |
|
} |
|
} |
|
|
|
return nil |
|
} |
|
|
|
func validateStep(wf *jw.Workflow, step *jw.Step) error { |
|
if step.Namespace == "" { |
|
return errors.New("namespace must not be empty") /////////////////////////////////////////////////////////////// |
|
} |
|
|
|
if step.Type == "" { |
|
return errors.New("type must not be empty") //////////////////////////////////////////////////////////////////// |
|
} |
|
|
|
return validateNext(wf, step.Next) |
|
} |
|
|
|
func (m *model) validateWorkflow(wf *jw.Workflow) error { |
|
if err := m.cs.Storage().ValidateWorkflow(wf); err != nil { |
|
return err |
|
} |
|
|
|
if err := validateID(&wf.ID); err != nil { |
|
return err |
|
} |
|
|
|
if wf.Name == "" { |
|
wf.Name = "?" |
|
} |
|
|
|
if wf.Description == "" { |
|
wf.Description = "?" |
|
} |
|
|
|
if wf.Origin == "" { |
|
wf.Origin = "?" |
|
} |
|
|
|
if wf.FirstStep == "" { |
|
return errors.New("first step must not be empty") ////////////////////////////////////////////////////////////// |
|
} |
|
|
|
if len(wf.AllSteps) == 0 { |
|
return errors.New("there are no steps") //////////////////////////////////////////////////////////////////////// |
|
} |
|
|
|
if _, ok := wf.AllSteps[wf.FirstStep]; !ok { |
|
return errors.New("first step does not match any step") //////////////////////////////////////////////////////// |
|
} |
|
|
|
for name, step := range wf.AllSteps { |
|
if err := validateStep(wf, step); err != nil { |
|
return errors.WithMessage( ///////////////////////////////////////////////////////////////////////////////// |
|
err, |
|
"this step is not valid", |
|
"name", name, |
|
) |
|
} |
|
} |
|
|
|
if wf.Data == nil { |
|
wf.Data = make(map[string]interface{}) |
|
} |
|
|
|
wf.CreatedAt = time.Now() |
|
wf.Status = jw.StatusRunning |
|
wf.FinishedAt = nil |
|
|
|
return nil |
|
} |
|
|
|
/* |
|
######################################################################################################## @(°_°)@ ####### |
|
*/
|
|
|