// 2017 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 mongo import ( "context" "crypto/md5" // #nosec "encoding/json" "time" "go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson" "github.com/sirupsen/logrus" ) // InsertOne is a small exported method to expose the InsertOne method in Mongo to the client. func (c *Client) InsertOne(table string, document bson.D) error { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() _, err := c.db3.Database(database).Collection(table).InsertOne(ctx, document) return err } // UpdateOne is a small exported method to expose the UpdateOne method in Mongo to the client. func (c *Client) UpdateOne(table string, query bson.D, update bson.D, upsert bool) error { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() _, err := c.db3.Database(database).Collection(table).UpdateOne( ctx, query, update, options.Update().SetUpsert(upsert), ) return err } // UpdateMany is a small exported method to expose the UpdateMany method in Mongo to the client. func (c *Client) UpdateMany(table string, query bson.D, update bson.D, upsert bool, timeout *int) error { duration := 60 * time.Second if timeout != nil { duration = time.Duration(*timeout) * time.Second } ctx, cancel := context.WithTimeout(context.Background(), duration) defer cancel() _, err := c.db3.Database(database).Collection(table).UpdateMany( ctx, query, update, options.Update().SetUpsert(upsert), ) return err } // Delete is a small exported method to expose the DeleteMany method in Mongo to the client. func (c *Client) Delete(table string, query bson.D) error { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() _, err := c.db3.Database(database).Collection(table).DeleteMany(ctx, query) return err } // UpdateProcessTypes method will query the processMaps collection for the process type logic and // update the MongoDB collections process.os_type according to the logic gathered. func (c *Client) UpdateProcessTypes(filterMap string, table string) error { qry := bson.D{} if filterMap != "" { objID, err := primitive.ObjectIDFromHex(filterMap) if err != nil { return err } qry = append(qry, bson.E{"_id", objID}) } pMaps, err := c.CollectProcessMaps(qry) if err != nil { return err } for _, pMap := range pMaps { // If there are no where clauses, we definitely don't want to update // with an empty query. Move to the next process map if len(pMap.Where) == 0 { continue } logrus.Debugf("Applying process map %d %s", pMap.Order, pMap.ProcessType) qry := bson.D{} for _, where := range pMap.Where { qry = append(qry, bson.E{where.Name, where.Value}) } err := c.UpdateMany(table, qry, bson.D{{"$set", bson.D{{"process.os_type", pMap.ProcessType}}}}, false, nil, ) if err != nil { return err } } return nil } // InsertProcessMap method will add a process map to the processMaps collection in the migration // database. Duplicate hashes will return a dup key error. func (c *Client) InsertProcessMap(pMap ProcessMap) error { /* #nosec */ hash := md5.New() byt, err := json.Marshal(pMap) if err != nil { return err } if _, err := hash.Write(byt); err != nil { return err } docWhere := make([]processEntry, 0) for _, where := range pMap.Where { docWhere = append(docWhere, processEntry{Name: where.Name, Value: where.Value}) } doc := map[string]interface{}{ "order": pMap.Order, "process_os_type": pMap.ProcessType, "where": docWhere, } ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() _, err = c.db3.Database(database).Collection("processMaps").InsertOne(ctx, doc) return err } // DeleteProcessMap method will remove a specific process map by ID. func (c *Client) DeleteProcessMap(id string) error { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() objID, err := primitive.ObjectIDFromHex(id) if err != nil { return err } _, err = c.db3.Database(database).Collection("processMaps").DeleteOne(ctx, bson.M{"_id": objID}) return err }