Пример #1
0
// JsonRequest JSON encodes and sends the object in reqData.ReqValue (if any) to the specified URL.
// Optional method arguments are passed using the RequestData object.
// Relevant RequestData fields:
// ReqHeaders: additional HTTP header values to add to the request.
// ExpectedStatus: the allowed HTTP response status values, else an error is returned.
// ReqValue: the data object to send.
// RespValue: the data object to decode the result into.
func (c *Client) JsonRequest(method, url, rfc1123Date string, request *RequestData, response *ResponseData) (err error) {
	err = nil
	var body []byte
	if request.Params != nil {
		url += "?" + request.Params.Encode()
	}
	if request.ReqValue != nil {
		body, err = json.Marshal(request.ReqValue)
		if err != nil {
			err = errors.Newf(err, "failed marshalling the request body")
			return
		}
	}
	headers, err := createHeaders(request.ReqHeaders, c.credentials, contentTypeJSON, rfc1123Date, c.apiVersion,
		isMantaRequest(url, c.credentials.UserAuthentication.User))
	if err != nil {
		return err
	}
	respBody, respHeader, err := c.sendRequest(
		method, url, bytes.NewReader(body), len(body), headers, response.ExpectedStatus, c.logger)
	if err != nil {
		return
	}
	defer respBody.Close()
	respData, err := ioutil.ReadAll(respBody)
	if err != nil {
		err = errors.Newf(err, "failed reading the response body")
		return
	}

	if len(respData) > 0 {
		if response.RespValue != nil {
			if _, ok := response.RespValue.(*[]byte); ok {
				response.RespValue = respData
				//err = decodeJSON(bytes.NewReader(respData), false, response.RespValue)
				//if err != nil {
				//	err = errors.Newf(err, "failed unmarshaling/decoding the response body: %s", respData)
				//}
			} else {
				err = json.Unmarshal(respData, response.RespValue)
				if err != nil {
					err = decodeJSON(bytes.NewReader(respData), true, response.RespValue)
					if err != nil {
						err = errors.Newf(err, "failed unmarshaling/decoding the response body: %s", respData)
					}
				}
			}
		}
	}

	if respHeader != nil {
		response.RespHeaders = respHeader
	}

	return
}
Пример #2
0
func (s *ErrorsSuite) TestErrorCause(c *gc.C) {
	rootCause := errors.NewResourceNotFoundf(nil, "some value", "")
	// Construct a new error, based on a resource not found root cause.
	err := errors.Newf(rootCause, "an error occurred")
	c.Assert(err.Cause(), gc.Equals, rootCause)
	// Check the other error attributes.
	c.Assert(err.Error(), gc.Equals, "an error occurred\ncaused by: Resource Not Found: some value")
}
Пример #3
0
func (s *ErrorsSuite) TestErrorIsType(c *gc.C) {
	rootCause := errors.NewBadRequestf(nil, "some value", "")
	// Construct a new error, based on a bad request root cause.
	err := errors.Newf(rootCause, "an error occurred")
	// Check that the error is not falsely identified as something it is not.
	c.Assert(errors.IsNotAuthorized(err), gc.Equals, false)
	// Check that the error is correctly identified as a not found error.
	c.Assert(errors.IsBadRequest(err), gc.Equals, true)
}
Пример #4
0
func (c *Client) sendRateLimitedRequest(method, URL string, headers http.Header, reqData []byte,
	logger *loggo.Logger) (resp *http.Response, err error) {
	for i := 0; i < c.maxSendAttempts; i++ {
		var reqReader io.Reader
		if reqData != nil {
			reqReader = bytes.NewReader(reqData)
		}
		req, err := http.NewRequest(method, URL, reqReader)
		if err != nil {
			err = errors.Newf(err, "failed creating the request %s", URL)
			return nil, err
		}
		// Setting req.Close to true to avoid malformed HTTP version "nullHTTP/1.1" error
		// See http://stackoverflow.com/questions/17714494/golang-http-request-results-in-eof-errors-when-making-multiple-requests-successi
		req.Close = true
		for header, values := range headers {
			for _, value := range values {
				req.Header.Add(header, value)
			}
		}
		req.ContentLength = int64(len(reqData))
		resp, err = c.Do(req)
		if err != nil {
			return nil, errors.Newf(err, "failed executing the request %s", URL)
		}
		if resp.StatusCode != http.StatusRequestEntityTooLarge || resp.Header.Get("Retry-After") == "" {
			return resp, nil
		}
		resp.Body.Close()
		retryAfter, err := strconv.ParseFloat(resp.Header.Get("Retry-After"), 64)
		if err != nil {
			return nil, errors.Newf(err, "Invalid Retry-After header %s", URL)
		}
		if retryAfter == 0 {
			return nil, errors.Newf(err, "Resource limit exeeded at URL %s", URL)
		}
		if logger != nil {
			logger.Warningf("Too many requests, retrying in %dms.", int(retryAfter*1000))
		}
		time.Sleep(time.Duration(retryAfter) * time.Second)
	}
	return nil, errors.Newf(err, "Maximum number of attempts (%d) reached sending request to %s", c.maxSendAttempts, URL)
}
Пример #5
0
// This cancels a job from doing any further work.
// Cancellation is asynchronous and "best effort"; there is no guarantee the job will actually stop
// See API docs: http://apidocs.joyent.com/manta/api.html#CancelJob
func (c *Client) CancelJob(jobId string) error {
	req := request{
		method:         client.POST,
		url:            makeURL(apiJobs, jobId, apiJobsLive, apiJobsCancel),
		expectedStatus: http.StatusAccepted,
	}
	if _, err := c.sendRequest(req); err != nil {
		return errors.Newf(err, "failed to cancel job %s", jobId)
	}
	return nil
}
Пример #6
0
// This closes input for a job, and finalize the job.
// See API docs: http://apidocs.joyent.com/manta/api.html#EndJobInput
func (c *Client) EndJobInputs(jobId string) error {
	req := request{
		method:         client.POST,
		url:            makeURL(apiJobs, jobId, apiJobsLive, apiJobsIn, apiJobsEnd),
		expectedStatus: http.StatusAccepted,
	}
	if _, err := c.sendRequest(req); err != nil {
		return errors.Newf(err, "failed to end inputs for job %s", jobId)
	}
	return nil
}
Пример #7
0
// Submits inputs to an already created job.
// See API docs: http://apidocs.joyent.com/manta/api.html#AddJobInputs
func (c *Client) AddJobInputs(jobId string, jobInputs io.Reader) error {
	inputData, errI := ioutil.ReadAll(jobInputs)
	if errI != nil {
		return errors.Newf(errI, "failed to read inputs for job %s", jobId)
	}
	requestHeaders := make(http.Header)
	requestHeaders.Set("Accept", "*/*")
	requestHeaders.Set("Content-Type", "text/plain")
	req := request{
		method:         client.POST,
		url:            makeURL(apiJobs, jobId, apiJobsLive, apiJobsIn),
		reqValue:       string(inputData),
		reqHeader:      requestHeaders,
		expectedStatus: http.StatusNoContent,
	}
	if _, err := c.sendRequest(req); err != nil {
		return errors.Newf(err, "failed to add inputs to job %s", jobId)
	}
	return nil
}
Пример #8
0
// DeleteMachineTag deletes a single tag from the specified machine.
// See API docs: http://apidocs.joyent.com/cloudapi/#DeleteMachineTag
func (c *Client) DeleteMachineTag(machineID, tagKey string) error {
	req := request{
		method:         client.DELETE,
		url:            makeURL(apiMachines, machineID, apiTags, tagKey),
		expectedStatus: http.StatusNoContent,
	}
	if _, err := c.sendRequest(req); err != nil {
		return errors.Newf(err, "failed to delete tag with key %s for machine with id %s", tagKey, machineID)
	}
	return nil
}
Пример #9
0
// DeleteImage (Beta) Delete the image specified by imageId. Must be image owner to do so.
// See API docs: http://apidocs.joyent.com/cloudapi/#DeleteImage
func (c *Client) DeleteImage(imageID string) error {
	req := request{
		method:         client.DELETE,
		url:            makeURL(apiImages, imageID),
		expectedStatus: http.StatusNoContent,
	}
	if _, err := c.sendRequest(req); err != nil {
		return errors.Newf(err, "failed to delete image with id: %s", imageID)
	}
	return nil
}
Пример #10
0
// DeleteKey deletes the key identified by keyName.
// See API docs: http://apidocs.joyent.com/cloudapi/#DeleteKey
func (c *Client) DeleteKey(keyName string) error {
	req := request{
		method:         client.DELETE,
		url:            makeURL(apiKeys, keyName),
		expectedStatus: http.StatusNoContent,
	}
	if _, err := c.sendRequest(req); err != nil {
		return errors.Newf(err, "failed to delete key with name: %s", keyName)
	}
	return nil
}
Пример #11
0
// DeleteFirewallRule removes the given firewall rule record from all the required account machines.
// See API docs: http://apidocs.joyent.com/cloudapi/#DeleteFirewallRule
func (c *Client) DeleteFirewallRule(fwRuleID string) error {
	req := request{
		method:         client.DELETE,
		url:            makeURL(apiFirewallRules, fwRuleID),
		expectedStatus: http.StatusNoContent,
	}
	if _, err := c.sendRequest(req); err != nil {
		return errors.Newf(err, "failed to delete firewall rule with id %s", fwRuleID)
	}
	return nil
}
Пример #12
0
// DeleteMachineSnapshot deletes the specified snapshot.
// See API docs: http://apidocs.joyent.com/cloudapi/#DeleteMachineSnapshot
func (c *Client) DeleteMachineSnapshot(machineID, snapshotName string) error {
	req := request{
		method:         client.DELETE,
		url:            makeURL(apiMachines, machineID, apiSnapshots, snapshotName),
		expectedStatus: http.StatusNoContent,
	}
	if _, err := c.sendRequest(req); err != nil {
		return errors.Newf(err, "failed to delete snapshot %s for machine with id %s", snapshotName, machineID)
	}
	return nil
}
Пример #13
0
// StartMachineFromSnapshot starts the machine from the specified snapshot.
// Machine must be in 'stopped' state.
// See API docs: http://apidocs.joyent.com/cloudapi/#StartMachineFromSnapshot
func (c *Client) StartMachineFromSnapshot(machineID, snapshotName string) error {
	req := request{
		method:         client.POST,
		url:            makeURL(apiMachines, machineID, apiSnapshots, snapshotName),
		expectedStatus: http.StatusAccepted,
	}
	if _, err := c.sendRequest(req); err != nil {
		return errors.Newf(err, "failed to start machine with id %s from snapshot %s", machineID, snapshotName)
	}
	return nil
}
Пример #14
0
// Starts a stopped machine.
// See API docs: http://apidocs.joyent.com/cloudapi/#StartMachine
func (c *Client) StartMachine(machineId string) error {
	req := request{
		method:         client.POST,
		url:            fmt.Sprintf("%s/%s?action=%s", apiMachines, machineId, actionStart),
		expectedStatus: http.StatusAccepted,
	}
	if _, err := c.sendRequest(req); err != nil {
		return errors.Newf(err, "failed to start machine with id: %s", machineId)
	}
	return nil
}
Пример #15
0
// Destroys an instrumentation.
// See API docs: http://apidocs.joyent.com/cloudapi/#DeleteInstrumentation
func (c *Client) DeleteInstrumentation(instrumentationId string) error {
	req := request{
		method:         client.DELETE,
		url:            makeURL(apiAnalytics, apiInstrumentations, instrumentationId),
		expectedStatus: http.StatusNoContent,
	}
	if _, err := c.sendRequest(req); err != nil {
		return errors.Newf(err, "failed to delete instrumentation with id %s", instrumentationId)
	}
	return nil
}
Пример #16
0
// DeleteFabricNetwork deletes an existing fabric network
// See API docs: https://apidocs.joyent.com/cloudapi/#DeleteFabricNetwork
func (c *Client) DeleteFabricNetwork(vlanID int16, networkID string) error {
	req := request{
		method:         client.DELETE,
		url:            makeURL(apiFabricVLANs, strconv.Itoa(int(vlanID)), apiFabricNetworks, networkID),
		expectedStatus: http.StatusNoContent,
	}
	if _, err := c.sendRequest(req); err != nil {
		return errors.Newf(err, "failed to delete fabric network %s on vlan %d", networkID, vlanID)
	}
	return nil
}
Пример #17
0
// Retrieves the specified object from the specified location.
// See API docs: http://apidocs.joyent.com/manta/api.html#GetObject
func (c *Client) GetObject(path, objectName string) ([]byte, error) {
	var resp []byte
	requestHeaders := make(http.Header)
	requestHeaders.Set("Accept", "*/*")
	req := request{
		method:    client.GET,
		url:       makeURL(apiStorage, path, objectName),
		reqHeader: requestHeaders,
		resp:      &resp,
	}
	respData, err := c.sendRequest(req)
	if err != nil {
		return nil, errors.Newf(err, "failed to get object %s/%s", path, objectName)
	}
	res, ok := respData.RespValue.(*[]byte)
	if !ok {
		return nil, errors.Newf(err, "failed to assert downloaded data as type *[]byte for object %s/%s", path, objectName)
	}
	return *res, nil
}
Пример #18
0
// RenameMachine renames an existing machine.
// See API docs: http://apidocs.joyent.com/cloudapi/#RenameMachine
func (c *Client) RenameMachine(machineID, machineName string) error {
	req := request{
		method:         client.POST,
		url:            fmt.Sprintf("%s/%s?action=%s&name=%s", apiMachines, machineID, actionRename, machineName),
		expectedStatus: http.StatusAccepted,
	}
	if _, err := c.sendRequest(req); err != nil {
		return errors.Newf(err, "failed to rename machine with id: %s", machineID)
	}
	return nil
}
Пример #19
0
// Deletes the specified object from the specified location.
// See API docs: http://apidocs.joyent.com/manta/api.html#DeleteObject
func (c *Client) DeleteObject(path, objectName string) error {
	req := request{
		method:         client.DELETE,
		url:            makeURL(apiStorage, path, objectName),
		expectedStatus: http.StatusNoContent,
	}
	if _, err := c.sendRequest(req); err != nil {
		return errors.Newf(err, "failed to delete object %s/%s", path, objectName)
	}
	return nil
}
Пример #20
0
// DeleteFabricVLAN delets a given VLAN as specified by ID
// See API docs: https://apidocs.joyent.com/cloudapi/#DeleteFabricVLAN
func (c *Client) DeleteFabricVLAN(vlanID int16) error {
	req := request{
		method:         client.DELETE,
		url:            makeURL(apiFabricVLANs, strconv.Itoa(int(vlanID))),
		expectedStatus: http.StatusNoContent,
	}
	if _, err := c.sendRequest(req); err != nil {
		return errors.Newf(err, "failed to delete fabric VLAN with id %d", vlanID)
	}
	return nil
}
Пример #21
0
// RemoveNIC removes a NIC on a machine belonging to a given account.
// *WARNING*: this causes the machine to reboot while removing the NIC.
// See API docs: https://apidocs.joyent.com/cloudapi/#RemoveNic
func (c *Client) RemoveNIC(machineID, MAC string) error {
	req := request{
		method:         client.DELETE,
		url:            makeURL(apiMachines, machineID, apiNICs, MAC),
		expectedStatus: http.StatusNoContent,
	}
	if _, err := c.sendRequest(req); err != nil {
		return errors.Newf(err, "failed to remove NIC: %s", MAC)
	}
	return nil
}
Пример #22
0
// DisableFirewallMachine disables the firewall for the specified machine.
// See API docs: http://apidocs.joyent.com/cloudapi/#DisableMachineFirewall
func (c *Client) DisableFirewallMachine(machineID string) error {
	req := request{
		method:         client.POST,
		url:            fmt.Sprintf("%s/%s?action=%s", apiMachines, machineID, actionDisableFw),
		expectedStatus: http.StatusAccepted,
	}
	if _, err := c.sendRequest(req); err != nil {
		return errors.Newf(err, "failed to disable firewall on machine with id: %s", machineID)
	}
	return nil
}
Пример #23
0
// DeleteAllMachineMetadata deletes all metadata keys from the specified machine.
// See API docs: http://apidocs.joyent.com/cloudapi/#DeleteAllMachineMetadata
func (c *Client) DeleteAllMachineMetadata(machineID string) error {
	req := request{
		method:         client.DELETE,
		url:            makeURL(apiMachines, machineID, apiMetadata),
		expectedStatus: http.StatusNoContent,
	}
	if _, err := c.sendRequest(req); err != nil {
		return errors.Newf(err, "failed to delete metadata for machine with id %s", machineID)
	}
	return nil
}
Пример #24
0
// MachineAudit provides a list of machine's accomplished actions, (sorted from
// latest to older one).
// See API docs: http://apidocs.joyent.com/cloudapi/#MachineAudit
func (c *Client) MachineAudit(machineID string) ([]AuditAction, error) {
	var resp []AuditAction
	req := request{
		method: client.GET,
		url:    makeURL(apiMachines, machineID, apiAudit),
		resp:   &resp,
	}
	if _, err := c.sendRequest(req); err != nil {
		return nil, errors.Newf(err, "failed to get actions for machine with id %s", machineID)
	}
	return resp, nil
}
Пример #25
0
// ListDatacenters provides a list of all datacenters this cloud is aware of.
// See API docs: http://apidocs.joyent.com/cloudapi/#ListDatacenters
func (c *Client) ListDatacenters() (map[string]interface{}, error) {
	var resp map[string]interface{}
	req := request{
		method: client.GET,
		url:    apiDatacenters,
		resp:   &resp,
	}
	if _, err := c.sendRequest(req); err != nil {
		return nil, errors.Newf(err, "failed to get list of datcenters")
	}
	return resp, nil
}
Пример #26
0
// GetPackage returns the package specified by packageName. NOTE: packageName can
// specify either the package name or package ID.
// See API docs: http://apidocs.joyent.com/cloudapi/#GetPackage
func (c *Client) GetPackage(packageName string) (*Package, error) {
	var resp Package
	req := request{
		method: client.GET,
		url:    makeURL(apiPackages, packageName),
		resp:   &resp,
	}
	if _, err := c.sendRequest(req); err != nil {
		return nil, errors.Newf(err, "failed to get package with name: %s", packageName)
	}
	return &resp, nil
}
Пример #27
0
// GetNetwork retrieves an individual network record.
// See API docs: http://apidocs.joyent.com/cloudapi/#GetNetwork
func (c *Client) GetNetwork(networkID string) (*Network, error) {
	var resp Network
	req := request{
		method: client.GET,
		url:    makeURL(apiNetworks, networkID),
		resp:   &resp,
	}
	if _, err := c.sendRequest(req); err != nil {
		return nil, errors.Newf(err, "failed to get network with id %s", networkID)
	}
	return &resp, nil
}
Пример #28
0
// ListNetworks lists all the networks which can be used by the given account.
// See API docs: http://apidocs.joyent.com/cloudapi/#ListNetworks
func (c *Client) ListNetworks() ([]Network, error) {
	var resp []Network
	req := request{
		method: client.GET,
		url:    apiNetworks,
		resp:   &resp,
	}
	if _, err := c.sendRequest(req); err != nil {
		return nil, errors.Newf(err, "failed to get list of networks")
	}
	return resp, nil
}
Пример #29
0
// ListMachineFirewallRules lists all the firewall rules for the specified machine.
// See API docs: http://apidocs.joyent.com/cloudapi/#ListMachineFirewallRules
func (c *Client) ListMachineFirewallRules(machineID string) ([]FirewallRule, error) {
	var resp []FirewallRule
	req := request{
		method: client.GET,
		url:    makeURL(apiMachines, machineID, apiFirewallRules),
		resp:   &resp,
	}
	if _, err := c.sendRequest(req); err != nil {
		return nil, errors.Newf(err, "failed to get list of firewall rules for machine with id %s", machineID)
	}
	return resp, nil
}
Пример #30
0
// GetMachineMetadata returns the complete set of metadata associated with the
// specified machine.
// See API docs: http://apidocs.joyent.com/cloudapi/#GetMachineMetadata
func (c *Client) GetMachineMetadata(machineID string) (map[string]interface{}, error) {
	var resp map[string]interface{}
	req := request{
		method: client.GET,
		url:    makeURL(apiMachines, machineID, apiMetadata),
		resp:   &resp,
	}
	if _, err := c.sendRequest(req); err != nil {
		return nil, errors.Newf(err, "failed to get list of metadata for machine with id %s", machineID)
	}
	return resp, nil
}