diff --git a/doc/model.puml b/doc/model.puml index a7bd83b..ce1d9ce 100644 --- a/doc/model.puml +++ b/doc/model.puml @@ -7,15 +7,15 @@ abstract Ressource { +icon: string +description: string +graphic: GraphicElement - +element: Data/Processing/Storage/Workflow/Datacenter + +element: DataResource/ProcessingResource/StorageResource/Workflow/DatacenterResource } -class Data { +class DataResource { +UUID: int +name: string } -class Processing { +class ProcessingResource { +UUID: int +name: string +container: string @@ -24,14 +24,14 @@ class Processing { } -class Storage { +class StorageResource { +UUID: int +name: string +url: string +capacity: int } -class Datacenter { +class DatacenterResource { +UUID: int +name: string @@ -96,7 +96,7 @@ class UserWorkflows { class DatacenterWorkflows { +UUID: int - +datacenter: Datacenter + +datacenter: DatacenterResource +workflows: Workflow[] } @@ -112,10 +112,10 @@ UserWorkflows "1" o-- "0..*" Workflow DatacenterWorkflows "1" o-- "0..*" Workflow -Ressource <|-- Data -Ressource <|-- Processing -Ressource <|-- Storage -Ressource <|-- Datacenter +Ressource <|-- DataResource +Ressource <|-- ProcessingResource +Ressource <|-- StorageResource +Ressource <|-- DatacenterResource Ressource <|-- Workflow ResourceSet "1" o-- "0..*" Ressource diff --git a/entrypoint.go b/entrypoint.go index 444a2c2..b5c9745 100644 --- a/entrypoint.go +++ b/entrypoint.go @@ -4,7 +4,6 @@ import ( "cloud.o-forge.io/core/oc-lib/dbs/mongo" "cloud.o-forge.io/core/oc-lib/logs" "cloud.o-forge.io/core/oc-lib/models" - "cloud.o-forge.io/core/oc-lib/models/resources" "cloud.o-forge.io/core/oc-lib/models/utils" "github.com/rs/zerolog" ) @@ -12,12 +11,13 @@ import ( type LibDataEnum int const ( - INVALID LibDataEnum = iota - DATA = resources.DATA - PROCESSING = resources.PROCESSING - STORAGE = resources.STORAGE - DATACENTER = resources.DATACENTER - WORKFLOW = resources.WORKFLOW + INVALID LibDataEnum = iota + DATA_RESOURCE = utils.DATA_RESOURCE + PROCESSING_RESOURCE = utils.PROCESSING_RESOURCE + STORAGE_RESOURCE = utils.STORAGE_RESOURCE + DATACENTER_RESOURCE = utils.DATACENTER_RESOURCE + WORKFLOW_RESOURCE = utils.WORKFLOW_RESOURCE + WORKFLOW = utils.WORKFLOW ) func (d LibDataEnum) EnumIndex() int { @@ -25,8 +25,8 @@ func (d LibDataEnum) EnumIndex() int { } type LibData struct { - Data utils.DBObject `bson:"data" json:"data"` - Err error `bson:"error" json:"error"` + DataResource utils.DBObject `bson:"data" json:"data"` + Err error `bson:"error" json:"error"` } func Init(appName string) { @@ -41,23 +41,23 @@ func GetLogger() zerolog.Logger { func LoadOne(collection LibDataEnum, id string) LibData { d, err := models.Model(collection.EnumIndex()).GetAccessor().LoadOne(id) - return LibData{Data: d, Err: err} + return LibData{DataResource: d, Err: err} } func UpdateOne(collection LibDataEnum, set map[string]interface{}, id string) LibData { model := models.Model(collection.EnumIndex()) set = model.Deserialize(set).Serialize() d, err := model.GetAccessor().UpdateOne(set, id) - return LibData{Data: d, Err: err} + return LibData{DataResource: d, Err: err} } func DeleteOne(collection LibDataEnum, id string) LibData { d, err := models.Model(collection.EnumIndex()).GetAccessor().DeleteOne(id) - return LibData{Data: d, Err: err} + return LibData{DataResource: d, Err: err} } func StoreOne(collection LibDataEnum, object map[string]interface{}) LibData { model := models.Model(collection.EnumIndex()) d, err := model.GetAccessor().StoreOne(model.Deserialize(object)) - return LibData{Data: d, Err: err} + return LibData{DataResource: d, Err: err} } diff --git a/go.mod b/go.mod index 0e84393..a8192e5 100644 --- a/go.mod +++ b/go.mod @@ -23,6 +23,7 @@ require ( github.com/go-playground/validator/v10 v10.22.0 // indirect github.com/go-stack/stack v1.8.1 // indirect github.com/golang/snappy v0.0.4 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/klauspost/compress v1.17.9 // indirect github.com/leodido/go-urn v1.4.0 // indirect diff --git a/go.sum b/go.sum index 7b55d9f..0e8f24c 100644 --- a/go.sum +++ b/go.sum @@ -50,6 +50,8 @@ github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= diff --git a/models/models.go b/models/models.go index d331904..8ee20ad 100644 --- a/models/models.go +++ b/models/models.go @@ -2,29 +2,31 @@ package models import ( "cloud.o-forge.io/core/oc-lib/logs" - r "cloud.o-forge.io/core/oc-lib/models/resources" + d "cloud.o-forge.io/core/oc-lib/models/resources/data" dc "cloud.o-forge.io/core/oc-lib/models/resources/datacenter" p "cloud.o-forge.io/core/oc-lib/models/resources/processing" s "cloud.o-forge.io/core/oc-lib/models/resources/storage" w "cloud.o-forge.io/core/oc-lib/models/resources/workflow" "cloud.o-forge.io/core/oc-lib/models/utils" + w2 "cloud.o-forge.io/core/oc-lib/models/workflow" ) var models = map[string]func() utils.DBObject{ - r.WORKFLOW.String(): func() utils.DBObject { return &w.Workflow{} }, - r.DATA.String(): func() utils.DBObject { return &d.Data{} }, - r.DATACENTER.String(): func() utils.DBObject { return &dc.Datacenter{} }, - r.STORAGE.String(): func() utils.DBObject { return &s.Storage{} }, - r.PROCESSING.String(): func() utils.DBObject { return &p.Processing{} }, + utils.WORKFLOW_RESOURCE.String(): func() utils.DBObject { return &w.WorkflowResource{} }, + utils.DATA_RESOURCE.String(): func() utils.DBObject { return &d.DataResource{} }, + utils.DATACENTER_RESOURCE.String(): func() utils.DBObject { return &dc.DatacenterResource{} }, + utils.STORAGE_RESOURCE.String(): func() utils.DBObject { return &s.StorageResource{} }, + utils.PROCESSING_RESOURCE.String(): func() utils.DBObject { return &p.ProcessingResource{} }, + utils.WORKFLOW.String(): func() utils.DBObject { return &w2.Workflow{} }, } func Model(model int) utils.DBObject { log := logs.GetLogger() - if _, ok := models[r.FromInt(model)]; ok { - return models[r.FromInt(model)]() + if _, ok := models[utils.FromInt(model)]; ok { + return models[utils.FromInt(model)]() } - log.Error().Msg("Can't find model " + r.FromInt(model) + ".") + log.Error().Msg("Can't find model " + utils.FromInt(model) + ".") return nil } diff --git a/models/resources/data/data.go b/models/resources/data/data.go index 3d6cc00..ceacb36 100644 --- a/models/resources/data/data.go +++ b/models/resources/data/data.go @@ -7,14 +7,14 @@ import ( "cloud.o-forge.io/core/oc-lib/models/utils" ) -type Data struct { +type DataResource struct { resources.AbstractResource Protocols []string `json:"protocol,omitempty" bson:"protocol,omitempty"` //TODO Enum type DataType string `json:"datatype" required:"true" bson:"datatype"` Example string `json:"example" bson:"example" required:"true" validate:"required" description:"base64 encoded data"` } -func (dma *Data) Deserialize(j map[string]interface{}) utils.DBObject { +func (dma *DataResource) Deserialize(j map[string]interface{}) utils.DBObject { b, err := json.Marshal(j) if err != nil { return nil @@ -23,7 +23,7 @@ func (dma *Data) Deserialize(j map[string]interface{}) utils.DBObject { return dma } -func (dma *Data) Serialize() map[string]interface{} { +func (dma *DataResource) Serialize() map[string]interface{} { var m map[string]interface{} b, err := json.Marshal(dma) if err != nil { @@ -33,12 +33,8 @@ func (dma *Data) Serialize() map[string]interface{} { return m } -func (d *Data) GetType() resources.ResourceType { - return resources.DATA -} - -func (d *Data) GetAccessor() utils.Accessor { +func (d *DataResource) GetAccessor() utils.Accessor { data := &DataMongoAccessor{} - data.SetLogger(resources.DATA) + data.SetLogger(utils.DATACENTER_RESOURCE) return data } diff --git a/models/resources/data/data_mongo_accessor.go b/models/resources/data/data_mongo_accessor.go index 6555d09..6a600c7 100644 --- a/models/resources/data/data_mongo_accessor.go +++ b/models/resources/data/data_mongo_accessor.go @@ -18,20 +18,11 @@ func (dma *DataMongoAccessor) UpdateOne(set map[string]interface{}, id string) ( } func (dma *DataMongoAccessor) StoreOne(data utils.DBObject) (utils.DBObject, error) { - err := utils.Validate.Struct(data) - if err != nil { - return nil, err - } - id, err := mongo.MONGOService.StoreOne(data.(*Data), dma.GetType()) - if err != nil { - dma.Logger.Error().Msg("Could not store " + data.GetName() + " to db. Error: " + err.Error()) - return nil, err - } - return dma.LoadOne(id) + return dma.GenericStoreOne(data, dma) } func (dma *DataMongoAccessor) LoadOne(id string) (utils.DBObject, error) { - var data Data + var data DataResource res_mongo, err := mongo.MONGOService.LoadOne(id, dma.GetType()) if err != nil { dma.Logger.Error().Msg("Could not retrieve " + id + " from db. Error: " + err.Error()) diff --git a/models/resources/data/data_test.go b/models/resources/data/data_test.go index 5ba8353..e266ce6 100644 --- a/models/resources/data/data_test.go +++ b/models/resources/data/data_test.go @@ -4,20 +4,20 @@ import ( "testing" resources "cloud.o-forge.io/core/oc-lib/models/resources" + "cloud.o-forge.io/core/oc-lib/models/utils" "github.com/stretchr/testify/assert" ) func TestStoreOneData(t *testing.T) { - d := Data{DataType: "jpeg", Example: "123456", + d := DataResource{DataType: "jpeg", Example: "123456", AbstractResource: resources.AbstractResource{ - Uuid: "123", - Name: "testData", - Description: "Lorem Ipsum", - Logo: "azerty.com", - Owner: "toto", - OwnerLogo: "totoLogo", - SourceUrl: "azerty.fr", + AbstractObject: utils.AbstractObject{Name: "testData"}, + Description: "Lorem Ipsum", + Logo: "azerty.com", + Owner: "toto", + OwnerLogo: "totoLogo", + SourceUrl: "azerty.fr", }, } @@ -28,15 +28,14 @@ func TestStoreOneData(t *testing.T) { } func TestLoadOneDate(t *testing.T) { - d := Data{DataType: "jpeg", Example: "123456", + d := DataResource{DataType: "jpeg", Example: "123456", AbstractResource: resources.AbstractResource{ - Uuid: "123", - Name: "testData", - Description: "Lorem Ipsum", - Logo: "azerty.com", - Owner: "toto", - OwnerLogo: "totoLogo", - SourceUrl: "azerty.fr", + AbstractObject: utils.AbstractObject{Name: "testData"}, + Description: "Lorem Ipsum", + Logo: "azerty.com", + Owner: "toto", + OwnerLogo: "totoLogo", + SourceUrl: "azerty.fr", }, } diff --git a/models/resources/datacenter/datacenter.go b/models/resources/datacenter/datacenter.go index bf1c2f5..98a4f43 100644 --- a/models/resources/datacenter/datacenter.go +++ b/models/resources/datacenter/datacenter.go @@ -7,7 +7,7 @@ import ( "cloud.o-forge.io/core/oc-lib/models/utils" ) -type Datacenter struct { +type DatacenterResource struct { resources.AbstractResource Owner string `bson:"owner" json:"owner" required:"true"` BookingPrice int `bson:"booking_price" json:"booking_price" required:"true"` @@ -37,7 +37,7 @@ type DatacenterGpuModel struct { TensorCores uint `bson:"tensor_cores,omitempty" json:"tensor_cores,omitempty"` } -func (dma *Datacenter) Deserialize(j map[string]interface{}) utils.DBObject { +func (dma *DatacenterResource) Deserialize(j map[string]interface{}) utils.DBObject { b, err := json.Marshal(j) if err != nil { return nil @@ -46,7 +46,7 @@ func (dma *Datacenter) Deserialize(j map[string]interface{}) utils.DBObject { return dma } -func (dma *Datacenter) Serialize() map[string]interface{} { +func (dma *DatacenterResource) Serialize() map[string]interface{} { var m map[string]interface{} b, err := json.Marshal(dma) if err != nil { @@ -56,12 +56,8 @@ func (dma *Datacenter) Serialize() map[string]interface{} { return m } -func (d *Datacenter) GetType() resources.ResourceType { - return resources.DATACENTER -} - -func (d *Datacenter) GetAccessor() utils.Accessor { +func (d *DatacenterResource) GetAccessor() utils.Accessor { data := &DatacenterMongoAccessor{} - data.SetLogger(resources.DATACENTER) + data.SetLogger(utils.DATACENTER_RESOURCE) return data } diff --git a/models/resources/datacenter/datacenter_mongo_accessor.go b/models/resources/datacenter/datacenter_mongo_accessor.go index 700abea..02e7f4c 100644 --- a/models/resources/datacenter/datacenter_mongo_accessor.go +++ b/models/resources/datacenter/datacenter_mongo_accessor.go @@ -18,20 +18,11 @@ func (dca *DatacenterMongoAccessor) UpdateOne(set map[string]interface{}, id str } func (dca *DatacenterMongoAccessor) StoreOne(data utils.DBObject) (utils.DBObject, error) { - err := utils.Validate.Struct(data) - if err != nil { - return nil, err - } - id, err := mongo.MONGOService.StoreOne(data.(*Datacenter), dca.GetType()) - if err != nil { - dca.Logger.Error().Msg("Could not store " + data.GetName() + " to db. Error: " + err.Error()) - return nil, err - } - return dca.LoadOne(id) + return dca.GenericStoreOne(data, dca) } func (dca *DatacenterMongoAccessor) LoadOne(id string) (utils.DBObject, error) { - var datacenter Datacenter + var datacenter DatacenterResource res_mongo, err := mongo.MONGOService.LoadOne(id, dca.GetType()) if err != nil { diff --git a/models/resources/datacenter/datacenter_test.go b/models/resources/datacenter/datacenter_test.go index ee7e8af..9128f91 100644 --- a/models/resources/datacenter/datacenter_test.go +++ b/models/resources/datacenter/datacenter_test.go @@ -4,20 +4,20 @@ import ( "testing" resources "cloud.o-forge.io/core/oc-lib/models/resources" + "cloud.o-forge.io/core/oc-lib/models/utils" "github.com/stretchr/testify/assert" ) func TestStoreOneDatacenter(t *testing.T) { - dc := Datacenter{Owner: "toto", BookingPrice: 123, + dc := DatacenterResource{Owner: "toto", BookingPrice: 123, AbstractResource: resources.AbstractResource{ - Uuid: "123", - Name: "testDatacenter", - Description: "Lorem Ipsum", - Logo: "azerty.com", - Owner: "toto", - OwnerLogo: "totoLogo", - SourceUrl: "azerty.fr", + AbstractObject: utils.AbstractObject{Name: "testDatacenter"}, + Description: "Lorem Ipsum", + Logo: "azerty.com", + Owner: "toto", + OwnerLogo: "totoLogo", + SourceUrl: "azerty.fr", }, } @@ -28,15 +28,14 @@ func TestStoreOneDatacenter(t *testing.T) { } func TestLoadOneDatacenter(t *testing.T) { - dc := Datacenter{Owner: "toto", BookingPrice: 123, + dc := DatacenterResource{Owner: "toto", BookingPrice: 123, AbstractResource: resources.AbstractResource{ - Uuid: "123", - Name: "testDatacenter", - Description: "Lorem Ipsum", - Logo: "azerty.com", - Owner: "toto", - OwnerLogo: "totoLogo", - SourceUrl: "azerty.fr", + AbstractObject: utils.AbstractObject{Name: "testDatacenter"}, + Description: "Lorem Ipsum", + Logo: "azerty.com", + Owner: "toto", + OwnerLogo: "totoLogo", + SourceUrl: "azerty.fr", }, } diff --git a/models/resources/processing/processing.go b/models/resources/processing/processing.go index d967193..61503ed 100644 --- a/models/resources/processing/processing.go +++ b/models/resources/processing/processing.go @@ -7,7 +7,7 @@ import ( "cloud.o-forge.io/core/oc-lib/models/utils" ) -type Processing struct { +type ProcessingResource struct { resources.AbstractResource Container string `bson:"container,omitempty" json:"container,omitempty"` // We could create a specific class for container, that could check if the name exists/is available Repository string `bson:"repository,omitempty" json:"repository,omitempty"` // Indicate where to find the container image => Could add a struct handling authentication to the repo @@ -31,7 +31,7 @@ type ExecutionRequirementsModel struct { DiskIO string `bson:"disk_io,omitempty" json:"disk_io,omitempty"` } -func (dma *Processing) Deserialize(j map[string]interface{}) utils.DBObject { +func (dma *ProcessingResource) Deserialize(j map[string]interface{}) utils.DBObject { b, err := json.Marshal(j) if err != nil { return nil @@ -40,7 +40,7 @@ func (dma *Processing) Deserialize(j map[string]interface{}) utils.DBObject { return dma } -func (dma *Processing) Serialize() map[string]interface{} { +func (dma *ProcessingResource) Serialize() map[string]interface{} { var m map[string]interface{} b, err := json.Marshal(dma) if err != nil { @@ -50,12 +50,8 @@ func (dma *Processing) Serialize() map[string]interface{} { return m } -func (p *Processing) GetType() resources.ResourceType { - return resources.PROCESSING -} - -func (d *Processing) GetAccessor() utils.Accessor { +func (d *ProcessingResource) GetAccessor() utils.Accessor { data := &ProcessingMongoAccessor{} - data.SetLogger(resources.PROCESSING) + data.SetLogger(utils.PROCESSING_RESOURCE) return data } diff --git a/models/resources/processing/processing_mongo_accessor.go b/models/resources/processing/processing_mongo_accessor.go index 85dd413..91d5b6a 100644 --- a/models/resources/processing/processing_mongo_accessor.go +++ b/models/resources/processing/processing_mongo_accessor.go @@ -18,21 +18,12 @@ func (pma *ProcessingMongoAccessor) UpdateOne(set map[string]interface{}, id str } func (pma *ProcessingMongoAccessor) StoreOne(data utils.DBObject) (utils.DBObject, error) { - err := utils.Validate.Struct(data) - if err != nil { - return nil, err - } - id, err := mongo.MONGOService.StoreOne(data.(*Processing), pma.GetType()) - if err != nil { - pma.Logger.Error().Msg("Could not store " + data.GetName() + " to db. Error: " + err.Error()) - return nil, err - } - return pma.LoadOne(id) + return pma.GenericStoreOne(data, pma) } func (pma *ProcessingMongoAccessor) LoadOne(id string) (utils.DBObject, error) { - var processing Processing + var processing ProcessingResource res_mongo, err := mongo.MONGOService.LoadOne(id, pma.GetType()) if err != nil { diff --git a/models/resources/processing/processing_test.go b/models/resources/processing/processing_test.go index 2642c2c..832319c 100644 --- a/models/resources/processing/processing_test.go +++ b/models/resources/processing/processing_test.go @@ -4,20 +4,20 @@ import ( "testing" resources "cloud.o-forge.io/core/oc-lib/models/resources" + "cloud.o-forge.io/core/oc-lib/models/utils" "github.com/stretchr/testify/assert" ) func TestStoreOneProcessing(t *testing.T) { - p := Processing{Container: "totoCont", + p := ProcessingResource{Container: "totoCont", AbstractResource: resources.AbstractResource{ - Uuid: "123", - Name: "testData", - Description: "Lorem Ipsum", - Logo: "azerty.com", - Owner: "toto", - OwnerLogo: "totoLogo", - SourceUrl: "azerty.fr", + AbstractObject: utils.AbstractObject{Name: "testData"}, + Description: "Lorem Ipsum", + Logo: "azerty.com", + Owner: "toto", + OwnerLogo: "totoLogo", + SourceUrl: "azerty.fr", }, } @@ -28,15 +28,14 @@ func TestStoreOneProcessing(t *testing.T) { } func TestLoadOneProcessing(t *testing.T) { - p := Processing{Container: "totoCont", + p := ProcessingResource{Container: "totoCont", AbstractResource: resources.AbstractResource{ - Uuid: "123", - Name: "testData", - Description: "Lorem Ipsum", - Logo: "azerty.com", - Owner: "toto", - OwnerLogo: "totoLogo", - SourceUrl: "azerty.fr", + AbstractObject: utils.AbstractObject{Name: "testData"}, + Description: "Lorem Ipsum", + Logo: "azerty.com", + Owner: "toto", + OwnerLogo: "totoLogo", + SourceUrl: "azerty.fr", }, } diff --git a/models/resources/resource.go b/models/resources/resource.go index 68fb683..fb43176 100644 --- a/models/resources/resource.go +++ b/models/resources/resource.go @@ -1,51 +1,21 @@ package resources +import ( + "cloud.o-forge.io/core/oc-lib/models/utils" +) + // AbstractResource is the struct containing all of the attributes commons to all ressources // Resource is the interface to be implemented by all classes inheriting from Resource to have the same behavior //http://www.inanzzz.com/index.php/post/wqbs/a-basic-usage-of-int-and-string-enum-types-in-golang -type ResourceType int - -const ( - INVALID ResourceType = iota - DATA - PROCESSING - STORAGE - DATACENTER - WORKFLOW -) - -var str = [...]string{ - "invalid", - "data", - "processing", - "storage", - "datacenter", - "workflow", -} - -func FromInt(i int) string { - return str[i] -} - -func (d ResourceType) String() string { - return str[d] -} - -// EnumIndex - Creating common behavior - give the type a EnumIndex functio -func (d ResourceType) EnumIndex() int { - return int(d) -} - type Resource interface { - GetType() ResourceType + GetType() utils.DataType } type AbstractResource struct { - Uuid string `json:"uuid" required:"true" bson:"uuid" validate:"required"` - Name string `json:"name" required:"true" bson:"name" validate:"required"` + utils.AbstractObject ShortDescription string `json:"short_description" required:"true" bson:"short_description" validate:"required"` Description string `json:"description,omitempty" bson:"description"` Logo string `json:"logo" required:"true" bson:"logo" validate:"required"` @@ -55,7 +25,7 @@ type AbstractResource struct { } func (r *AbstractResource) GetID() string { - return r.Uuid + return r.UUID } func (r *AbstractResource) GetName() string { diff --git a/models/resources/storage/storage.go b/models/resources/storage/storage.go index 7cc1e68..baf5f24 100644 --- a/models/resources/storage/storage.go +++ b/models/resources/storage/storage.go @@ -12,7 +12,7 @@ type URL struct { Path string `bson:"path" json:"path"` } -type Storage struct { +type StorageResource struct { resources.AbstractResource Capacity uint `bson:"capacity,omitempty" json:"capacity,omitempty"` @@ -24,7 +24,7 @@ type Storage struct { BookingPrice uint `bson:"booking_price,omitempty" json:"booking_price,omitempty"` } -func (dma *Storage) Deserialize(j map[string]interface{}) utils.DBObject { +func (dma *StorageResource) Deserialize(j map[string]interface{}) utils.DBObject { b, err := json.Marshal(j) if err != nil { return nil @@ -33,7 +33,7 @@ func (dma *Storage) Deserialize(j map[string]interface{}) utils.DBObject { return dma } -func (dma *Storage) Serialize() map[string]interface{} { +func (dma *StorageResource) Serialize() map[string]interface{} { var m map[string]interface{} b, err := json.Marshal(dma) if err != nil { @@ -43,8 +43,8 @@ func (dma *Storage) Serialize() map[string]interface{} { return m } -func (d *Storage) GetAccessor() utils.Accessor { +func (d *StorageResource) GetAccessor() utils.Accessor { data := &StorageMongoAccessor{} - data.SetLogger(resources.STORAGE) + data.SetLogger(utils.STORAGE_RESOURCE) return data } diff --git a/models/resources/storage/storage_mongo_accessor.go b/models/resources/storage/storage_mongo_accessor.go index 6fb1c2f..fdf1b57 100644 --- a/models/resources/storage/storage_mongo_accessor.go +++ b/models/resources/storage/storage_mongo_accessor.go @@ -18,21 +18,12 @@ func (sma *StorageMongoAccessor) UpdateOne(set map[string]interface{}, id string } func (sma *StorageMongoAccessor) StoreOne(data utils.DBObject) (utils.DBObject, error) { - err := utils.Validate.Struct(data) - if err != nil { - return nil, err - } - id, err := mongo.MONGOService.StoreOne(data.(*Storage), sma.GetType()) - if err != nil { - sma.Logger.Error().Msg("Could not store " + data.GetName() + " to db. Error: " + err.Error()) - return nil, err - } - return sma.LoadOne(id) + return sma.GenericStoreOne(data, sma) } func (sma *StorageMongoAccessor) LoadOne(id string) (utils.DBObject, error) { - var storage Storage + var storage StorageResource res_mongo, err := mongo.MONGOService.LoadOne(id, sma.GetType()) if err != nil { diff --git a/models/resources/storage/storage_test.go b/models/resources/storage/storage_test.go index d5194de..8a25772 100644 --- a/models/resources/storage/storage_test.go +++ b/models/resources/storage/storage_test.go @@ -4,20 +4,20 @@ import ( "testing" resources "cloud.o-forge.io/core/oc-lib/models/resources" + "cloud.o-forge.io/core/oc-lib/models/utils" "github.com/stretchr/testify/assert" ) func TestStoreOneStorage(t *testing.T) { - s := Storage{Capacity: 123, Url: URL{Protocol: "http", Path: "azerty.fr"}, + s := StorageResource{Capacity: 123, Url: URL{Protocol: "http", Path: "azerty.fr"}, AbstractResource: resources.AbstractResource{ - Uuid: "123", - Name: "testData", - Description: "Lorem Ipsum", - Logo: "azerty.com", - Owner: "toto", - OwnerLogo: "totoLogo", - SourceUrl: "azerty.fr", + AbstractObject: utils.AbstractObject{Name: "testData"}, + Description: "Lorem Ipsum", + Logo: "azerty.com", + Owner: "toto", + OwnerLogo: "totoLogo", + SourceUrl: "azerty.fr", }, } @@ -28,15 +28,14 @@ func TestStoreOneStorage(t *testing.T) { } func TestLoadOneStorage(t *testing.T) { - s := Storage{Capacity: 123, Url: URL{Protocol: "http", Path: "azerty.fr"}, + s := StorageResource{Capacity: 123, Url: URL{Protocol: "http", Path: "azerty.fr"}, AbstractResource: resources.AbstractResource{ - Uuid: "123", - Name: "testData", - Description: "Lorem Ipsum", - Logo: "azerty.com", - Owner: "toto", - OwnerLogo: "totoLogo", - SourceUrl: "azerty.fr", + AbstractObject: utils.AbstractObject{Name: "testData"}, + Description: "Lorem Ipsum", + Logo: "azerty.com", + Owner: "toto", + OwnerLogo: "totoLogo", + SourceUrl: "azerty.fr", }, } diff --git a/models/resources/workflow/workflow.go b/models/resources/workflow/workflow.go index a3caa02..37419b9 100644 --- a/models/resources/workflow/workflow.go +++ b/models/resources/workflow/workflow.go @@ -12,42 +12,17 @@ import ( "cloud.o-forge.io/core/oc-lib/models/utils" ) -type Workflow struct { - resources.AbstractResource - Graph graph.Graph `bson:"graph,omitempty" json:"graph,omitempty"` - Datas map[string]data.Data `bson:"datas,omitempty" json:"datas,omitempty"` - Storages map[string]storage.Storage `bson:"storages,omitempty" json:"storages,omitempty"` - Processing map[string]processing.Processing `bson:"processing,omitempty" json:"processing,omitempty"` - Datacenters map[string]datacenter.Datacenter `bson:"datacenters,omitempty" json:"datacenters,omitempty"` - Schedule WorkflowSchedule `bson:"schedule,omitempty" json:"schedule,omitempty"` +type AbstractWorkflow struct { + Graph graph.Graph `bson:"graph,omitempty" json:"graph,omitempty"` + Datas map[string]data.DataResource `bson:"datas,omitempty" json:"datas,omitempty"` + Storages map[string]storage.StorageResource `bson:"storages,omitempty" json:"storages,omitempty"` + ProcessingResource map[string]processing.ProcessingResource `bson:"processing,omitempty" json:"processing,omitempty"` + Datacenters map[string]datacenter.DatacenterResource `bson:"datacenters,omitempty" json:"datacenters,omitempty"` + Workflows map[string]WorkflowResource `bson:"workflows,omitempty" json:"workflows,omitempty"` + Schedule WorkflowSchedule `bson:"schedule,omitempty" json:"schedule,omitempty"` } -func (d *Workflow) GetAccessor() utils.Accessor { - data := &WorkflowMongoAccessor{} - data.SetLogger(resources.WORKFLOW) - return data -} - -func (dma *Workflow) Deserialize(j map[string]interface{}) utils.DBObject { - b, err := json.Marshal(j) - if err != nil { - return nil - } - json.Unmarshal(b, dma) - return dma -} - -func (dma *Workflow) Serialize() map[string]interface{} { - var m map[string]interface{} - b, err := json.Marshal(dma) - if err != nil { - return nil - } - json.Unmarshal(b, dma) - return m -} - -func (w *Workflow) isDCLink(link graph.GraphLink) bool { +func (w *AbstractWorkflow) isDCLink(link graph.GraphLink) bool { if _, exists := w.Datacenters[link.Destination.ID]; exists { return true } else if _, exists := w.Datacenters[link.Source.ID]; exists { @@ -56,3 +31,34 @@ func (w *Workflow) isDCLink(link graph.GraphLink) bool { return false } + +type WorkflowResource struct { + resources.AbstractResource + AbstractWorkflow + WorkflowID string `bson:"workflow_id,omitempty" json:"workflow_id,omitempty"` +} + +func (d *WorkflowResource) GetAccessor() utils.Accessor { + data := &WorkflowResourceMongoAccessor{} + data.SetLogger(utils.WORKFLOW_RESOURCE) + return data +} + +func (dma *WorkflowResource) Deserialize(j map[string]interface{}) utils.DBObject { + b, err := json.Marshal(j) + if err != nil { + return nil + } + json.Unmarshal(b, dma) + return dma +} + +func (dma *WorkflowResource) Serialize() map[string]interface{} { + var m map[string]interface{} + b, err := json.Marshal(dma) + if err != nil { + return nil + } + json.Unmarshal(b, dma) + return m +} diff --git a/models/resources/workflow/workflow_mongo_accessor.go b/models/resources/workflow/workflow_mongo_accessor.go index aef9082..0e1fbe0 100644 --- a/models/resources/workflow/workflow_mongo_accessor.go +++ b/models/resources/workflow/workflow_mongo_accessor.go @@ -5,34 +5,24 @@ import ( "cloud.o-forge.io/core/oc-lib/models/utils" ) -type WorkflowMongoAccessor struct { +type WorkflowResourceMongoAccessor struct { utils.AbstractAccessor } -func (wfa *WorkflowMongoAccessor) DeleteOne(id string) (utils.DBObject, error) { +func (wfa *WorkflowResourceMongoAccessor) DeleteOne(id string) (utils.DBObject, error) { return wfa.GenericDeleteOne(id, wfa) } -func (wfa *WorkflowMongoAccessor) UpdateOne(set map[string]interface{}, id string) (utils.DBObject, error) { +func (wfa *WorkflowResourceMongoAccessor) UpdateOne(set map[string]interface{}, id string) (utils.DBObject, error) { return wfa.GenericUpdateOne(set, id, wfa) } -func (wfa *WorkflowMongoAccessor) StoreOne(data utils.DBObject) (utils.DBObject, error) { - err := utils.Validate.Struct(data) - wfa.Logger.Error().Msg("Could not store " + data.GetName() + " to db. Error: " + err.Error()) - if err != nil { - return nil, err - } - id, err := mongo.MONGOService.StoreOne(data.(*Workflow), wfa.GetType()) - if err != nil { - wfa.Logger.Error().Msg("Could not store " + data.GetName() + " to db. Error: " + err.Error()) - return nil, err - } - return wfa.LoadOne(id) +func (wfa *WorkflowResourceMongoAccessor) StoreOne(data utils.DBObject) (utils.DBObject, error) { + return wfa.GenericStoreOne(data, wfa) } -func (wfa *WorkflowMongoAccessor) LoadOne(id string) (utils.DBObject, error) { - var workflow Workflow +func (wfa *WorkflowResourceMongoAccessor) LoadOne(id string) (utils.DBObject, error) { + var workflow WorkflowResource res_mongo, err := mongo.MONGOService.LoadOne(id, wfa.GetType()) if err != nil { wfa.Logger.Error().Msg("Could not retrieve " + id + " from db. Error: " + err.Error()) diff --git a/models/resources/workflow/workflow_test.go b/models/resources/workflow/workflow_test.go index d3a6163..86c3a96 100644 --- a/models/resources/workflow/workflow_test.go +++ b/models/resources/workflow/workflow_test.go @@ -4,41 +4,40 @@ import ( "testing" "cloud.o-forge.io/core/oc-lib/models/resources" + "cloud.o-forge.io/core/oc-lib/models/utils" "github.com/stretchr/testify/assert" ) func TestStoreOneWorkflow(t *testing.T) { - w := Workflow{AbstractResource: resources.AbstractResource{ - Uuid: "123", - Name: "testWorkflow", - Description: "Lorem Ipsum", - Logo: "azerty.com", - Owner: "toto", - OwnerLogo: "totoLogo", - SourceUrl: "azerty.fr", + w := WorkflowResource{AbstractResource: resources.AbstractResource{ + AbstractObject: utils.AbstractObject{Name: "testWorkflow"}, + Description: "Lorem Ipsum", + Logo: "azerty.com", + Owner: "toto", + OwnerLogo: "totoLogo", + SourceUrl: "azerty.fr", }, } - wma := WorkflowMongoAccessor{} + wma := WorkflowResourceMongoAccessor{} id, _ := wma.StoreOne(&w) assert.NotEmpty(t, id) } func TestLoadOneWorkflow(t *testing.T) { - w := Workflow{AbstractResource: resources.AbstractResource{ - Uuid: "123", - Name: "testWorkflow", - Description: "Lorem Ipsum", - Logo: "azerty.com", - Owner: "toto", - OwnerLogo: "totoLogo", - SourceUrl: "azerty.fr", + w := WorkflowResource{AbstractResource: resources.AbstractResource{ + AbstractObject: utils.AbstractObject{Name: "testWorkflow"}, + Description: "Lorem Ipsum", + Logo: "azerty.com", + Owner: "toto", + OwnerLogo: "totoLogo", + SourceUrl: "azerty.fr", }, } - wma := WorkflowMongoAccessor{} + wma := WorkflowResourceMongoAccessor{} new_w, _ := wma.StoreOne(&w) assert.Equal(t, w, new_w) } diff --git a/models/utils/abstracts.go b/models/utils/abstracts.go index 4d89dfb..ede990d 100644 --- a/models/utils/abstracts.go +++ b/models/utils/abstracts.go @@ -3,12 +3,21 @@ package utils import ( "cloud.o-forge.io/core/oc-lib/dbs/mongo" "cloud.o-forge.io/core/oc-lib/logs" - "cloud.o-forge.io/core/oc-lib/models/resources" "github.com/go-playground/validator/v10" + "github.com/google/uuid" "github.com/rs/zerolog" ) -var Validate = validator.New(validator.WithRequiredStructEnabled()) +var validate = validator.New(validator.WithRequiredStructEnabled()) + +type AbstractObject struct { + UUID string `json:"id" required:"true" bson:"_id" validate:"required"` + Name string `json:"name" required:"true" bson:"name" validate:"required"` +} + +func (r *AbstractObject) GenerateID() { + r.UUID = uuid.New().String() +} type AbstractAccessor struct { Logger zerolog.Logger @@ -19,10 +28,26 @@ func (dma *AbstractAccessor) GetType() string { return dma.Type } -func (dma *AbstractAccessor) SetLogger(t resources.ResourceType) { +func (dma *AbstractAccessor) SetLogger(t DataType) { dma.Logger = logs.CreateLogger(t.String(), "") dma.Type = t.String() } + +func (wfa *AbstractAccessor) GenericStoreOne(data DBObject, accessor Accessor) (DBObject, error) { + err := validate.Struct(data) + wfa.Logger.Error().Msg("Could not store " + data.GetName() + " to db. Error: " + err.Error()) + if err != nil { + return nil, err + } + data.GenerateID() + id, err := mongo.MONGOService.StoreOne(data, wfa.GetType()) + if err != nil { + wfa.Logger.Error().Msg("Could not store " + data.GetName() + " to db. Error: " + err.Error()) + return nil, err + } + return accessor.LoadOne(id) +} + func (dma *AbstractAccessor) GenericDeleteOne(id string, accessor Accessor) (DBObject, error) { res, err := accessor.LoadOne(id) if err != nil { diff --git a/models/utils/enums.go b/models/utils/enums.go new file mode 100644 index 0000000..34e18f9 --- /dev/null +++ b/models/utils/enums.go @@ -0,0 +1,36 @@ +package utils + +type DataType int + +const ( + INVALID DataType = iota + DATA_RESOURCE + PROCESSING_RESOURCE + STORAGE_RESOURCE + DATACENTER_RESOURCE + WORKFLOW_RESOURCE + WORKFLOW +) + +var str = [...]string{ + "invalid", + "data_resource", + "processing_resource", + "storage_resource", + "datacenter_resource", + "workflow_resource", + "workflow", +} + +func FromInt(i int) string { + return str[i] +} + +func (d DataType) String() string { + return str[d] +} + +// EnumIndex - Creating common behavior - give the type a EnumIndex functio +func (d DataType) EnumIndex() int { + return int(d) +} diff --git a/models/utils/interfaces.go b/models/utils/interfaces.go index 450f098..d845088 100644 --- a/models/utils/interfaces.go +++ b/models/utils/interfaces.go @@ -1,8 +1,7 @@ package utils -import "cloud.o-forge.io/core/oc-lib/models/resources" - type DBObject interface { + GenerateID() GetName() string Deserialize(j map[string]interface{}) DBObject Serialize() map[string]interface{} @@ -10,7 +9,7 @@ type DBObject interface { } type Accessor interface { - SetLogger(t resources.ResourceType) + SetLogger(t DataType) GetType() string LoadOne(id string) (DBObject, error) DeleteOne(id string) (DBObject, error) diff --git a/models/workflow/workflow.go b/models/workflow/workflow.go new file mode 100644 index 0000000..88fdbba --- /dev/null +++ b/models/workflow/workflow.go @@ -0,0 +1,42 @@ +package oclib + +import ( + "encoding/json" + + w "cloud.o-forge.io/core/oc-lib/models/resources/workflow" + "cloud.o-forge.io/core/oc-lib/models/utils" +) + +type Workflow struct { + utils.AbstractObject + w.AbstractWorkflow +} + +func (d *Workflow) GetName() string { + return d.Name +} + +func (d *Workflow) GetAccessor() utils.Accessor { + data := &WorkflowMongoAccessor{} + data.SetLogger(utils.WORKFLOW) + return data +} + +func (dma *Workflow) Deserialize(j map[string]interface{}) utils.DBObject { + b, err := json.Marshal(j) + if err != nil { + return nil + } + json.Unmarshal(b, dma) + return dma +} + +func (dma *Workflow) Serialize() map[string]interface{} { + var m map[string]interface{} + b, err := json.Marshal(dma) + if err != nil { + return nil + } + json.Unmarshal(b, dma) + return m +} diff --git a/models/workflow/workflow_mongo_accessor.go b/models/workflow/workflow_mongo_accessor.go new file mode 100644 index 0000000..27840a7 --- /dev/null +++ b/models/workflow/workflow_mongo_accessor.go @@ -0,0 +1,33 @@ +package oclib + +import ( + "cloud.o-forge.io/core/oc-lib/dbs/mongo" + "cloud.o-forge.io/core/oc-lib/models/utils" +) + +type WorkflowMongoAccessor struct { + utils.AbstractAccessor +} + +func (wfa *WorkflowMongoAccessor) DeleteOne(id string) (utils.DBObject, error) { + return wfa.GenericDeleteOne(id, wfa) +} + +func (wfa *WorkflowMongoAccessor) UpdateOne(set map[string]interface{}, id string) (utils.DBObject, error) { + return wfa.GenericUpdateOne(set, id, wfa) +} + +func (wfa *WorkflowMongoAccessor) StoreOne(data utils.DBObject) (utils.DBObject, error) { + return wfa.GenericStoreOne(data, wfa) +} + +func (wfa *WorkflowMongoAccessor) LoadOne(id string) (utils.DBObject, error) { + var workflow Workflow + res_mongo, err := mongo.MONGOService.LoadOne(id, wfa.GetType()) + if err != nil { + wfa.Logger.Error().Msg("Could not retrieve " + id + " from db. Error: " + err.Error()) + return nil, err + } + res_mongo.Decode(&workflow) + return &workflow, nil +} diff --git a/models/workflow/workflow_schedule.go b/models/workflow/workflow_schedule.go new file mode 100644 index 0000000..7d5d5a1 --- /dev/null +++ b/models/workflow/workflow_schedule.go @@ -0,0 +1,15 @@ +package oclib + +import "time" + +type WorkflowSchedule struct { + Id string `json:"id"` + Start time.Time + End time.Time + Cron string +} + +func (ws *WorkflowSchedule) GetAllDates() (timetable []time.Time){ + // Return all the execution time generated by the Cron + return +} \ No newline at end of file diff --git a/models/workflow/workflow_test.go b/models/workflow/workflow_test.go new file mode 100644 index 0000000..daca312 --- /dev/null +++ b/models/workflow/workflow_test.go @@ -0,0 +1,29 @@ +package oclib + +import ( + "testing" + + "cloud.o-forge.io/core/oc-lib/models/utils" + "github.com/stretchr/testify/assert" +) + +func TestStoreOneWorkflow(t *testing.T) { + w := Workflow{ + AbstractObject: utils.AbstractObject{Name: "testWorkflow"}, + } + + wma := WorkflowMongoAccessor{} + id, _ := wma.StoreOne(&w) + + assert.NotEmpty(t, id) +} + +func TestLoadOneWorkflow(t *testing.T) { + w := Workflow{ + AbstractObject: utils.AbstractObject{Name: "testWorkflow"}, + } + + wma := WorkflowMongoAccessor{} + new_w, _ := wma.StoreOne(&w) + assert.Equal(t, w, new_w) +}