initial commit
This commit is contained in:
418
models/workspace.go
Normal file
418
models/workspace.go
Normal file
@@ -0,0 +1,418 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"cloud.o-forge.io/core/oc-catalog/models/rtype"
|
||||
"cloud.o-forge.io/core/oc-catalog/services"
|
||||
"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
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user