diff --git a/entrypoint.go b/entrypoint.go index 2737b40..348c884 100644 --- a/entrypoint.go +++ b/entrypoint.go @@ -18,12 +18,8 @@ import ( "cloud.o-forge.io/core/oc-lib/models/collaborative_area" "cloud.o-forge.io/core/oc-lib/models/collaborative_area/rules/rule" "cloud.o-forge.io/core/oc-lib/models/peer" - "cloud.o-forge.io/core/oc-lib/models/resources/compute" - "cloud.o-forge.io/core/oc-lib/models/resources/data" - "cloud.o-forge.io/core/oc-lib/models/resources/processing" + "cloud.o-forge.io/core/oc-lib/models/resources" "cloud.o-forge.io/core/oc-lib/models/resources/resource_model" - "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" "cloud.o-forge.io/core/oc-lib/models/workflow_execution" @@ -452,73 +448,73 @@ func CopyOne(collection LibDataEnum, object map[string]interface{}, peerID strin // ================ CAST ========================= // -func (l *LibData) ToDataResource() *data.DataResource { - if l.Data.GetAccessor("", []string{}, nil).GetType() == tools.DATA_RESOURCE.String() { - return l.Data.(*data.DataResource) +func (l *LibData) ToDataResource() *resources.DataResource { + if l.Data.GetAccessor("", []string{}, nil).GetType() == tools.DATA_RESOURCE { + return l.Data.(*resources.DataResource) } return nil } -func (l *LibData) ToComputeResource() *compute.ComputeResource { - if l.Data != nil && l.Data.GetAccessor("", []string{}, nil).GetType() == tools.COMPUTE_RESOURCE.String() { - return l.Data.(*compute.ComputeResource) +func (l *LibData) ToComputeResource() *resources.ComputeResource { + if l.Data != nil && l.Data.GetAccessor("", []string{}, nil).GetType() == tools.COMPUTE_RESOURCE { + return l.Data.(*resources.ComputeResource) } return nil } -func (l *LibData) ToStorageResource() *storage.StorageResource { - if l.Data.GetAccessor("", []string{}, nil).GetType() == tools.STORAGE_RESOURCE.String() { - return l.Data.(*storage.StorageResource) +func (l *LibData) ToStorageResource() *resources.StorageResource { + if l.Data.GetAccessor("", []string{}, nil).GetType() == tools.STORAGE_RESOURCE { + return l.Data.(*resources.StorageResource) } return nil } -func (l *LibData) ToProcessingResource() *processing.ProcessingResource { - if l.Data.GetAccessor("", []string{}, nil).GetType() == tools.PROCESSING_RESOURCE.String() { - return l.Data.(*processing.ProcessingResource) +func (l *LibData) ToProcessingResource() *resources.ProcessingResource { + if l.Data.GetAccessor("", []string{}, nil).GetType() == tools.PROCESSING_RESOURCE { + return l.Data.(*resources.ProcessingResource) } return nil } -func (l *LibData) ToWorkflowResource() *w.WorkflowResource { - if l.Data.GetAccessor("", []string{}, nil).GetType() == tools.WORKFLOW_RESOURCE.String() { - return l.Data.(*w.WorkflowResource) +func (l *LibData) ToWorkflowResource() *resources.WorkflowResource { + if l.Data.GetAccessor("", []string{}, nil).GetType() == tools.WORKFLOW_RESOURCE { + return l.Data.(*resources.WorkflowResource) } return nil } func (l *LibData) ToPeer() *peer.Peer { - if l.Data.GetAccessor("", []string{}, nil).GetType() == tools.PEER.String() { + if l.Data.GetAccessor("", []string{}, nil).GetType() == tools.PEER { return l.Data.(*peer.Peer) } return nil } func (l *LibData) ToWorkflow() *w2.Workflow { - if l.Data.GetAccessor("", []string{}, nil).GetType() == tools.WORKFLOW.String() { + if l.Data.GetAccessor("", []string{}, nil).GetType() == tools.WORKFLOW { return l.Data.(*w2.Workflow) } return nil } func (l *LibData) ToWorkspace() *workspace.Workspace { - if l.Data.GetAccessor("", []string{}, nil).GetType() == tools.WORKSPACE.String() { + if l.Data.GetAccessor("", []string{}, nil).GetType() == tools.WORKSPACE { return l.Data.(*workspace.Workspace) } return nil } func (l *LibData) ToCollaborativeArea() *collaborative_area.CollaborativeArea { - if l.Data.GetAccessor("", []string{}, nil).GetType() == tools.COLLABORATIVE_AREA.String() { + if l.Data.GetAccessor("", []string{}, nil).GetType() == tools.COLLABORATIVE_AREA { return l.Data.(*collaborative_area.CollaborativeArea) } return nil } func (l *LibData) ToRule() *rule.Rule { - if l.Data.GetAccessor("", []string{}, nil).GetType() == tools.COLLABORATIVE_AREA.String() { + if l.Data.GetAccessor("", []string{}, nil).GetType() == tools.COLLABORATIVE_AREA { return l.Data.(*rule.Rule) } return nil } func (l *LibData) ToWorkflowExecution() *workflow_execution.WorkflowExecution { - if l.Data.GetAccessor("", []string{}, nil).GetType() == tools.WORKFLOW_EXECUTION.String() { + if l.Data.GetAccessor("", []string{}, nil).GetType() == tools.WORKFLOW_EXECUTION { return l.Data.(*workflow_execution.WorkflowExecution) } return nil diff --git a/models/booking/booking_mongo_accessor.go b/models/booking/booking_mongo_accessor.go index e66b63d..f189e60 100644 --- a/models/booking/booking_mongo_accessor.go +++ b/models/booking/booking_mongo_accessor.go @@ -4,7 +4,6 @@ import ( "time" "cloud.o-forge.io/core/oc-lib/dbs" - "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/utils" "cloud.o-forge.io/core/oc-lib/models/workflow_execution" @@ -23,7 +22,7 @@ func New(t tools.DataType, peerID string, groups []string, caller *tools.HTTPCal Caller: caller, PeerID: peerID, Groups: groups, // Set the caller - Type: t.String(), + Type: t, }, } } @@ -47,67 +46,30 @@ func (wfa *bookingMongoAccessor) CopyOne(data utils.DBObject) (utils.DBObject, i return wfa.GenericStoreOne(data, wfa) } -func (wfa *bookingMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { - var workflow Booking - res_mongo, code, 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, code, err - } - res_mongo.Decode(&workflow) - if workflow.State == workflow_execution.SCHEDULED && time.Now().UTC().After(*workflow.ExecDate) { - workflow.State = workflow_execution.FORGOTTEN - wfa.GenericRawUpdateOne(&workflow, id, wfa) - } - return &workflow, 200, nil +func (a *bookingMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { + return utils.GenericLoadOne[*Booking](id, func(d utils.DBObject) (utils.DBObject, int, error) { + if d.(*Booking).State == workflow_execution.SCHEDULED && time.Now().UTC().After(*d.(*Booking).ExecDate) { + d.(*Booking).State = workflow_execution.FORGOTTEN + a.GenericRawUpdateOne(d, id, a) + } + return d, 200, nil + }, a) } -func (wfa *bookingMongoAccessor) LoadAll() ([]utils.ShallowDBObject, int, error) { - objs := []utils.ShallowDBObject{} - res_mongo, code, err := mongo.MONGOService.LoadAll(wfa.GetType()) - if err != nil { - wfa.Logger.Error().Msg("Could not retrieve any from db. Error: " + err.Error()) - return nil, code, err - } - var results []Booking - if err = res_mongo.All(mongo.MngoCtx, &results); err != nil { - return nil, 404, err - } - for _, r := range results { - if r.State == workflow_execution.SCHEDULED && time.Now().UTC().After(*r.ExecDate) { - r.State = workflow_execution.FORGOTTEN - wfa.GenericRawUpdateOne(&r, r.UUID, wfa) - } - objs = append(objs, &r.AbstractObject) // Warning only AbstractObject is returned - } - return objs, 200, nil +func (a *bookingMongoAccessor) LoadAll() ([]utils.ShallowDBObject, int, error) { + return utils.GenericLoadAll[*Booking](a.getExec(), a) } -// Search is a function that searches for a booking in the database -func (wfa *bookingMongoAccessor) Search(filters *dbs.Filters, search string) ([]utils.ShallowDBObject, int, error) { - objs := []utils.ShallowDBObject{} - if (filters == nil || len(filters.And) == 0 || len(filters.Or) == 0) && search != "" { - filters = &dbs.Filters{ - Or: map[string][]dbs.Filter{ // filter by name if no filters are provided - "abstractobject.name": {{Operator: dbs.LIKE.String(), Value: search}}, - }, - } - } - res_mongo, code, err := mongo.MONGOService.Search(filters, wfa.GetType()) - if err != nil { - wfa.Logger.Error().Msg("Could not store to db. Error: " + err.Error()) - return nil, code, err - } - var results []Booking - if err = res_mongo.All(mongo.MngoCtx, &results); err != nil { - return nil, 404, err - } - for _, r := range results { - if r.State == workflow_execution.SCHEDULED && time.Now().UTC().After(*r.ExecDate) { - r.State = workflow_execution.FORGOTTEN - wfa.GenericRawUpdateOne(&r, r.UUID, wfa) - } - objs = append(objs, &r) - } - return objs, 200, nil +func (a *bookingMongoAccessor) Search(filters *dbs.Filters, search string) ([]utils.ShallowDBObject, int, error) { + return utils.GenericSearch[*Booking](filters, search, (&Booking{}).GetObjectFilters(search), a.getExec(), a) +} + +func (a *bookingMongoAccessor) getExec() func(utils.DBObject) utils.ShallowDBObject { + return func(d utils.DBObject) utils.ShallowDBObject { + if d.(*Booking).State == workflow_execution.SCHEDULED && time.Now().UTC().After(*d.(*Booking).ExecDate) { + d.(*Booking).State = workflow_execution.FORGOTTEN + a.GenericRawUpdateOne(d, d.GetID(), a) + } + return d + } } diff --git a/models/collaborative_area/collaborative_area_mongo_accessor.go b/models/collaborative_area/collaborative_area_mongo_accessor.go index 19a51dd..f41677f 100644 --- a/models/collaborative_area/collaborative_area_mongo_accessor.go +++ b/models/collaborative_area/collaborative_area_mongo_accessor.go @@ -35,7 +35,7 @@ func New(t tools.DataType, peerID string, groups []string, caller *tools.HTTPCal Caller: caller, PeerID: peerID, Groups: groups, // Set the caller - Type: t.String(), + Type: t, }, workspaceAccessor: (&workspace.Workspace{}).GetAccessor(peerID, groups, nil), workflowAccessor: (&w.Workflow{}).GetAccessor(peerID, groups, nil), @@ -311,7 +311,7 @@ func (wfa *collaborativeAreaMongoAccessor) enrich(sharedWorkspace *Collaborative // LoadOne loads a collaborative area from the database, given its ID and enrich it func (wfa *collaborativeAreaMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { var sharedWorkspace CollaborativeArea - res_mongo, code, err := mongo.MONGOService.LoadOne(id, wfa.GetType()) + res_mongo, code, err := mongo.MONGOService.LoadOne(id, wfa.GetType().String()) if err != nil { wfa.Logger.Error().Msg("Could not retrieve " + id + " from db. Error: " + err.Error()) return nil, code, err @@ -326,7 +326,7 @@ func (wfa *collaborativeAreaMongoAccessor) LoadOne(id string) (utils.DBObject, i // LoadAll loads all the collaborative areas from the database and enrich them func (wfa collaborativeAreaMongoAccessor) LoadAll() ([]utils.ShallowDBObject, int, error) { objs := []utils.ShallowDBObject{} - res_mongo, code, err := mongo.MONGOService.LoadAll(wfa.GetType()) + res_mongo, code, err := mongo.MONGOService.LoadAll(wfa.GetType().String()) if err != nil { wfa.Logger.Error().Msg("Could not retrieve any from db. Error: " + err.Error()) return nil, code, err @@ -354,7 +354,7 @@ func (wfa *collaborativeAreaMongoAccessor) Search(filters *dbs.Filters, search s }, } } - res_mongo, code, err := mongo.MONGOService.Search(filters, wfa.GetType()) + res_mongo, code, err := mongo.MONGOService.Search(filters, wfa.GetType().String()) if err != nil { wfa.Logger.Error().Msg("Could not store to db. Error: " + err.Error()) return nil, code, err diff --git a/models/collaborative_area/rules/rule/rule_mongo_accessor.go b/models/collaborative_area/rules/rule/rule_mongo_accessor.go index d3d7fe6..764a5e9 100644 --- a/models/collaborative_area/rules/rule/rule_mongo_accessor.go +++ b/models/collaborative_area/rules/rule/rule_mongo_accessor.go @@ -20,7 +20,7 @@ func New(t tools.DataType, peerID string, groups []string, caller *tools.HTTPCal Caller: caller, PeerID: peerID, Groups: groups, // Set the caller - Type: t.String(), + Type: t, }, } } @@ -47,7 +47,7 @@ func (wfa *ruleMongoAccessor) CopyOne(data utils.DBObject) (utils.DBObject, int, // LoadOne loads a rule from the database func (wfa *ruleMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { var rule Rule - res_mongo, code, err := mongo.MONGOService.LoadOne(id, wfa.GetType()) + res_mongo, code, err := mongo.MONGOService.LoadOne(id, wfa.GetType().String()) if err != nil { wfa.Logger.Error().Msg("Could not retrieve " + id + " from db. Error: " + err.Error()) return nil, code, err @@ -59,7 +59,7 @@ func (wfa *ruleMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { // LoadAll loads all rules from the database func (wfa ruleMongoAccessor) LoadAll() ([]utils.ShallowDBObject, int, error) { objs := []utils.ShallowDBObject{} - res_mongo, code, err := mongo.MONGOService.LoadAll(wfa.GetType()) + res_mongo, code, err := mongo.MONGOService.LoadAll(wfa.GetType().String()) if err != nil { wfa.Logger.Error().Msg("Could not retrieve any from db. Error: " + err.Error()) return nil, code, err @@ -84,7 +84,7 @@ func (wfa *ruleMongoAccessor) Search(filters *dbs.Filters, search string) ([]uti }, } } - res_mongo, code, err := mongo.MONGOService.Search(filters, wfa.GetType()) + res_mongo, code, err := mongo.MONGOService.Search(filters, wfa.GetType().String()) if err != nil { wfa.Logger.Error().Msg("Could not store to db. Error: " + err.Error()) return nil, code, err diff --git a/models/collaborative_area/shallow_collaborative_area/shallow_collaborative_area_mongo_accessor.go b/models/collaborative_area/shallow_collaborative_area/shallow_collaborative_area_mongo_accessor.go index 72fb553..3535d55 100644 --- a/models/collaborative_area/shallow_collaborative_area/shallow_collaborative_area_mongo_accessor.go +++ b/models/collaborative_area/shallow_collaborative_area/shallow_collaborative_area_mongo_accessor.go @@ -2,7 +2,6 @@ package shallow_collaborative_area import ( "cloud.o-forge.io/core/oc-lib/dbs" - "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/utils" "cloud.o-forge.io/core/oc-lib/tools" @@ -19,75 +18,41 @@ func New(t tools.DataType, peerID string, groups []string, caller *tools.HTTPCal Caller: caller, PeerID: peerID, Groups: groups, // Set the caller - Type: t.String(), + Type: t, }, } } -func (wfa *shallowSharedWorkspaceMongoAccessor) DeleteOne(id string) (utils.DBObject, int, error) { - return wfa.GenericDeleteOne(id, wfa) +func (a *shallowSharedWorkspaceMongoAccessor) DeleteOne(id string) (utils.DBObject, int, error) { + return a.GenericDeleteOne(id, a) } -func (wfa *shallowSharedWorkspaceMongoAccessor) UpdateOne(set utils.DBObject, id string) (utils.DBObject, int, error) { - return wfa.GenericUpdateOne(set.(*ShallowCollaborativeArea), id, wfa, &ShallowCollaborativeArea{}) +func (a *shallowSharedWorkspaceMongoAccessor) UpdateOne(set utils.DBObject, id string) (utils.DBObject, int, error) { + return a.GenericUpdateOne(set.(*ShallowCollaborativeArea), id, a, &ShallowCollaborativeArea{}) } -func (wfa *shallowSharedWorkspaceMongoAccessor) StoreOne(data utils.DBObject) (utils.DBObject, int, error) { - return wfa.GenericStoreOne(data.(*ShallowCollaborativeArea), wfa) +func (a *shallowSharedWorkspaceMongoAccessor) StoreOne(data utils.DBObject) (utils.DBObject, int, error) { + return a.GenericStoreOne(data.(*ShallowCollaborativeArea), a) } -func (wfa *shallowSharedWorkspaceMongoAccessor) CopyOne(data utils.DBObject) (utils.DBObject, int, error) { - return wfa.StoreOne(data) +func (a *shallowSharedWorkspaceMongoAccessor) CopyOne(data utils.DBObject) (utils.DBObject, int, error) { + return a.StoreOne(data) } -func (wfa *shallowSharedWorkspaceMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { - var sharedWorkspace ShallowCollaborativeArea - res_mongo, code, 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, code, err - } - res_mongo.Decode(&sharedWorkspace) - return &sharedWorkspace, 200, nil +func (a *shallowSharedWorkspaceMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { + return utils.GenericLoadOne[*ShallowCollaborativeArea](id, func(d utils.DBObject) (utils.DBObject, int, error) { + return d, 200, nil + }, a) } -func (wfa shallowSharedWorkspaceMongoAccessor) LoadAll() ([]utils.ShallowDBObject, int, error) { - objs := []utils.ShallowDBObject{} - res_mongo, code, err := mongo.MONGOService.LoadAll(wfa.GetType()) - if err != nil { - wfa.Logger.Error().Msg("Could not retrieve any from db. Error: " + err.Error()) - return nil, code, err - } - var results []ShallowCollaborativeArea - if err = res_mongo.All(mongo.MngoCtx, &results); err != nil { - return nil, 404, err - } - for _, r := range results { - objs = append(objs, &r) - } - return objs, 200, nil +func (a *shallowSharedWorkspaceMongoAccessor) LoadAll() ([]utils.ShallowDBObject, int, error) { + return utils.GenericLoadAll[*ShallowCollaborativeArea](func(d utils.DBObject) utils.ShallowDBObject { + return d + }, a) } -func (wfa *shallowSharedWorkspaceMongoAccessor) Search(filters *dbs.Filters, search string) ([]utils.ShallowDBObject, int, error) { - objs := []utils.ShallowDBObject{} - if (filters == nil || len(filters.And) == 0 || len(filters.Or) == 0) && search != "" { - filters = &dbs.Filters{ - Or: map[string][]dbs.Filter{ - "abstractobject.name": {{Operator: dbs.LIKE.String(), Value: search}}, - }, - } - } - res_mongo, code, err := mongo.MONGOService.Search(filters, wfa.GetType()) - if err != nil { - wfa.Logger.Error().Msg("Could not store to db. Error: " + err.Error()) - return nil, code, err - } - var results []ShallowCollaborativeArea - if err = res_mongo.All(mongo.MngoCtx, &results); err != nil { - return nil, 404, err - } - for _, r := range results { - objs = append(objs, &r) - } - return objs, 200, nil +func (a *shallowSharedWorkspaceMongoAccessor) Search(filters *dbs.Filters, search string) ([]utils.ShallowDBObject, int, error) { + return utils.GenericSearch[*ShallowCollaborativeArea](filters, search, (&ShallowCollaborativeArea{}).GetObjectFilters(search), func(d utils.DBObject) utils.ShallowDBObject { + return d + }, a) } diff --git a/models/models.go b/models/models.go index 92db19b..682459a 100644 --- a/models/models.go +++ b/models/models.go @@ -8,12 +8,8 @@ import ( "cloud.o-forge.io/core/oc-lib/models/collaborative_area" "cloud.o-forge.io/core/oc-lib/models/collaborative_area/rules/rule" "cloud.o-forge.io/core/oc-lib/models/peer" - "cloud.o-forge.io/core/oc-lib/models/resources/compute" - d "cloud.o-forge.io/core/oc-lib/models/resources/data" - p "cloud.o-forge.io/core/oc-lib/models/resources/processing" + resource "cloud.o-forge.io/core/oc-lib/models/resources" "cloud.o-forge.io/core/oc-lib/models/resources/resource_model" - 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" "cloud.o-forge.io/core/oc-lib/models/workflow_execution" @@ -25,11 +21,11 @@ This package contains the models used in the application It's used to create the models dynamically */ var models = map[string]func() utils.DBObject{ - tools.WORKFLOW_RESOURCE.String(): func() utils.DBObject { return &w.WorkflowResource{} }, - tools.DATA_RESOURCE.String(): func() utils.DBObject { return &d.DataResource{} }, - tools.COMPUTE_RESOURCE.String(): func() utils.DBObject { return &compute.ComputeResource{} }, - tools.STORAGE_RESOURCE.String(): func() utils.DBObject { return &s.StorageResource{} }, - tools.PROCESSING_RESOURCE.String(): func() utils.DBObject { return &p.ProcessingResource{} }, + tools.WORKFLOW_RESOURCE.String(): func() utils.DBObject { return &resource.WorkflowResource{} }, + tools.DATA_RESOURCE.String(): func() utils.DBObject { return &resource.DataResource{} }, + tools.COMPUTE_RESOURCE.String(): func() utils.DBObject { return &resource.ComputeResource{} }, + tools.STORAGE_RESOURCE.String(): func() utils.DBObject { return &resource.StorageResource{} }, + tools.PROCESSING_RESOURCE.String(): func() utils.DBObject { return &resource.ProcessingResource{} }, tools.WORKFLOW.String(): func() utils.DBObject { return &w2.Workflow{} }, tools.WORKFLOW_EXECUTION.String(): func() utils.DBObject { return &workflow_execution.WorkflowExecution{} }, tools.WORKSPACE.String(): func() utils.DBObject { return &w3.Workspace{} }, diff --git a/models/peer/peer_mongo_accessor.go b/models/peer/peer_mongo_accessor.go index c357f0e..3f2baf0 100644 --- a/models/peer/peer_mongo_accessor.go +++ b/models/peer/peer_mongo_accessor.go @@ -4,7 +4,6 @@ import ( "strconv" "cloud.o-forge.io/core/oc-lib/dbs" - "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/utils" "cloud.o-forge.io/core/oc-lib/tools" @@ -19,7 +18,7 @@ func NewShallow() *peerMongoAccessor { return &peerMongoAccessor{ utils.AbstractAccessor{ Logger: logs.CreateLogger(tools.PEER.String()), // Create a logger with the data type - Type: tools.PEER.String(), + Type: tools.PEER, }, } } @@ -31,7 +30,7 @@ func New(t tools.DataType, peerID string, groups []string, caller *tools.HTTPCal Caller: caller, PeerID: peerID, Groups: groups, // Set the caller - Type: t.String(), + Type: t, }, } } @@ -56,65 +55,38 @@ func (wfa *peerMongoAccessor) CopyOne(data utils.DBObject) (utils.DBObject, int, return wfa.GenericStoreOne(data, wfa) } -func (wfa *peerMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { - var peer Peer - res_mongo, code, 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, code, err - } - res_mongo.Decode(&peer) - - return &peer, 200, nil +func (dca *peerMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { + return utils.GenericLoadOne[*Peer](id, func(d utils.DBObject) (utils.DBObject, int, error) { + return d, 200, nil + }, dca) } -func (wfa peerMongoAccessor) LoadAll() ([]utils.ShallowDBObject, int, error) { - objs := []utils.ShallowDBObject{} - res_mongo, code, err := mongo.MONGOService.LoadAll(wfa.GetType()) - if err != nil { - wfa.Logger.Error().Msg("Could not retrieve any from db. Error: " + err.Error()) - return nil, code, err - } - var results []Peer - if err = res_mongo.All(mongo.MngoCtx, &results); err != nil { - return nil, 404, err - } - for _, r := range results { - objs = append(objs, &r) - } - return objs, 200, nil +func (wfa *peerMongoAccessor) LoadAll() ([]utils.ShallowDBObject, int, error) { + return utils.GenericLoadAll[*Peer](func(d utils.DBObject) utils.ShallowDBObject { + return d + }, wfa) } func (wfa *peerMongoAccessor) Search(filters *dbs.Filters, search string) ([]utils.ShallowDBObject, int, error) { - objs := []utils.ShallowDBObject{} - if (filters == nil || len(filters.And) == 0 || len(filters.Or) == 0) && search != "" { - s, err := strconv.Atoi(search) - if err == nil { - filters = &dbs.Filters{ - Or: map[string][]dbs.Filter{ // search by name if no filters are provided - "state": {{Operator: dbs.EQUAL.String(), Value: s}}, - }, - } - } else { - filters = &dbs.Filters{ - Or: map[string][]dbs.Filter{ // search by name if no filters are provided - "abstractobject.name": {{Operator: dbs.LIKE.String(), Value: search}}, - "url": {{Operator: dbs.LIKE.String(), Value: search}}, - }, - } + return utils.GenericSearch[*Peer](filters, search, wfa.getDefaultFilter(search), + func(d utils.DBObject) utils.ShallowDBObject { + return d + }, wfa) +} +func (a *peerMongoAccessor) getDefaultFilter(search string) *dbs.Filters { + s, err := strconv.Atoi(search) + if err == nil { + return &dbs.Filters{ + Or: map[string][]dbs.Filter{ // search by name if no filters are provided + "state": {{Operator: dbs.EQUAL.String(), Value: s}}, + }, + } + } else { + return &dbs.Filters{ + Or: map[string][]dbs.Filter{ // search by name if no filters are provided + "abstractobject.name": {{Operator: dbs.LIKE.String(), Value: search}}, + "url": {{Operator: dbs.LIKE.String(), Value: search}}, + }, } } - res_mongo, code, err := mongo.MONGOService.Search(filters, wfa.GetType()) - if err != nil { - wfa.Logger.Error().Msg("Could not store to db. Error: " + err.Error()) - return nil, code, err - } - var results []Peer - if err = res_mongo.All(mongo.MngoCtx, &results); err != nil { - return nil, 404, err - } - for _, r := range results { - objs = append(objs, &r) - } - return objs, 200, nil } diff --git a/models/resources/compute/compute.go b/models/resources/compute.go similarity index 90% rename from models/resources/compute/compute.go rename to models/resources/compute.go index 80597c6..75d5dd9 100644 --- a/models/resources/compute/compute.go +++ b/models/resources/compute.go @@ -1,4 +1,4 @@ -package compute +package resources import ( "cloud.o-forge.io/core/oc-lib/models/resources/resource_model" @@ -6,6 +6,48 @@ import ( "cloud.o-forge.io/core/oc-lib/tools" ) +/* +* ComputeResource is a struct that represents a compute resource +* it defines the resource compute + */ +type ComputeResource struct { + resource_model.AbstractResource + Technology TechnologyEnum `json:"technology" bson:"technology" default:"0"` // Technology is the technology + Architecture string `json:"architecture,omitempty" bson:"architecture,omitempty"` // Architecture is the architecture + Access AccessEnum `json:"access" bson:"access" default:"0"` // Access is the access + + Localisation string `json:"localisation,omitempty" bson:"localisation,omitempty"` // Localisation is the localisation + + CPUs []*CPU `bson:"cpus,omitempty" json:"cpus,omitempty"` // CPUs is the list of CPUs + RAM *RAM `bson:"ram,omitempty" json:"ram,omitempty"` // RAM is the RAM + GPUs []*GPU `bson:"gpus,omitempty" json:"gpus,omitempty"` // GPUs is the list of GPUs +} + +func (d *ComputeResource) GetAccessor(peerID string, groups []string, caller *tools.HTTPCaller) utils.Accessor { + return New[*ComputeResource](tools.COMPUTE_RESOURCE, peerID, groups, caller, func() utils.DBObject { return &ComputeResource{} }) +} + +// CPU is a struct that represents a CPU +type CPU struct { + Cores uint `bson:"cores,omitempty" json:"cores,omitempty"` //TODO: validate + Architecture string `bson:"architecture,omitempty" json:"architecture,omitempty"` //TOOD: enum + Shared bool `bson:"shared,omitempty" json:"shared,omitempty"` + MinimumMemory uint `bson:"minimum_memory,omitempty" json:"minimum_memory,omitempty"` + Platform string `bson:"platform,omitempty" json:"platform,omitempty"` +} + +type RAM struct { + Size uint `bson:"size,omitempty" json:"size,omitempty" description:"Units in MB"` + Ecc bool `bson:"ecc,omitempty" json:"ecc,omitempty"` +} + +type GPU struct { + CudaCores uint `bson:"cuda_cores,omitempty" json:"cuda_cores,omitempty"` + Model string `bson:"model,omitempty" json:"model,omitempty"` + Memory uint `bson:"memory,omitempty" json:"memory,omitempty" description:"Units in MB"` + TensorCores uint `bson:"tensor_cores,omitempty" json:"tensor_cores,omitempty"` +} + type TechnologyEnum int const ( @@ -34,45 +76,3 @@ const ( func (a AccessEnum) String() string { return [...]string{"SSH", "SSH_KUBE_API", "SSH_SLURM", "SSH_DOCKER", "OPENCLOUD", "VPN"}[a] } - -/* -* ComputeResource is a struct that represents a compute resource -* it defines the resource compute - */ -type ComputeResource struct { - resource_model.AbstractResource - Technology TechnologyEnum `json:"technology" bson:"technology" default:"0"` // Technology is the technology - Architecture string `json:"architecture,omitempty" bson:"architecture,omitempty"` // Architecture is the architecture - Access AccessEnum `json:"access" bson:"access default:"0"` // Access is the access - - Localisation string `json:"localisation,omitempty" bson:"localisation,omitempty"` // Localisation is the localisation - - CPUs []*CPU `bson:"cpus,omitempty" json:"cpus,omitempty"` // CPUs is the list of CPUs - RAM *RAM `bson:"ram,omitempty" json:"ram,omitempty"` // RAM is the RAM - GPUs []*GPU `bson:"gpus,omitempty" json:"gpus,omitempty"` // GPUs is the list of GPUs -} - -func (d *ComputeResource) GetAccessor(peerID string, groups []string, caller *tools.HTTPCaller) utils.Accessor { - return New(tools.COMPUTE_RESOURCE, peerID, groups, caller) -} - -// CPU is a struct that represents a CPU -type CPU struct { - Cores uint `bson:"cores,omitempty" json:"cores,omitempty"` //TODO: validate - Architecture string `bson:"architecture,omitempty" json:"architecture,omitempty"` //TOOD: enum - Shared bool `bson:"shared,omitempty" json:"shared,omitempty"` - MinimumMemory uint `bson:"minimum_memory,omitempty" json:"minimum_memory,omitempty"` - Platform string `bson:"platform,omitempty" json:"platform,omitempty"` -} - -type RAM struct { - Size uint `bson:"size,omitempty" json:"size,omitempty" description:"Units in MB"` - Ecc bool `bson:"ecc,omitempty" json:"ecc,omitempty"` -} - -type GPU struct { - CudaCores uint `bson:"cuda_cores,omitempty" json:"cuda_cores,omitempty"` - Model string `bson:"model,omitempty" json:"model,omitempty"` - Memory uint `bson:"memory,omitempty" json:"memory,omitempty" description:"Units in MB"` - TensorCores uint `bson:"tensor_cores,omitempty" json:"tensor_cores,omitempty"` -} diff --git a/models/resources/compute/compute_mongo_accessor.go b/models/resources/compute/compute_mongo_accessor.go deleted file mode 100644 index 2c8a067..0000000 --- a/models/resources/compute/compute_mongo_accessor.go +++ /dev/null @@ -1,81 +0,0 @@ -package compute - -import ( - "cloud.o-forge.io/core/oc-lib/dbs" - "cloud.o-forge.io/core/oc-lib/logs" - "cloud.o-forge.io/core/oc-lib/models/resources/resource_model" - "cloud.o-forge.io/core/oc-lib/models/utils" - "cloud.o-forge.io/core/oc-lib/tools" -) - -type computeMongoAccessor struct { - utils.AbstractAccessor // AbstractAccessor contains the basic fields of an accessor (model, caller) -} - -// New creates a new instance of the computeMongoAccessor -func New(t tools.DataType, peerID string, groups []string, caller *tools.HTTPCaller) *computeMongoAccessor { - return &computeMongoAccessor{ - utils.AbstractAccessor{ - ResourceModelAccessor: resource_model.New(), - Logger: logs.CreateLogger(t.String()), // Create a logger with the data type - Caller: caller, - PeerID: peerID, - Groups: groups, // Set the caller - Type: t.String(), - }, - } -} - -/* -* Nothing special here, just the basic CRUD operations - */ - -func (dca *computeMongoAccessor) DeleteOne(id string) (utils.DBObject, int, error) { - return dca.GenericDeleteOne(id, dca) -} - -func (dca *computeMongoAccessor) UpdateOne(set utils.DBObject, id string) (utils.DBObject, int, error) { - set.(*ComputeResource).ResourceModel = nil - return dca.GenericUpdateOne(set.(*ComputeResource).Trim(), id, dca, &ComputeResource{}) -} - -func (dca *computeMongoAccessor) StoreOne(data utils.DBObject) (utils.DBObject, int, error) { - data.(*ComputeResource).ResourceModel = nil - return dca.GenericStoreOne(data.(*ComputeResource).Trim(), dca) -} - -func (dca *computeMongoAccessor) CopyOne(data utils.DBObject) (utils.DBObject, int, error) { - return dca.StoreOne(data) -} - -func (dca *computeMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { - return utils.GenericLoadOne[*ComputeResource](id, func(d utils.DBObject) (utils.DBObject, int, error) { - resources, _, err := dca.ResourceModelAccessor.Search(nil, dca.GetType()) - if err == nil && len(resources) > 0 { - d.(*ComputeResource).ResourceModel = resources[0].(*resource_model.ResourceModel) - } - return d, 200, nil - }, dca) -} - -func (wfa *computeMongoAccessor) LoadAll() ([]utils.ShallowDBObject, int, error) { - resources, _, err := wfa.ResourceModelAccessor.Search(nil, wfa.GetType()) - return utils.GenericLoadAll[*ComputeResource](func(d utils.DBObject) utils.ShallowDBObject { - if err == nil && len(resources) > 0 { - d.(*ComputeResource).ResourceModel = resources[0].(*resource_model.ResourceModel) - } - return d - }, wfa) -} - -func (wfa *computeMongoAccessor) Search(filters *dbs.Filters, search string) ([]utils.ShallowDBObject, int, error) { - root := &ComputeResource{} - resources, _, err := wfa.ResourceModelAccessor.Search(nil, wfa.GetType()) - return utils.GenericSearch[*ComputeResource](filters, search, root.GetResourceFilter(search), - func(d utils.DBObject) utils.ShallowDBObject { - if err == nil && len(resources) > 0 { - d.(*ComputeResource).ResourceModel = resources[0].(*resource_model.ResourceModel) - } - return d - }, wfa) -} diff --git a/models/resources/compute/compute_test.go b/models/resources/compute/compute_test.go deleted file mode 100644 index b2b14ec..0000000 --- a/models/resources/compute/compute_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package compute - -import ( - "testing" - - "cloud.o-forge.io/core/oc-lib/models/resources/resource_model" - "cloud.o-forge.io/core/oc-lib/models/utils" - "cloud.o-forge.io/core/oc-lib/tools" - - "github.com/stretchr/testify/assert" -) - -func TestStoreOneCompute(t *testing.T) { - dc := ComputeResource{ - AbstractResource: resource_model.AbstractResource{ - AbstractObject: utils.AbstractObject{Name: "testCompute"}, - Description: "Lorem Ipsum", - Logo: "azerty.com", - Owner: "toto", - OwnerLogo: "totoLogo", - SourceUrl: "azerty.fr", - }, - } - - dcma := New(tools.COMPUTE_RESOURCE, "", nil, nil) - id, _, _ := dcma.StoreOne(&dc) - - assert.NotEmpty(t, id) -} - -func TestLoadOneCompute(t *testing.T) { - dc := ComputeResource{ - AbstractResource: resource_model.AbstractResource{ - AbstractObject: utils.AbstractObject{Name: "testCompute"}, - Description: "Lorem Ipsum", - Logo: "azerty.com", - Owner: "toto", - OwnerLogo: "totoLogo", - SourceUrl: "azerty.fr", - }, - } - - dcma := New(tools.COMPUTE_RESOURCE, "", nil, nil) - new_dc, _, _ := dcma.StoreOne(&dc) - - assert.Equal(t, dc, new_dc) -} diff --git a/models/resources/data/data.go b/models/resources/data.go similarity index 91% rename from models/resources/data/data.go rename to models/resources/data.go index 6a1f75c..5da620b 100644 --- a/models/resources/data/data.go +++ b/models/resources/data.go @@ -1,4 +1,4 @@ -package data +package resources import ( "cloud.o-forge.io/core/oc-lib/models/resources/resource_model" @@ -38,5 +38,5 @@ type DataResource struct { } func (d *DataResource) GetAccessor(peerID string, groups []string, caller *tools.HTTPCaller) utils.Accessor { - return New(tools.DATA_RESOURCE, peerID, groups, caller) // Create a new instance of the accessor + return New[*DataResource](tools.DATA_RESOURCE, peerID, groups, caller, func() utils.DBObject { return &DataResource{} }) // Create a new instance of the accessor } diff --git a/models/resources/data/data_mongo_accessor.go b/models/resources/data/data_mongo_accessor.go deleted file mode 100644 index 5b60c3b..0000000 --- a/models/resources/data/data_mongo_accessor.go +++ /dev/null @@ -1,129 +0,0 @@ -package data - -import ( - "errors" - - "cloud.o-forge.io/core/oc-lib/dbs" - mongo "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/resource_model" - "cloud.o-forge.io/core/oc-lib/models/utils" - "cloud.o-forge.io/core/oc-lib/tools" -) - -type dataMongoAccessor struct { - utils.AbstractAccessor // AbstractAccessor contains the basic fields of an accessor (model, caller) -} - -// New creates a new instance of the dataMongoAccessor -func New(t tools.DataType, peerID string, groups []string, caller *tools.HTTPCaller) *dataMongoAccessor { - return &dataMongoAccessor{ - utils.AbstractAccessor{ - ResourceModelAccessor: resource_model.New(), - Logger: logs.CreateLogger(t.String()), // Create a logger with the data type - Caller: caller, - PeerID: peerID, - Groups: groups, // Set the caller - Type: t.String(), - }, - } -} - -/* -* Nothing special here, just the basic CRUD operations - */ - -func (dma *dataMongoAccessor) DeleteOne(id string) (utils.DBObject, int, error) { - return dma.GenericDeleteOne(id, dma) -} - -func (dma *dataMongoAccessor) UpdateOne(set utils.DBObject, id string) (utils.DBObject, int, error) { - set.(*DataResource).ResourceModel = nil - return dma.GenericUpdateOne(set.(*DataResource).Trim(), id, dma, &DataResource{}) -} - -func (dma *dataMongoAccessor) StoreOne(data utils.DBObject) (utils.DBObject, int, error) { - data.(*DataResource).ResourceModel = nil - return dma.GenericStoreOne(data.(*DataResource).Trim(), dma) -} - -func (dma *dataMongoAccessor) CopyOne(data utils.DBObject) (utils.DBObject, int, error) { - return dma.StoreOne(data) -} - -func (dma *dataMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { - var data DataResource - res_mongo, code, err := mongo.MONGOService.LoadOne(id, dma.GetType()) - if err != nil { - dma.Logger.Error().Msg("Could not retrieve " + id + " from db. Error: " + err.Error()) - return nil, code, err - } - res_mongo.Decode(&data) - if !data.VerifyAuth(dma.PeerID, dma.Groups) { - return nil, 403, errors.New("You are not allowed to access this collaborative area") - } - resources, _, err := dma.ResourceModelAccessor.Search(nil, dma.GetType()) - if err == nil && len(resources) > 0 { - data.ResourceModel = resources[0].(*resource_model.ResourceModel) - } - return &data, 200, nil -} - -func (wfa dataMongoAccessor) LoadAll() ([]utils.ShallowDBObject, int, error) { - objs := []utils.ShallowDBObject{} - res_mongo, code, err := mongo.MONGOService.LoadAll(wfa.GetType()) - if err != nil { - wfa.Logger.Error().Msg("Could not retrieve any from db. Error: " + err.Error()) - return nil, code, err - } - var results []DataResource - if err = res_mongo.All(mongo.MngoCtx, &results); err != nil { - return nil, 404, err - } - resources, _, err := wfa.ResourceModelAccessor.Search(nil, wfa.GetType()) - for _, r := range results { - if !r.VerifyAuth(wfa.PeerID, wfa.Groups) { - continue - } - if err == nil && len(resources) > 0 { - r.ResourceModel = resources[0].(*resource_model.ResourceModel) - } - objs = append(objs, &r) // only get the abstract resource ! - } - return objs, 200, nil -} - -func (wfa *dataMongoAccessor) Search(filters *dbs.Filters, search string) ([]utils.ShallowDBObject, int, error) { - objs := []utils.ShallowDBObject{} - if (filters == nil || len(filters.And) == 0 || len(filters.Or) == 0) && search != "" { - filters = &dbs.Filters{ - Or: map[string][]dbs.Filter{ // filter by like name, short_description, description, owner, url if no filters are provided - "abstractresource.abstractobject.name": {{Operator: dbs.LIKE.String(), Value: search}}, - "abstractresource.short_description": {{Operator: dbs.LIKE.String(), Value: search}}, - "abstractresource.description": {{Operator: dbs.LIKE.String(), Value: search}}, - "abstractresource.owner": {{Operator: dbs.LIKE.String(), Value: search}}, - "abstractresource.source_url": {{Operator: dbs.LIKE.String(), Value: search}}, - }, - } - } - res_mongo, code, err := mongo.MONGOService.Search(filters, wfa.GetType()) - if err != nil { - wfa.Logger.Error().Msg("Could not store to db. Error: " + err.Error()) - return nil, code, err - } - var results []DataResource - if err = res_mongo.All(mongo.MngoCtx, &results); err != nil { - return nil, 404, err - } - resources, _, err := wfa.ResourceModelAccessor.Search(nil, wfa.GetType()) - for _, r := range results { - if !r.VerifyAuth(wfa.PeerID, wfa.Groups) { - continue - } - if err == nil && len(resources) > 0 { - r.ResourceModel = resources[0].(*resource_model.ResourceModel) - } - objs = append(objs, &r) // only get the abstract resource ! - } - return objs, 200, nil -} diff --git a/models/resources/data/data_test.go b/models/resources/data/data_test.go deleted file mode 100644 index 0cb5e34..0000000 --- a/models/resources/data/data_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package data - -import ( - "testing" - - "cloud.o-forge.io/core/oc-lib/models/resources/resource_model" - "cloud.o-forge.io/core/oc-lib/models/utils" - "cloud.o-forge.io/core/oc-lib/tools" - - "github.com/stretchr/testify/assert" -) - -func TestStoreOneData(t *testing.T) { - d := DataResource{ - WebResource: resource_model.WebResource{ - Protocol: "http", Path: "azerty.fr", - }, - Example: "123456", - AbstractResource: resource_model.AbstractResource{ - AbstractObject: utils.AbstractObject{Name: "testData"}, - Description: "Lorem Ipsum", - Logo: "azerty.com", - Owner: "toto", - OwnerLogo: "totoLogo", - SourceUrl: "azerty.fr", - }, - } - - dma := New(tools.DATA_RESOURCE, "", nil, nil) - id, _, _ := dma.StoreOne(&d) - - assert.NotEmpty(t, id) -} - -func TestLoadOneDate(t *testing.T) { - d := DataResource{ - WebResource: resource_model.WebResource{ - Protocol: "http", Path: "azerty.fr", - }, - Example: "123456", - AbstractResource: resource_model.AbstractResource{ - AbstractObject: utils.AbstractObject{Name: "testData"}, - Description: "Lorem Ipsum", - Logo: "azerty.com", - Owner: "toto", - OwnerLogo: "totoLogo", - SourceUrl: "azerty.fr", - }, - } - - dma := New(tools.DATA_RESOURCE, "", nil, nil) - new_d, _, _ := dma.StoreOne(&d) - assert.Equal(t, d, new_d) -} diff --git a/models/resources/processing.go b/models/resources/processing.go new file mode 100644 index 0000000..2837365 --- /dev/null +++ b/models/resources/processing.go @@ -0,0 +1,43 @@ +package resources + +import ( + "cloud.o-forge.io/core/oc-lib/models/resources/resource_model" + "cloud.o-forge.io/core/oc-lib/models/utils" + "cloud.o-forge.io/core/oc-lib/tools" +) + +type Container struct { + Image string `json:"image,omitempty" bson:"image,omitempty"` // Image is the container image + Command string `json:"command,omitempty" bson:"command,omitempty"` // Command is the container command + Args string `json:"args,omitempty" bson:"args,omitempty"` // Args is the container arguments + Env map[string]string `json:"env,omitempty" bson:"env,omitempty"` // Env is the container environment variables + Volumes map[string]string `json:"volumes,omitempty" bson:"volumes,omitempty"` // Volumes is the container volumes +} + +type Expose struct { + Port int `json:"port,omitempty" bson:"port,omitempty"` // Port is the port + Reverse string `json:"reverse,omitempty" bson:"reverse,omitempty"` // Reverse is the reverse + PAT int `json:"pat,omitempty" bson:"pat,omitempty"` // PAT is the PAT +} + +/* +* ProcessingResource is a struct that represents a processing resource +* it defines the resource processing + */ +type ProcessingResource struct { + resource_model.AbstractResource + IsService bool `json:"is_service,omitempty" bson:"is_service,omitempty"` // IsService is a flag that indicates if the processing is a service + CPUs []*CPU `bson:"cpus,omitempty" json:"cp_us,omitempty"` // CPUs is the list of CPUs + GPUs []*GPU `bson:"gpus,omitempty" json:"gp_us,omitempty"` // GPUs is the list of GPUs + RAM *RAM `bson:"ram,omitempty" json:"ram,omitempty"` // RAM is the RAM + Storage uint `bson:"storage,omitempty" json:"storage,omitempty"` // Storage is the storage + Parallel bool `bson:"parallel,omitempty" json:"parallel,omitempty"` // Parallel is a flag that indicates if the processing is parallel + ScalingModel uint `bson:"scaling_model,omitempty" json:"scaling_model,omitempty"` // ScalingModel is the scaling model + DiskIO string `bson:"disk_io,omitempty" json:"disk_io,omitempty"` // DiskIO is the disk IO + Container *Container `bson:"container,omitempty" json:"container,omitempty"` // Container is the container + Expose []Expose `bson:"expose,omitempty" json:"expose,omitempty"` // Expose is the execution +} + +func (d *ProcessingResource) GetAccessor(peerID string, groups []string, caller *tools.HTTPCaller) utils.Accessor { + return New[*ProcessingResource](tools.PROCESSING_RESOURCE, peerID, groups, caller, func() utils.DBObject { return &ProcessingResource{} }) // Create a new instance of the accessor +} diff --git a/models/resources/processing/processing.go b/models/resources/processing/processing.go deleted file mode 100644 index 4d971ff..0000000 --- a/models/resources/processing/processing.go +++ /dev/null @@ -1,44 +0,0 @@ -package processing - -import ( - "cloud.o-forge.io/core/oc-lib/models/resources/compute" - "cloud.o-forge.io/core/oc-lib/models/resources/resource_model" - "cloud.o-forge.io/core/oc-lib/models/utils" - "cloud.o-forge.io/core/oc-lib/tools" -) - -type Container struct { - Image string `json:"image,omitempty" bson:"image,omitempty"` // Image is the container image - Command string `json:"command,omitempty" bson:"command,omitempty"` // Command is the container command - Args string `json:"args,omitempty" bson:"args,omitempty"` // Args is the container arguments - Env map[string]string `json:"env,omitempty" bson:"env,omitempty"` // Env is the container environment variables - Volumes map[string]string `json:"volumes,omitempty" bson:"volumes,omitempty"` // Volumes is the container volumes -} - -type Expose struct { - Port int `json:"port,omitempty" bson:"port,omitempty"` // Port is the port - Reverse string `json:"reverse,omitempty" bson:"reverse,omitempty"` // Reverse is the reverse - PAT int `json:"pat,omitempty" bson:"pat,omitempty"` // PAT is the PAT -} - -/* -* ProcessingResource is a struct that represents a processing resource -* it defines the resource processing - */ -type ProcessingResource struct { - resource_model.AbstractResource - IsService bool `json:"is_service,omitempty" bson:"is_service,omitempty"` // IsService is a flag that indicates if the processing is a service - CPUs []*compute.CPU `bson:"cpus,omitempty" json:"cp_us,omitempty"` // CPUs is the list of CPUs - GPUs []*compute.GPU `bson:"gpus,omitempty" json:"gp_us,omitempty"` // GPUs is the list of GPUs - RAM *compute.RAM `bson:"ram,omitempty" json:"ram,omitempty"` // RAM is the RAM - Storage uint `bson:"storage,omitempty" json:"storage,omitempty"` // Storage is the storage - Parallel bool `bson:"parallel,omitempty" json:"parallel,omitempty"` // Parallel is a flag that indicates if the processing is parallel - ScalingModel uint `bson:"scaling_model,omitempty" json:"scaling_model,omitempty"` // ScalingModel is the scaling model - DiskIO string `bson:"disk_io,omitempty" json:"disk_io,omitempty"` // DiskIO is the disk IO - Container *Container `bson:"container,omitempty" json:"container,omitempty"` // Container is the container - Expose []Expose `bson:"expose,omitempty" json:"expose,omitempty"` // Expose is the execution -} - -func (d *ProcessingResource) GetAccessor(peerID string, groups []string, caller *tools.HTTPCaller) utils.Accessor { - return New(tools.PROCESSING_RESOURCE, peerID, groups, caller) // Create a new instance of the accessor -} diff --git a/models/resources/processing/processing_mongo_accessor.go b/models/resources/processing/processing_mongo_accessor.go deleted file mode 100644 index 8385258..0000000 --- a/models/resources/processing/processing_mongo_accessor.go +++ /dev/null @@ -1,133 +0,0 @@ -package processing - -import ( - "errors" - - "cloud.o-forge.io/core/oc-lib/dbs" - "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/resource_model" - "cloud.o-forge.io/core/oc-lib/models/utils" - "cloud.o-forge.io/core/oc-lib/tools" -) - -type processingMongoAccessor struct { - utils.AbstractAccessor // AbstractAccessor contains the basic fields of an accessor (model, caller) -} - -// New creates a new instance of the storageMongoAccessor -func New(t tools.DataType, peerID string, groups []string, caller *tools.HTTPCaller) *processingMongoAccessor { - return &processingMongoAccessor{ - utils.AbstractAccessor{ - ResourceModelAccessor: resource_model.New(), - Logger: logs.CreateLogger(t.String()), // Create a logger with the data type - Caller: caller, - PeerID: peerID, - Groups: groups, // Set the caller - Type: t.String(), - }, - } -} - -/* -* Nothing special here, just the basic CRUD operations - */ - -func (pma *processingMongoAccessor) DeleteOne(id string) (utils.DBObject, int, error) { - return pma.GenericDeleteOne(id, pma) -} - -func (pma *processingMongoAccessor) UpdateOne(set utils.DBObject, id string) (utils.DBObject, int, error) { - set.(*ProcessingResource).ResourceModel = nil - return pma.GenericUpdateOne(set.(*ProcessingResource).Trim(), id, pma, &ProcessingResource{}) -} - -func (pma *processingMongoAccessor) StoreOne(data utils.DBObject) (utils.DBObject, int, error) { - data.(*ProcessingResource).ResourceModel = nil - return pma.GenericStoreOne(data.(*ProcessingResource).Trim(), pma) -} - -func (pma *processingMongoAccessor) CopyOne(data utils.DBObject) (utils.DBObject, int, error) { - return pma.StoreOne(data) -} - -func (pma *processingMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { - - var processing ProcessingResource - - res_mongo, code, err := mongo.MONGOService.LoadOne(id, pma.GetType()) - if err != nil { - pma.Logger.Error().Msg("Could not retrieve " + id + " from db. Error: " + err.Error()) - return nil, code, err - } - - res_mongo.Decode(&processing) - if !processing.VerifyAuth(pma.PeerID, pma.Groups) { - return nil, 403, errors.New("You are not allowed to access this collaborative area") - } - resources, _, err := pma.ResourceModelAccessor.Search(nil, pma.GetType()) - if err == nil && len(resources) > 0 { - processing.ResourceModel = resources[0].(*resource_model.ResourceModel) - } - return &processing, 200, nil -} - -func (wfa processingMongoAccessor) LoadAll() ([]utils.ShallowDBObject, int, error) { - objs := []utils.ShallowDBObject{} - res_mongo, code, err := mongo.MONGOService.LoadAll(wfa.GetType()) - if err != nil { - wfa.Logger.Error().Msg("Could not retrieve any from db. Error: " + err.Error()) - return nil, code, err - } - var results []ProcessingResource - if err = res_mongo.All(mongo.MngoCtx, &results); err != nil { - return nil, 404, err - } - resources, _, err := wfa.ResourceModelAccessor.Search(nil, wfa.GetType()) - for _, r := range results { - if !r.VerifyAuth(wfa.PeerID, wfa.Groups) { - continue - } - if err == nil && len(resources) > 0 { - r.ResourceModel = resources[0].(*resource_model.ResourceModel) - } - objs = append(objs, &r) // only get the abstract resource ! - } - return objs, 200, nil -} - -// Search searches for processing resources in the database, given some filters OR a search string -func (wfa *processingMongoAccessor) Search(filters *dbs.Filters, search string) ([]utils.ShallowDBObject, int, error) { - objs := []utils.ShallowDBObject{} - if (filters == nil || len(filters.And) == 0 || len(filters.Or) == 0) && search != "" { - filters = &dbs.Filters{ - Or: map[string][]dbs.Filter{ // filter by like name, short_description, description, owner, url if no filters are provided - "abstractresource.abstractobject.name": {{Operator: dbs.LIKE.String(), Value: search}}, - "abstractresource.short_description": {{Operator: dbs.LIKE.String(), Value: search}}, - "abstractresource.description": {{Operator: dbs.LIKE.String(), Value: search}}, - "abstractresource.owner": {{Operator: dbs.LIKE.String(), Value: search}}, - "abstractresource.source_url": {{Operator: dbs.LIKE.String(), Value: search}}, - }, - } - } - res_mongo, code, err := mongo.MONGOService.Search(filters, wfa.GetType()) - if err != nil { - wfa.Logger.Error().Msg("Could not store to db. Error: " + err.Error()) - return nil, code, err - } - var results []ProcessingResource - if err = res_mongo.All(mongo.MngoCtx, &results); err != nil { - return nil, 404, err - } - resources, _, err := wfa.ResourceModelAccessor.Search(nil, wfa.GetType()) - for _, r := range results { - if !r.VerifyAuth(wfa.PeerID, wfa.Groups) { - continue - } - if err == nil && len(resources) > 0 { - r.ResourceModel = resources[0].(*resource_model.ResourceModel) - } - objs = append(objs, &r) // only get the abstract resource ! - } - return objs, 200, nil -} diff --git a/models/resources/processing/processing_test.go b/models/resources/processing/processing_test.go deleted file mode 100644 index b66b381..0000000 --- a/models/resources/processing/processing_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package processing - -/* -func TestStoreOneProcessing(t *testing.T) { - p := ProcessingResource{Container: "totoCont", - AbstractResource: resources.AbstractResource{ - AbstractObject: utils.AbstractObject{Name: "testData"}, - Description: "Lorem Ipsum", - Logo: "azerty.com", - Owner: "toto", - OwnerLogo: "totoLogo", - SourceUrl: "azerty.fr", - }, - } - - sma := ProcessingMongoAccessor{} - id, _, _ := sma.StoreOne(&p) - - assert.NotEmpty(t, id) -} - -func TestLoadOneProcessing(t *testing.T) { - p := ProcessingResource{Container: "totoCont", - AbstractResource: resources.AbstractResource{ - AbstractObject: utils.AbstractObject{Name: "testData"}, - Description: "Lorem Ipsum", - Logo: "azerty.com", - Owner: "toto", - OwnerLogo: "totoLogo", - SourceUrl: "azerty.fr", - }, - } - - sma := ProcessingMongoAccessor{} - new_s, _, _ := sma.StoreOne(&p) - assert.Equal(t, p, new_s) -} -*/ diff --git a/models/resources/resource.go b/models/resources/resource.go index 4c8d617..f164531 100644 --- a/models/resources/resource.go +++ b/models/resources/resource.go @@ -1,12 +1,7 @@ package resources import ( - "cloud.o-forge.io/core/oc-lib/models/resources/compute" - "cloud.o-forge.io/core/oc-lib/models/resources/data" - "cloud.o-forge.io/core/oc-lib/models/resources/processing" "cloud.o-forge.io/core/oc-lib/models/resources/resource_model" - "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" ) @@ -15,6 +10,12 @@ import ( // 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 ResourceInterface interface { + utils.DBObject + Trim() *resource_model.AbstractResource + SetResourceModel(model *resource_model.ResourceModel) +} + type ResourceSet struct { Datas []string `bson:"datas,omitempty" json:"datas,omitempty"` Storages []string `bson:"storages,omitempty" json:"storages,omitempty"` @@ -22,35 +23,43 @@ type ResourceSet struct { Computes []string `bson:"computes,omitempty" json:"computes,omitempty"` Workflows []string `bson:"workflows,omitempty" json:"workflows,omitempty"` - DataResources []*data.DataResource `bson:"-" json:"data_resources,omitempty"` - StorageResources []*storage.StorageResource `bson:"-" json:"storage_resources,omitempty"` - ProcessingResources []*processing.ProcessingResource `bson:"-" json:"processing_resources,omitempty"` - ComputeResources []*compute.ComputeResource `bson:"-" json:"compute_resources,omitempty"` - WorkflowResources []*w.WorkflowResource `bson:"-" json:"workflow_resources,omitempty"` + DataResources []*DataResource `bson:"-" json:"data_resources,omitempty"` + StorageResources []*StorageResource `bson:"-" json:"storage_resources,omitempty"` + ProcessingResources []*ProcessingResource `bson:"-" json:"processing_resources,omitempty"` + ComputeResources []*ComputeResource `bson:"-" json:"compute_resources,omitempty"` + WorkflowResources []*WorkflowResource `bson:"-" json:"workflow_resources,omitempty"` +} + +func (r *ResourceSet) Clear() { + r.DataResources = nil + r.StorageResources = nil + r.ProcessingResources = nil + r.ComputeResources = nil + r.WorkflowResources = nil } func (r *ResourceSet) Fill(peerID string, groups []string) { for k, v := range map[utils.DBObject][]string{ - (&data.DataResource{}): r.Datas, - (&compute.ComputeResource{}): r.Computes, - (&storage.StorageResource{}): r.Storages, - (&processing.ProcessingResource{}): r.Processings, - (&w.WorkflowResource{}): r.Workflows, + (&DataResource{}): r.Datas, + (&ComputeResource{}): r.Computes, + (&StorageResource{}): r.Storages, + (&ProcessingResource{}): r.Processings, + (&WorkflowResource{}): r.Workflows, } { for _, id := range v { d, _, e := k.GetAccessor(peerID, groups, nil).LoadOne(id) if e == nil { switch k.(type) { - case *data.DataResource: - r.DataResources = append(r.DataResources, d.(*data.DataResource)) - case *compute.ComputeResource: - r.ComputeResources = append(r.ComputeResources, d.(*compute.ComputeResource)) - case *storage.StorageResource: - r.StorageResources = append(r.StorageResources, d.(*storage.StorageResource)) - case *processing.ProcessingResource: - r.ProcessingResources = append(r.ProcessingResources, d.(*processing.ProcessingResource)) - case *w.WorkflowResource: - r.WorkflowResources = append(r.WorkflowResources, d.(*w.WorkflowResource)) + case *DataResource: + r.DataResources = append(r.DataResources, d.(*DataResource)) + case *ComputeResource: + r.ComputeResources = append(r.ComputeResources, d.(*ComputeResource)) + case *StorageResource: + r.StorageResources = append(r.StorageResources, d.(*StorageResource)) + case *ProcessingResource: + r.ProcessingResources = append(r.ProcessingResources, d.(*ProcessingResource)) + case *WorkflowResource: + r.WorkflowResources = append(r.WorkflowResources, d.(*WorkflowResource)) } } } @@ -58,11 +67,11 @@ func (r *ResourceSet) Fill(peerID string, groups []string) { } type ItemResource struct { - Data *data.DataResource `bson:"data,omitempty" json:"data,omitempty"` - Processing *processing.ProcessingResource `bson:"processing,omitempty" json:"processing,omitempty"` - Storage *storage.StorageResource `bson:"storage,omitempty" json:"storage,omitempty"` - Compute *compute.ComputeResource `bson:"compute,omitempty" json:"compute,omitempty"` - Workflow *w.WorkflowResource `bson:"workflow,omitempty" json:"workflow,omitempty"` + Data *DataResource `bson:"data,omitempty" json:"data,omitempty"` + Processing *ProcessingResource `bson:"processing,omitempty" json:"processing,omitempty"` + Storage *StorageResource `bson:"storage,omitempty" json:"storage,omitempty"` + Compute *ComputeResource `bson:"compute,omitempty" json:"compute,omitempty"` + Workflow *WorkflowResource `bson:"workflow,omitempty" json:"workflow,omitempty"` } func (i *ItemResource) GetAbstractRessource() *resource_model.AbstractResource { diff --git a/models/resources/resource_accessor.go b/models/resources/resource_accessor.go new file mode 100644 index 0000000..4d504a6 --- /dev/null +++ b/models/resources/resource_accessor.go @@ -0,0 +1,94 @@ +package resources + +import ( + "cloud.o-forge.io/core/oc-lib/dbs" + "cloud.o-forge.io/core/oc-lib/logs" + "cloud.o-forge.io/core/oc-lib/models/resources/resource_model" + "cloud.o-forge.io/core/oc-lib/models/utils" + "cloud.o-forge.io/core/oc-lib/tools" +) + +type resourceMongoAccessor[T ResourceInterface] struct { + utils.AbstractAccessor // AbstractAccessor contains the basic fields of an accessor (model, caller) + generateData func() utils.DBObject +} + +// New creates a new instance of the computeMongoAccessor +func New[T ResourceInterface](t tools.DataType, peerID string, groups []string, caller *tools.HTTPCaller, g func() utils.DBObject) *resourceMongoAccessor[T] { + return &resourceMongoAccessor[T]{ + AbstractAccessor: utils.AbstractAccessor{ + ResourceModelAccessor: resource_model.New(), + Logger: logs.CreateLogger(t.String()), // Create a logger with the data type + Caller: caller, + PeerID: peerID, + Groups: groups, // Set the caller + Type: t, + }, + generateData: g, + } +} + +/* +* Nothing special here, just the basic CRUD operations + */ + +func (dca *resourceMongoAccessor[T]) DeleteOne(id string) (utils.DBObject, int, error) { + return dca.GenericDeleteOne(id, dca) +} + +func (dca *resourceMongoAccessor[T]) UpdateOne(set utils.DBObject, id string) (utils.DBObject, int, error) { + set.(T).SetResourceModel(nil) + return dca.GenericUpdateOne(set.(T).Trim(), id, dca, dca.generateData()) // TODO CHANGE +} + +func (dca *resourceMongoAccessor[T]) StoreOne(data utils.DBObject) (utils.DBObject, int, error) { + data.(T).SetResourceModel(nil) + return dca.GenericStoreOne(data.(T).Trim(), dca) +} + +func (dca *resourceMongoAccessor[T]) CopyOne(data utils.DBObject) (utils.DBObject, int, error) { + return dca.StoreOne(data) +} + +func (dca *resourceMongoAccessor[T]) LoadOne(id string) (utils.DBObject, int, error) { + return utils.GenericLoadOne[T](id, func(d utils.DBObject) (utils.DBObject, int, error) { + resources, _, err := dca.ResourceModelAccessor.Search(nil, dca.GetType().String()) + if err == nil && len(resources) > 0 { + d.(T).SetResourceModel(resources[0].(*resource_model.ResourceModel)) + } + return d, 200, nil + }, dca) +} + +func (wfa *resourceMongoAccessor[T]) LoadAll() ([]utils.ShallowDBObject, int, error) { + resources, _, err := wfa.ResourceModelAccessor.Search(nil, wfa.GetType().String()) + return utils.GenericLoadAll[T](func(d utils.DBObject) utils.ShallowDBObject { + if err == nil && len(resources) > 0 { + d.(T).SetResourceModel(resources[0].(*resource_model.ResourceModel)) + } + return d + }, wfa) +} + +func (wfa *resourceMongoAccessor[T]) Search(filters *dbs.Filters, search string) ([]utils.ShallowDBObject, int, error) { + resources, _, err := wfa.ResourceModelAccessor.Search(nil, wfa.GetType().String()) + return utils.GenericSearch[T](filters, search, wfa.getResourceFilter(search), + func(d utils.DBObject) utils.ShallowDBObject { + if err == nil && len(resources) > 0 { + d.(T).SetResourceModel(resources[0].(*resource_model.ResourceModel)) + } + return d + }, wfa) +} + +func (abs *resourceMongoAccessor[T]) getResourceFilter(search string) *dbs.Filters { + return &dbs.Filters{ + Or: map[string][]dbs.Filter{ // filter by like name, short_description, description, owner, url if no filters are provided + "abstractresource.abstractobject.name": {{Operator: dbs.LIKE.String(), Value: search}}, + "abstractresource.short_description": {{Operator: dbs.LIKE.String(), Value: search}}, + "abstractresource.description": {{Operator: dbs.LIKE.String(), Value: search}}, + "abstractresource.owner": {{Operator: dbs.LIKE.String(), Value: search}}, + "abstractresource.source_url": {{Operator: dbs.LIKE.String(), Value: search}}, + }, + } +} diff --git a/models/resources/resource_model/resource_model.go b/models/resources/resource_model/resource_model.go index 7ee2faa..f993c42 100644 --- a/models/resources/resource_model/resource_model.go +++ b/models/resources/resource_model/resource_model.go @@ -5,7 +5,6 @@ import ( "slices" "cloud.o-forge.io/core/oc-lib/config" - "cloud.o-forge.io/core/oc-lib/dbs" "cloud.o-forge.io/core/oc-lib/models/peer" "cloud.o-forge.io/core/oc-lib/models/utils" "cloud.o-forge.io/core/oc-lib/tools" @@ -39,6 +38,10 @@ type AbstractResource struct { Currency string `json:"currency,omitempty" bson:"currency,omitempty"` // Currency is the currency of the price } +func (abs *AbstractResource) SetResourceModel(model *ResourceModel) { + abs.ResourceModel = model +} + func (abs *AbstractResource) VerifyAuth(peerID string, groups []string) bool { if grps, ok := abs.AllowedPeersGroup[peerID]; ok || config.GetConfig().Whitelist { if (ok && slices.Contains(grps, "*")) || (!ok && config.GetConfig().Whitelist) { @@ -53,18 +56,6 @@ func (abs *AbstractResource) VerifyAuth(peerID string, groups []string) bool { return false } -func (abs *AbstractResource) GetResourceFilter(search string) *dbs.Filters { - return &dbs.Filters{ - Or: map[string][]dbs.Filter{ // filter by like name, short_description, description, owner, url if no filters are provided - "abstractresource.abstractobject.name": {{Operator: dbs.LIKE.String(), Value: search}}, - "abstractresource.short_description": {{Operator: dbs.LIKE.String(), Value: search}}, - "abstractresource.description": {{Operator: dbs.LIKE.String(), Value: search}}, - "abstractresource.owner": {{Operator: dbs.LIKE.String(), Value: search}}, - "abstractresource.source_url": {{Operator: dbs.LIKE.String(), Value: search}}, - }, - } -} - /* * GetModelType returns the type of the model key */ @@ -147,7 +138,7 @@ func (abs *ResourceModel) VerifyAuth(peerID string, groups []string) bool { func (d *ResourceModel) GetAccessor(peerID string, groups []string, caller *tools.HTTPCaller) utils.Accessor { return &ResourceModelMongoAccessor{ utils.AbstractAccessor{ - Type: tools.RESOURCE_MODEL.String(), + Type: tools.RESOURCE_MODEL, PeerID: peerID, Groups: groups, Caller: caller, diff --git a/models/resources/resource_model/resource_model_mongo_accessor.go b/models/resources/resource_model/resource_model_mongo_accessor.go index 431e406..bfa9110 100644 --- a/models/resources/resource_model/resource_model_mongo_accessor.go +++ b/models/resources/resource_model/resource_model_mongo_accessor.go @@ -2,7 +2,6 @@ package resource_model import ( "cloud.o-forge.io/core/oc-lib/dbs" - "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/utils" "cloud.o-forge.io/core/oc-lib/tools" @@ -19,7 +18,7 @@ type ResourceModelMongoAccessor struct { func New() *ResourceModelMongoAccessor { return &ResourceModelMongoAccessor{ utils.AbstractAccessor{ - Type: tools.RESOURCE_MODEL.String(), + Type: tools.RESOURCE_MODEL, Logger: logs.CreateLogger(tools.RESOURCE_MODEL.String()), }, } @@ -41,54 +40,23 @@ func (wfa *ResourceModelMongoAccessor) CopyOne(data utils.DBObject) (utils.DBObj return wfa.GenericStoreOne(data, wfa) } -func (wfa *ResourceModelMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { - var workflow ResourceModel - res_mongo, code, 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, code, err - } - res_mongo.Decode(&workflow) - return &workflow, 200, nil +func (a *ResourceModelMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { + return utils.GenericLoadOne[*ResourceModel](id, func(d utils.DBObject) (utils.DBObject, int, error) { + return d, 200, nil + }, a) } -func (wfa ResourceModelMongoAccessor) LoadAll() ([]utils.ShallowDBObject, int, error) { - objs := []utils.ShallowDBObject{} - res_mongo, code, err := mongo.MONGOService.LoadAll(wfa.GetType()) - if err != nil { - wfa.Logger.Error().Msg("Could not retrieve any from db. Error: " + err.Error()) - return nil, code, err - } - var results []ResourceModel - if err = res_mongo.All(mongo.MngoCtx, &results); err != nil { - return nil, 404, err - } - for _, r := range results { - objs = append(objs, &r) - } - return objs, 200, nil +func (a *ResourceModelMongoAccessor) LoadAll() ([]utils.ShallowDBObject, int, error) { + return utils.GenericLoadAll[*ResourceModel](func(d utils.DBObject) utils.ShallowDBObject { + return d + }, a) } -func (wfa *ResourceModelMongoAccessor) Search(filters *dbs.Filters, search string) ([]utils.ShallowDBObject, int, error) { - objs := []utils.ShallowDBObject{} - if (filters == nil || len(filters.And) == 0 || len(filters.Or) == 0) && search != "" { - filters = &dbs.Filters{ +func (a *ResourceModelMongoAccessor) Search(filters *dbs.Filters, search string) ([]utils.ShallowDBObject, int, error) { + return utils.GenericSearch[*ResourceModel](filters, search, + &dbs.Filters{ Or: map[string][]dbs.Filter{ "resource_type": {{Operator: dbs.LIKE.String(), Value: search}}, }, - } - } - res_mongo, code, err := mongo.MONGOService.Search(filters, wfa.GetType()) - if err != nil { - wfa.Logger.Error().Msg("Could not store to db. Error: " + err.Error()) - return nil, code, err - } - var results []ResourceModel - if err = res_mongo.All(mongo.MngoCtx, &results); err != nil { - return nil, 404, err - } - for _, r := range results { - objs = append(objs, &r) - } - return objs, 200, nil + }, func(d utils.DBObject) utils.ShallowDBObject { return d }, a) } diff --git a/models/resources/storage/storage.go b/models/resources/storage.go similarity index 91% rename from models/resources/storage/storage.go rename to models/resources/storage.go index 9604a01..ca8289c 100644 --- a/models/resources/storage/storage.go +++ b/models/resources/storage.go @@ -1,4 +1,4 @@ -package storage +package resources import ( "cloud.o-forge.io/core/oc-lib/models/resources/resource_model" @@ -57,5 +57,5 @@ type StorageResource struct { } func (d *StorageResource) GetAccessor(peerID string, groups []string, caller *tools.HTTPCaller) utils.Accessor { - return New(tools.STORAGE_RESOURCE, peerID, groups, caller) // Create a new instance of the accessor + return New[*StorageResource](tools.STORAGE_RESOURCE, peerID, groups, caller, func() utils.DBObject { return &StorageResource{} }) // Create a new instance of the accessor } diff --git a/models/resources/storage/storage_mongo_accessor.go b/models/resources/storage/storage_mongo_accessor.go deleted file mode 100644 index 098335e..0000000 --- a/models/resources/storage/storage_mongo_accessor.go +++ /dev/null @@ -1,133 +0,0 @@ -package storage - -import ( - "errors" - - "cloud.o-forge.io/core/oc-lib/dbs" - "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/resource_model" - "cloud.o-forge.io/core/oc-lib/models/utils" - "cloud.o-forge.io/core/oc-lib/tools" -) - -type storageMongoAccessor struct { - utils.AbstractAccessor // AbstractAccessor contains the basic fields of an accessor (model, caller) -} - -// New creates a new instance of the storageMongoAccessor -func New(t tools.DataType, peerID string, groups []string, caller *tools.HTTPCaller) *storageMongoAccessor { - return &storageMongoAccessor{ - utils.AbstractAccessor{ - ResourceModelAccessor: resource_model.New(), - Logger: logs.CreateLogger(t.String()), // Create a logger with the data type - Caller: caller, - PeerID: peerID, - Groups: groups, // Set the caller - Type: t.String(), - }, - } -} - -/* -* Nothing special here, just the basic CRUD operations - */ - -func (sma *storageMongoAccessor) DeleteOne(id string) (utils.DBObject, int, error) { - return sma.GenericDeleteOne(id, sma) -} - -func (sma *storageMongoAccessor) UpdateOne(set utils.DBObject, id string) (utils.DBObject, int, error) { - set.(*StorageResource).ResourceModel = nil - return sma.GenericUpdateOne(set.(*StorageResource).Trim(), id, sma, &StorageResource{}) -} - -func (sma *storageMongoAccessor) StoreOne(data utils.DBObject) (utils.DBObject, int, error) { - data.(*StorageResource).ResourceModel = nil - return sma.GenericStoreOne(data.(*StorageResource).Trim(), sma) -} - -func (sma *storageMongoAccessor) CopyOne(data utils.DBObject) (utils.DBObject, int, error) { - return sma.StoreOne(data) -} - -func (sma *storageMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { - - var storage StorageResource - - res_mongo, code, err := mongo.MONGOService.LoadOne(id, sma.GetType()) - if err != nil { - sma.Logger.Error().Msg("Could not retrieve " + id + " from db. Error: " + err.Error()) - return nil, code, err - } - - res_mongo.Decode(&storage) - if !storage.VerifyAuth(sma.PeerID, sma.Groups) { - return nil, 403, errors.New("You are not allowed to access this collaborative area") - } - resources, _, err := sma.ResourceModelAccessor.Search(nil, sma.GetType()) - if err == nil && len(resources) > 0 { - storage.ResourceModel = resources[0].(*resource_model.ResourceModel) - } - return &storage, 200, nil -} - -func (wfa storageMongoAccessor) LoadAll() ([]utils.ShallowDBObject, int, error) { - objs := []utils.ShallowDBObject{} - res_mongo, code, err := mongo.MONGOService.LoadAll(wfa.GetType()) - if err != nil { - wfa.Logger.Error().Msg("Could not retrieve any from db. Error: " + err.Error()) - return nil, code, err - } - var results []StorageResource - if err = res_mongo.All(mongo.MngoCtx, &results); err != nil { - return nil, 404, err - } - resources, _, err := wfa.ResourceModelAccessor.Search(nil, wfa.GetType()) - for _, r := range results { - if !r.VerifyAuth(wfa.PeerID, wfa.Groups) { - continue - } - if err == nil && len(resources) > 0 { - r.ResourceModel = resources[0].(*resource_model.ResourceModel) - } - objs = append(objs, &r) // only get the abstract resource ! - } - return objs, 200, nil -} - -// Search searches for storage resources in the database, given some filters OR a search string -func (wfa *storageMongoAccessor) Search(filters *dbs.Filters, search string) ([]utils.ShallowDBObject, int, error) { - objs := []utils.ShallowDBObject{} - if (filters == nil || len(filters.And) == 0 || len(filters.Or) == 0) && search != "" { - filters = &dbs.Filters{ - Or: map[string][]dbs.Filter{ // filter by like name, short_description, description, owner, url if no filters are provided - "abstractresource.abstractobject.name": {{Operator: dbs.LIKE.String(), Value: search}}, - "abstractresource.short_description": {{Operator: dbs.LIKE.String(), Value: search}}, - "abstractresource.description": {{Operator: dbs.LIKE.String(), Value: search}}, - "abstractresource.owner": {{Operator: dbs.LIKE.String(), Value: search}}, - "abstractresource.source_url": {{Operator: dbs.LIKE.String(), Value: search}}, - }, - } - } - res_mongo, code, err := mongo.MONGOService.Search(filters, wfa.GetType()) - if err != nil { - wfa.Logger.Error().Msg("Could not store to db. Error: " + err.Error()) - return nil, code, err - } - var results []StorageResource - if err = res_mongo.All(mongo.MngoCtx, &results); err != nil { - return nil, 404, err - } - resources, _, err := wfa.ResourceModelAccessor.Search(nil, wfa.GetType()) - for _, r := range results { - if !r.VerifyAuth(wfa.PeerID, wfa.Groups) { - continue - } - if err == nil && len(resources) > 0 { - r.ResourceModel = resources[0].(*resource_model.ResourceModel) - } - objs = append(objs, &r) // only get the abstract resource ! - } - return objs, 200, nil -} diff --git a/models/resources/storage/storage_test.go b/models/resources/storage/storage_test.go deleted file mode 100644 index ad30fe9..0000000 --- a/models/resources/storage/storage_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package storage - -import ( - "testing" - - "cloud.o-forge.io/core/oc-lib/models/resources/resource_model" - "cloud.o-forge.io/core/oc-lib/models/utils" - "cloud.o-forge.io/core/oc-lib/tools" - - "github.com/stretchr/testify/assert" -) - -func TestStoreOneStorage(t *testing.T) { - s := StorageResource{Size: 123, WebResource: resource_model.WebResource{Protocol: "http", Path: "azerty.fr"}, - AbstractResource: resource_model.AbstractResource{ - AbstractObject: utils.AbstractObject{Name: "testData"}, - Description: "Lorem Ipsum", - Logo: "azerty.com", - Owner: "toto", - OwnerLogo: "totoLogo", - SourceUrl: "azerty.fr", - }, - } - - sma := New(tools.STORAGE_RESOURCE, "peerID", []string{}, nil) - id, _, _ := sma.StoreOne(&s) - - assert.NotEmpty(t, id) -} - -func TestLoadOneStorage(t *testing.T) { - s := StorageResource{Size: 123, WebResource: resource_model.WebResource{Protocol: "http", Path: "azerty.fr"}, - AbstractResource: resource_model.AbstractResource{ - AbstractObject: utils.AbstractObject{Name: "testData"}, - Description: "Lorem Ipsum", - Logo: "azerty.com", - Owner: "toto", - OwnerLogo: "totoLogo", - SourceUrl: "azerty.fr", - }, - } - - sma := New(tools.STORAGE_RESOURCE, "peerID", []string{}, nil) - new_s, _, _ := sma.StoreOne(&s) - - assert.Equal(t, s, new_s) -} diff --git a/models/resources/workflow/workflow.go b/models/resources/workflow.go similarity index 74% rename from models/resources/workflow/workflow.go rename to models/resources/workflow.go index 5fdd7a7..41eaa8c 100644 --- a/models/resources/workflow/workflow.go +++ b/models/resources/workflow.go @@ -1,4 +1,4 @@ -package oclib +package resources import ( "cloud.o-forge.io/core/oc-lib/models/resources/resource_model" @@ -14,5 +14,5 @@ type WorkflowResource struct { } func (d *WorkflowResource) GetAccessor(peerID string, groups []string, caller *tools.HTTPCaller) utils.Accessor { - return New(tools.WORKFLOW_RESOURCE, peerID, groups, caller) // Create a new instance of the accessor + return New[*WorkflowResource](tools.WORKFLOW_RESOURCE, peerID, groups, caller, func() utils.DBObject { return &WorkflowResource{} }) // Create a new instance of the accessor } diff --git a/models/resources/workflow/workflow_mongo_accessor.go b/models/resources/workflow/workflow_mongo_accessor.go deleted file mode 100644 index 7dd0c5f..0000000 --- a/models/resources/workflow/workflow_mongo_accessor.go +++ /dev/null @@ -1,132 +0,0 @@ -package oclib - -import ( - "errors" - - "cloud.o-forge.io/core/oc-lib/dbs" - "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/resource_model" - "cloud.o-forge.io/core/oc-lib/models/utils" - "cloud.o-forge.io/core/oc-lib/tools" -) - -type workflowResourceMongoAccessor struct { - utils.AbstractAccessor // AbstractAccessor contains the basic fields of an accessor (model, caller) -} - -func New(t tools.DataType, peerID string, groups []string, caller *tools.HTTPCaller) *workflowResourceMongoAccessor { - return &workflowResourceMongoAccessor{ - utils.AbstractAccessor{ - ResourceModelAccessor: resource_model.New(), - Logger: logs.CreateLogger(t.String()), // Create a logger with the data type - Caller: caller, - PeerID: peerID, - Groups: groups, // Set the caller - Type: t.String(), - }, - } -} - -func (wfa *workflowResourceMongoAccessor) DeleteOne(id string) (utils.DBObject, int, error) { - return wfa.GenericDeleteOne(id, wfa) -} - -func (wfa *workflowResourceMongoAccessor) UpdateOne(set utils.DBObject, id string) (utils.DBObject, int, error) { - set.(*WorkflowResource).ResourceModel = nil - return wfa.GenericUpdateOne(set.(*WorkflowResource).Trim(), id, wfa, &WorkflowResource{}) -} - -func (wfa *workflowResourceMongoAccessor) StoreOne(data utils.DBObject) (utils.DBObject, int, error) { - data.(*WorkflowResource).ResourceModel = nil - return wfa.GenericStoreOne(data.(*WorkflowResource).Trim(), wfa) -} - -func (wfa *workflowResourceMongoAccessor) CopyOne(data utils.DBObject) (utils.DBObject, int, error) { - res, _, _ := wfa.LoadOne(data.GetID()) - data.(*WorkflowResource).WorkflowID = data.GetID() - if res == nil { - return wfa.GenericStoreOne(data.(*WorkflowResource).Trim(), wfa) - } else { - data.(*WorkflowResource).UUID = res.GetID() - return wfa.GenericUpdateOne(data.(*WorkflowResource).Trim(), res.GetID(), wfa, &WorkflowResource{}) - } -} - -func (wfa *workflowResourceMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { - var workflow WorkflowResource - res_mongo, code, 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, code, err - } - res_mongo.Decode(&workflow) - if !workflow.VerifyAuth(wfa.PeerID, wfa.Groups) { - return nil, 403, errors.New("You are not allowed to access this collaborative area") - } - resources, _, err := wfa.ResourceModelAccessor.Search(nil, wfa.GetType()) - if err == nil && len(resources) > 0 { - workflow.ResourceModel = resources[0].(*resource_model.ResourceModel) - } - return &workflow, 200, nil -} - -func (wfa workflowResourceMongoAccessor) LoadAll() ([]utils.ShallowDBObject, int, error) { - objs := []utils.ShallowDBObject{} - res_mongo, code, err := mongo.MONGOService.LoadAll(wfa.GetType()) - if err != nil { - wfa.Logger.Error().Msg("Could not retrieve any from db. Error: " + err.Error()) - return nil, code, err - } - var results []WorkflowResource - if err = res_mongo.All(mongo.MngoCtx, &results); err != nil { - return nil, 404, err - } - resources, _, err := wfa.ResourceModelAccessor.Search(nil, wfa.GetType()) - for _, r := range results { - if !r.VerifyAuth(wfa.PeerID, wfa.Groups) { - continue - } - if err == nil && len(resources) > 0 { - r.ResourceModel = resources[0].(*resource_model.ResourceModel) - } - objs = append(objs, &r) - } - return objs, 200, nil -} - -// Search searches for workflow resources in the database, given some filters OR a search string -func (wfa *workflowResourceMongoAccessor) Search(filters *dbs.Filters, search string) ([]utils.ShallowDBObject, int, error) { - objs := []utils.ShallowDBObject{} - if (filters == nil || len(filters.And) == 0 || len(filters.Or) == 0) && search != "" { - filters = &dbs.Filters{ - Or: map[string][]dbs.Filter{ // filter by like name, short_description, description, owner, url if no filters are provided - "abstractresource.abstractobject.name": {{Operator: dbs.LIKE.String(), Value: search}}, - "abstractresource.short_description": {{Operator: dbs.LIKE.String(), Value: search}}, - "abstractresource.description": {{Operator: dbs.LIKE.String(), Value: search}}, - "abstractresource.owner": {{Operator: dbs.LIKE.String(), Value: search}}, - "abstractresource.source_url": {{Operator: dbs.LIKE.String(), Value: search}}, - }, - } - } - res_mongo, code, err := mongo.MONGOService.Search(filters, wfa.GetType()) - if err != nil { - wfa.Logger.Error().Msg("Could not store to db. Error: " + err.Error()) - return nil, code, err - } - var results []WorkflowResource - if err = res_mongo.All(mongo.MngoCtx, &results); err != nil { - return nil, 404, err - } - resources, _, err := wfa.ResourceModelAccessor.Search(nil, wfa.GetType()) - for _, r := range results { - if !r.VerifyAuth(wfa.PeerID, wfa.Groups) { - continue - } - if err == nil && len(resources) > 0 { - r.ResourceModel = resources[0].(*resource_model.ResourceModel) - } - objs = append(objs, &r) - } - return objs, 200, nil -} diff --git a/models/resources/workflow/workflow_test.go b/models/resources/workflow/workflow_test.go deleted file mode 100644 index 7d30257..0000000 --- a/models/resources/workflow/workflow_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package oclib - -import ( - "testing" - - "cloud.o-forge.io/core/oc-lib/models/resources/resource_model" - "cloud.o-forge.io/core/oc-lib/models/utils" - "cloud.o-forge.io/core/oc-lib/tools" - - "github.com/stretchr/testify/assert" -) - -func TestStoreOneWorkflow(t *testing.T) { - w := WorkflowResource{AbstractResource: resource_model.AbstractResource{ - AbstractObject: utils.AbstractObject{Name: "testWorkflow"}, - Description: "Lorem Ipsum", - Logo: "azerty.com", - Owner: "toto", - OwnerLogo: "totoLogo", - SourceUrl: "azerty.fr", - }, - } - - wma := New(tools.WORKFLOW_RESOURCE, "peerID", []string{}, nil) - id, _, _ := wma.StoreOne(&w) - - assert.NotEmpty(t, id) -} - -func TestLoadOneWorkflow(t *testing.T) { - w := WorkflowResource{AbstractResource: resource_model.AbstractResource{ - AbstractObject: utils.AbstractObject{Name: "testWorkflow"}, - Description: "Lorem Ipsum", - Logo: "azerty.com", - Owner: "toto", - OwnerLogo: "totoLogo", - SourceUrl: "azerty.fr", - }, - } - - wma := New(tools.WORKFLOW_RESOURCE, "peerID", []string{}, nil) - new_w, _, _ := wma.StoreOne(&w) - assert.Equal(t, w, new_w) -} diff --git a/models/utils/abstracts.go b/models/utils/abstracts.go index e9ea2de..0ec35b0 100644 --- a/models/utils/abstracts.go +++ b/models/utils/abstracts.go @@ -30,13 +30,20 @@ type AbstractObject struct { LastPeerWriter string `json:"last_peer_writer" bson:"last_peer_writer"` } -// GetID returns the id of the object (abstract) -func (ao *AbstractObject) GetID() string { +func (ao *AbstractObject) GetObjectFilters(search string) *dbs.Filters { + return &dbs.Filters{ + Or: map[string][]dbs.Filter{ // filter by name if no filters are provided + "abstractobject.name": {{Operator: dbs.LIKE.String(), Value: search}}, + }} +} + +// GetID implements ShallowDBObject. +func (ao AbstractObject) GetID() string { return ao.UUID } -// GetName returns the name of the object (abstract) -func (ao *AbstractObject) GetName() string { +// GetName implements ShallowDBObject. +func (ao AbstractObject) GetName() string { return ao.Name } @@ -81,7 +88,7 @@ func (r *AbstractObject) GenerateID() { type AbstractAccessor struct { Logger zerolog.Logger // Logger is the logger of the accessor, it's a specilized logger for the accessor - Type string // Type is the data type of the accessor + Type tools.DataType // Type is the data type of the accessor Caller *tools.HTTPCaller // Caller is the http caller of the accessor (optionnal) only need in a peer connection PeerID string // PeerID is the id of the peer Groups []string // Groups is the list of groups that can access the accessor @@ -93,7 +100,7 @@ func (dma *AbstractAccessor) VerifyAuth() string { return "" } -func (dma *AbstractAccessor) GetType() string { +func (dma *AbstractAccessor) GetType() tools.DataType { return dma.Type } @@ -117,13 +124,13 @@ func (wfa *AbstractAccessor) GenericStoreOne(data DBObject, accessor Accessor) ( }, } if cursor, _, _ := accessor.Search(&f, ""); len(cursor) > 0 { - return nil, 409, errors.New(accessor.GetType() + " with name " + data.GetName() + " already exists") + return nil, 409, errors.New(accessor.GetType().String() + " with name " + data.GetName() + " already exists") } err := validate.Struct(data) if err != nil { return nil, 422, err } - id, code, err := mongo.MONGOService.StoreOne(data, data.GetID(), wfa.GetType()) + id, code, err := mongo.MONGOService.StoreOne(data, data.GetID(), wfa.GetType().String()) if err != nil { wfa.Logger.Error().Msg("Could not store " + data.GetName() + " to db. Error: " + err.Error()) return nil, code, err @@ -138,7 +145,7 @@ func (dma *AbstractAccessor) GenericDeleteOne(id string, accessor Accessor) (DBO dma.Logger.Error().Msg("Could not retrieve " + id + " to db. Error: " + err.Error()) return nil, code, err } - _, code, err = mongo.MONGOService.DeleteOne(id, accessor.GetType()) + _, code, err = mongo.MONGOService.DeleteOne(id, accessor.GetType().String()) if err != nil { dma.Logger.Error().Msg("Could not delete " + id + " to db. Error: " + err.Error()) return nil, code, err @@ -159,7 +166,7 @@ func (dma *AbstractAccessor) GenericUpdateOne(set DBObject, id string, accessor for k, v := range change { // apply the changes, with a flatten method loaded[k] = v } - id, code, err := mongo.MONGOService.UpdateOne(new.Deserialize(loaded, new), id, accessor.GetType()) + id, code, err := mongo.MONGOService.UpdateOne(new.Deserialize(loaded, new), id, accessor.GetType().String()) if err != nil { dma.Logger.Error().Msg("Could not update " + id + " to db. Error: " + err.Error()) return nil, code, err @@ -169,7 +176,7 @@ func (dma *AbstractAccessor) GenericUpdateOne(set DBObject, id string, accessor func GenericLoadOne[T DBObject](id string, f func(DBObject) (DBObject, int, error), wfa Accessor) (DBObject, int, error) { var data T - res_mongo, code, err := mongo.MONGOService.LoadOne(id, wfa.GetType()) + res_mongo, code, err := mongo.MONGOService.LoadOne(id, wfa.GetType().String()) if !data.VerifyAuth(wfa.GetPeerID(), wfa.GetGroups()) { return nil, 403, errors.New("You are not allowed to access this collaborative area") } @@ -202,7 +209,7 @@ func genericLoadAll[T DBObject](res *mgb.Cursor, code int, err error, f func(DBO } func GenericLoadAll[T DBObject](f func(DBObject) ShallowDBObject, wfa Accessor) ([]ShallowDBObject, int, error) { - res_mongo, code, err := mongo.MONGOService.LoadAll(wfa.GetType()) + res_mongo, code, err := mongo.MONGOService.LoadAll(wfa.GetType().String()) return genericLoadAll[T](res_mongo, code, err, f, wfa) } @@ -211,14 +218,14 @@ func GenericSearch[T DBObject](filters *dbs.Filters, search string, defaultFilte if (filters == nil || len(filters.And) == 0 || len(filters.Or) == 0) && search != "" { filters = defaultFilters } - res_mongo, code, err := mongo.MONGOService.Search(filters, wfa.GetType()) + res_mongo, code, err := mongo.MONGOService.Search(filters, wfa.GetType().String()) return genericLoadAll[T](res_mongo, code, err, f, wfa) } // GenericLoadOne loads one object from the database (generic) // json expected in entry is a flatted object no need to respect the inheritance hierarchy func (dma *AbstractAccessor) GenericRawUpdateOne(set DBObject, id string, accessor Accessor) (DBObject, int, error) { - id, code, err := mongo.MONGOService.UpdateOne(set, id, accessor.GetType()) + id, code, err := mongo.MONGOService.UpdateOne(set, id, accessor.GetType().String()) if err != nil { dma.Logger.Error().Msg("Could not update " + id + " to db. Error: " + err.Error()) return nil, code, err diff --git a/models/utils/interfaces.go b/models/utils/interfaces.go index 5172980..7ae4f44 100644 --- a/models/utils/interfaces.go +++ b/models/utils/interfaces.go @@ -29,7 +29,7 @@ type DBObject interface { // Accessor is an interface that defines the basic methods for an Accessor type Accessor interface { - GetType() string + GetType() tools.DataType GetPeerID() string GetGroups() []string GetLogger() *zerolog.Logger diff --git a/models/resources/workflow/graph/graph.go b/models/workflow/graph/graph.go similarity index 100% rename from models/resources/workflow/graph/graph.go rename to models/workflow/graph/graph.go diff --git a/models/workflow/workflow.go b/models/workflow/workflow.go index 4956dc9..6aa4b3b 100644 --- a/models/workflow/workflow.go +++ b/models/workflow/workflow.go @@ -5,10 +5,8 @@ import ( "cloud.o-forge.io/core/oc-lib/models/peer" "cloud.o-forge.io/core/oc-lib/models/resources" - "cloud.o-forge.io/core/oc-lib/models/resources/compute" - "cloud.o-forge.io/core/oc-lib/models/resources/storage" - "cloud.o-forge.io/core/oc-lib/models/resources/workflow/graph" "cloud.o-forge.io/core/oc-lib/models/utils" + "cloud.o-forge.io/core/oc-lib/models/workflow/graph" "cloud.o-forge.io/core/oc-lib/tools" ) @@ -35,8 +33,8 @@ func (w *AbstractWorkflow) GetWorkflows() (list_computings []graph.GraphItem) { return } -func (w *AbstractWorkflow) GetComputeByRelatedProcessing(processingID string) []*compute.ComputeResource { - storages := []*compute.ComputeResource{} +func (w *AbstractWorkflow) GetComputeByRelatedProcessing(processingID string) []*resources.ComputeResource { + storages := []*resources.ComputeResource{} for _, link := range w.Graph.Links { nodeID := link.Destination.ID // we considers that the processing is the destination node := w.Graph.Items[link.Source.ID].Compute // we are looking for the storage as source @@ -51,8 +49,8 @@ func (w *AbstractWorkflow) GetComputeByRelatedProcessing(processingID string) [] return storages } -func (w *AbstractWorkflow) GetStoragesByRelatedProcessing(processingID string) []*storage.StorageResource { - storages := []*storage.StorageResource{} +func (w *AbstractWorkflow) GetStoragesByRelatedProcessing(processingID string) []*resources.StorageResource { + storages := []*resources.StorageResource{} for _, link := range w.Graph.Links { nodeID := link.Destination.ID // we considers that the processing is the destination node := w.Graph.Items[link.Source.ID].Storage // we are looking for the storage as source @@ -107,7 +105,7 @@ func (wfa *Workflow) CheckBooking(caller *tools.HTTPCaller) (bool, error) { if wfa.Graph == nil { // no graph no booking return false, nil } - accessor := (&compute.ComputeResource{}).GetAccessor("", []string{}, caller) + accessor := (&resources.ComputeResource{}).GetAccessor("", []string{}, caller) for _, link := range wfa.Graph.Links { if ok, dc_id := wfa.isDCLink(link); ok { // check if the link is a link between a compute and a resource dc, code, _ := accessor.LoadOne(dc_id) @@ -115,7 +113,7 @@ func (wfa *Workflow) CheckBooking(caller *tools.HTTPCaller) (bool, error) { continue } // CHECK BOOKING ON PEER, compute could be a remote one - peerID := dc.(*compute.ComputeResource).PeerID + peerID := dc.(*resources.ComputeResource).PeerID if peerID == "" { return false, errors.New("no peer id") } // no peer id no booking, we need to know where to book diff --git a/models/workflow/workflow_mongo_accessor.go b/models/workflow/workflow_mongo_accessor.go index 09add7f..f7a6eb8 100644 --- a/models/workflow/workflow_mongo_accessor.go +++ b/models/workflow/workflow_mongo_accessor.go @@ -42,7 +42,7 @@ func New(t tools.DataType, peerID string, groups []string, caller *tools.HTTPCal Caller: caller, PeerID: peerID, Groups: groups, // Set the caller - Type: t.String(), + Type: t, }, } } @@ -157,7 +157,7 @@ func (wfa *workflowMongoAccessor) book(id string, realData *Workflow, execs []*w continue } // CHECK BOOKING - peerID := dc.(*compute.ComputeResource).PeerID + peerID := dc.(*resources.ComputeResource).PeerID if peerID == "" { // no peer id no booking continue } @@ -319,7 +319,7 @@ func (wfa *workflowMongoAccessor) execute(workflow *Workflow, delete bool, activ filters := &dbs.Filters{ Or: map[string][]dbs.Filter{ // filter by standard workspace name attached to a workflow - "abstractobject.name": {{dbs.LIKE.String(), workflow.Name + "_workspace"}}, + "abstractobject.name": {{Operator: dbs.LIKE.String(), Value: workflow.Name + "_workspace"}}, }, } resource, _, err := wfa.workspaceAccessor.Search(filters, "") @@ -355,64 +355,25 @@ func (wfa *workflowMongoAccessor) execute(workflow *Workflow, delete bool, activ } } -// LoadOne loads a workflow from the database -func (wfa *workflowMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { - var workflow Workflow - res_mongo, code, 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, code, err - } - res_mongo.Decode(&workflow) - if workflow.ScheduleActive && workflow.Schedule != nil { // if the workflow is scheduled, update the executions - now := time.Now().UTC() - if (workflow.Schedule.End != nil && now.After(*workflow.Schedule.End)) || (workflow.Schedule.End == nil && workflow.Schedule.Start != nil && now.After(*workflow.Schedule.Start)) { // if the start date is passed, then you can book - workflow.ScheduleActive = false - wfa.GenericRawUpdateOne(&workflow, id, wfa) - } // if the start date is passed, update the executions - } - wfa.execute(&workflow, false, true) // if no workspace is attached to the workflow, create it - return &workflow, 200, nil -} - -// LoadAll loads all the workflows from the database -func (wfa workflowMongoAccessor) LoadAll() ([]utils.ShallowDBObject, int, error) { - objs := []utils.ShallowDBObject{} - res_mongo, code, err := mongo.MONGOService.LoadAll(wfa.GetType()) - if err != nil { - wfa.Logger.Error().Msg("Could not retrieve any from db. Error: " + err.Error()) - return nil, code, err - } - var results []Workflow - if err = res_mongo.All(mongo.MngoCtx, &results); err != nil { - return nil, 404, err - } - for _, r := range results { - objs = append(objs, &r.AbstractObject) // only AbstractObject fields ! - } - return objs, 200, nil -} - -func (wfa *workflowMongoAccessor) Search(filters *dbs.Filters, search string) ([]utils.ShallowDBObject, int, error) { - objs := []utils.ShallowDBObject{} - if (filters == nil || len(filters.And) == 0 || len(filters.Or) == 0) && search != "" { - filters = &dbs.Filters{ - Or: map[string][]dbs.Filter{ // filter by name if no filters are provided - "abstractobject.name": {{Operator: dbs.LIKE.String(), Value: search}}, - }, +func (a *workflowMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { + return utils.GenericLoadOne[*Workflow](id, func(d utils.DBObject) (utils.DBObject, int, error) { + w := d.(*Workflow) + if w.ScheduleActive && w.Schedule != nil { // if the workflow is scheduled, update the executions + now := time.Now().UTC() + if (w.Schedule.End != nil && now.After(*w.Schedule.End)) || (w.Schedule.End == nil && w.Schedule.Start != nil && now.After(*w.Schedule.Start)) { // if the start date is passed, then you can book + w.ScheduleActive = false + a.GenericRawUpdateOne(d, id, a) + } // if the start date is passed, update the executions } - } - res_mongo, code, err := mongo.MONGOService.Search(filters, wfa.GetType()) - if err != nil { - wfa.Logger.Error().Msg("Could not store to db. Error: " + err.Error()) - return nil, code, err - } - var results []Workflow - if err = res_mongo.All(mongo.MngoCtx, &results); err != nil { - return nil, 404, err - } - for _, r := range results { - objs = append(objs, &r) - } - return objs, 200, nil + a.execute(w, false, true) // if no workspace is attached to the workflow, create it + return d, 200, nil + }, a) +} + +func (a *workflowMongoAccessor) LoadAll() ([]utils.ShallowDBObject, int, error) { + return utils.GenericLoadAll[*Workflow](func(d utils.DBObject) utils.ShallowDBObject { return &d.(*Workflow).AbstractObject }, a) +} + +func (a *workflowMongoAccessor) Search(filters *dbs.Filters, search string) ([]utils.ShallowDBObject, int, error) { + return utils.GenericSearch[*Workflow](filters, search, (&Workflow{}).GetObjectFilters(search), func(d utils.DBObject) utils.ShallowDBObject { return d }, a) } diff --git a/models/workflow_execution/workflow_execution_mongo_accessor.go b/models/workflow_execution/workflow_execution_mongo_accessor.go index 0a0975a..d58b6e3 100644 --- a/models/workflow_execution/workflow_execution_mongo_accessor.go +++ b/models/workflow_execution/workflow_execution_mongo_accessor.go @@ -4,7 +4,6 @@ import ( "time" "cloud.o-forge.io/core/oc-lib/dbs" - "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/utils" "cloud.o-forge.io/core/oc-lib/tools" @@ -21,7 +20,7 @@ func New(t tools.DataType, peerID string, groups []string, caller *tools.HTTPCal Caller: caller, PeerID: peerID, Groups: groups, // Set the caller - Type: t.String(), + Type: t, }, } } @@ -42,67 +41,30 @@ func (wfa *workflowExecutionMongoAccessor) CopyOne(data utils.DBObject) (utils.D return wfa.GenericStoreOne(data, wfa) } -func (wfa *workflowExecutionMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { - var workflow WorkflowExecution - res_mongo, code, 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, code, err - } - res_mongo.Decode(&workflow) - if workflow.State == SCHEDULED && time.Now().UTC().After(*workflow.ExecDate) { - workflow.State = FORGOTTEN - wfa.GenericRawUpdateOne(&workflow, id, wfa) - } - return &workflow, 200, nil +func (a *workflowExecutionMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { + return utils.GenericLoadOne[*WorkflowExecution](id, func(d utils.DBObject) (utils.DBObject, int, error) { + if d.(*WorkflowExecution).State == SCHEDULED && time.Now().UTC().After(*d.(*WorkflowExecution).ExecDate) { + d.(*WorkflowExecution).State = FORGOTTEN + a.GenericRawUpdateOne(d, id, a) + } + return d, 200, nil + }, a) } -func (wfa *workflowExecutionMongoAccessor) LoadAll() ([]utils.ShallowDBObject, int, error) { - objs := []utils.ShallowDBObject{} - res_mongo, code, err := mongo.MONGOService.LoadAll(wfa.GetType()) - if err != nil { - wfa.Logger.Error().Msg("Could not retrieve any from db. Error: " + err.Error()) - return nil, code, err - } - var results []WorkflowExecution - if err = res_mongo.All(mongo.MngoCtx, &results); err != nil { - return nil, 404, err - } - for _, r := range results { - if r.State == SCHEDULED && time.Now().UTC().After(*r.ExecDate) { - r.State = FORGOTTEN - wfa.GenericRawUpdateOne(&r, r.UUID, wfa) - } - objs = append(objs, &r.AbstractObject) - } - return objs, 200, nil +func (a *workflowExecutionMongoAccessor) LoadAll() ([]utils.ShallowDBObject, int, error) { + return utils.GenericLoadAll[*WorkflowExecution](a.getExec(), a) } -// Search searches for workflow executions in the database, given some filters OR a search string -func (wfa *workflowExecutionMongoAccessor) Search(filters *dbs.Filters, search string) ([]utils.ShallowDBObject, int, error) { - objs := []utils.ShallowDBObject{} - if (filters == nil || len(filters.And) == 0 || len(filters.Or) == 0) && search != "" { - filters = &dbs.Filters{ - Or: map[string][]dbs.Filter{ // filter by name if no filters are provided - "abstractobject.name": {{Operator: dbs.LIKE.String(), Value: search}}, - }, - } - } - res_mongo, code, err := mongo.MONGOService.Search(filters, wfa.GetType()) - if err != nil { - wfa.Logger.Error().Msg("Could not store to db. Error: " + err.Error()) - return nil, code, err - } - var results []WorkflowExecution - if err = res_mongo.All(mongo.MngoCtx, &results); err != nil { - return nil, 404, err - } - for _, r := range results { - if r.State == SCHEDULED && time.Now().UTC().After(*r.ExecDate) { - r.State = FORGOTTEN - wfa.GenericRawUpdateOne(&r, r.UUID, wfa) - } - objs = append(objs, &r) - } - return objs, 200, nil +func (a *workflowExecutionMongoAccessor) Search(filters *dbs.Filters, search string) ([]utils.ShallowDBObject, int, error) { + return utils.GenericSearch[*WorkflowExecution](filters, search, (&WorkflowExecution{}).GetObjectFilters(search), a.getExec(), a) +} + +func (a *workflowExecutionMongoAccessor) getExec() func(utils.DBObject) utils.ShallowDBObject { + return func(d utils.DBObject) utils.ShallowDBObject { + if d.(*WorkflowExecution).State == SCHEDULED && time.Now().UTC().After(*d.(*WorkflowExecution).ExecDate) { + d.(*WorkflowExecution).State = FORGOTTEN + a.GenericRawUpdateOne(d, d.GetID(), a) + } + return d + } } diff --git a/models/workspace/workspace_mongo_accessor.go b/models/workspace/workspace_mongo_accessor.go index 1de546d..2176b96 100644 --- a/models/workspace/workspace_mongo_accessor.go +++ b/models/workspace/workspace_mongo_accessor.go @@ -5,7 +5,6 @@ import ( "fmt" "cloud.o-forge.io/core/oc-lib/dbs" - "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/collaborative_area/shallow_collaborative_area" "cloud.o-forge.io/core/oc-lib/models/peer" @@ -26,7 +25,7 @@ func New(t tools.DataType, peerID string, groups []string, caller *tools.HTTPCal Caller: caller, PeerID: peerID, Groups: groups, // Set the caller - Type: t.String(), + Type: t, }, } } @@ -44,11 +43,7 @@ func (wfa *workspaceMongoAccessor) DeleteOne(id string) (utils.DBObject, int, er // UpdateOne updates a workspace in the database, given its ID, it automatically share to peers if the workspace is shared func (wfa *workspaceMongoAccessor) UpdateOne(set utils.DBObject, id string) (utils.DBObject, int, error) { d := set.(*Workspace) // Get the workspace from the set - d.DataResources = nil // Reset the resources - d.ComputeResources = nil - d.StorageResources = nil - d.ProcessingResources = nil - d.WorkflowResources = nil + d.Clear() if d.Active { // If the workspace is active, deactivate all the other workspaces res, _, err := wfa.LoadAll() if err == nil { @@ -80,11 +75,7 @@ func (wfa *workspaceMongoAccessor) StoreOne(data utils.DBObject) (utils.DBObject } // reset the resources d := data.(*Workspace) - d.DataResources = nil - d.ComputeResources = nil - d.StorageResources = nil - d.ProcessingResources = nil - d.WorkflowResources = nil + d.Clear() return wfa.GenericStoreOne(d, wfa) } @@ -93,62 +84,25 @@ func (wfa *workspaceMongoAccessor) CopyOne(data utils.DBObject) (utils.DBObject, return wfa.GenericStoreOne(data, wfa) } -// LoadOne loads a workspace from the database, given its ID -func (wfa *workspaceMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { - var workflow Workspace - res_mongo, code, 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, code, err - } - res_mongo.Decode(&workflow) - workflow.Fill(wfa.PeerID, wfa.Groups) - return &workflow, 200, nil +func (a *workspaceMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { + return utils.GenericLoadOne[*Workspace](id, func(d utils.DBObject) (utils.DBObject, int, error) { + d.(*Workspace).Fill(a.PeerID, a.Groups) + return d, 200, nil + }, a) } -// LoadAll loads all the workspaces from the database -func (wfa workspaceMongoAccessor) LoadAll() ([]utils.ShallowDBObject, int, error) { - objs := []utils.ShallowDBObject{} - res_mongo, code, err := mongo.MONGOService.LoadAll(wfa.GetType()) - if err != nil { - wfa.Logger.Error().Msg("Could not retrieve any from db. Error: " + err.Error()) - return nil, code, err - } - var results []Workspace - if err = res_mongo.All(mongo.MngoCtx, &results); err != nil { - return nil, 404, err - } - for _, r := range results { - r.Fill(wfa.PeerID, wfa.Groups) - objs = append(objs, &r) - } - return objs, 200, nil +func (wfa *workspaceMongoAccessor) LoadAll() ([]utils.ShallowDBObject, int, error) { + return utils.GenericLoadAll[*Workspace](func(d utils.DBObject) utils.ShallowDBObject { + d.(*Workspace).Fill(wfa.PeerID, wfa.Groups) + return d + }, wfa) } -// Search searches for workspaces in the database, given some filters OR a search string func (wfa *workspaceMongoAccessor) Search(filters *dbs.Filters, search string) ([]utils.ShallowDBObject, int, error) { - objs := []utils.ShallowDBObject{} - if (filters == nil || len(filters.And) == 0 || len(filters.Or) == 0) && search != "" { - filters = &dbs.Filters{ - Or: map[string][]dbs.Filter{ // filter by name if no filters are provided - "abstractobject.name": {{Operator: dbs.LIKE.String(), Value: search}}, - }, - } - } - res_mongo, code, err := mongo.MONGOService.Search(filters, wfa.GetType()) - if err != nil { - wfa.Logger.Error().Msg("Could not store to db. Error: " + err.Error()) - return nil, code, err - } - var results []Workspace - if err = res_mongo.All(mongo.MngoCtx, &results); err != nil { - return nil, 404, err - } - for _, r := range results { - r.Fill(wfa.PeerID, wfa.Groups) - objs = append(objs, &r) - } - return objs, 200, nil + return utils.GenericSearch[*Workspace](filters, search, (&Workspace{}).GetObjectFilters(search), func(d utils.DBObject) utils.ShallowDBObject { + d.(*Workspace).Fill(wfa.PeerID, wfa.Groups) + return d + }, wfa) } /*