github.com/aclisp/heapster@v0.19.2-0.20160613100040-51756f899a96/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() bool 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() bool { 106 code, _, _ := monClient.SendRequest("GET", "/", nil) 107 return code == http.StatusOK 108 } 109 110 // NewMonascaClient creates a monasca client. 111 func NewMonascaClient(config Config) (Client, error) { 112 // create keystone client 113 ksClient, err := NewKeystoneClient(config) 114 if err != nil { 115 return nil, err 116 } 117 118 // detect monasca URL 119 monascaURL := (*url.URL)(nil) 120 if config.MonascaURL != "" { 121 monascaURL, err = url.Parse(config.MonascaURL) 122 if err != nil { 123 return nil, fmt.Errorf("Malformed monasca-url sink parameter. %s", err) 124 } 125 } else { 126 monascaURL, err = ksClient.MonascaURL() 127 if err != nil { 128 return nil, fmt.Errorf("Failed to automatically detect Monasca service: %s", err) 129 } 130 } 131 132 // create monasca client 133 client := &ClientImpl{ksClient: ksClient, monascaURL: monascaURL} 134 healthy := client.CheckHealth() 135 if !healthy { 136 return nil, fmt.Errorf("Monasca is not running on the provided/discovered URL: %s", client.GetURL().String()) 137 } 138 return client, nil 139 }