package switchAPI import ( "bytes" "encoding/json" "errors" "net/http" "regexp" "strings" "github.rackspace.com/gorax/tools/webutil" ) const sshAPIURL = "http://sshapi.nsi.rackspace.com:9090" var ( moreRegex = regexp.MustCompile(`\n --More--.*?\b`) ) type ( SwitchCommandRequest struct { Switch string `json:"switch_name"` Commands []SwitchCommand `json:"run"` } SwitchCommand struct { Run string `json:"run"` TimeOut int `json:"timeout"` Res string `json:"response"` Prompt string `json:"prompt"` } SwitchCommandResponse struct { RequestData SwitchCommandRequest `json:"request_data"` } SCPCommandRequest struct { FileName string `json:"file_name"` DC string `json:"dc"` Host string `json:"host"` } SCPCommandResponse struct { Success bool `json:"success"` Error string `json:"error"` Response string `json:"response"` } ) func MarshalCommands(commands []string, Switch string) *[]byte { req := &SwitchCommandRequest{ Switch: Switch, Commands: GenerateCommands(commands), } js, err := json.Marshal(req) if err != nil { return nil } return &js } func GenerateCommands(commands []string) (sc []SwitchCommand) { for _, cmd := range commands { sc = append(sc, SwitchCommand{ Run: cmd, }) } return } func SwitchPostCommands(payload *[]byte, Switch, token string) (*SwitchCommandRequest, error) { req, err := http.NewRequest("POST", sshAPIURL+"/swapi/v2/cmds", bytes.NewBuffer(*payload)) req.Header.Set("device", Switch) req.Header.Set("X-Auth", token) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() res, _, err := webutil.ResponseCheck(resp) if err != nil { return nil, err } var cr SwitchCommandResponse if err = json.Unmarshal(res, &cr); err != nil { return nil, err } return &cr.RequestData, nil } func (s *SwitchCommandRequest) FindResponse(f string) *string { for _, c := range s.Commands { if c.Run == f { if c.Res == "" { return nil } return MoreStrip(&c.Res) } } return nil } func MoreStrip(s *string) *string { var n string for _, l := range strings.Split(*s, "\r") { ns := bytes.Replace([]byte(l), []byte{27, 91, 75}, []byte{}, -1) ns = bytes.Replace(ns, []byte{27, 91, 44, 109}, []byte{}, -1) ns = bytes.Replace(ns, []byte{27, 91, 109}, []byte{}, -1) l = string(ns) if !strings.Contains(l, "--More--") { n += l continue } if l == "\n--More--" { n += "\n" continue } s := strings.Split(l, "\b") if !strings.Contains(s[len(s)-1], "--More--") { n += "\n" + s[len(s)-1] continue } n += "\n" } return &n } func SCPRequest(file, dc, host string) (*SCPCommandResponse, error) { if file == "" || dc == "" || host == "" { return nil, errors.New("one or more items are missing.") } req := SCPCommandRequest{ FileName: file, DC: dc, Host: host, } js, err := json.Marshal(req) if err != nil { return nil, err } return SCPCommandPost(&js) } func SCPCommandPost(payload *[]byte) (*SCPCommandResponse, error) { req, err := http.NewRequest("POST", sshAPIURL+"/scp/", bytes.NewBuffer(*payload)) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() res, _, err := webutil.ResponseCheck(resp) if err != nil { return nil, err } var sr SCPCommandResponse if err := json.Unmarshal(res, &sr); err != nil { return nil, err } if sr.Success == false { return nil, errors.New(sr.Error) } return &sr, nil }