package rapi import ( "fmt" "net/http" "crypto/tls" "encoding/json" "io/ioutil" ) type RapiClient interface { Do(request_type, path string) ([]byte, error) GetClusterInformation() (map[string]interface{}, error) GetNetworks() ([]map[string]interface{}, error) GetNetworksBulk() ([]map[string]interface{}, error) GetNetworkInfo(name string) (map[string]interface{}, error) GetInstancesBulk() ([]map[string]interface{}, error) } type Client struct { Username string Password string Host string Port int ApiVersion int TlsVerify bool } func NewClient(username, password, host string, port, apiversion int, tlsverify bool) *Client { return &Client{ Username: username, Password: password, Host: host, Port: port, ApiVersion: apiversion, TlsVerify: tlsverify, } } func (s *Client) GetClusterInformation() (map[string]interface{}, error) { result, err := s.Do("GET", "info") if err != nil { return nil, err } data := make(map[string]interface{}) err = json.Unmarshal(result, &data) if err != nil { return nil, err } return data, nil } func (s *Client) GetNetworks() ([]map[string]interface{}, error) { result, err := s.Do("GET", "networks") if err != nil { return nil, err } data := make([]map[string]interface{}, 0) err = json.Unmarshal(result, &data) if err != nil { return nil, err } return data, nil } func (s *Client) GetNetworksBulk() ([]map[string]interface{}, error) { result, err := s.Do("GET", "networks?bulk=1") if err != nil { return nil, err } data := make([]map[string]interface{}, 0) err = json.Unmarshal(result, &data) if err != nil { return nil, err } return data, nil } func (s *Client) GetInstancesBulk() ([]map[string]interface{}, error) { result, err := s.Do("GET", "instances?bulk=1") if err != nil { return nil, err } data := make([]map[string]interface{}, 0) err = json.Unmarshal(result, &data) if err != nil { return nil, err } return data, nil } func (s *Client) GetNetworkInformation(name string) (map[string]interface{}, error) { result, err := s.Do("GET", "networks/" + name) if err != nil { return nil, err } data := make(map[string]interface{}) err = json.Unmarshal(result, &data) if err != nil { return nil, err } return data, nil } func (s *Client) Do(request_type, path string) ([]byte, error) { req, err := s.GetRequest(request_type, path) if err != nil { return nil, err } result := make([]byte, 0) result, err = s.DoRequest(req) if err != nil { return nil, err } return result, err } func (s *Client) GetRequest(request_type, path string) (*http.Request, error) { url := fmt.Sprintf("https://%s:%d/%d/%s", s.Host, s.Port, s.ApiVersion, path) return http.NewRequest(request_type, url, nil) } func (s *Client) GetHttpClient() (*http.Client) { // Ganeti often has a self-signed certificate that is used for the RAPI // @TODO This should be configural tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: !s.TlsVerify}, } return &http.Client{Transport: tr} } func (s *Client) DoRequest(req *http.Request) ([]byte, error) { req.SetBasicAuth(s.Username, s.Password) resp, err := s.GetHttpClient().Do(req) if err != nil { return nil, err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err } if 200 != resp.StatusCode { return nil, fmt.Errorf("%s", body) } return body, nil }