Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(304)

Side by Side Diff: go/src/infra/monorail/endpoints.go

Issue 2037143002: Monorail client in Go (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package monorail
6
7 import (
8 "bytes"
9 "encoding/json"
10 "fmt"
11 "io"
12 "io/ioutil"
13 "net/http"
14
15 "golang.org/x/net/context"
16 "google.golang.org/grpc"
17
18 "github.com/luci/luci-go/common/errors"
19 "github.com/luci/luci-go/common/logging"
20
21 "infra/httputil"
22 )
23
24 // epClient implements MonorailClient by sending requests to Monorail's
25 // Cloud Endpoints API.
26 // See https://monorail-staging.appspot.com/_ah/api/explorer#p/monorail/v1/
27 type epClient struct {
28 HTTP *http.Client
29 Host string
30 }
31
32 // NewEndpointsClient creates a MonorailClient that send requests to Monorail's
33 // Cloud Endpoints.
34 func NewEndpointsClient(client *http.Client, host string) MonorailClient {
35 return &epClient{HTTP: client, Host: host}
36 }
37
38 func (c *epClient) call(ctx context.Context, urlSuffix string, request, response interface{}) error {
39 var buf bytes.Buffer
40 if err := json.NewEncoder(&buf).Encode(request); err != nil {
41 return err
42 }
43 reqBytes := buf.Bytes()
44
45 u := fmt.Sprintf("https://%s/_ah/api/monorail/v1/%s", c.Host, urlSuffix)
46 req, err := http.NewRequest("POST", u, nil)
47 if err != nil {
48 return err
49 }
50 req.Header.Set("Content-Type", "application/json")
51 req.Header.Set("Accept", "application/json")
52
53 logging.Debugf(ctx, "POST %s %s", u, reqBytes)
54
55 return httputil.RetryRequest(ctx, c.HTTP, req, reqBytes, func(res *http. Response) error {
56 if res.StatusCode != http.StatusOK {
57 text, _ := ioutil.ReadAll(io.LimitReader(res.Body, 1024) )
58 err := fmt.Errorf("unexpected status %q. Response: %s", res.Status, text)
59 if res.StatusCode == http.StatusNotFound {
60 // Occasionally Cloud Endpoints returns 404.
seanmccullough1 2016/06/03 18:45:33 Even when it really should be a 500 :)
nodir 2016/06/03 18:56:12 yes!
61 err = errors.WrapTransient(err)
62 }
63 return err
64 }
65 if response == nil {
66 return nil
67 }
68 return json.NewDecoder(res.Body).Decode(response)
69 })
70 }
71
72 func (c *epClient) InsertIssue(ctx context.Context, req *InsertIssueRequest, opt ions ...grpc.CallOption) (*InsertIssueResponse, error) {
seanmccullough1 2016/06/03 18:45:33 Godoc here and below. Mention that even though the
nodir 2016/06/03 18:56:12 these functions are internal, so nobody will see t
73 if err := checkOptions(options); err != nil {
74 return nil, err
75 }
76 if err := req.Validate(); err != nil {
77 return nil, err
78 }
79 url := fmt.Sprintf("projects/%s/issues?sendEmail=%v", req.ProjectId, req .SendEmail)
80 res := &InsertIssueResponse{&Issue{}}
81 return res, c.call(ctx, url, &req.Issue, res.Issue)
82 }
83
84 func (c *epClient) InsertComment(ctx context.Context, req *InsertCommentRequest, options ...grpc.CallOption) (*InsertCommentResponse, error) {
85 if err := checkOptions(options); err != nil {
86 return nil, err
87 }
88 url := fmt.Sprintf("projects/%s/issues/%d/comments", req.Issue.ProjectId , req.Issue.IssueId)
89 return &InsertCommentResponse{}, c.call(ctx, url, req.Comment, nil)
90 }
91
92 func checkOptions(options []grpc.CallOption) error {
93 if len(options) > 0 {
94 return errGrpcOptions
95 }
96 return nil
97 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698