351 lines
10 KiB
Go
351 lines
10 KiB
Go
|
package client
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"encoding/json"
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"io/ioutil"
|
||
|
"net/http"
|
||
|
"net/http/httputil"
|
||
|
"os"
|
||
|
"path/filepath"
|
||
|
"regexp"
|
||
|
"text/template"
|
||
|
|
||
|
services "github.com/maximilien/softlayer-go/services"
|
||
|
softlayer "github.com/maximilien/softlayer-go/softlayer"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
SOFTLAYER_API_URL = "api.softlayer.com/rest/v3"
|
||
|
TEMPLATE_ROOT_PATH = "templates"
|
||
|
SL_GO_NON_VERBOSE = "SL_GO_NON_VERBOSE"
|
||
|
)
|
||
|
|
||
|
type SoftLayerClient struct {
|
||
|
username string
|
||
|
apiKey string
|
||
|
|
||
|
templatePath string
|
||
|
|
||
|
HTTPClient *http.Client
|
||
|
|
||
|
softLayerServices map[string]softlayer.Service
|
||
|
|
||
|
nonVerbose bool
|
||
|
}
|
||
|
|
||
|
func NewSoftLayerClient(username, apiKey string) *SoftLayerClient {
|
||
|
pwd, err := os.Getwd()
|
||
|
if err != nil {
|
||
|
panic(err) // this should be handled by the user
|
||
|
}
|
||
|
|
||
|
slc := &SoftLayerClient{
|
||
|
username: username,
|
||
|
apiKey: apiKey,
|
||
|
|
||
|
templatePath: filepath.Join(pwd, TEMPLATE_ROOT_PATH),
|
||
|
|
||
|
HTTPClient: http.DefaultClient,
|
||
|
nonVerbose: checkNonVerbose(),
|
||
|
|
||
|
softLayerServices: map[string]softlayer.Service{},
|
||
|
}
|
||
|
|
||
|
slc.initSoftLayerServices()
|
||
|
|
||
|
return slc
|
||
|
}
|
||
|
|
||
|
//softlayer.Client interface methods
|
||
|
|
||
|
func (slc *SoftLayerClient) GetService(serviceName string) (softlayer.Service, error) {
|
||
|
slService, ok := slc.softLayerServices[serviceName]
|
||
|
if !ok {
|
||
|
return nil, errors.New(fmt.Sprintf("softlayer-go does not support service '%s'", serviceName))
|
||
|
}
|
||
|
|
||
|
return slService, nil
|
||
|
}
|
||
|
|
||
|
func (slc *SoftLayerClient) GetSoftLayer_Account_Service() (softlayer.SoftLayer_Account_Service, error) {
|
||
|
slService, err := slc.GetService("SoftLayer_Account")
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return slService.(softlayer.SoftLayer_Account_Service), nil
|
||
|
}
|
||
|
|
||
|
func (slc *SoftLayerClient) GetSoftLayer_Virtual_Guest_Service() (softlayer.SoftLayer_Virtual_Guest_Service, error) {
|
||
|
slService, err := slc.GetService("SoftLayer_Virtual_Guest")
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return slService.(softlayer.SoftLayer_Virtual_Guest_Service), nil
|
||
|
}
|
||
|
|
||
|
func (slc *SoftLayerClient) GetSoftLayer_Dns_Domain_Service() (softlayer.SoftLayer_Dns_Domain_Service, error) {
|
||
|
slService, err := slc.GetService("SoftLayer_Dns_Domain")
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return slService.(softlayer.SoftLayer_Dns_Domain_Service), nil
|
||
|
}
|
||
|
|
||
|
func (slc *SoftLayerClient) GetSoftLayer_Virtual_Disk_Image_Service() (softlayer.SoftLayer_Virtual_Disk_Image_Service, error) {
|
||
|
slService, err := slc.GetService("SoftLayer_Virtual_Disk_Image")
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return slService.(softlayer.SoftLayer_Virtual_Disk_Image_Service), nil
|
||
|
}
|
||
|
|
||
|
func (slc *SoftLayerClient) GetSoftLayer_Security_Ssh_Key_Service() (softlayer.SoftLayer_Security_Ssh_Key_Service, error) {
|
||
|
slService, err := slc.GetService("SoftLayer_Security_Ssh_Key")
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return slService.(softlayer.SoftLayer_Security_Ssh_Key_Service), nil
|
||
|
}
|
||
|
|
||
|
func (slc *SoftLayerClient) GetSoftLayer_Product_Package_Service() (softlayer.SoftLayer_Product_Package_Service, error) {
|
||
|
slService, err := slc.GetService("SoftLayer_Product_Package")
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return slService.(softlayer.SoftLayer_Product_Package_Service), nil
|
||
|
}
|
||
|
|
||
|
func (slc *SoftLayerClient) GetSoftLayer_Virtual_Guest_Block_Device_Template_Group_Service() (softlayer.SoftLayer_Virtual_Guest_Block_Device_Template_Group_Service, error) {
|
||
|
slService, err := slc.GetService("SoftLayer_Virtual_Guest_Block_Device_Template_Group")
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return slService.(softlayer.SoftLayer_Virtual_Guest_Block_Device_Template_Group_Service), nil
|
||
|
}
|
||
|
|
||
|
func (slc *SoftLayerClient) GetSoftLayer_Network_Storage_Service() (softlayer.SoftLayer_Network_Storage_Service, error) {
|
||
|
slService, err := slc.GetService("SoftLayer_Network_Storage")
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return slService.(softlayer.SoftLayer_Network_Storage_Service), nil
|
||
|
}
|
||
|
|
||
|
func (slc *SoftLayerClient) GetSoftLayer_Network_Storage_Allowed_Host_Service() (softlayer.SoftLayer_Network_Storage_Allowed_Host_Service, error) {
|
||
|
slService, err := slc.GetService("SoftLayer_Network_Storage_Allowed_Host")
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return slService.(softlayer.SoftLayer_Network_Storage_Allowed_Host_Service), nil
|
||
|
}
|
||
|
|
||
|
func (slc *SoftLayerClient) GetSoftLayer_Product_Order_Service() (softlayer.SoftLayer_Product_Order_Service, error) {
|
||
|
slService, err := slc.GetService("SoftLayer_Product_Order")
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return slService.(softlayer.SoftLayer_Product_Order_Service), nil
|
||
|
}
|
||
|
|
||
|
func (slc *SoftLayerClient) GetSoftLayer_Billing_Item_Cancellation_Request_Service() (softlayer.SoftLayer_Billing_Item_Cancellation_Request_Service, error) {
|
||
|
slService, err := slc.GetService("SoftLayer_Billing_Item_Cancellation_Request")
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return slService.(softlayer.SoftLayer_Billing_Item_Cancellation_Request_Service), nil
|
||
|
}
|
||
|
|
||
|
func (slc *SoftLayerClient) GetSoftLayer_Hardware_Service() (softlayer.SoftLayer_Hardware_Service, error) {
|
||
|
slService, err := slc.GetService("SoftLayer_Hardware")
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return slService.(softlayer.SoftLayer_Hardware_Service), nil
|
||
|
}
|
||
|
|
||
|
func (slc *SoftLayerClient) GetSoftLayer_Dns_Domain_ResourceRecord_Service() (softlayer.SoftLayer_Dns_Domain_ResourceRecord_Service, error) {
|
||
|
slService, err := slc.GetService("SoftLayer_Dns_Domain_ResourceRecord")
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return slService.(softlayer.SoftLayer_Dns_Domain_ResourceRecord_Service), nil
|
||
|
}
|
||
|
|
||
|
//Public methods
|
||
|
|
||
|
func (slc *SoftLayerClient) DoRawHttpRequestWithObjectMask(path string, masks []string, requestType string, requestBody *bytes.Buffer) ([]byte, error) {
|
||
|
url := fmt.Sprintf("https://%s:%s@%s/%s", slc.username, slc.apiKey, SOFTLAYER_API_URL, path)
|
||
|
|
||
|
url += "?objectMask="
|
||
|
for i := 0; i < len(masks); i++ {
|
||
|
url += masks[i]
|
||
|
if i != len(masks)-1 {
|
||
|
url += ";"
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return slc.makeHttpRequest(url, requestType, requestBody)
|
||
|
}
|
||
|
|
||
|
func (slc *SoftLayerClient) DoRawHttpRequestWithObjectFilter(path string, filters string, requestType string, requestBody *bytes.Buffer) ([]byte, error) {
|
||
|
url := fmt.Sprintf("https://%s:%s@%s/%s", slc.username, slc.apiKey, SOFTLAYER_API_URL, path)
|
||
|
url += "?objectFilter=" + filters
|
||
|
|
||
|
return slc.makeHttpRequest(url, requestType, requestBody)
|
||
|
}
|
||
|
|
||
|
func (slc *SoftLayerClient) DoRawHttpRequestWithObjectFilterAndObjectMask(path string, masks []string, filters string, requestType string, requestBody *bytes.Buffer) ([]byte, error) {
|
||
|
url := fmt.Sprintf("https://%s:%s@%s/%s", slc.username, slc.apiKey, SOFTLAYER_API_URL, path)
|
||
|
|
||
|
url += "?objectFilter=" + filters
|
||
|
|
||
|
url += "&objectMask=filteredMask["
|
||
|
for i := 0; i < len(masks); i++ {
|
||
|
url += masks[i]
|
||
|
if i != len(masks)-1 {
|
||
|
url += ";"
|
||
|
}
|
||
|
}
|
||
|
url += "]"
|
||
|
|
||
|
return slc.makeHttpRequest(url, requestType, requestBody)
|
||
|
}
|
||
|
|
||
|
func (slc *SoftLayerClient) DoRawHttpRequest(path string, requestType string, requestBody *bytes.Buffer) ([]byte, error) {
|
||
|
url := fmt.Sprintf("https://%s:%s@%s/%s", slc.username, slc.apiKey, SOFTLAYER_API_URL, path)
|
||
|
return slc.makeHttpRequest(url, requestType, requestBody)
|
||
|
}
|
||
|
|
||
|
func (slc *SoftLayerClient) GenerateRequestBody(templateData interface{}) (*bytes.Buffer, error) {
|
||
|
cwd, err := os.Getwd()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
bodyTemplate := template.Must(template.ParseFiles(filepath.Join(cwd, slc.templatePath)))
|
||
|
body := new(bytes.Buffer)
|
||
|
bodyTemplate.Execute(body, templateData)
|
||
|
|
||
|
return body, nil
|
||
|
}
|
||
|
|
||
|
func (slc *SoftLayerClient) HasErrors(body map[string]interface{}) error {
|
||
|
if errString, ok := body["error"]; !ok {
|
||
|
return nil
|
||
|
} else {
|
||
|
return errors.New(errString.(string))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (slc *SoftLayerClient) CheckForHttpResponseErrors(data []byte) error {
|
||
|
var decodedResponse map[string]interface{}
|
||
|
err := json.Unmarshal(data, &decodedResponse)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
if err := slc.HasErrors(decodedResponse); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
//Private methods
|
||
|
|
||
|
func (slc *SoftLayerClient) initSoftLayerServices() {
|
||
|
slc.softLayerServices["SoftLayer_Account"] = services.NewSoftLayer_Account_Service(slc)
|
||
|
slc.softLayerServices["SoftLayer_Virtual_Guest"] = services.NewSoftLayer_Virtual_Guest_Service(slc)
|
||
|
slc.softLayerServices["SoftLayer_Virtual_Disk_Image"] = services.NewSoftLayer_Virtual_Disk_Image_Service(slc)
|
||
|
slc.softLayerServices["SoftLayer_Security_Ssh_Key"] = services.NewSoftLayer_Security_Ssh_Key_Service(slc)
|
||
|
slc.softLayerServices["SoftLayer_Product_Package"] = services.NewSoftLayer_Product_Package_Service(slc)
|
||
|
slc.softLayerServices["SoftLayer_Network_Storage"] = services.NewSoftLayer_Network_Storage_Service(slc)
|
||
|
slc.softLayerServices["SoftLayer_Network_Storage_Allowed_Host"] = services.NewSoftLayer_Network_Storage_Allowed_Host_Service(slc)
|
||
|
slc.softLayerServices["SoftLayer_Product_Order"] = services.NewSoftLayer_Product_Order_Service(slc)
|
||
|
slc.softLayerServices["SoftLayer_Billing_Item_Cancellation_Request"] = services.NewSoftLayer_Billing_Item_Cancellation_Request_Service(slc)
|
||
|
slc.softLayerServices["SoftLayer_Virtual_Guest_Block_Device_Template_Group"] = services.NewSoftLayer_Virtual_Guest_Block_Device_Template_Group_Service(slc)
|
||
|
slc.softLayerServices["SoftLayer_Hardware"] = services.NewSoftLayer_Hardware_Service(slc)
|
||
|
slc.softLayerServices["SoftLayer_Dns_Domain"] = services.NewSoftLayer_Dns_Domain_Service(slc)
|
||
|
slc.softLayerServices["SoftLayer_Dns_Domain_ResourceRecord"] = services.NewSoftLayer_Dns_Domain_ResourceRecord_Service(slc)
|
||
|
}
|
||
|
|
||
|
func hideCredentials(s string) string {
|
||
|
hiddenStr := "\"password\":\"******\""
|
||
|
r := regexp.MustCompile(`"password":"[^"]*"`)
|
||
|
|
||
|
return r.ReplaceAllString(s, hiddenStr)
|
||
|
}
|
||
|
|
||
|
func (slc *SoftLayerClient) makeHttpRequest(url string, requestType string, requestBody *bytes.Buffer) ([]byte, error) {
|
||
|
req, err := http.NewRequest(requestType, url, requestBody)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
bs, err := httputil.DumpRequest(req, true)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
if !slc.nonVerbose {
|
||
|
fmt.Fprintf(os.Stderr, "\n---\n[softlayer-go] Request:\n%s\n", hideCredentials(string(bs)))
|
||
|
}
|
||
|
|
||
|
resp, err := slc.HTTPClient.Do(req)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
defer resp.Body.Close()
|
||
|
|
||
|
bs, err = httputil.DumpResponse(resp, true)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
if !slc.nonVerbose {
|
||
|
fmt.Fprintf(os.Stderr, "[softlayer-go] Response:\n%s\n", hideCredentials(string(bs)))
|
||
|
}
|
||
|
|
||
|
responseBody, err := ioutil.ReadAll(resp.Body)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return responseBody, nil
|
||
|
}
|
||
|
|
||
|
//Private helper methods
|
||
|
|
||
|
func checkNonVerbose() bool {
|
||
|
slGoNonVerbose := os.Getenv(SL_GO_NON_VERBOSE)
|
||
|
switch slGoNonVerbose {
|
||
|
case "yes":
|
||
|
return true
|
||
|
case "YES":
|
||
|
return true
|
||
|
case "true":
|
||
|
return true
|
||
|
case "TRUE":
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
return false
|
||
|
}
|