Vendor main dependencies.
This commit is contained in:
parent
49a09ab7dd
commit
dd5e3fba01
2738 changed files with 1045689 additions and 0 deletions
26
vendor/github.com/ovh/go-ovh/LICENSE
generated
vendored
Normal file
26
vendor/github.com/ovh/go-ovh/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
Copyright (c) 2015-2016, OVH SAS.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of OVH SAS nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY OVH SAS AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL OVH SAS AND CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
123
vendor/github.com/ovh/go-ovh/ovh/configuration.go
generated
vendored
Normal file
123
vendor/github.com/ovh/go-ovh/ovh/configuration.go
generated
vendored
Normal file
|
@ -0,0 +1,123 @@
|
|||
package ovh
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
// Use variables for easier test overload
|
||||
var (
|
||||
systemConfigPath = "/etc/ovh.conf"
|
||||
userConfigPath = "/.ovh.conf" // prefixed with homeDir
|
||||
localConfigPath = "./ovh.conf"
|
||||
)
|
||||
|
||||
// currentUserHome attempts to get current user's home directory
|
||||
func currentUserHome() (string, error) {
|
||||
usr, err := user.Current()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return usr.HomeDir, nil
|
||||
}
|
||||
|
||||
// appendConfigurationFile only if it exists. We need to do this because
|
||||
// ini package will fail to load configuration at all if a configuration
|
||||
// file is missing. This is racy, but better than always failing.
|
||||
func appendConfigurationFile(cfg *ini.File, path string) {
|
||||
if file, err := os.Open(path); err == nil {
|
||||
file.Close()
|
||||
cfg.Append(path)
|
||||
}
|
||||
}
|
||||
|
||||
// loadConfig loads client configuration from params, environments or configuration
|
||||
// files (by order of decreasing precedence).
|
||||
//
|
||||
// loadConfig will check OVH_CONSUMER_KEY, OVH_APPLICATION_KEY, OVH_APPLICATION_SECRET
|
||||
// and OVH_ENDPOINT environment variables. If any is present, it will take precedence
|
||||
// over any configuration from file.
|
||||
//
|
||||
// Configuration files are ini files. They share the same format as python-ovh,
|
||||
// node-ovh, php-ovh and all other wrappers. If any wrapper is configured, all
|
||||
// can re-use the same configuration. loadConfig will check for configuration in:
|
||||
//
|
||||
// - ./ovh.conf
|
||||
// - $HOME/.ovh.conf
|
||||
// - /etc/ovh.conf
|
||||
//
|
||||
func (c *Client) loadConfig(endpointName string) error {
|
||||
// Load configuration files by order of increasing priority. All configuration
|
||||
// files are optional. Only load file from user home if home could be resolve
|
||||
cfg := ini.Empty()
|
||||
appendConfigurationFile(cfg, systemConfigPath)
|
||||
if home, err := currentUserHome(); err == nil {
|
||||
userConfigFullPath := filepath.Join(home, userConfigPath)
|
||||
appendConfigurationFile(cfg, userConfigFullPath)
|
||||
}
|
||||
appendConfigurationFile(cfg, localConfigPath)
|
||||
|
||||
// Canonicalize configuration
|
||||
if endpointName == "" {
|
||||
endpointName = getConfigValue(cfg, "default", "endpoint", "ovh-eu")
|
||||
}
|
||||
|
||||
if c.AppKey == "" {
|
||||
c.AppKey = getConfigValue(cfg, endpointName, "application_key", "")
|
||||
}
|
||||
|
||||
if c.AppSecret == "" {
|
||||
c.AppSecret = getConfigValue(cfg, endpointName, "application_secret", "")
|
||||
}
|
||||
|
||||
if c.ConsumerKey == "" {
|
||||
c.ConsumerKey = getConfigValue(cfg, endpointName, "consumer_key", "")
|
||||
}
|
||||
|
||||
// Load real endpoint URL by name. If endpoint contains a '/', consider it as a URL
|
||||
if strings.Contains(endpointName, "/") {
|
||||
c.endpoint = endpointName
|
||||
} else {
|
||||
c.endpoint = Endpoints[endpointName]
|
||||
}
|
||||
|
||||
// If we still have no valid endpoint, AppKey or AppSecret, return an error
|
||||
if c.endpoint == "" {
|
||||
return fmt.Errorf("Unknown endpoint '%s'. Consider checking 'Endpoints' list of using an URL.", endpointName)
|
||||
}
|
||||
if c.AppKey == "" {
|
||||
return fmt.Errorf("Missing application key. Please check your configuration or consult the documentation to create one.")
|
||||
}
|
||||
if c.AppSecret == "" {
|
||||
return fmt.Errorf("Missing application secret. Please check your configuration or consult the documentation to create one.")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getConfigValue returns the value of OVH_<NAME> or ``name`` value from ``section``. If
|
||||
// the value could not be read from either env or any configuration files, return 'def'
|
||||
func getConfigValue(cfg *ini.File, section, name, def string) string {
|
||||
// Attempt to load from environment
|
||||
fromEnv := os.Getenv("OVH_" + strings.ToUpper(name))
|
||||
if len(fromEnv) > 0 {
|
||||
return fromEnv
|
||||
}
|
||||
|
||||
// Attempt to load from configuration
|
||||
fromSection := cfg.Section(section)
|
||||
if fromSection == nil {
|
||||
return def
|
||||
}
|
||||
|
||||
fromSectionKey := fromSection.Key(name)
|
||||
if fromSectionKey == nil {
|
||||
return def
|
||||
}
|
||||
return fromSectionKey.String()
|
||||
}
|
113
vendor/github.com/ovh/go-ovh/ovh/consumer_key.go
generated
vendored
Normal file
113
vendor/github.com/ovh/go-ovh/ovh/consumer_key.go
generated
vendored
Normal file
|
@ -0,0 +1,113 @@
|
|||
package ovh
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Map user friendly access level names to corresponding HTTP verbs
|
||||
var (
|
||||
ReadOnly = []string{"GET"}
|
||||
ReadWrite = []string{"GET", "POST", "PUT", "DELETE"}
|
||||
ReadWriteSafe = []string{"GET", "POST", "PUT"}
|
||||
)
|
||||
|
||||
// AccessRule represents a method allowed for a path
|
||||
type AccessRule struct {
|
||||
// Allowed HTTP Method for the requested AccessRule.
|
||||
// Can be set to GET/POST/PUT/DELETE.
|
||||
Method string `json:"method"`
|
||||
// Allowed path.
|
||||
// Can be an exact string or a string with '*' char.
|
||||
// Example :
|
||||
// /me : only /me is authorized
|
||||
// /* : all calls are authorized
|
||||
Path string `json:"path"`
|
||||
}
|
||||
|
||||
// CkValidationState represents the response when asking a new consumerKey.
|
||||
type CkValidationState struct {
|
||||
// Consumer key, which need to be validated by customer.
|
||||
ConsumerKey string `json:"consumerKey"`
|
||||
// Current status, should be always "pendingValidation".
|
||||
State string `json:"state"`
|
||||
// URL to redirect user in order to log in.
|
||||
ValidationURL string `json:"validationUrl"`
|
||||
}
|
||||
|
||||
// CkRequest represents the parameters to fill in order to ask a new
|
||||
// consumerKey.
|
||||
type CkRequest struct {
|
||||
client *Client
|
||||
AccessRules []AccessRule `json:"accessRules"`
|
||||
Redirection string `json:"redirection,omitempty"`
|
||||
}
|
||||
|
||||
func (ck *CkValidationState) String() string {
|
||||
return fmt.Sprintf("CK: %q\nStatus: %q\nValidation URL: %q\n",
|
||||
ck.ConsumerKey,
|
||||
ck.State,
|
||||
ck.ValidationURL,
|
||||
)
|
||||
}
|
||||
|
||||
// NewCkRequest helps create a new ck request
|
||||
func (c *Client) NewCkRequest() *CkRequest {
|
||||
return &CkRequest{
|
||||
client: c,
|
||||
AccessRules: []AccessRule{},
|
||||
}
|
||||
}
|
||||
|
||||
// NewCkRequestWithRedirection helps create a new ck request with a redirect URL
|
||||
func (c *Client) NewCkRequestWithRedirection(redirection string) *CkRequest {
|
||||
return &CkRequest{
|
||||
client: c,
|
||||
AccessRules: []AccessRule{},
|
||||
Redirection: redirection,
|
||||
}
|
||||
}
|
||||
|
||||
// AddRule adds a new rule to the ckRequest
|
||||
func (ck *CkRequest) AddRule(method, path string) {
|
||||
ck.AccessRules = append(ck.AccessRules, AccessRule{
|
||||
Method: method,
|
||||
Path: path,
|
||||
})
|
||||
}
|
||||
|
||||
// AddRules adds grant requests on "path" for all methods. "ReadOnly",
|
||||
// "ReadWrite" and "ReadWriteSafe" should be used for "methods" unless
|
||||
// specific access are required.
|
||||
func (ck *CkRequest) AddRules(methods []string, path string) {
|
||||
for _, method := range methods {
|
||||
ck.AddRule(method, path)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// AddRecursiveRules adds grant requests on "path" and "path/*", for all
|
||||
// methods "ReadOnly", "ReadWrite" and "ReadWriteSafe" should be used for
|
||||
// "methods" unless specific access are required.
|
||||
func (ck *CkRequest) AddRecursiveRules(methods []string, path string) {
|
||||
path = strings.TrimRight(path, "/")
|
||||
|
||||
// Add rules. Skip base rule when requesting access to "/"
|
||||
if path != "" {
|
||||
ck.AddRules(methods, path)
|
||||
}
|
||||
ck.AddRules(methods, path+"/*")
|
||||
}
|
||||
|
||||
// Do executes the request. On success, set the consumer key in the client
|
||||
// and return the URL the user needs to visit to validate the key
|
||||
func (ck *CkRequest) Do() (*CkValidationState, error) {
|
||||
state := CkValidationState{}
|
||||
err := ck.client.PostUnAuth("/auth/credential", ck, &state)
|
||||
|
||||
if err == nil {
|
||||
ck.client.ConsumerKey = state.ConsumerKey
|
||||
}
|
||||
|
||||
return &state, err
|
||||
}
|
17
vendor/github.com/ovh/go-ovh/ovh/error.go
generated
vendored
Normal file
17
vendor/github.com/ovh/go-ovh/ovh/error.go
generated
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
package ovh
|
||||
|
||||
import "fmt"
|
||||
|
||||
// APIError represents an error that can occurred while calling the API.
|
||||
type APIError struct {
|
||||
// Error message.
|
||||
Message string
|
||||
// HTTP code.
|
||||
Code int
|
||||
// ID of the request
|
||||
QueryID string
|
||||
}
|
||||
|
||||
func (err *APIError) Error() string {
|
||||
return fmt.Sprintf("Error %d: %q", err.Code, err.Message)
|
||||
}
|
331
vendor/github.com/ovh/go-ovh/ovh/ovh.go
generated
vendored
Normal file
331
vendor/github.com/ovh/go-ovh/ovh/ovh.go
generated
vendored
Normal file
|
@ -0,0 +1,331 @@
|
|||
// Package ovh provides a HTTP wrapper for the OVH API.
|
||||
package ovh
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha1"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// DefaultTimeout api requests after 180s
|
||||
const DefaultTimeout = 180 * time.Second
|
||||
|
||||
// Endpoints
|
||||
const (
|
||||
OvhEU = "https://eu.api.ovh.com/1.0"
|
||||
OvhCA = "https://ca.api.ovh.com/1.0"
|
||||
KimsufiEU = "https://eu.api.kimsufi.com/1.0"
|
||||
KimsufiCA = "https://ca.api.kimsufi.com/1.0"
|
||||
SoyoustartEU = "https://eu.api.soyoustart.com/1.0"
|
||||
SoyoustartCA = "https://ca.api.soyoustart.com/1.0"
|
||||
RunaboveCA = "https://api.runabove.com/1.0"
|
||||
)
|
||||
|
||||
// Endpoints conveniently maps endpoints names to their URI for external configuration
|
||||
var Endpoints = map[string]string{
|
||||
"ovh-eu": OvhEU,
|
||||
"ovh-ca": OvhCA,
|
||||
"kimsufi-eu": KimsufiEU,
|
||||
"kimsufi-ca": KimsufiCA,
|
||||
"soyoustart-eu": SoyoustartEU,
|
||||
"soyoustart-ca": SoyoustartCA,
|
||||
"runabove-ca": RunaboveCA,
|
||||
}
|
||||
|
||||
// Errors
|
||||
var (
|
||||
ErrAPIDown = errors.New("go-vh: the OVH API is down, it does't respond to /time anymore")
|
||||
)
|
||||
|
||||
// Client represents a client to call the OVH API
|
||||
type Client struct {
|
||||
// Self generated tokens. Create one by visiting
|
||||
// https://eu.api.ovh.com/createApp/
|
||||
// AppKey holds the Application key
|
||||
AppKey string
|
||||
|
||||
// AppSecret holds the Application secret key
|
||||
AppSecret string
|
||||
|
||||
// ConsumerKey holds the user/app specific token. It must have been validated before use.
|
||||
ConsumerKey string
|
||||
|
||||
// API endpoint
|
||||
endpoint string
|
||||
|
||||
// Client is the underlying HTTP client used to run the requests. It may be overloaded but a default one is instanciated in ``NewClient`` by default.
|
||||
Client *http.Client
|
||||
|
||||
// Ensures that the timeDelta function is only ran once
|
||||
// sync.Once would consider init done, even in case of error
|
||||
// hence a good old flag
|
||||
timeDeltaMutex *sync.Mutex
|
||||
timeDeltaDone bool
|
||||
timeDelta time.Duration
|
||||
Timeout time.Duration
|
||||
}
|
||||
|
||||
// NewClient represents a new client to call the API
|
||||
func NewClient(endpoint, appKey, appSecret, consumerKey string) (*Client, error) {
|
||||
client := Client{
|
||||
AppKey: appKey,
|
||||
AppSecret: appSecret,
|
||||
ConsumerKey: consumerKey,
|
||||
Client: &http.Client{},
|
||||
timeDeltaMutex: &sync.Mutex{},
|
||||
timeDeltaDone: false,
|
||||
Timeout: time.Duration(DefaultTimeout),
|
||||
}
|
||||
|
||||
// Get and check the configuration
|
||||
if err := client.loadConfig(endpoint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &client, nil
|
||||
}
|
||||
|
||||
// NewEndpointClient will create an API client for specified
|
||||
// endpoint and load all credentials from environment or
|
||||
// configuration files
|
||||
func NewEndpointClient(endpoint string) (*Client, error) {
|
||||
return NewClient(endpoint, "", "", "")
|
||||
}
|
||||
|
||||
// NewDefaultClient will load all it's parameter from environment
|
||||
// or configuration files
|
||||
func NewDefaultClient() (*Client, error) {
|
||||
return NewClient("", "", "", "")
|
||||
}
|
||||
|
||||
//
|
||||
// High level helpers
|
||||
//
|
||||
|
||||
// Ping performs a ping to OVH API.
|
||||
// In fact, ping is just a /auth/time call, in order to check if API is up.
|
||||
func (c *Client) Ping() error {
|
||||
_, err := c.getTime()
|
||||
return err
|
||||
}
|
||||
|
||||
// TimeDelta represents the delay between the machine that runs the code and the
|
||||
// OVH API. The delay shouldn't change, let's do it only once.
|
||||
func (c *Client) TimeDelta() (time.Duration, error) {
|
||||
return c.getTimeDelta()
|
||||
}
|
||||
|
||||
// Time returns time from the OVH API, by asking GET /auth/time.
|
||||
func (c *Client) Time() (*time.Time, error) {
|
||||
return c.getTime()
|
||||
}
|
||||
|
||||
//
|
||||
// Common request wrappers
|
||||
//
|
||||
|
||||
// Get is a wrapper for the GET method
|
||||
func (c *Client) Get(url string, resType interface{}) error {
|
||||
return c.CallAPI("GET", url, nil, resType, true)
|
||||
}
|
||||
|
||||
// GetUnAuth is a wrapper for the unauthenticated GET method
|
||||
func (c *Client) GetUnAuth(url string, resType interface{}) error {
|
||||
return c.CallAPI("GET", url, nil, resType, false)
|
||||
}
|
||||
|
||||
// Post is a wrapper for the POST method
|
||||
func (c *Client) Post(url string, reqBody, resType interface{}) error {
|
||||
return c.CallAPI("POST", url, reqBody, resType, true)
|
||||
}
|
||||
|
||||
// PostUnAuth is a wrapper for the unauthenticated POST method
|
||||
func (c *Client) PostUnAuth(url string, reqBody, resType interface{}) error {
|
||||
return c.CallAPI("POST", url, reqBody, resType, false)
|
||||
}
|
||||
|
||||
// Put is a wrapper for the PUT method
|
||||
func (c *Client) Put(url string, reqBody, resType interface{}) error {
|
||||
return c.CallAPI("PUT", url, reqBody, resType, true)
|
||||
}
|
||||
|
||||
// PutUnAuth is a wrapper for the unauthenticated PUT method
|
||||
func (c *Client) PutUnAuth(url string, reqBody, resType interface{}) error {
|
||||
return c.CallAPI("PUT", url, reqBody, resType, false)
|
||||
}
|
||||
|
||||
// Delete is a wrapper for the DELETE method
|
||||
func (c *Client) Delete(url string, resType interface{}) error {
|
||||
return c.CallAPI("DELETE", url, nil, resType, true)
|
||||
}
|
||||
|
||||
// DeleteUnAuth is a wrapper for the unauthenticated DELETE method
|
||||
func (c *Client) DeleteUnAuth(url string, resType interface{}) error {
|
||||
return c.CallAPI("DELETE", url, nil, resType, false)
|
||||
}
|
||||
|
||||
//
|
||||
// Low level API access
|
||||
//
|
||||
|
||||
// getResult check the response and unmarshals it into the response type if needed.
|
||||
// Helper function, called from CallAPI.
|
||||
func (c *Client) getResponse(response *http.Response, resType interface{}) error {
|
||||
// Read all the response body
|
||||
defer response.Body.Close()
|
||||
body, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// < 200 && >= 300 : API error
|
||||
if response.StatusCode < http.StatusOK || response.StatusCode >= http.StatusMultipleChoices {
|
||||
apiError := &APIError{Code: response.StatusCode}
|
||||
if err = json.Unmarshal(body, apiError); err != nil {
|
||||
return err
|
||||
}
|
||||
apiError.QueryID = response.Header.Get("X-Ovh-QueryID")
|
||||
return apiError
|
||||
}
|
||||
|
||||
// Nothing to unmarshal
|
||||
if len(body) == 0 || resType == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return json.Unmarshal(body, &resType)
|
||||
}
|
||||
|
||||
// timeDelta returns the time delta between the host and the remote API
|
||||
func (c *Client) getTimeDelta() (time.Duration, error) {
|
||||
|
||||
if !c.timeDeltaDone {
|
||||
// Ensure only one thread is updating
|
||||
c.timeDeltaMutex.Lock()
|
||||
|
||||
// Did we wait ? Maybe no more needed
|
||||
if !c.timeDeltaDone {
|
||||
ovhTime, err := c.getTime()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
c.timeDelta = time.Since(*ovhTime)
|
||||
c.timeDeltaDone = true
|
||||
}
|
||||
c.timeDeltaMutex.Unlock()
|
||||
}
|
||||
|
||||
return c.timeDelta, nil
|
||||
}
|
||||
|
||||
// getTime t returns time from for a given api client endpoint
|
||||
func (c *Client) getTime() (*time.Time, error) {
|
||||
var timestamp int64
|
||||
|
||||
err := c.GetUnAuth("/auth/time", ×tamp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
serverTime := time.Unix(timestamp, 0)
|
||||
return &serverTime, nil
|
||||
}
|
||||
|
||||
// getLocalTime is a function to be overwritten during the tests, it return the time
|
||||
// on the the local machine
|
||||
var getLocalTime = func() time.Time {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
// getEndpointForSignature is a function to be overwritten during the tests, it returns a
|
||||
// the endpoint
|
||||
var getEndpointForSignature = func(c *Client) string {
|
||||
return c.endpoint
|
||||
}
|
||||
|
||||
// CallAPI is the lowest level call helper. If needAuth is true,
|
||||
// inject authentication headers and sign the request.
|
||||
//
|
||||
// Request signature is a sha1 hash on following fields, joined by '+':
|
||||
// - applicationSecret (from Client instance)
|
||||
// - consumerKey (from Client instance)
|
||||
// - capitalized method (from arguments)
|
||||
// - full request url, including any query string argument
|
||||
// - full serialized request body
|
||||
// - server current time (takes time delta into account)
|
||||
//
|
||||
// Call will automatically assemble the target url from the endpoint
|
||||
// configured in the client instance and the path argument. If the reqBody
|
||||
// argument is not nil, it will also serialize it as json and inject
|
||||
// the required Content-Type header.
|
||||
//
|
||||
// If everyrthing went fine, unmarshall response into resType and return nil
|
||||
// otherwise, return the error
|
||||
func (c *Client) CallAPI(method, path string, reqBody, resType interface{}, needAuth bool) error {
|
||||
var body []byte
|
||||
var err error
|
||||
|
||||
if reqBody != nil {
|
||||
body, err = json.Marshal(reqBody)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
target := fmt.Sprintf("%s%s", c.endpoint, path)
|
||||
req, err := http.NewRequest(method, target, bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Inject headers
|
||||
if body != nil {
|
||||
req.Header.Add("Content-Type", "application/json;charset=utf-8")
|
||||
}
|
||||
req.Header.Add("X-Ovh-Application", c.AppKey)
|
||||
req.Header.Add("Accept", "application/json")
|
||||
|
||||
// Inject signature. Some methods do not need authentication, especially /time,
|
||||
// /auth and some /order methods are actually broken if authenticated.
|
||||
if needAuth {
|
||||
timeDelta, err := c.TimeDelta()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
timestamp := getLocalTime().Add(-timeDelta).Unix()
|
||||
|
||||
req.Header.Add("X-Ovh-Timestamp", strconv.FormatInt(timestamp, 10))
|
||||
req.Header.Add("X-Ovh-Consumer", c.ConsumerKey)
|
||||
|
||||
h := sha1.New()
|
||||
h.Write([]byte(fmt.Sprintf("%s+%s+%s+%s%s+%s+%d",
|
||||
c.AppSecret,
|
||||
c.ConsumerKey,
|
||||
method,
|
||||
getEndpointForSignature(c),
|
||||
path,
|
||||
body,
|
||||
timestamp,
|
||||
)))
|
||||
req.Header.Add("X-Ovh-Signature", fmt.Sprintf("$1$%x", h.Sum(nil)))
|
||||
}
|
||||
|
||||
// Send the request with requested timeout
|
||||
c.Client.Timeout = c.Timeout
|
||||
response, err := c.Client.Do(req)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Unmarshal the result into the resType if possible
|
||||
return c.getResponse(response, resType)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue