// 2020 Rackspace, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"): you may // not use this file except in compliance with the License. You may obtain // a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations // under the License. package tools import ( "context" "fmt" "time" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo/options" ) // TrolleyCollection is an exportable constant with the name of the trolleys // mongo collection. const TrolleyCollection = "trolley" // Trolley type represents details about a DCOPs migration trolley type Trolley struct { ID string `json:"_id" bson:"_id"` Description string `json:"description" bson:"description"` Type string `json:"type" bson:"type"` SlotCount int `json:"slot_count" bson:"slot_count"` UHeight int `json:"u_height" bson:"u_height"` Platforms []string `json:"platforms" bson:"platforms"` Active bool `json:"active" bson:"active"` } // CreateTrolley method will insert a new trolley into the trolley's collection func (c *Client) CreateTrolley(trolley Trolley) (err error) { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() // Generate a new _id trolley.ID = primitive.NewObjectID().String() // Assume that if we're creating one, it needs to be set as // active. trolley.Active = true _, err = c.db.Database(migrationDB).Collection(TrolleyCollection).InsertOne(ctx, trolley) return } // ReadTrolleys method will query the trolley collection and return a list of trolleys func (c *Client) ReadTrolleys(query bson.M) (trolleys []Trolley, err error) { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() opts := options.Find() cursor, err := c.db.Database(migrationDB).Collection(TrolleyCollection).Find(ctx, query, opts) if err != nil { return } trolleys = make([]Trolley, 0) err = cursor.All(ctx, &trolleys) return } // UpdateTrolley method will update an existing trolley into the new trolley information func (c *Client) UpdateTrolley(id string, trolley Trolley) (err error) { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() objID, err := primitive.ObjectIDFromHex(id) if err != nil { return fmt.Errorf("trolley.ObjectIDFromHex#objID_%s: %s", id, err) } update := bson.M{"$set": bson.M{ "description": trolley.Description, "slot_count": trolley.SlotCount, "type": trolley.Type, "u_height": trolley.UHeight, "platforms": trolley.Platforms, "active": trolley.Active, }} _, err = c.db.Database(migrationDB).Collection(TrolleyCollection).UpdateOne(ctx, bson.M{"_id": objID}, update) return } // DeleteTrolley method will delete an existing trolley from the trolley collection func (c *Client) DeleteTrolley(id string) (err error) { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() objID, err := primitive.ObjectIDFromHex(id) if err != nil { return fmt.Errorf("trolley.ObjectIDFromHex#objID_%s: %s", id, err) } _, err = c.db.Database(migrationDB).Collection(TrolleyCollection).DeleteOne(ctx, bson.M{"_id": objID}) return } // ReadTrolleyDevices method will query the trolley collection and return a list of devices with // trolley information from the move-group func (c *Client) ReadTrolleyDevices(collection string, filters bson.M) (devices []Device, err error) { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() query := bson.M{ "deleted": bson.M{"$ne": true}, "environment.current.container": bson.M{"$nin": []interface{}{"", nil, "Unknown"}}, } for k, v := range filters { query[k] = v } opts := options.Find().SetProjection(bson.D{ {"icon_url", 1}, {"network.public.zone", 1}, {"environment.current", 1}, {"environment.migration", 1}, {"move_group", 1}, {"process", 1}, {"linked", 1}, {"trolley", 1}, {"account", 1}, {"device", 1}, }) cursor, err := c.db.Database(migrationDB).Collection(collection).Find(ctx, query, opts) if err != nil { return } devices = make([]Device, 0) err = cursor.All(ctx, &devices) return } // UpdateTrolleyDevice method will query the trolley collection and return a list of devices with // trolley information from the move-group func (c *Client) UpdateTrolleyDevice(device int, record DeviceTrolley, collection string) (err error) { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() update := bson.M{ "$set": bson.M{ "trolley._id": record.ID, "trolley.number": record.Number, "trolley.slot": record.Slot, }, } if _, err = c.db.Database(migrationDB).Collection(collection).UpdateOne(ctx, bson.M{"_id": device}, update); err != nil { return } return } // IsValid method attached to the Trolley receiver will contain all the things we will check to // ensure that the Trolley type is valid for read/write operations. func (r *Trolley) IsValid() error { if r.SlotCount == 0 { return fmt.Errorf("slot_count required for new trolley") } if r.UHeight == 0 { return fmt.Errorf("u_height required for new trolley") } return nil }