| 
									
										
										
										
											2023-03-03 14:43:11 +01:00
										 |  |  | package models | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"context" | 
					
						
							|  |  |  | 	"errors" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-29 18:02:29 +02:00
										 |  |  | 	"cloud.o-forge.io/core/deprecated-oc-catalog/models/rtype" | 
					
						
							|  |  |  | 	"cloud.o-forge.io/core/deprecated-oc-catalog/services" | 
					
						
							| 
									
										
										
										
											2023-03-03 14:43:11 +01:00
										 |  |  | 	"github.com/beego/beego/v2/core/logs" | 
					
						
							|  |  |  | 	"go.mongodb.org/mongo-driver/bson/primitive" | 
					
						
							|  |  |  | 	"go.mongodb.org/mongo-driver/mongo" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Assure consistency by using a const which refers to the MongoDB entry name | 
					
						
							|  |  |  | // Workspace.Projects | 
					
						
							|  |  |  | const WorkflowDB = "workflows" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type Workspace struct { | 
					
						
							|  |  |  | 	UserID string `bson:"_id" json:"user_id"` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Workflows map[string]Workflow //WorkflowDB | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// ID: rtype | 
					
						
							|  |  |  | 	Data       []string `json:"data"` | 
					
						
							|  |  |  | 	Computing  []string `json:"computing"` | 
					
						
							|  |  |  | 	Datacenter []string `json:"datacenter"` | 
					
						
							|  |  |  | 	Storage    []string `json:"storage"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type ResourceModel interface { | 
					
						
							|  |  |  | 	getRtype() rtype.Rtype | 
					
						
							|  |  |  | 	getName() string | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (w Workspace) getRtype(rID string) (resModel rtype.Rtype) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, compVal := range w.Computing { | 
					
						
							|  |  |  | 		if compVal == rID { | 
					
						
							|  |  |  | 			return rtype.COMPUTING | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, datVal := range w.Data { | 
					
						
							|  |  |  | 		if datVal == rID { | 
					
						
							|  |  |  | 			return rtype.DATA | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, storVal := range w.Storage { | 
					
						
							|  |  |  | 		if storVal == rID { | 
					
						
							|  |  |  | 			return rtype.STORAGE | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, datcentVal := range w.Datacenter { | 
					
						
							|  |  |  | 		if datcentVal == rID { | 
					
						
							|  |  |  | 			return rtype.DATACENTER | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return rtype.INVALID | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (w *Workspace) GetResources() map[rtype.Rtype][]string { | 
					
						
							|  |  |  | 	return map[rtype.Rtype][]string{ | 
					
						
							|  |  |  | 		rtype.DATA:       w.Data, | 
					
						
							|  |  |  | 		rtype.COMPUTING:  w.Computing, | 
					
						
							|  |  |  | 		rtype.STORAGE:    w.Storage, | 
					
						
							|  |  |  | 		rtype.DATACENTER: w.Datacenter, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (w *Workspace) GetWorkflow(workflowName string) *Workflow { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var proj Workflow | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	proj = w.Workflows[workflowName] | 
					
						
							|  |  |  | 	return &proj | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (w *Workspace) GetWorkflows() []string { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(w.Workflows) == 0 { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	workflowNames := make([]string, len(w.Workflows)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	i := 0 | 
					
						
							|  |  |  | 	for k := range w.Workflows { | 
					
						
							|  |  |  | 		workflowNames[i] = k | 
					
						
							|  |  |  | 		i++ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return workflowNames | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type WorkspaceModel struct { | 
					
						
							|  |  |  | 	UserID string `bson:"_id" json:"user_id"` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Data       []DataModel       `json:"data"` | 
					
						
							|  |  |  | 	Computing  []ComputingModel  `json:"computing"` | 
					
						
							|  |  |  | 	Datacenter []DatacenterModel `json:"datacenter"` | 
					
						
							|  |  |  | 	Storage    []StorageModel    `json:"storage"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func ListFullWorkspace(userID string) (*WorkspaceModel, error) { | 
					
						
							|  |  |  | 	ws := GetWorkspace(userID) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ws == nil { | 
					
						
							|  |  |  | 		return nil, errors.New("Internal error") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fws := &WorkspaceModel{ | 
					
						
							|  |  |  | 		UserID: ws.UserID, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Data:       []DataModel{}, | 
					
						
							|  |  |  | 		Computing:  []ComputingModel{}, | 
					
						
							|  |  |  | 		Datacenter: []DatacenterModel{}, | 
					
						
							|  |  |  | 		Storage:    []StorageModel{}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pipeline := []primitive.M{ | 
					
						
							|  |  |  | 		{"$match": primitive.M{"_id": userID}}, | 
					
						
							|  |  |  | 		{"$lookup": primitive.M{ | 
					
						
							|  |  |  | 			"localField":   "data", | 
					
						
							|  |  |  | 			"from":         services.MngoNamesCollection.DATA, | 
					
						
							|  |  |  | 			"foreignField": "_id", | 
					
						
							|  |  |  | 			"as":           "data", | 
					
						
							|  |  |  | 		}}, | 
					
						
							|  |  |  | 		{"$lookup": primitive.M{ | 
					
						
							|  |  |  | 			"localField":   "computing", | 
					
						
							|  |  |  | 			"from":         services.MngoNamesCollection.COMPUTING, | 
					
						
							|  |  |  | 			"foreignField": "_id", | 
					
						
							|  |  |  | 			"as":           "computing", | 
					
						
							|  |  |  | 		}}, | 
					
						
							|  |  |  | 		{"$lookup": primitive.M{ | 
					
						
							|  |  |  | 			"localField":   "datacenter", | 
					
						
							|  |  |  | 			"from":         services.MngoNamesCollection.DATACENTER, | 
					
						
							|  |  |  | 			"foreignField": "_id", | 
					
						
							|  |  |  | 			"as":           "datacenter", | 
					
						
							|  |  |  | 		}}, | 
					
						
							|  |  |  | 		{"$lookup": primitive.M{ | 
					
						
							|  |  |  | 			"localField":   "storage", | 
					
						
							|  |  |  | 			"from":         services.MngoNamesCollection.STORAGE, | 
					
						
							|  |  |  | 			"foreignField": "_id", | 
					
						
							|  |  |  | 			"as":           "storage", | 
					
						
							|  |  |  | 		}}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ret, err := services.MngoCollWorkspace.Aggregate(services.MngoCtx, pipeline) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		message := "Couldn't obtain subobjects" | 
					
						
							|  |  |  | 		logs.Debug(message + "; " + err.Error()) | 
					
						
							|  |  |  | 		return nil, errors.New(message) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ret.RemainingBatchLength() == 1 { | 
					
						
							|  |  |  | 		ret.Next(context.Background()) | 
					
						
							|  |  |  | 		ret.Decode(&fws) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return fws, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Contains tells whether a contains x. | 
					
						
							|  |  |  | func contains(a []string, x string) bool { | 
					
						
							|  |  |  | 	for _, n := range a { | 
					
						
							|  |  |  | 		if x == n { | 
					
						
							|  |  |  | 			return true | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return false | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func RemoveResource(userID, rID, rType string) error { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rIDObj, err := primitive.ObjectIDFromHex(rID) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		message := "ID " + rID + " is not valid" | 
					
						
							|  |  |  | 		logs.Debug(message + "; " + err.Error()) | 
					
						
							|  |  |  | 		return errors.New(message) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	result, err := services.MngoCollWorkspace.UpdateOne(services.MngoCtx, | 
					
						
							|  |  |  | 		primitive.M{"_id": userID}, | 
					
						
							|  |  |  | 		primitive.M{"$pull": primitive.M{rType: rIDObj}}, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		message := err.Error() | 
					
						
							|  |  |  | 		logs.Debug(message) | 
					
						
							|  |  |  | 		return errors.New(message) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if result.MatchedCount == 0 { | 
					
						
							|  |  |  | 		message := "No user " + userID + " in workspace" | 
					
						
							|  |  |  | 		logs.Debug(message) | 
					
						
							|  |  |  | 		return errors.New(message) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if result.ModifiedCount == 0 { | 
					
						
							|  |  |  | 		message := "No rID " + rID + " in rtype " + rType | 
					
						
							|  |  |  | 		logs.Debug(message) | 
					
						
							|  |  |  | 		return errors.New(message) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (w *Workspace) updateDB() (err error) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_, err = services.MngoCollWorkspace.ReplaceOne(services.MngoCtx, | 
					
						
							|  |  |  | 		primitive.M{"_id": w.UserID}, | 
					
						
							|  |  |  | 		w, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (w *Workspace) NewResource(rID string, rType string) (err error) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var targetArray *[]string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch rType { | 
					
						
							|  |  |  | 	case rtype.DATA.String(): | 
					
						
							|  |  |  | 		targetArray = &w.Data | 
					
						
							|  |  |  | 	case rtype.COMPUTING.String(): | 
					
						
							|  |  |  | 		targetArray = &w.Computing | 
					
						
							|  |  |  | 	case rtype.STORAGE.String(): | 
					
						
							|  |  |  | 		targetArray = &w.Storage | 
					
						
							|  |  |  | 	case rtype.DATACENTER.String(): | 
					
						
							|  |  |  | 		targetArray = &w.Datacenter | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		return errors.New("Rtype " + rType + " is not valid") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, models := range *targetArray { | 
					
						
							|  |  |  | 		if models == rID { | 
					
						
							|  |  |  | 			return errors.New("Resource " + rID + " of type " + rType + | 
					
						
							|  |  |  | 				" is already registered for user " + w.UserID) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*targetArray = append(*targetArray, rID) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	w.updateDB() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func AddResource(userID, rID, rType string) (err error) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var rIDObj *primitive.ObjectID | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if rIDObj, err = IsValidResource(rID, rType); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//TODO: Maybe operate directly in the DB instead retriving the full object? | 
					
						
							|  |  |  | 	userWorkspace := GetWorkspace(userID) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Exist in the DB | 
					
						
							|  |  |  | 	if userWorkspace != nil { | 
					
						
							|  |  |  | 		var targetArray []string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		switch rType { | 
					
						
							|  |  |  | 		case rtype.DATA.String(): | 
					
						
							|  |  |  | 			targetArray = userWorkspace.Data | 
					
						
							|  |  |  | 		case rtype.COMPUTING.String(): | 
					
						
							|  |  |  | 			targetArray = userWorkspace.Computing | 
					
						
							|  |  |  | 		case rtype.STORAGE.String(): | 
					
						
							|  |  |  | 			targetArray = userWorkspace.Storage | 
					
						
							|  |  |  | 		case rtype.DATACENTER.String(): | 
					
						
							|  |  |  | 			targetArray = userWorkspace.Datacenter | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			message := "Rtype " + rType + " is not valid" | 
					
						
							|  |  |  | 			logs.Debug(message) | 
					
						
							|  |  |  | 			return errors.New(message) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if ok := contains(targetArray, rID); ok { | 
					
						
							|  |  |  | 			// Element already registered | 
					
						
							|  |  |  | 			message := "Resource " + rID + " of type " + rType + | 
					
						
							|  |  |  | 				" is already registered for user " + userID | 
					
						
							|  |  |  | 			logs.Debug(message) | 
					
						
							|  |  |  | 			return errors.New(message) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// New element | 
					
						
							|  |  |  | 		// userWorkspace.ResourceList[rID] = rType | 
					
						
							|  |  |  | 		_, err := services.MngoCollWorkspace.UpdateOne(services.MngoCtx, | 
					
						
							|  |  |  | 			primitive.M{"_id": userID}, | 
					
						
							|  |  |  | 			primitive.M{"$push": primitive.M{rType: rIDObj}}, | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			message := "Internal error when updating in DB" | 
					
						
							|  |  |  | 			logs.Debug(message + "; " + err.Error()) | 
					
						
							|  |  |  | 			return errors.New(message) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return errors.New("Internal error") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func rTypeToCollection(rType string) (*mongo.Collection, error) { | 
					
						
							|  |  |  | 	switch rType { | 
					
						
							|  |  |  | 	case rtype.DATA.String(): | 
					
						
							|  |  |  | 		return services.MngoCollData, nil | 
					
						
							|  |  |  | 	case rtype.COMPUTING.String(): | 
					
						
							|  |  |  | 		return services.MngoCollComputing, nil | 
					
						
							|  |  |  | 	case rtype.DATACENTER.String(): | 
					
						
							|  |  |  | 		return services.MngoCollDatacenter, nil | 
					
						
							|  |  |  | 	case rtype.STORAGE.String(): | 
					
						
							|  |  |  | 		return services.MngoCollStorage, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	message := rType + " is not a valid resource type" | 
					
						
							|  |  |  | 	logs.Debug(message) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil, errors.New(message) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func IsValidResource(rID, rType string) (*primitive.ObjectID, error) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	targetColl, err := rTypeToCollection(rType) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rIDObj, err := primitive.ObjectIDFromHex(rID) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		message := "ID " + rID + " is not valid" | 
					
						
							|  |  |  | 		logs.Debug(message + "; " + err.Error()) | 
					
						
							|  |  |  | 		return nil, errors.New(message) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	result := targetColl.FindOne(services.MngoCtx, primitive.M{"_id": rIDObj}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if result.Err() != nil { | 
					
						
							|  |  |  | 		message := "ID " + rID + " doesn't exist for resource type " + rType | 
					
						
							|  |  |  | 		logs.Debug(message + "; " + result.Err().Error()) | 
					
						
							|  |  |  | 		return nil, errors.New(message) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return &rIDObj, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func GetAllWorkspaces() <-chan *Workspace { | 
					
						
							|  |  |  | 	ch := make(chan *Workspace) | 
					
						
							|  |  |  | 	go func() { | 
					
						
							|  |  |  | 		cursor, err := services.MngoCollWorkspace.Find(services.MngoCtx, primitive.M{}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			logs.Error(cursor.Err()) | 
					
						
							|  |  |  | 			close(ch) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for cursor.Next(services.MngoCtx) { | 
					
						
							|  |  |  | 			var item Workspace | 
					
						
							|  |  |  | 			if err = cursor.Decode(&item); err != nil { | 
					
						
							|  |  |  | 				logs.Error(err) | 
					
						
							|  |  |  | 				close(ch) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			ch <- &item | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		close(ch) // Remember to close or the loop never ends! | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 	return ch | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (w *Workspace) GetAllWorkspacesProjects() <-chan *Workflow { | 
					
						
							|  |  |  | 	ch := make(chan *Workflow) | 
					
						
							|  |  |  | 	go func() { | 
					
						
							|  |  |  | 		for _, wproj := range w.Workflows { | 
					
						
							|  |  |  | 			ch <- &wproj | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		close(ch) | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 	return ch | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func GetWorkspace(userID string) (retObj *Workspace) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err := services.MngoCollWorkspace.FindOne(services.MngoCtx, primitive.M{"_id": userID}).Decode(&retObj); err != nil { | 
					
						
							|  |  |  | 		logs.Error(err.Error()) | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func NewWorkspace(userID string) (*Workspace, error) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	newWsp := &Workspace{ | 
					
						
							|  |  |  | 		UserID:     userID, | 
					
						
							|  |  |  | 		Data:       []string{}, | 
					
						
							|  |  |  | 		Computing:  []string{}, | 
					
						
							|  |  |  | 		Datacenter: []string{}, | 
					
						
							|  |  |  | 		Storage:    []string{}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_, err := services.MngoCollWorkspace.InsertOne(services.MngoCtx, newWsp) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		logs.Warning(err.Error()) | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return newWsp, nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |