// AttachFileAction attaches a file to an alert at OpsGenie. func AttachFileAction(c *gcli.Context) { cli, err := NewAlertClient(c) if err != nil { os.Exit(1) } req := alerts.AttachFileAlertRequest{} if val, success := getVal("id", c); success { req.ID = val } if val, success := getVal("alias", c); success { req.Alias = val } if val, success := getVal("attachment", c); success { f, err := os.Open(val) defer f.Close() if err != nil { fmt.Printf("%s\n", err.Error()) os.Exit(1) } req.Attachment = f } if val, success := getVal("indexFile", c); success { req.IndexFile = val } req.User = grabUsername(c) if val, success := getVal("source", c); success { req.Source = val } if val, success := getVal("note", c); success { req.Note = val } printVerboseMessage("Attach request prepared from flags, sending request to OpsGenie..") _, err = cli.AttachFile(req) if err != nil { fmt.Printf("%s\n", err.Error()) os.Exit(1) } printVerboseMessage("File attached to alert successfully.") }
// AttachFile method attaches a file to an alert at OpsGenie. func (cli *OpsGenieAlertClient) AttachFile(req alerts.AttachFileAlertRequest) (*alerts.AttachFileAlertResponse, error) { req.APIKey = cli.apiKey var b bytes.Buffer w := multipart.NewWriter(&b) path := req.Attachment.Name() file, err := os.Open(path) defer file.Close() if err != nil { message := "Attachment can not be opened for reading. " + err.Error() logging.Logger().Warn(message) return nil, errors.New(message) } // add the attachment fw, err := w.CreateFormFile("attachment", filepath.Base(path)) if err != nil { message := "Can not build the request with the field attachment. " + err.Error() logging.Logger().Warn(message) return nil, errors.New(message) } if _, err := io.Copy(fw, file); err != nil { message := "Can not copy the attachment into the request. " + err.Error() logging.Logger().Warn(message) return nil, errors.New(message) } // Add the other fields // empty fields should not be placed into the request // otherwise it yields an incomplete boundary exception if req.APIKey != "" { if err = writeField(*w, "apiKey", req.APIKey); err != nil { return nil, err } } if req.ID != "" { if err = writeField(*w, "id", req.ID); err != nil { return nil, err } } if req.Alias != "" { if err = writeField(*w, "alias", req.Alias); err != nil { return nil, err } } if req.User != "" { if err = writeField(*w, "user", req.User); err != nil { return nil, err } } if req.Source != "" { if err = writeField(*w, "source", req.Source); err != nil { return nil, err } } if req.IndexFile != "" { if err = writeField(*w, "indexFile", req.IndexFile); err != nil { return nil, err } } if req.Note != "" { if err = writeField(*w, "note", req.Note); err != nil { return nil, err } } w.Close() httpReq, err := http.NewRequest("POST", cli.opsGenieAPIURL+attachFileAlertURL, &b) if err != nil { message := "Can not create the multipart/form-data request. " + err.Error() logging.Logger().Warn(message) return nil, errors.New(message) } httpReq.Header.Set("Content-Type", w.FormDataContentType()) transport := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, Proxy: http.ProxyFromEnvironment, Dial: func(netw, addr string) (net.Conn, error) { conn, err := net.DialTimeout(netw, addr, cli.httpTransportSettings.ConnectionTimeout) if err != nil { message := "Error occurred while connecting: " + err.Error() logging.Logger().Warn(message) return nil, errors.New(message) } conn.SetDeadline(time.Now().Add(cli.httpTransportSettings.RequestTimeout)) return conn, nil }, } client := &http.Client{Transport: transport} // proxy settings if cli.proxy != nil { proxyURL, proxyErr := url.Parse(cli.proxy.toString()) if proxyErr != nil { message := "Can not set the proxy configuration " + proxyErr.Error() logging.Logger().Warn(message) return nil, errors.New(message) } transport.Proxy = http.ProxyURL(proxyURL) } url := httpReq.URL.String() logging.Logger().Info("Executing OpsGenie request to [" + url + "] with multipart data.") var res *http.Response for i := 0; i < cli.httpTransportSettings.MaxRetryAttempts; i++ { res, err = client.Do(httpReq) if err == nil { defer res.Body.Close() break } if res != nil { logging.Logger().Info(fmt.Sprintf("Retrying request [%s] ResponseCode:[%d]. RetryCount: %d", url, res.StatusCode, (i + 1))) } else { logging.Logger().Info(fmt.Sprintf("Retrying request [%s] Reason:[%s]. RetryCount: %d", url, err.Error(), (i + 1))) } time.Sleep(timeSleepBetweenRequests) } if err != nil { message := "Can not attach the file, unable to send the request. " + err.Error() logging.Logger().Warn(message) return nil, errors.New(message) } httpStatusCode := res.StatusCode if httpStatusCode >= 400 { body, err := ioutil.ReadAll(res.Body) if err == nil { return nil, errorMessage(httpStatusCode, string(body[:])) } message := fmt.Sprint("Couldn't read the response, %s", err.Error()) logging.Logger().Warn(message) return nil, errors.New(message) } attachFileAlertResp := alerts.AttachFileAlertResponse{Status: res.Status, Code: res.StatusCode} return &attachFileAlertResp, nil }
func (cli *OpsGenieAlertClient) AttachFile(req alerts.AttachFileAlertRequest) (*alerts.AttachFileAlertResponse, error) { req.ApiKey = cli.apiKey // validate the mandatory parameters: apiKey, alertId/alias, attachment if req.ApiKey == "" { return nil, errors.New("ApiKey is a mandatory field and can not be empty.") } if req.Attachment == "" { return nil, errors.New("Attachment is a mandatory field and can not be empty.") } if req.AlertId == "" && req.Alias == "" { return nil, errors.New("At least either Alert Id or Alias should be set in the request.") } if req.AlertId != "" && req.Alias != "" { return nil, errors.New("Either Alert Id or Alias should be set in the request not both.") } var b bytes.Buffer w := multipart.NewWriter(&b) fileName := req.Attachment file, err := os.Open(fileName) if err != nil { return nil, errors.New("Attachment can not be opened for reading.") } // add the attachment fw, err := w.CreateFormFile("attachment", fileName) if err != nil { return nil, errors.New("Can not build the request with the field attachment.") } if _, err := io.Copy(fw, file); err != nil { return nil, errors.New("Can not copy the attachment into the request.") } defer file.Close() // Add the other fields // empty fields should not be placed into the request // otherwise it yields an incomplete boundary exception if req.ApiKey != "" { if fw, err = w.CreateFormField("apiKey"); err != nil { return nil, errors.New("Can not build the request with the field apiKey.") } if _, err = fw.Write([]byte(req.ApiKey)); err != nil { return nil, errors.New("Can not write the ApiKey value into the request.") } } if req.AlertId != "" { if fw, err = w.CreateFormField("alertId"); err != nil { return nil, errors.New("Can not build the request with the field alertId.") } if _, err = fw.Write([]byte(req.AlertId)); err != nil { return nil, errors.New("Can not write the AlertId value into the request.") } } if req.Alias != "" { if fw, err = w.CreateFormField("alias"); err != nil { return nil, errors.New("Can not build the request with the field alias.") } if _, err = fw.Write([]byte(req.Alias)); err != nil { return nil, errors.New("Can not write the Alias value into the request.") } } if req.User != "" { if fw, err = w.CreateFormField("user"); err != nil { return nil, errors.New("Can not build the request with the field user.") } if _, err = fw.Write([]byte(req.User)); err != nil { return nil, errors.New("Can not write the User value into the request.") } } if req.Source != "" { if fw, err = w.CreateFormField("source"); err != nil { return nil, errors.New("Can not build the request with the field source.") } if _, err = fw.Write([]byte(req.Source)); err != nil { return nil, errors.New("Can not write the Source value into the request.") } } if req.IndexFile != "" { if fw, err = w.CreateFormField("indexFile"); err != nil { return nil, errors.New("Can not build the request with the field indexFile.") } if _, err = fw.Write([]byte(req.IndexFile)); err != nil { return nil, errors.New("Can not write the IndexFile value into the request.") } } if req.Note != "" { if fw, err = w.CreateFormField("note"); err != nil { return nil, errors.New("Can not build the request with the field note.") } if _, err = fw.Write([]byte(req.Note)); err != nil { return nil, errors.New("Can not write the Note value into the request.") } } w.Close() httpReq, err := http.NewRequest("POST", ATTACH_FILE_ALERT_URL, &b) if err != nil { return nil, errors.New("Can not create the multipart/form-data request.") } httpReq.Header.Set("Content-Type", w.FormDataContentType()) client := &http.Client{} // proxy settings if cli.proxy != "" { proxyUrl, proxyErr := url.Parse(cli.proxy) if proxyErr != nil { return nil, errors.New("Can not set the proxy configuration") } client.Transport = &http.Transport{Proxy: http.ProxyURL(proxyUrl)} } var res *http.Response for i := 0; i < cli.retries; i++ { res, err = client.Do(httpReq) if err == nil { break } time.Sleep(TIME_SLEEP_BETWEEN_REQUESTS) } if err != nil { return nil, errors.New("Can not attach the file, unable to send the request.") } // check the returning HTTP status code httpStatusCode := res.StatusCode if httpStatusCode >= 400 && httpStatusCode < 500 { return nil, errors.New(fmt.Sprintf("Client error %d returned", httpStatusCode)) } if httpStatusCode >= 500 { return nil, errors.New(fmt.Sprintf("Server error %d returned", httpStatusCode)) } attachFileAlertResp := alerts.AttachFileAlertResponse{Status: res.Status, Code: res.StatusCode} return &attachFileAlertResp, nil }