update the object stored for one workflow with user input

This commit is contained in:
pb 2024-03-29 17:00:53 +01:00
parent 1017f4404e
commit 10ec990a15
3 changed files with 81 additions and 26 deletions

View File

@ -1,11 +1,13 @@
package models package models
import ( import (
"encoding/xml"
"fmt" "fmt"
"strings" "strings"
"cloud.o-forge.io/core/oc-catalog/models/rtype" "cloud.o-forge.io/core/oc-catalog/models/rtype"
"cloud.o-forge.io/core/oc-catalog/services" "cloud.o-forge.io/core/oc-catalog/services"
structtomap "github.com/Klathmon/StructToMap"
"github.com/beego/beego/v2/core/logs" "github.com/beego/beego/v2/core/logs"
"go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson/primitive"
) )
@ -35,21 +37,21 @@ type ComputingNEWModel struct {
ShortDescription string `json:"short_description,omitempty" required:"true" validate:"required"` ShortDescription string `json:"short_description,omitempty" required:"true" validate:"required"`
Logo string `json:"logo,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"` Owner string `json:"owner,omitempty"`
License string `json:"license,omitempty"` License string `json:"license,omitempty"`
Price uint `json:"price,omitempty"` Price uint `json:"price,omitempty"`
ExecutionRequirements ExecutionRequirementsModel `json:"execution_requirements,omitempty"` ExecutionRequirements ExecutionRequirementsModel `json:"execution_requirements,omitempty"`
// Dinputs []string `json:"dinputs,omitempty"` // Possibly redundant with Links object 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 Doutputs []string `json:"doutputs,omitempty"` // Possibly redundant with Links objects in oc-schedule
Image string `json:"image,omitempty"` Image string `json:"image,omitempty"`
Command string `json:"command,omitempty"` Command string `json:"command,omitempty"`
Arguments []string `json:"arguments,omitempty"` Arguments []string `json:"arguments,omitempty"`
Environment []string `json:"environment,omitempty"` Environment []string `json:"environment,omitempty"`
// Ports []string `json:"ports,omitempty"` Ports []string `json:"ports,omitempty"`
// CustomDeployment string `json:"custom_deployment,omitempty"` // CustomDeployment string `json:"custom_deployment,omitempty"`
@ -77,6 +79,11 @@ type ComputingObject struct {
Inputs []string `json:"inputs"` Inputs []string `json:"inputs"`
Outputs []string `json:"outputs"` 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"` 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) 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 // 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 // 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": case "command":
obj.Command = value.(string) obj.Command = value.(string)
case "arguments": case "args":
obj.Arguments = value.([]string) empty, sliced_arguments := getSliceSettings(value.(string))
if (!empty){
obj.Arguments = sliced_arguments
}
case "env" : case "env" :
obj.Environment = value.([]string) empty, sliced_arguments := getSliceSettings(value.(string))
if (!empty){
obj.Environment = sliced_arguments
}
default: 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
} }

View File

@ -2,6 +2,7 @@ package models
import ( import (
"encoding/xml" "encoding/xml"
"strconv"
) )
type MxGraphModel struct { type MxGraphModel struct {
@ -43,3 +44,18 @@ func (m *mxissue) Error() string {
func newMxIssue(message string) error { func newMxIssue(message string) error {
return &mxissue{message} 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:]...)
}
}
}

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"encoding/xml" "encoding/xml"
"errors" "errors"
"fmt"
"net/url" "net/url"
"os" "os"
"sort" "sort"
@ -73,7 +74,7 @@ type ResourceObject interface {
addLink(direction LinkingState, rObjID string) 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 // which can get input from the user
type EditableResourceObject interface{ type EditableResourceObject interface{
ResourceObject ResourceObject
@ -600,10 +601,10 @@ func (ws Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Wor
// For each cell of the xml graph, // 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 // in the case cell has a rID retrieve its rType from the value of rID of the component in the worfklow
// retrieve the componant's type // retrieve the component's type
// create an object from the rType // 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 // or by defautlt : the cell represents an arrow
// if the source or the target of the arrow is a datacenter // if the source or the target of the arrow is a datacenter
// define which end of the arrow is the DC // 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{ 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 { if err != nil {
issues = append(issues, mxissues...) issues = append(issues, mxissues...)
} }
returned_wf.UpdateObj(resObj,object.ID)
// // retrieve the rType in the mxCell // add the component to the worflow's attribute that stores
// rType := w.getRtype(*object.MxCell.RID) // all components in a map[string]Component where the key
// // create a composant and add it to the appropriate list // is the component's ID in the mxGraph and the value the Component object
// resObj := returned_wf.CreateResourceObject(rType) returned_wf.UpdateObj(resObj,object.ID)
// // use the addUserInput method with a map[string]string made of the xmlmodel.removeMxCell(object.ID)
// resObj
// 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 { switch {
case cell.RID != nil: case cell.RID != nil:
resObj, err, mxissues := returned_wf.mxCellToComponant(cell,ws) resObj, err, mxissues := returned_wf.mxCellToComponent(cell,ws)
if err != nil { if err != nil {
issues = append(issues, mxissues...) issues = append(issues, mxissues...)
} }
@ -705,7 +714,7 @@ func (ws Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Wor
// datalist := make(map[string]bool) // 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 { for _, comp := range returned_wf.Computing {
if comp.DataCenterID == "" { if comp.DataCenterID == "" {
issues = append(issues, errors.New("Computing "+*comp.getName()+" without a Datacenter")) 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 // 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) rType := ws.getRtype(*cell.RID)
if rType == rtype.INVALID { if rType == rtype.INVALID {