github.com/jonaz/heapster@v1.3.0-beta.0.0.20170208112634-cd3c15ca3d29/metrics/sinks/monasca/monasca_client.go (about) 1 // Copyright 2015 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package monasca 16 17 import ( 18 "bytes" 19 "encoding/json" 20 "fmt" 21 "io" 22 "io/ioutil" 23 "net/http" 24 "net/url" 25 26 "github.com/golang/glog" 27 ) 28 29 // Client specifies the methods of any client ot the Monasca API 30 type Client interface { 31 SendRequest(method, path string, request interface{}) (int, string, error) 32 GetURL() *url.URL 33 CheckHealth() error 34 } 35 36 // ClientImpl implements the monasca API client interface. 37 type ClientImpl struct { 38 ksClient KeystoneClient 39 monascaURL *url.URL 40 } 41 42 // SendRequest to the Monasca API, authenticating on the fly. 43 // Returns 0, "", err if the request cannot be built. 44 // Returns statusCode, response, nil if communication with the server was OK. 45 func (monClient *ClientImpl) SendRequest(method, path string, request interface{}) (int, string, error) { 46 req, err := monClient.prepareRequest(method, path, request) 47 if err != nil { 48 return 0, "", err 49 } 50 statusCode, response, err := monClient.receiveResponse(req) 51 if err != nil { 52 return 0, "", err 53 } 54 return statusCode, response, nil 55 } 56 57 func (monClient *ClientImpl) prepareRequest(method string, path string, request interface{}) (*http.Request, error) { 58 // authenticate 59 token, err := monClient.ksClient.GetToken() 60 if err != nil { 61 return nil, err 62 } 63 // marshal 64 var rawRequest io.Reader 65 if request != nil { 66 jsonRequest, err := json.Marshal(request) 67 if err != nil { 68 return nil, err 69 } 70 rawRequest = bytes.NewReader(jsonRequest) 71 } 72 // build request 73 req, err := http.NewRequest(method, monClient.GetURL().String()+path, rawRequest) 74 if err != nil { 75 return nil, err 76 } 77 req.Header.Add("Content-Type", "application/json") 78 req.Header.Add("X-Auth-Token", token) 79 return req, nil 80 } 81 82 func (monClient *ClientImpl) receiveResponse(req *http.Request) (int, string, error) { 83 resp, err := (&http.Client{}).Do(req) 84 if err != nil { 85 return 0, "", err 86 } 87 defer resp.Body.Close() 88 contents, err := ioutil.ReadAll(resp.Body) 89 respString := "" 90 if err != nil { 91 glog.Warning("Cannot read monasca API's response.") 92 respString = "Cannot read monasca API's response." 93 } else { 94 respString = string(contents) 95 } 96 return resp.StatusCode, fmt.Sprintf("%s", respString), nil 97 } 98 99 // GetURL of the Monasca API server. 100 func (monClient *ClientImpl) GetURL() *url.URL { 101 return monClient.monascaURL 102 } 103 104 // CheckHealth of the monasca API server. 105 func (monClient *ClientImpl) CheckHealth() error { 106 code, _, err := monClient.SendRequest("GET", "/", nil) 107 if err != nil { 108 return fmt.Errorf("Failed to connect to Monasca: %s", err) 109 } 110 if code != http.StatusOK { 111 return fmt.Errorf("Monasca is not running on the provided/discovered URL: %s", monClient.GetURL().String()) 112 } 113 return nil 114 } 115 116 // NewMonascaClient creates a monasca client. 117 func NewMonascaClient(config Config) (Client, error) { 118 // create keystone client 119 ksClient, err := NewKeystoneClient(config) 120 if err != nil { 121 return nil, err 122 } 123 124 // detect monasca URL 125 monascaURL := (*url.URL)(nil) 126 if config.MonascaURL != "" { 127 monascaURL, err = url.Parse(config.MonascaURL) 128 if err != nil { 129 return nil, fmt.Errorf("Malformed monasca-url sink parameter. %s", err) 130 } 131 } else { 132 monascaURL, err = ksClient.MonascaURL() 133 if err != nil { 134 return nil, fmt.Errorf("Failed to automatically detect Monasca service: %s", err) 135 } 136 } 137 138 // create monasca client 139 client := &ClientImpl{ksClient: ksClient, monascaURL: monascaURL} 140 err = client.CheckHealth() 141 if err != nil { 142 return nil, err 143 } 144 return client, nil 145 }