Merge branch 'bugfix/settings_handling'
This commit is contained in:
commit
9ebd5cd5b0
35
README.md
35
README.md
@ -63,4 +63,37 @@ This script should be updated to be ran from anywhere.
|
|||||||
|
|
||||||
# More documentation
|
# More documentation
|
||||||
|
|
||||||
[Visit the docs/ directory](/docs/)
|
[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
|
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,7 +37,7 @@ 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"`
|
||||||
@ -49,7 +51,7 @@ type ComputingNEWModel struct {
|
|||||||
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,45 @@ 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){
|
||||||
|
|
||||||
|
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
|
// 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
|
||||||
}
|
}
|
@ -22,19 +22,6 @@ type DataNEWModel struct {
|
|||||||
Location string `json:"location" required:"true" validate:"required"`
|
Location string `json:"location" required:"true" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DataModel struct {
|
|
||||||
ID string `json:"ID" bson:"_id" required:"true" validate:"required"`
|
|
||||||
DataNEWModel `bson:",inline"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (obj DataModel) getRtype() rtype.Rtype {
|
|
||||||
return rtype.DATA
|
|
||||||
}
|
|
||||||
|
|
||||||
func (model DataModel) getName() string {
|
|
||||||
return model.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
type DataIO struct {
|
type DataIO struct {
|
||||||
Counter uint `description:"Incremental number starting from 0"`
|
Counter uint `description:"Incremental number starting from 0"`
|
||||||
}
|
}
|
||||||
@ -43,6 +30,18 @@ type DataObject struct {
|
|||||||
ReferenceID primitive.ObjectID `json:"referenceID" description:"Data model ID"`
|
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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (obj DataModel) getRtype() rtype.Rtype {
|
||||||
|
return rtype.DATA
|
||||||
|
}
|
||||||
|
|
||||||
|
func (model DataModel) getName() string {
|
||||||
|
return model.Name
|
||||||
|
}
|
||||||
func (obj DataObject) getHost() *string {
|
func (obj DataObject) getHost() *string {
|
||||||
return nil // Host is DC only attribute
|
return nil // Host is DC only attribute
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,9 @@ type MxGraphModel struct {
|
|||||||
XMLName xml.Name `xml:"mxGraphModel"`
|
XMLName xml.Name `xml:"mxGraphModel"`
|
||||||
|
|
||||||
Root struct {
|
Root struct {
|
||||||
XMLName xml.Name `xml:"root"`
|
XMLName xml.Name `xml:"root"`
|
||||||
MxCell []MxCell `xml:"mxCell"`
|
MxCell []MxCell `xml:"mxCell"`
|
||||||
|
MxObject *[]MxObject `xml:"object"`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,6 +21,15 @@ type MxCell struct {
|
|||||||
RID *string `xml:"rID,attr"`
|
RID *string `xml:"rID,attr"`
|
||||||
Source *string `xml:"source,attr"`
|
Source *string `xml:"source,attr"`
|
||||||
Target *string `xml:"target,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 {
|
type mxissue struct {
|
||||||
@ -33,3 +43,4 @@ func (m *mxissue) Error() string {
|
|||||||
func newMxIssue(message string) error {
|
func newMxIssue(message string) error {
|
||||||
return &mxissue{message}
|
return &mxissue{message}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"errors"
|
"errors"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -71,18 +73,25 @@ type ResourceObject interface {
|
|||||||
addLink(direction LinkingState, rObjID string)
|
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
|
// 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
|
// 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")
|
return ExecutionRequirementsModel{}, errors.New("DC obj" + dcIDobj + " doesn't exist in the Workflow")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all elements that are attached to the DC
|
// Get all elements that are attached to the DC
|
||||||
|
|
||||||
for _, computingObj := range w.Computing {
|
for _, computingObj := range wf.Computing {
|
||||||
if computingObj.DataCenterID == dcIDobj {
|
if computingObj.DataCenterID == dcIDobj {
|
||||||
mymodel, err := computingObj.getModel()
|
mymodel, err := computingObj.getModel()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -159,6 +168,7 @@ func (w *Workflow) CreateResourceObject(rt rtype.Rtype) ResourceObject {
|
|||||||
default:
|
default:
|
||||||
res = nil
|
res = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return res
|
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
|
//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
|
var xmlModel MxGraphModel
|
||||||
|
|
||||||
// logs.Debug(xmlData)
|
// logs.Debug(xmlData)
|
||||||
@ -518,13 +536,17 @@ func ParseMxGraph(username, workflowName, xmlData string) (err error, mxissues [
|
|||||||
return err, nil
|
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)
|
targetWorkspaceWorkflow, err, mxissues := userWorkspace.ConsumeMxGraphModel(xmlModel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, nil
|
return err, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
targetWorkspaceWorkflow.MxgraphXML = xmlData
|
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,
|
_, err = services.MngoCollWorkspace.UpdateOne(services.MngoCtx,
|
||||||
primitive.M{"_id": username},
|
primitive.M{"_id": username},
|
||||||
@ -564,7 +586,8 @@ func FindSliceInSlice(slice1 []string, slice2 []string) (int, int, bool) {
|
|||||||
return -1, -1, false
|
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{}
|
returned_wf = &Workflow{}
|
||||||
|
|
||||||
@ -574,11 +597,13 @@ func (w Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Work
|
|||||||
return xmlmodel.Root.MxCell[i].RID != nil
|
return xmlmodel.Root.MxCell[i].RID != nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 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
|
||||||
@ -586,30 +611,39 @@ func (w Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Work
|
|||||||
// create a computing object
|
// create a computing object
|
||||||
// attach the DC to it
|
// 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
|
// 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 {
|
for _, cell := range xmlmodel.Root.MxCell {
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case cell.RID != nil:
|
case cell.RID != nil:
|
||||||
// Case of a Resource
|
resObj, err, mxissues := returned_wf.mxCellToComponent(cell,ws)
|
||||||
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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil,
|
issues = append(issues, mxissues...)
|
||||||
errors.New("Bad ID format: " + *cell.RID),
|
|
||||||
nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resObj := returned_wf.CreateResourceObject(rType)
|
|
||||||
resObj.setReference(rIDObj)
|
|
||||||
|
|
||||||
returned_wf.UpdateObj(resObj, cell.ID)
|
returned_wf.UpdateObj(resObj, cell.ID)
|
||||||
|
|
||||||
case cell.ID == "0" || cell.ID == "1":
|
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)
|
// 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"))
|
||||||
@ -1005,9 +1039,49 @@ func CheckAndBookWorkflowSchedule(username, workflowName string, book bool) (myR
|
|||||||
SchedulesDB: ¤tWorkflow.Schedules}},
|
SchedulesDB: ¤tWorkflow.Schedules}},
|
||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logs.Critical("Internal error when updating in DB: " + err.Error())
|
logs.Critical("Internal error when updating in DB: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return myRet, nil
|
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