// 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 zsp import ( "bytes" "encoding/json" "fmt" "strconv" "github.com/sirupsen/logrus" "github.rackspace.com/DCM/gomigrate/shared" "github.rackspace.com/DCM/tools" "github.rackspace.com/gorax/clients/mongodbAPI" ) // TicketLike constant is the value we'll search for const TicketLike = "%Data Center%" type ticket struct { AccountNum int AccountName string Ticket string } // findTickets function is executed from the gomigrate caller func (c Client) findTickets(moveGroup string) ([]ticket, error) { accounts, err := c.AccountsForMoveGroup(moveGroup) if err != nil { return nil, err } // Get the list of account numbers and convert to int numbers := make([]int, 0) for number := range accounts { numbers = append(numbers, number) } tickets, err := c.ticketSearch(numbers) if err != nil { return nil, err } resp := make([]ticket, 0) for _, t := range tickets { acctInt, err := strconv.Atoi(t.AccountNumber) if err != nil { logrus.Errorf("Atoi convert error account:%s - %s", t.AccountNumber, err) continue } resp = append(resp, ticket{ AccountNum: acctInt, AccountName: accounts[acctInt], Ticket: t.Number, }) } return resp, nil } // AccountsForMoveGroup function will poll the migration DB for all the unique account // numbers for a given move-group. func (c Client) AccountsForMoveGroup(moveGroup string) (map[int]string, error) { byt, err := c.mgo.Find(&mongodbAPI.FindQuery{ Query: map[string]string{ "move_group": moveGroup, }, Projection: []string{ "account.number", "account.name", "process.os_type", }, }, shared.GetCollection(moveGroup)) if err != nil { return nil, err } // Decode the json response back var p struct { Result []tools.Device `json:"result"` } if err = json.NewDecoder(bytes.NewReader(byt)).Decode(&p); err != nil { return nil, err } accounts := make(map[int]string) for _, device := range p.Result { if _, ok := accounts[device.Account.Number]; ok { continue } accounts[device.Account.Number] = device.Account.Name } return accounts, nil } type ( ctkWhereQuery struct { Class string `json:"class"` LoadArg loadArg `json:"load_arg"` Attributes interface{} `json:"attributes"` } loadArg struct { Values []interface{} `json:"values"` Class string `json:"class"` Limit *int `json:"limit,omitempty"` Offset *int `json:"offset,omitempty"` } ctkResponse []struct { Count int `json:"count"` LoadArg loadArg `json:"load_arg"` Limit int `json:"limit"` Result []ctkResponseResult `json:"result"` Offset int `json:"offset"` Class string `json:"class"` } ctkResponseResult struct { AccountNumber string `json:"account.number"` Number string `json:"number"` } ) // ticketSearch will return a list of ticket/account_numbers for a list of account // numbers passed in. func (c Client) ticketSearch(accounts []int) ([]ctkResponseResult, error) { var ( t = ctkWhereQuery{ Class: "Ticket.Ticket", LoadArg: loadArg{ Class: "Ticket.TicketWhere", Values: []interface{}{ []interface{}{"account_number", "IN", accounts}, "&", []interface{}{"subject", "LIKE", TicketLike}, "&", []interface{}{"status_name", "NOT IN", []string{"Closed", "Confirm Solved"}}, }, }, Attributes: []string{ "number", "account.number", "status.name", "subject", }, } ) js, err := json.Marshal(t) if err != nil { return nil, err } res, err := c.ctk.Query(js) if err != nil { return nil, err } var r ctkResponse if err = json.NewDecoder(bytes.NewReader(res)).Decode(&r); err != nil { return nil, err } if len(r) != 1 { return nil, fmt.Errorf("response length incorrect: %v", r) } if len(r[0].Result) == 0 { return nil, fmt.Errorf("no tickets found") } return r[0].Result, nil }