From 10ec990a15adeecd9fe6d0230ebc3381b6845f87 Mon Sep 17 00:00:00 2001 From: pb Date: Fri, 29 Mar 2024 17:00:53 +0100 Subject: [PATCH] update the object stored for one workflow with user input --- models/computing.go | 52 +++++++++++++++++++++++++++++++++++---------- models/mxgraph.go | 16 ++++++++++++++ models/workflow.go | 39 +++++++++++++++++++++------------- 3 files changed, 81 insertions(+), 26 deletions(-) diff --git a/models/computing.go b/models/computing.go index 846f06d..c9f74d0 100644 --- a/models/computing.go +++ b/models/computing.go @@ -1,11 +1,13 @@ package models import ( + "encoding/xml" "fmt" "strings" "cloud.o-forge.io/core/oc-catalog/models/rtype" "cloud.o-forge.io/core/oc-catalog/services" + structtomap "github.com/Klathmon/StructToMap" "github.com/beego/beego/v2/core/logs" "go.mongodb.org/mongo-driver/bson/primitive" ) @@ -35,21 +37,21 @@ type ComputingNEWModel struct { ShortDescription string `json:"short_description,omitempty" required:"true" validate:"required"` Logo string `json:"logo,omitempty" required:"true" validate:"required"` - // Type string `json:"type,omitempty" required:"true"` + Type string `json:"type,omitempty" required:"true"` Owner string `json:"owner,omitempty"` License string `json:"license,omitempty"` Price uint `json:"price,omitempty"` ExecutionRequirements ExecutionRequirementsModel `json:"execution_requirements,omitempty"` - // Dinputs []string `json:"dinputs,omitempty"` // Possibly redundant with Links object in oc-schedule - // Doutputs []string `json:"doutputs,omitempty"` // Possibly redundant with Links objects in oc-schedule + Dinputs []string `json:"dinputs,omitempty"` // Possibly redundant with Links object in oc-schedule + Doutputs []string `json:"doutputs,omitempty"` // Possibly redundant with Links objects in oc-schedule Image string `json:"image,omitempty"` Command string `json:"command,omitempty"` Arguments []string `json:"arguments,omitempty"` Environment []string `json:"environment,omitempty"` - // Ports []string `json:"ports,omitempty"` + Ports []string `json:"ports,omitempty"` // CustomDeployment string `json:"custom_deployment,omitempty"` @@ -77,6 +79,11 @@ type ComputingObject struct { Inputs []string `json:"inputs"` Outputs []string `json:"outputs"` + Image string `json:"image,omitempty"` + Command string `json:"command,omitempty"` + Arguments []string `json:"arguments,omitempty"` + Environment []string `json:"environment,omitempty"` + Ports []string `json:"ports,omitempty"` DataCenterID string `json:"datacenterID" description:"Datacenter where the computing will be executed"` } @@ -174,19 +181,42 @@ func PostOneComputing(obj ComputingNEWModel) (ID string, err error) { return postOneResource(obj, rtype.COMPUTING) } -func (obj ComputingModel) AddUserInput(inputs map[string]interface{} ){ +func (obj *ComputingObject) AddUserInput(inputs []xml.Attr){ // So far only a few input to handle so a switch with a case for each type of attribute // is enough, to prevent too much complexity - for key, value := range inputs { - switch strings.ToLower(key) { + + for _, j := range(inputs){ + setting, _ := structtomap.Convert(j) + // fmt.Println(strings.ToLower(setting["Name"])) + name := setting["Name"].(xml.Name).Local + value := setting["Value"] + switch name { case "command": obj.Command = value.(string) - case "arguments": - obj.Arguments = value.([]string) + case "args": + empty, sliced_arguments := getSliceSettings(value.(string)) + if (!empty){ + obj.Arguments = sliced_arguments + } case "env" : - obj.Environment = value.([]string) + empty, sliced_arguments := getSliceSettings(value.(string)) + if (!empty){ + obj.Environment = sliced_arguments + } default: - logs.Alert(fmt.Printf("%s is not an attribute of storage componants", key)) + logs.Alert(fmt.Printf("%s is not an attribute of computing componants", name)) } + } + + +} + +func getSliceSettings(string_to_parse string)(empty bool, sliced_string []string){ + if len(string_to_parse) == 0 { + return true, nil + } + empty = false + sliced_string = strings.Split(string_to_parse," ") + return } \ No newline at end of file diff --git a/models/mxgraph.go b/models/mxgraph.go index 71ce58f..57cfd01 100644 --- a/models/mxgraph.go +++ b/models/mxgraph.go @@ -2,6 +2,7 @@ package models import ( "encoding/xml" + "strconv" ) type MxGraphModel struct { @@ -43,3 +44,18 @@ func (m *mxissue) Error() string { func newMxIssue(message string) error { return &mxissue{message} } + +// mxCell inside object tags are create twice when unmarshalling +// once as they appear in the xml inside the MxObject struct and once in the MxCell struct +// so once retrieved from object we remove them from the root's MxCell list +func (m *MxGraphModel) removeMxCell(id string){ + int_id,_ := strconv.Atoi(id) + int_id = int_id + 1 + cell_id := strconv.Itoa(int_id) + + for i, cell := range(m.Root.MxCell){ + if cell.ID == cell_id { + m.Root.MxCell = append(m.Root.MxCell[:i],m.Root.MxCell[i+1:]...) + } + } +} \ No newline at end of file diff --git a/models/workflow.go b/models/workflow.go index 38f96ae..46241f0 100644 --- a/models/workflow.go +++ b/models/workflow.go @@ -4,6 +4,7 @@ import ( "context" "encoding/xml" "errors" + "fmt" "net/url" "os" "sort" @@ -73,7 +74,7 @@ type ResourceObject interface { addLink(direction LinkingState, rObjID string) } -// This type allows to process computing and storage componant +// This type allows to process computing and storage component // which can get input from the user type EditableResourceObject interface{ ResourceObject @@ -600,10 +601,10 @@ func (ws Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Wor // For each cell of the xml graph, - // in the case cell has a rID retrieve its rType from the value of rID of the componant in the worfklow - // retrieve the componant's type + // in the case cell has a rID retrieve its rType from the value of rID of the component in the worfklow + // retrieve the component's type // create an object from the rType - // update the existing workflow with the new componant + // update the existing workflow with the new component // or by defautlt : the cell represents an arrow // if the source or the target of the arrow is a datacenter // define which end of the arrow is the DC @@ -614,18 +615,26 @@ func (ws Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Wor for _, object := range *xmlmodel.Root.MxObject{ - resObj, err, mxissues := returned_wf.mxCellToComponant(object.MxCell,ws) + resObj, err, mxissues := returned_wf.mxCellToComponent(object.MxCell,ws) if err != nil { issues = append(issues, mxissues...) } - returned_wf.UpdateObj(resObj,object.ID) - // // retrieve the rType in the mxCell - // rType := w.getRtype(*object.MxCell.RID) - // // create a composant and add it to the appropriate list - // resObj := returned_wf.CreateResourceObject(rType) - // // use the addUserInput method with a map[string]string made of the - // resObj + // add the component to the worflow's attribute that stores + // all components in a map[string]Component where the key + // is the component's ID in the mxGraph and the value the Component object + returned_wf.UpdateObj(resObj,object.ID) + xmlmodel.removeMxCell(object.ID) + + // Construct the object corresponding to the componant's type and use its addUserInput method + if(resObj.getRtype() == rtype.COMPUTING){ + comp_obj := returned_wf.GetResource(&object.ID).(*ComputingObject) + comp_obj.AddUserInput(object.Settings) + returned_wf.UpdateObj(comp_obj,object.ID) + } + // if(resObj.getRtype() == rtype.DATA){ + fmt.Printf("Test") + // } } @@ -633,7 +642,7 @@ func (ws Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Wor switch { case cell.RID != nil: - resObj, err, mxissues := returned_wf.mxCellToComponant(cell,ws) + resObj, err, mxissues := returned_wf.mxCellToComponent(cell,ws) if err != nil { issues = append(issues, mxissues...) } @@ -705,7 +714,7 @@ func (ws Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Wor // datalist := make(map[string]bool) - // Test wether the computing componants are linked with a DC + // Test wether the computing components are linked with a DC for _, comp := range returned_wf.Computing { if comp.DataCenterID == "" { issues = append(issues, errors.New("Computing "+*comp.getName()+" without a Datacenter")) @@ -1041,7 +1050,7 @@ func CheckAndBookWorkflowSchedule(username, workflowName string, book bool) (myR } // Not sure if this method handles error propagation well -func (wf Workflow) mxCellToComponant(cell MxCell, ws Workspace) (resObj ResourceObject,err error, issues []error){ +func (wf Workflow) mxCellToComponent(cell MxCell, ws Workspace) (resObj ResourceObject,err error, issues []error){ rType := ws.getRtype(*cell.RID) if rType == rtype.INVALID {