// 2019 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 notes import ( "context" "fmt" "net/url" "os" "time" "github.rackspace.com/gorax/tools/passkey" "github.com/gin-gonic/gin" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo/options" redisPkg "github.com/go-redis/redis/v7" "github.com/pquerna/cachecontrol/cacheobject" "github.com/sirupsen/logrus" "github.rackspace.com/gorax/clients/goctk" "github.rackspace.com/gorax/tools/util" "go.mongodb.org/mongo-driver/mongo" ) const ( dbName = "migration" colCustomer = "customer" colViews = "customerViews" ) type ( // Client is the initialized type to access route methods using a Client pointer receiver. Client struct { db *mongo.Client cache *cacheobject.RequestCacheDirectives ctk *goctk.Client mgoCol *mongo.Collection mgoViews *mongo.Collection redis *redisPkg.Client } // Note type represents the generic note structure that is stored/retrieved from the // migration/customer collection. Note struct { ID primitive.ObjectID `json:"_id" bson:"_id"` Account Account `json:"account" bson:"account"` Assoc struct { MoveGroup string `json:"move_group" bson:"move_group"` Ticket string `json:"ticket" bson:"ticket"` Devices []string `json:"devices" bson:"devices"` } `json:"associated" bson:"associated"` Attachments []string `json:"attachments" bson:"attachments"` DataCenter string `json:"data_center" bson:"data_center"` DateCreated string `json:"date_created" bson:"date_created"` DateDue string `json:"date_due" bson:"date_due"` DateCompleted string `json:"date_completed" bson:"date_completed"` Details string `json:"details" bson:"details"` Metadata interface{} `json:"metadata" bson:"metadata"` Owner string `json:"owner" bson:"owner"` Status string `json:"status" bson:"status"` Summary string `json:"summary" bson:"summary"` Team string `json:"team" bson:"team"` Type string `json:"type" bson:"type"` Updates []update `json:"updates" bson:"updates"` } // NotePayload type represents the generic note structure that is stored/retrieved from the // migration/customer collection. // // swagger:model NotePayload struct { ID primitive.ObjectID `json:"_id" bson:"_id"` Account Account `bson:"account" json:"account"` Assoc struct { MoveGroup string `bson:"move_group" json:"move_group"` Ticket string `bson:"ticket" json:"ticket"` Devices []string `bson:"devices" json:"devices"` } `bson:"associated" json:"associated"` DataCenter string `bson:"data_center" json:"data_center"` DateDue string `bson:"date_due" json:"date_due"` DateCompleted string `bson:"date_completed" json:"date_completed"` Details string `bson:"details" json:"details"` Metadata interface{} `bson:"metadata" json:"metadata"` Owner string `bson:"owner" json:"owner"` Status string `bson:"status" json:"status"` Summary string `bson:"summary" json:"summary"` Team string `bson:"team" json:"team"` Type string `bson:"type" json:"type"` Update update `bson:"update" json:"update"` } update struct { Message string `bson:"message" json:"message"` Timestamp string `bson:"timestamp" json:"timestamp"` UpdatedBy string `bson:"updated_by" json:"updated_by"` } // Account type represents the account level information that we track as part of // the customer tracking tool. Account struct { LT string `bson:"lead_tech" json:"lead_tech"` Manager string `bson:"manager" json:"manager"` Name string `bson:"name" json:"name"` Number int `bson:"number" json:"number"` PrimaryContact string `bson:"primary_contact" json:"primary_contact"` TeamName string `bson:"team_name" json:"team_name"` NetSecTeam string `bson:"netsec_team" json:"netsec_team"` MRR string `bson:"mrr" json:"mrr"` } // AccountSearch type represents the account data returned from a // CTK search for account name AccountSearch struct { Name string `bson:"name" json:"name"` Number string `bson:"number" json:"number"` } // MoveGroup type represents the move-group level information that we track as part of // the customer tracking tool. MoveGroup struct { ID string `bson:"_id" json:"_id"` End struct { Datetime string `bson:"datetime" json:"datetime"` Timestamp int64 `bson:"timestamp" json:"timestamp"` } `bson:"end" json:"end"` Start struct { Datetime string `bson:"datetime" json:"datetime"` Timestamp int64 `bson:"timestamp" json:"timestamp"` } `bson:"start" json:"start"` } ) // New function will initialize the resource client to interface with the routes methods. // Cache type is also required to apply proper route fetching rules. func New(c *gin.Context) (*Client, error) { cache, err := cacheobject.ParseRequestCacheControl(c.GetHeader("Cache-Control")) if err != nil { logrus.Errorf("migui.resource.New:cacheobject: %s", err) return nil, err } // Grab the passkey from the Gin Context key := c.MustGet("passkey").(*passkey.Client) ctkClient, err := goctk.NewCTK( goctk.SSO(key.Service.Netsec01.Credential.Username, key.Service.Netsec01.Credential.Password), goctk.WithStaging(util.IsStaging(os.Getenv("ENVIRONMENT"))), ) if err != nil { logrus.Errorf("migui.resource.New:ctkInit: %s", err) return nil, err } mongoClient := c.MustGet("mongoClient").(*mongo.Client) return &Client{ cache: cache, ctk: ctkClient, db: mongoClient, mgoCol: mongoClient.Database(dbName).Collection(colCustomer), mgoViews: mongoClient.Database(dbName).Collection(colViews), redis: c.MustGet("redisClient").(*redisPkg.Client), }, nil } // NewTest function will initialize the resource client with passkey for the test client func NewTest(pk *passkey.Client, cache string, staging bool) (*Client, error) { cacheObj, err := cacheobject.ParseRequestCacheControl(cache) if err != nil { logrus.Errorf("migui.resource.New:cacheobject: %s", err) return nil, err } ctkClient, err := goctk.NewCTK( goctk.SSO(pk.Service.Netsec01.Credential.Username, pk.Service.Netsec01.Credential.Password), goctk.WithStaging(staging), ) if err != nil { logrus.Errorf("migui.resource.New:goctk: %s", err) return nil, err } mongoURI := fmt.Sprintf("mongodb://%s:%s@%s/migration?ssl=true", pk.Keys.Mongo.NSIMongoUser.Credential.Username, url.QueryEscape(pk.Keys.Mongo.NSIMongoUser.Credential.Password), pk.Keys.Mongo.NSIMongoUser.Credential.HostName, ) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() mongoClient, err := mongo.Connect(ctx, options.Client().ApplyURI(mongoURI)) if err != nil { logrus.Errorf("Error initializing mongo3 DB: %v", err.Error()) return nil, err } redisClient := redisPkg.NewClient(&redisPkg.Options{ Addr: "redis.nsi.rackspace.com:6379", Password: pk.Keys.Redis.Credential.Password, DB: 0, // use default DB }) if !staging { if _, err = redisClient.Ping().Result(); err != nil { logrus.Errorf("Error initializing go-redis DB: %v", err.Error()) return nil, err } } return &Client{ cache: cacheObj, ctk: ctkClient, db: mongoClient, mgoCol: mongoClient.Database(dbName).Collection(colCustomer), mgoViews: mongoClient.Database(dbName).Collection(colViews), redis: redisClient, }, nil }