Merge branch 'bugfix/settings_handling'
This commit is contained in:
commit
9ebd5cd5b0
33
README.md
33
README.md
@ -64,3 +64,36 @@ This script should be updated to be ran from anywhere.
|
||||
# More documentation
|
||||
|
||||
[Visit the docs/ directory](/docs/)
|
||||
|
||||
## UML
|
||||
|
||||
We are currently using [goplantuml](https://github.com/jfeliu007/goplantuml/) to generate the oject diagrams directly from the go files. This tools creates `.plums` files directly from the directory where the go files are located. These UML files can then be visualized using plantuml and the VS Code extensions plantuml.
|
||||
|
||||
**Setting up the plantuml environment** :
|
||||
|
||||
```
|
||||
# Downloading the go tool goplantuml
|
||||
go get github.com/jfeliu007/goplantuml/parser
|
||||
go install github.com/jfeliu007/goplantuml/cmd/goplantuml@latest
|
||||
|
||||
# Install the plantuml environment
|
||||
sudo apt install default-jre
|
||||
sudo apt install plantuml
|
||||
|
||||
```
|
||||
**Rich PlantUML extension Link**: https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml or search it in the marketplace panel of VS Code
|
||||
|
||||
**Generate and view an UML diagram**
|
||||
|
||||
```
|
||||
goplantuml path/to/code/directory > path/to/dest/file.puml
|
||||
```
|
||||
|
||||
- open the .puml file generated
|
||||
- alt + d to have the extension preview the plantUML code
|
||||
- right click inside the .puml and select 'Export Current Diagram' to create an image file
|
||||
- the output will be generated in a `out/` directory in the current path
|
||||
|
||||
### Note
|
||||
|
||||
Only `.puml` files ought to be commited to the git repository, because their nature allows to track changes, while image file do not fit the purpose of versioning.
|
77
docs/UML/plantuml/diagram_object_controllers.puml
Normal file
77
docs/UML/plantuml/diagram_object_controllers.puml
Normal file
@ -0,0 +1,77 @@
|
||||
@startuml
|
||||
namespace controllers {
|
||||
class ComputingController << (S,Aquamarine) >> {
|
||||
+ GetOneComputing(ID string)
|
||||
+ PostComputing(body models.ComputingNEWModel)
|
||||
+ GetMultipleComputing(IDs []string)
|
||||
|
||||
}
|
||||
class DataController << (S,Aquamarine) >> {
|
||||
+ GetOneData(ID string)
|
||||
+ GetMultipleData(IDs []string)
|
||||
+ PostData(body models.DataNEWModel)
|
||||
|
||||
}
|
||||
class DatacenterController << (S,Aquamarine) >> {
|
||||
+ GetMultipleDatacenter(IDs []string)
|
||||
+ GetOneDatacenter(ID string)
|
||||
+ PostDatacenter(body models.DatacenterNEWModel)
|
||||
|
||||
}
|
||||
class ScheduleController << (S,Aquamarine) >> {
|
||||
+ CreateSchedule(dcName string, workflowName string, cron string, duration uint, startDate time.Time, stopDate time.Time, requirements models.ExecutionRequirementsModel)
|
||||
+ CheckSchedule(cron string, duration uint, startDate time.Time, stopDate time.Time, requirements models.ExecutionRequirementsModel)
|
||||
+ GetSchedules(startDate time.Time, stopDate time.Time)
|
||||
+ GetNextSchedules(baseDate time.Time)
|
||||
+ GetPreviousSchedules(baseDate time.Time)
|
||||
|
||||
}
|
||||
class SearchController << (S,Aquamarine) >> {
|
||||
+ FindByWord(word string)
|
||||
|
||||
}
|
||||
class StorageController << (S,Aquamarine) >> {
|
||||
+ GetOneStorage(ID string)
|
||||
+ GetMultipleStorage(IDs []string)
|
||||
+ PostStorage(body models.StorageNEWModel)
|
||||
|
||||
}
|
||||
class UserController << (S,Aquamarine) >> {
|
||||
+ Login()
|
||||
+ Logout()
|
||||
|
||||
}
|
||||
class WorkflowController << (S,Aquamarine) >> {
|
||||
+ CreateWorkflow(workflowName string)
|
||||
+ ListWorkflows()
|
||||
+ GetWorkflow(workflowName string)
|
||||
+ AddElementWorkflow(workflowName string, rID string)
|
||||
+ MxGraphParser(workflowName string, xmlData string)
|
||||
+ MxGraphParserConsume(workflowName string)
|
||||
+ LinkElementsWorkflow(workflowName string, rObjIDsource string, rObjIDtarger string, isInput bool)
|
||||
+ GetWorkflowSchedule(workflowName string)
|
||||
+ SetWorkflowSchedule(workflowName string, cronString string, events string, isService bool, startDate time.Time, stopDate time.Time, duration uint)
|
||||
+ CheckWorkflowSchedule(workflowName string)
|
||||
+ BookWorkflowSchedule(workflowName string)
|
||||
|
||||
}
|
||||
class WorkspaceController << (S,Aquamarine) >> {
|
||||
+ AddModel(id string, rtype string)
|
||||
+ ListWorkspace()
|
||||
+ ListWorkspaceModel()
|
||||
+ DeleteElement(id string, rtype string)
|
||||
|
||||
}
|
||||
}
|
||||
"web.Controller" *-- "controllers.ComputingController"
|
||||
"web.Controller" *-- "controllers.DataController"
|
||||
"web.Controller" *-- "controllers.DatacenterController"
|
||||
"web.Controller" *-- "controllers.ScheduleController"
|
||||
"web.Controller" *-- "controllers.SearchController"
|
||||
"web.Controller" *-- "controllers.StorageController"
|
||||
"web.Controller" *-- "controllers.UserController"
|
||||
"web.Controller" *-- "controllers.WorkflowController"
|
||||
"web.Controller" *-- "controllers.WorkspaceController"
|
||||
|
||||
|
||||
@enduml
|
347
docs/UML/plantuml/diagram_object_models.puml
Normal file
347
docs/UML/plantuml/diagram_object_models.puml
Normal file
@ -0,0 +1,347 @@
|
||||
@startuml
|
||||
namespace models {
|
||||
class ComputingModel << (S,Aquamarine) >> {
|
||||
+ ID string
|
||||
|
||||
- getRtype() rtype.Rtype
|
||||
- getName() string
|
||||
|
||||
+ AddUserInput(inputs <font color=blue>map</font>[string]<font color=blue>interface</font>{})
|
||||
|
||||
}
|
||||
class ComputingNEWModel << (S,Aquamarine) >> {
|
||||
+ Name string
|
||||
+ Description string
|
||||
+ ShortDescription string
|
||||
+ Logo string
|
||||
+ Type string
|
||||
+ Owner string
|
||||
+ License string
|
||||
+ Price uint
|
||||
+ ExecutionRequirements ExecutionRequirementsModel
|
||||
+ Dinputs []string
|
||||
+ Doutputs []string
|
||||
+ Image string
|
||||
+ Command string
|
||||
+ Arguments []string
|
||||
+ Environment []string
|
||||
+ Ports []string
|
||||
|
||||
}
|
||||
class ComputingObject << (S,Aquamarine) >> {
|
||||
+ ReferenceID primitive.ObjectID
|
||||
+ Inputs []string
|
||||
+ Outputs []string
|
||||
+ DataCenterID string
|
||||
|
||||
- getHost() *string
|
||||
- setReference(rID primitive.ObjectID)
|
||||
- getReference() primitive.ObjectID
|
||||
- getRtype() rtype.Rtype
|
||||
- getModel() (ResourceModel, error)
|
||||
- getName() *string
|
||||
- isLinked(rObjID string) LinkingState
|
||||
- addLink(direction LinkingState, rID string)
|
||||
|
||||
}
|
||||
class DCstatus << (S,Aquamarine) >> {
|
||||
+ DCname string
|
||||
+ DCobjID string
|
||||
+ IsReachable bool
|
||||
+ IsAvailable bool
|
||||
+ Booked *ScheduleInfo
|
||||
+ ErrorMessage string
|
||||
|
||||
}
|
||||
class DataIO << (S,Aquamarine) >> {
|
||||
+ Counter uint
|
||||
|
||||
}
|
||||
class DataModel << (S,Aquamarine) >> {
|
||||
+ ID string
|
||||
|
||||
- getRtype() rtype.Rtype
|
||||
- getName() string
|
||||
|
||||
}
|
||||
class DataNEWModel << (S,Aquamarine) >> {
|
||||
+ Name string
|
||||
+ Description string
|
||||
+ ShortDescription string
|
||||
+ Logo string
|
||||
+ Dtype string
|
||||
+ Type string
|
||||
+ Example string
|
||||
+ Protocol []string
|
||||
+ Location string
|
||||
|
||||
}
|
||||
class DataObject << (S,Aquamarine) >> {
|
||||
+ ReferenceID primitive.ObjectID
|
||||
|
||||
- getHost() *string
|
||||
- getModel() (ResourceModel, error)
|
||||
- setReference(rID primitive.ObjectID)
|
||||
- getReference() primitive.ObjectID
|
||||
- getRtype() rtype.Rtype
|
||||
- getName() *string
|
||||
- isLinked(rID string) LinkingState
|
||||
- addLink(direction LinkingState, rObjID string)
|
||||
|
||||
}
|
||||
class DatacenterCpuModel << (S,Aquamarine) >> {
|
||||
+ Cores uint
|
||||
+ Architecture string
|
||||
+ Shared bool
|
||||
+ MinimumMemory uint
|
||||
+ Platform string
|
||||
|
||||
}
|
||||
class DatacenterGpuModel << (S,Aquamarine) >> {
|
||||
+ CudaCores uint
|
||||
+ Model string
|
||||
+ Memory uint
|
||||
+ TensorCores uint
|
||||
|
||||
}
|
||||
class DatacenterMemoryModel << (S,Aquamarine) >> {
|
||||
+ Size uint
|
||||
+ Ecc bool
|
||||
|
||||
}
|
||||
class DatacenterModel << (S,Aquamarine) >> {
|
||||
+ ID string
|
||||
|
||||
- getRtype() rtype.Rtype
|
||||
- getName() string
|
||||
|
||||
+ GetTotalCPUs() uint
|
||||
+ GetTotalGPUs() uint
|
||||
+ GetTotalRAM() uint
|
||||
|
||||
}
|
||||
class DatacenterNEWModel << (S,Aquamarine) >> {
|
||||
+ Name string
|
||||
+ Type string
|
||||
+ Acronym string
|
||||
+ Hosts []string
|
||||
+ Description string
|
||||
+ ShortDescription string
|
||||
+ Logo string
|
||||
+ CPU DatacenterCpuModel
|
||||
+ RAM DatacenterMemoryModel
|
||||
+ GPU []DatacenterGpuModel
|
||||
+ Owner string
|
||||
+ BookingPrice int
|
||||
|
||||
}
|
||||
class DatacenterObject << (S,Aquamarine) >> {
|
||||
+ ReferenceID primitive.ObjectID
|
||||
|
||||
- setReference(rID primitive.ObjectID)
|
||||
- getModel() (ResourceModel, error)
|
||||
- getReference() primitive.ObjectID
|
||||
- getHost() *string
|
||||
- getRtype() rtype.Rtype
|
||||
- getName() *string
|
||||
- isLinked(rID string) LinkingState
|
||||
- addLink(direction LinkingState, rObjID string)
|
||||
|
||||
}
|
||||
class ExecutionRequirementsModel << (S,Aquamarine) >> {
|
||||
+ CPUs uint
|
||||
+ GPUs uint
|
||||
+ RAM uint
|
||||
+ Parallel bool
|
||||
+ ScalingModel uint
|
||||
+ DiskIO string
|
||||
|
||||
}
|
||||
class MxCell << (S,Aquamarine) >> {
|
||||
+ XMLName xml.Name
|
||||
+ ID string
|
||||
+ Parent *string
|
||||
+ RID *string
|
||||
+ Source *string
|
||||
+ Target *string
|
||||
|
||||
}
|
||||
class MxGraphModel << (S,Aquamarine) >> {
|
||||
+ XMLName xml.Name
|
||||
+ Root <font color=blue>struct</font>{xml.Name, []MxCell, *[]Object}
|
||||
|
||||
}
|
||||
class Object << (S,Aquamarine) >> {
|
||||
+ XMLName xml.Name
|
||||
+ ID string
|
||||
+ Command *string
|
||||
+ Args *string
|
||||
+ Env *string
|
||||
+ MxCell MxCell
|
||||
|
||||
}
|
||||
class RepositoryModel << (S,Aquamarine) >> {
|
||||
+ Credentials string
|
||||
+ Url string
|
||||
|
||||
}
|
||||
interface ResourceModel {
|
||||
- getRtype() rtype.Rtype
|
||||
- getName() string
|
||||
|
||||
}
|
||||
interface ResourceObject {
|
||||
- getHost() *string
|
||||
- getName() *string
|
||||
- getModel() (ResourceModel, error)
|
||||
- getRtype() rtype.Rtype
|
||||
- setReference(rObjID primitive.ObjectID)
|
||||
- getReference() primitive.ObjectID
|
||||
- isLinked(rObjID string) LinkingState
|
||||
- addLink(direction LinkingState, rObjID string)
|
||||
|
||||
}
|
||||
class ScheduleDB << (S,Aquamarine) >> {
|
||||
+ StartDate time.Time
|
||||
+ StopDate time.Time
|
||||
+ Workflow string
|
||||
+ ResourceQty ExecutionRequirementsModel
|
||||
|
||||
}
|
||||
class ScheduleInfo << (S,Aquamarine) >> {
|
||||
+ Total int
|
||||
+ NextExecutions []string
|
||||
|
||||
}
|
||||
class SearchResult << (S,Aquamarine) >> {
|
||||
+ Computing []ComputingModel
|
||||
+ Datacenter []DatacenterModel
|
||||
+ Storage []StorageModel
|
||||
+ Data []DataModel
|
||||
|
||||
}
|
||||
class StorageModel << (S,Aquamarine) >> {
|
||||
+ ID string
|
||||
|
||||
- getRtype() rtype.Rtype
|
||||
- getName() string
|
||||
|
||||
+ AddUserInput(inputs <font color=blue>map</font>[string]<font color=blue>interface</font>{})
|
||||
|
||||
}
|
||||
class StorageNEWModel << (S,Aquamarine) >> {
|
||||
+ Name string
|
||||
+ Description string
|
||||
+ ShortDescription string
|
||||
+ Logo string
|
||||
+ Type string
|
||||
+ DCacronym string
|
||||
+ URL string
|
||||
+ Size uint
|
||||
+ Encryption bool
|
||||
+ Redundancy string
|
||||
+ Throughput string
|
||||
+ BookingPrice uint
|
||||
|
||||
}
|
||||
class StorageObject << (S,Aquamarine) >> {
|
||||
+ ReferenceID primitive.ObjectID
|
||||
+ Inputs []string
|
||||
+ Outputs []string
|
||||
|
||||
- getHost() *string
|
||||
- getModel() (ResourceModel, error)
|
||||
- setReference(rID primitive.ObjectID)
|
||||
- getReference() primitive.ObjectID
|
||||
- getRtype() rtype.Rtype
|
||||
- getName() *string
|
||||
- isLinked(rObjID string) LinkingState
|
||||
- addLink(direction LinkingState, rObjID string)
|
||||
|
||||
}
|
||||
class UserModel << (S,Aquamarine) >> {
|
||||
+ ID string
|
||||
+ Username string
|
||||
+ Password string
|
||||
+ Email string
|
||||
|
||||
}
|
||||
class Workflow << (S,Aquamarine) >> {
|
||||
+ Data <font color=blue>map</font>[string]DataObject
|
||||
+ Computing <font color=blue>map</font>[string]ComputingObject
|
||||
+ Storage <font color=blue>map</font>[string]StorageObject
|
||||
+ Datacenter <font color=blue>map</font>[string]DatacenterObject
|
||||
+ Schedules WorkflowSchedule
|
||||
+ MxgraphXML string
|
||||
|
||||
+ GetExecutionRequirements(dcIDobj string) (ExecutionRequirementsModel, error)
|
||||
+ GetResource(rObjID *string) ResourceObject
|
||||
+ GetResourceMapByRtype(rt rtype.Rtype) <font color=blue>interface</font>{}
|
||||
+ CreateResourceObject(rt rtype.Rtype) ResourceObject
|
||||
+ AddObj(robj ResourceObject) *primitive.ObjectID
|
||||
+ UpdateDB(userID string, workflowName string) error
|
||||
+ UpdateObj(robj ResourceObject, objID string)
|
||||
|
||||
}
|
||||
class WorkflowSchedule << (S,Aquamarine) >> {
|
||||
+ IsService bool
|
||||
+ StartDate time.Time
|
||||
+ StopDate time.Time
|
||||
+ Cron string
|
||||
+ Duration uint
|
||||
+ Events string
|
||||
+ IsBooked bool
|
||||
|
||||
}
|
||||
class Workspace << (S,Aquamarine) >> {
|
||||
+ UserID string
|
||||
+ Workflows <font color=blue>map</font>[string]Workflow
|
||||
+ Data []string
|
||||
+ Computing []string
|
||||
+ Datacenter []string
|
||||
+ Storage []string
|
||||
|
||||
- getRtype(rID string) rtype.Rtype
|
||||
- updateDB() error
|
||||
|
||||
+ ConsumeMxGraphModel(xmlmodel MxGraphModel) (*Workflow, error, []error)
|
||||
+ GetResources() <font color=blue>map</font>[rtype.Rtype][]string
|
||||
+ GetWorkflow(workflowName string) *Workflow
|
||||
+ GetWorkflows() []string
|
||||
+ NewResource(rID string, rType string) error
|
||||
+ GetAllWorkspacesProjects() <font color=blue>chan</font> *Workflow
|
||||
|
||||
}
|
||||
class WorkspaceModel << (S,Aquamarine) >> {
|
||||
+ UserID string
|
||||
+ Data []DataModel
|
||||
+ Computing []ComputingModel
|
||||
+ Datacenter []DatacenterModel
|
||||
+ Storage []StorageModel
|
||||
|
||||
}
|
||||
class models.LinkingState << (T, #FF7700) >> {
|
||||
}
|
||||
class mxissue << (S,Aquamarine) >> {
|
||||
- msg string
|
||||
|
||||
+ Error() string
|
||||
|
||||
}
|
||||
}
|
||||
"models.ComputingNEWModel" *-- "models.ComputingModel"
|
||||
"models.DataNEWModel" *-- "models.DataModel"
|
||||
"models.DatacenterNEWModel" *-- "models.DatacenterModel"
|
||||
"models.StorageNEWModel" *-- "models.StorageModel"
|
||||
|
||||
"models.ResourceModel" <|-- "models.ComputingModel"
|
||||
"models.ResourceObject" <|-- "models.ComputingObject"
|
||||
"models.ResourceModel" <|-- "models.DataModel"
|
||||
"models.ResourceObject" <|-- "models.DataObject"
|
||||
"models.ResourceModel" <|-- "models.DatacenterModel"
|
||||
"models.ResourceObject" <|-- "models.DatacenterObject"
|
||||
"models.ResourceModel" <|-- "models.StorageModel"
|
||||
"models.ResourceObject" <|-- "models.StorageObject"
|
||||
|
||||
"__builtin__.uint" #.. "models.LinkingState"
|
||||
@enduml
|
@ -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,7 +37,7 @@ 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"`
|
||||
@ -49,7 +51,7 @@ type ComputingNEWModel struct {
|
||||
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,45 @@ 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){
|
||||
|
||||
logs.Alert("AddUserInput() is going to throw some alerts while mxGraph GUI is not updated to adapt the inputs to the componant")
|
||||
|
||||
// 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
|
||||
}
|
@ -22,6 +22,14 @@ type DataNEWModel struct {
|
||||
Location string `json:"location" required:"true" validate:"required"`
|
||||
}
|
||||
|
||||
type DataIO struct {
|
||||
Counter uint `description:"Incremental number starting from 0"`
|
||||
}
|
||||
|
||||
type DataObject struct {
|
||||
ReferenceID primitive.ObjectID `json:"referenceID" description:"Data model ID"`
|
||||
}
|
||||
|
||||
type DataModel struct {
|
||||
ID string `json:"ID" bson:"_id" required:"true" validate:"required"`
|
||||
DataNEWModel `bson:",inline"`
|
||||
@ -34,15 +42,6 @@ func (obj DataModel) getRtype() rtype.Rtype {
|
||||
func (model DataModel) getName() string {
|
||||
return model.Name
|
||||
}
|
||||
|
||||
type DataIO struct {
|
||||
Counter uint `description:"Incremental number starting from 0"`
|
||||
}
|
||||
|
||||
type DataObject struct {
|
||||
ReferenceID primitive.ObjectID `json:"referenceID" description:"Data model ID"`
|
||||
}
|
||||
|
||||
func (obj DataObject) getHost() *string {
|
||||
return nil // Host is DC only attribute
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ type MxGraphModel struct {
|
||||
Root struct {
|
||||
XMLName xml.Name `xml:"root"`
|
||||
MxCell []MxCell `xml:"mxCell"`
|
||||
MxObject *[]MxObject `xml:"object"`
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,6 +21,15 @@ type MxCell struct {
|
||||
RID *string `xml:"rID,attr"`
|
||||
Source *string `xml:"source,attr"`
|
||||
Target *string `xml:"target,attr"`
|
||||
Rtype *string `xml:"rType,attr"`
|
||||
}
|
||||
|
||||
|
||||
type MxObject struct {
|
||||
XMLName xml.Name `xml:"object"`
|
||||
ID string `xml:"id,attr"`
|
||||
Settings []xml.Attr `xml:",any,attr"`
|
||||
MxCell MxCell `xml:"mxCell"`
|
||||
}
|
||||
|
||||
type mxissue struct {
|
||||
@ -33,3 +43,4 @@ func (m *mxissue) Error() string {
|
||||
func newMxIssue(message string) error {
|
||||
return &mxissue{message}
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,8 @@ import (
|
||||
"context"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"net/url"
|
||||
"os"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
@ -71,18 +73,25 @@ type ResourceObject interface {
|
||||
addLink(direction LinkingState, rObjID string)
|
||||
}
|
||||
|
||||
// This type allows to process computing and storage component
|
||||
// which can get input from the user
|
||||
type EditableResourceObject interface{
|
||||
ResourceObject
|
||||
addUserInput(map[string]interface{})
|
||||
}
|
||||
|
||||
// Get a sum of all execution requirements attached to a DC obj
|
||||
func (w Workflow) GetExecutionRequirements(dcIDobj string) (ret ExecutionRequirementsModel, err error) {
|
||||
func (wf Workflow) GetExecutionRequirements(dcIDobj string) (ret ExecutionRequirementsModel, err error) {
|
||||
|
||||
// Find the id of the DC obj
|
||||
|
||||
if _, ok := w.Datacenter[dcIDobj]; !ok {
|
||||
if _, ok := wf.Datacenter[dcIDobj]; !ok {
|
||||
return ExecutionRequirementsModel{}, errors.New("DC obj" + dcIDobj + " doesn't exist in the Workflow")
|
||||
}
|
||||
|
||||
// Get all elements that are attached to the DC
|
||||
|
||||
for _, computingObj := range w.Computing {
|
||||
for _, computingObj := range wf.Computing {
|
||||
if computingObj.DataCenterID == dcIDobj {
|
||||
mymodel, err := computingObj.getModel()
|
||||
if err != nil {
|
||||
@ -159,6 +168,7 @@ func (w *Workflow) CreateResourceObject(rt rtype.Rtype) ResourceObject {
|
||||
default:
|
||||
res = nil
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
@ -510,6 +520,14 @@ func ParseMxGraph(username, workflowName, xmlData string) (err error, mxissues [
|
||||
//return errors.New("Can't modify a booked workflow"), nil
|
||||
}
|
||||
|
||||
decodedValue, err := url.QueryUnescape(xmlData)
|
||||
if err != nil {
|
||||
return err, nil
|
||||
}
|
||||
|
||||
// TEMPORARY test the xml created
|
||||
os.WriteFile("graph.xml", []byte(decodedValue), 0660)
|
||||
|
||||
var xmlModel MxGraphModel
|
||||
|
||||
// logs.Debug(xmlData)
|
||||
@ -518,13 +536,17 @@ func ParseMxGraph(username, workflowName, xmlData string) (err error, mxissues [
|
||||
return err, nil
|
||||
}
|
||||
|
||||
// Move the attribute of the object's tags into the mxCell's for an easier processing
|
||||
|
||||
// currentWorkflow.extractMxCell(xmlModel)
|
||||
|
||||
targetWorkspaceWorkflow, err, mxissues := userWorkspace.ConsumeMxGraphModel(xmlModel)
|
||||
if err != nil {
|
||||
return err, nil
|
||||
}
|
||||
|
||||
targetWorkspaceWorkflow.MxgraphXML = xmlData
|
||||
targetWorkspaceWorkflow.Schedules = currentWorkflow.Schedules //TODO: Probably we should move schudles outside the workflow
|
||||
targetWorkspaceWorkflow.Schedules = currentWorkflow.Schedules //TODO: Probably we should move schedules outside the workflow
|
||||
|
||||
_, err = services.MngoCollWorkspace.UpdateOne(services.MngoCtx,
|
||||
primitive.M{"_id": username},
|
||||
@ -564,7 +586,8 @@ func FindSliceInSlice(slice1 []string, slice2 []string) (int, int, bool) {
|
||||
return -1, -1, false
|
||||
}
|
||||
|
||||
func (w Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Workflow, err error, issues []error) {
|
||||
// TODO : correct this method to suppport mxcells with settings
|
||||
func (ws Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Workflow, err error, issues []error) {
|
||||
|
||||
returned_wf = &Workflow{}
|
||||
|
||||
@ -574,11 +597,13 @@ func (w Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Work
|
||||
return xmlmodel.Root.MxCell[i].RID != nil
|
||||
})
|
||||
|
||||
|
||||
|
||||
// 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
|
||||
@ -586,30 +611,39 @@ func (w Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Work
|
||||
// create a computing object
|
||||
// attach the DC to it
|
||||
// update the workflow with the object : create the list of this type of component or update the list with the id of the component with the object
|
||||
|
||||
for _, object := range *xmlmodel.Root.MxObject{
|
||||
|
||||
resObj, err, mxissues := returned_wf.mxCellToComponent(object.MxCell,ws)
|
||||
if err != nil {
|
||||
issues = append(issues, mxissues...)
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
// 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){
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
for _, cell := range xmlmodel.Root.MxCell {
|
||||
|
||||
switch {
|
||||
case cell.RID != nil:
|
||||
// Case of a Resource
|
||||
rType := w.getRtype(*cell.RID)
|
||||
|
||||
if rType == rtype.INVALID {
|
||||
return nil,
|
||||
errors.New("Refering to a rID that is not in the workflow"),
|
||||
nil
|
||||
}
|
||||
|
||||
// Generate ObjectID for the reference ID
|
||||
rIDObj, err := primitive.ObjectIDFromHex(*cell.RID)
|
||||
resObj, err, mxissues := returned_wf.mxCellToComponent(cell,ws)
|
||||
if err != nil {
|
||||
return nil,
|
||||
errors.New("Bad ID format: " + *cell.RID),
|
||||
nil
|
||||
issues = append(issues, mxissues...)
|
||||
}
|
||||
|
||||
resObj := returned_wf.CreateResourceObject(rType)
|
||||
resObj.setReference(rIDObj)
|
||||
|
||||
returned_wf.UpdateObj(resObj, cell.ID)
|
||||
|
||||
case cell.ID == "0" || cell.ID == "1":
|
||||
@ -677,7 +711,7 @@ func (w Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Work
|
||||
// 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"))
|
||||
@ -1011,3 +1045,43 @@ func CheckAndBookWorkflowSchedule(username, workflowName string, book bool) (myR
|
||||
|
||||
return myRet, nil
|
||||
}
|
||||
|
||||
// Not sure if this method handles error propagation well
|
||||
func (wf Workflow) mxCellToComponent(cell MxCell, ws Workspace) (resObj ResourceObject,err error, issues []error){
|
||||
rType := ws.getRtype(*cell.RID)
|
||||
|
||||
if rType == rtype.INVALID {
|
||||
return nil,
|
||||
errors.New("Refering to a rID that is not in the workflow"),
|
||||
nil
|
||||
}
|
||||
|
||||
// Generate ObjectID for the reference ID
|
||||
rIDObj, err := primitive.ObjectIDFromHex(*cell.RID)
|
||||
if err != nil {
|
||||
return nil,
|
||||
errors.New("Bad ID format: " + *cell.RID),
|
||||
nil
|
||||
}
|
||||
|
||||
resObj = wf.CreateResourceObject(rType)
|
||||
resObj.setReference(rIDObj)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// func (ws Workspace) extractMxCell(xmlModel MxGraphModel){
|
||||
// // Iterate through all objects of the MxGraph
|
||||
// graphObjects := xmlModel.Root.MxObject
|
||||
// for _, object := range(*graphObjects){
|
||||
// current_obj_id, _ := strconv.Atoi(object.ID)
|
||||
// inside_cell_id := strconv.Itoa(current_obj_id + 1)
|
||||
|
||||
// cell := ws.GetResource(&inside_cell_id)
|
||||
// // component := w.GetResource(cell.RID)
|
||||
// fmt.Print(cell)
|
||||
// }
|
||||
// // Extract the mxCell object
|
||||
// // Invoke the addParameter method from the component
|
||||
// // Edit the ID to get the object's one
|
||||
// }
|
||||
|
Loading…
Reference in New Issue
Block a user