Пример #1
0
// This operation creates a new vault with the specified name. The name of the
// vault must be unique within a region for an AWS account.You can create up to
// 1,000 vaults per account.
//
// You must use the following guidelines when naming a vault.
// * Names can be between 1 and 255 characters long.
// * Allowed characters are a–z, A–Z, 0–9, '_' (underscore), '-' (hyphen), and
// '.' (period).
//
// This operation is idempotent, you can send the same request multiple times
// and it has no further effect after the first time Amazon Glacier creates the
// specified vault.
func (c *Connection) CreateVault(name string) error {
	// Build request.
	request, err := http.NewRequest("PUT", c.vault(name), nil)
	if err != nil {
		return err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	c.Signature.Sign(request, nil)

	// Perform request.
	response, err := c.client().Do(request)
	if err != nil {
		return err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusCreated {
		return aws.ParseError(response)
	}

	io.Copy(ioutil.Discard, response.Body)

	// Parse success response.
	return nil
}
Пример #2
0
// You can download all the job output or download a portion of the output by
// specifying a byte range. In the case of an archive retrieval job, depending
// on the byte range you specify, Amazon Glacier returns the checksum for the
// portion of the data.You can compute the checksum on the client and verify
// that the values match to ensure the portion you downloaded is the correct
// data.
//
// Returns a ReadCloser containing the requested data, a tree hash or the
// first error encountered.
// It is the caller's reposonsibility to call Close on the returned value. The
// tree hash is only returned under the following conditions:
// * You get the entire range of the archive.
// * You request a byte range of the archive that starts and ends on a multiple
// of 1 MB. For example, if you have a 3.1 MB archive and you specify a range
// to return that starts at 1 MB and ends at 2 MB, then the x-amz-sha256-tree-
// hash is returned as a response header.
// * You request a byte range that starts on a multiple of 1 MB and goes to the
// end of the archive. For example, if you have a 3.1 MB archive and you
// specify a range that starts at 2 MB and ends at 3.1 MB (the end of the
// archive), then the x-amz-sha256-tree-hash is returned as a response header.
//
// Make sure to fully consume the returned `io.ReadCloser`, otherwise `http.Client`
// won't be able to re-use the connection for a new request to AWS Glacier. If you
// are not interested in its contents, just do `ioutil.Copy(ioutil.Discard, response)`,
// where `response` is the `io.ReadCloser` retrieved from this function.
func (c *Connection) GetRetrievalJob(vault, job string, start, end int64) (io.ReadCloser, string, error) {
	// Build request.
	request, err := http.NewRequest("GET", c.vault(vault)+"/jobs/"+job+"/output", nil)
	if err != nil {
		return nil, "", err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")
	if end > 0 {
		request.Header.Add("Range", fmt.Sprintf("bytes=%d-%d", start, end))
	}

	c.Signature.Sign(request, nil)

	// Perform request.
	response, err := c.client().Do(request)
	if err != nil {
		return nil, "", err
	}

	if response.StatusCode != http.StatusOK && response.StatusCode != http.StatusPartialContent {
		err := aws.ParseError(response)
		response.Body.Close()
		return nil, "", err
	}

	// Parse success response.
	return response.Body, response.Header.Get("x-amz-sha256-tree-hash"), nil
}
Пример #3
0
// Retrieving an archive and a vault inventory are asynchronous operations in
// Amazon Glacier for which you must first initiate a job and wait for the job
// to complete before you can download the job output. Most Amazon Glacier jobs
// take about four hours to complete. So you can configure a vault to post a
// message to an Amazon Simple Notification Service (SNS) topic when these jobs
// complete. You can use this operation to set notification configuration on the
// vault.
//
// Amazon SNS topics must grant permission to the vault to be allowed to publish
// notifications to the topic.
//
// To configure vault notifications, send a request to the notification-
// configuration subresource of the vault. A notification configuration is
// specific to a vault; therefore, it is also referred to as a vault
// subresource.
func (c *Connection) SetVaultNotifications(name string, n *Notifications) error {
	// Build request.
	body, err := json.Marshal(n)
	if err != nil {
		return err
	}

	request, err := http.NewRequest("PUT", "https://"+c.Signature.Region.Glacier+"/-/vaults/"+name+
		"/notification-configuration", nil)
	if err != nil {
		return err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	c.Signature.Sign(request, aws.MemoryPayload(body))

	// Perform request.
	response, err := c.client().Do(request)
	if err != nil {
		return err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusNoContent {
		return aws.ParseError(response)
	}

	io.Copy(ioutil.Discard, response.Body)

	// Parse success response.
	return nil
}
Пример #4
0
// This operation initiates a multipart upload. Amazon Glacier creates a
// multipart upload resource and returns its ID in the response. You use this
// Upload ID in subsequent multipart upload operations.
//
// When you initiate a multipart upload, you specify the part size in number of
// bytes. The part size must be a megabyte (1024 KB) multiplied by a power of
// 2—for example, 1048576 (1 MB), 2097152 (2 MB), 4194304 (4 MB), 8388608 (8
// MB), and so on.The minimum allowable part size is 1 MB, and the maximum is 4
// GB.
//
// Every part you upload using this upload ID, except the last one, must have
// the same size. The last one can be the same size or smaller. For example,
// suppose you want to upload a 16.2 MB file. If you initiate the multipart
// upload with a part size of 4 MB, you will upload four parts of 4 MB each and
// one part of 0.2 MB.
//
// After you complete the multipart upload, Amazon Glacier removes the multipart
// upload resource referenced by the ID. Amazon Glacier will also remove the
// multipart upload resource if you cancel the multipart upload or or it may be
// removed if there is no activity for a period of 24 hours.
//
// Note: You don't need to know the size of the archive when you start a
// multipart upload because Amazon Glacier does not require you to specify the
// overall archive size.
func (c *Connection) InitiateMultipart(vault string, size int64, description string) (string, error) {
	// Build request.
	request, err := http.NewRequest("POST", c.vault(vault)+"/multipart-uploads", nil)
	if err != nil {
		return "", err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	// TODO check that size is valid
	request.Header.Add("x-amz-part-size", fmt.Sprint(size))

	if description != "" {
		request.Header.Add("x-amz-archive-description", description)
	}

	c.Signature.Sign(request, nil)

	// Perform request.
	response, err := c.client().Do(request)
	if err != nil {
		return "", err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusCreated {
		return "", aws.ParseError(response)
	}

	io.Copy(ioutil.Discard, response.Body)

	// Parse success response.
	return response.Header.Get("x-amz-multipart-upload-id"), nil
}
Пример #5
0
// This multipart upload operation aborts a multipart upload identified by the upload ID.
//
// After the Abort Multipart Upload request succeeds, you cannot use the upload
// ID to upload any more parts or perform any other operations. Aborting a
// completed multipart upload fails. However, aborting an already-aborted upload
// will succeed, for a short time.
//
// This operation is idempotent.
func (c *Connection) AbortMultipart(vault, uploadId string) error {
	// Build request.
	request, err := http.NewRequest("DELETE", c.vault(vault)+"/multipart-uploads/"+uploadId, nil)
	if err != nil {
		return err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	c.Signature.Sign(request, nil)

	// Perform request.
	response, err := c.client().Do(request)
	if err != nil {
		return err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusNoContent {
		return aws.ParseError(response)
	}

	io.Copy(ioutil.Discard, response.Body)

	// Parse success response.
	return nil
}
Пример #6
0
// You call this multipart upload operation to inform Amazon Glacier that all
// the archive parts have been uploaded and Amazon Glacier can now assemble the
// archive from the uploaded parts.
//
// After assembling and saving the archive to the vault, Amazon Glacier returns
// the archive ID of the newly created archive resource. After you upload an
// archive, you should save the archive ID returned to retrieve the archive at a
// later point.
//
// In the request, you must include the computed SHA256 tree hash of the entire
// archive you have uploaded. On the server side, Amazon Glacier also constructs
// the SHA256 tree hash of the assembled archive. If the values match, Amazon
// Glacier saves the archive to the vault; otherwise, it returns an error, and
// the operation fails. It includes checksum information for each uploaded part
// that can be used to debug a bad checksum issue.
//
// Additionally, Amazon Glacier also checks for any missing content ranges.When
// uploading parts, you specify range values identifying where each part fits in
// the final assembly of the archive.When assembling the final archive Amazon
// Glacier checks for any missing content ranges and if there are any missing
// content ranges, Amazon Glacier returns an error and the Complete Multipart
// Upload operation fails.
//
// Complete Multipart Upload is an idempotent operation. After your first
// successful complete multipart upload, if you call the operation again within
// a short period, the operation will succeed and return the same archive ID.
// This is useful in the event you experience a network issue that causes an
// aborted connection or receive a 500 server error, in which case you can
// repeat your Complete Multipart Upload request and get the same archive ID
// without creating duplicate archives. Note, however, that after the multipart
// upload completes, you cannot call the List Parts operation and the multipart
// upload will not appear in List Multipart Uploads response, even if idempotent
// complete is possible.
//
// Note: treeHash must be a hex-encoded string.
func (c *Connection) CompleteMultipart(vault, uploadId, treeHash string, size int64) (string, error) {
	// Build request.
	request, err := http.NewRequest("POST", c.vault(vault)+"/multipart-uploads/"+uploadId, nil)
	if err != nil {
		return "", err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	request.Header.Add("x-amz-sha256-tree-hash", treeHash)
	request.Header.Add("x-amz-archive-size", fmt.Sprint(size))

	c.Signature.Sign(request, nil)

	// Perform request.
	response, err := c.client().Do(request)
	if err != nil {
		return "", err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusCreated {
		return "", aws.ParseError(response)
	}

	io.Copy(ioutil.Discard, response.Body)

	// Parse success response.
	return response.Header.Get("x-amz-archive-id"), nil
}
Пример #7
0
// Initiate an vault inventory job with the vault name. You can also provide
// an optional job description when you initiate these jobs. If you specify a
// topic, Amazon Glacier sends notifications to both the supplied topic and
// the vault's ArchiveRetrievalCompleted notification topic.
//
// Returns the job ID or the first error encountered.
func (c *Connection) InitiateInventoryJob(vault, topic, description string) (string, error) {
	// Build request.
	j := jobRequest{Type: "inventory-retrieval", Description: description, SNSTopic: topic}
	body, _ := json.Marshal(j)

	request, err := http.NewRequest("POST", c.vault(vault)+"/jobs", nil)
	if err != nil {
		return "", err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	c.Signature.Sign(request, aws.MemoryPayload(body))

	// Perform request.
	response, err := c.client().Do(request)
	if err != nil {
		return "", err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusAccepted {
		return "", aws.ParseError(response)
	}

	io.Copy(ioutil.Discard, response.Body)

	// Parse success response.
	return response.Header.Get("x-amz-job-id"), nil
}
Пример #8
0
// This operation deletes a vault. Amazon Glacier will delete a vault only if
// there are no archives in the vault as per the last inventory and there have
// been no writes to the vault since the last inventory. If either of these
// conditions is not satisfied, the vault deletion fails (that is, the vault is
// not removed) and Amazon Glacier returns an error.
//
// This operation is idempotent.
func (c *Connection) DeleteVault(name string) error {
	// Build request.
	request, err := http.NewRequest("DELETE", "https://"+c.Signature.Region.Glacier+"/-/vaults/"+name, nil)
	if err != nil {
		return err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	c.Signature.Sign(request, nil)

	// Perform request.
	response, err := c.client().Do(request)
	if err != nil {
		return err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusNoContent {
		return aws.ParseError(response)
	}

	io.Copy(ioutil.Discard, response.Body)

	// Parse success response.
	return nil
}
Пример #9
0
// This operation returns information about a vault, including the vault Amazon
// Resource Name (ARN), the date the vault was created, the number of archives
// contained within the vault, and the total size of all the archives in the
// vault.The number of archives and their total size are as of the last vault
// inventory Amazon Glacier generated. Amazon Glacier generates vault
// inventories approximately daily. This means that if you add or remove an
// archive from a vault, and then immediately send a Describe Vault request, the
// response might not reflect the changes.
func (c *Connection) DescribeVault(name string) (*Vault, error) {
	// Build request.
	request, err := http.NewRequest("GET", "https://"+c.Signature.Region.Glacier+"/-/vaults/"+name, nil)
	if err != nil {
		return nil, err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	c.Signature.Sign(request, nil)

	// Perform request.
	response, err := c.client().Do(request)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusOK {
		return nil, aws.ParseError(response)
	}

	// Parse success response.
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	var v vault
	err = json.Unmarshal(body, &v)
	if err != nil {
		return nil, err
	}

	var result Vault
	result.CreationDate, err = time.Parse(time.RFC3339, v.CreationDate)
	if err != nil {
		return nil, err
	}
	if v.LastInventoryDate != nil {
		result.LastInventoryDate, err = time.Parse(time.RFC3339, *v.LastInventoryDate)
		if err != nil {
			return nil, err
		}
	}
	result.NumberOfArchives = v.NumberOfArchives
	result.SizeInBytes = v.SizeInBytes
	result.VaultARN = v.VaultARN
	result.VaultName = v.VaultName

	return &result, nil
}
Пример #10
0
// This multipart upload operation uploads a part of an archive.You can upload
// archive parts in any order because in your Upload Part request you specify
// the range of bytes in the assembled archive that will be uploaded in this
// part.You can also upload these parts in parallel.You can upload up to 10,000
// parts for a multipart upload.
//
// Amazon Glacier rejects your upload part request if any of the following
// conditions is true:
// * SHA256 tree hash does not match—To ensure that part data is not corrupted
// in transmission, you compute a SHA256 tree hash of the part and include it in
// your request. Upon receiving the part data, Amazon Glacier also computes a
// SHA256 tree hash. If the two hash values don't match, the operation fails.
// * Part size does not match—The size of each part except the last must match
// the size that is specified in the corresponding Initiate Multipart Upload.
// The size of the last part must be the same size as, or smaller than, the
// specified size. Note: If you upload a part whose size is smaller than the
// part size you specified in your initiate multipart upload request and that
// part is not the last part, then the upload part request will succeed.
// However, the subsequent Complete Multipart Upload request will fail.
// * Range does not align—The byte range value in the request does not align
// with the part size specified in the corresponding initiate request. For
// example, if you specify a part size of 4194304 bytes (4 MB), then 0 to
// 4194303 bytes (4 MB —1) and 4194304 (4 MB) to 8388607 (8 MB —1) are valid
// part ranges. However, if you set a range value of 2 MB to 6 MB, the range
// does not align with the part size and the upload will fail.
//
// This operation is idempotent. If you upload the same part multiple times, the
// data included in the most recent request overwrites the previously uploaded
// data.
func (c *Connection) UploadMultipart(vault, uploadId string, start int64, body io.ReadSeeker) error {
	// TODO check that data size and start location make sense

	// Build request.
	request, err := http.NewRequest("PUT", "https://"+c.Signature.Region.Glacier+"/-/vaults/"+vault+
		"/multipart-uploads/"+uploadId, body)
	if err != nil {
		return err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	th := NewTreeHash()
	n, err := io.Copy(th, body)
	if err != nil {
		return err
	}
	th.Close()

	_, err = body.Seek(0, 0)
	if err != nil {
		return err
	}

	hash := th.Hash()

	request.Header.Add("x-amz-content-sha256", toHex(hash))
	request.Header.Add("x-amz-sha256-tree-hash", toHex(th.TreeHash()))
	request.Header.Add("Content-Range", fmt.Sprintf("bytes %d-%d/*", start, start+n-1))
	request.ContentLength = n

	c.Signature.Sign(request, aws.HashedPayload(hash))

	// Perform request.
	response, err := c.client().Do(request)
	if err != nil {
		return err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusNoContent {
		return aws.ParseError(response)
	}

	io.Copy(ioutil.Discard, response.Body)

	// Parse success response.
	return nil
}
Пример #11
0
// Upload archive to vault with optional description. The entire archive will
// be read in order to create its tree hash before uploading.
//
// Returns the archive ID or the first error encountered.
func (c *Connection) UploadArchive(vault string, archive io.ReadSeeker, description string) (string, error) {
	// Build reuest.
	request, err := http.NewRequest("POST", c.vault(vault)+"/archives",
		archive)
	if err != nil {
		return "", err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	th := NewTreeHash()
	request.ContentLength, err = io.Copy(th, archive)
	if err != nil {
		return "", err
	}
	th.Close()

	_, err = archive.Seek(0, 0)
	if err != nil {
		return "", err
	}

	hash := th.Hash()

	request.Header.Add("x-amz-archive-description", description)
	request.Header.Add("x-amz-sha256-tree-hash", toHex(th.TreeHash()))
	request.Header.Add("x-amz-content-sha256", toHex(hash))

	c.Signature.Sign(request, aws.HashedPayload(hash))

	// Perform request.
	response, err := c.client().Do(request)
	if err != nil {
		return "", err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusCreated {
		return "", aws.ParseError(response)
	}

	io.Copy(ioutil.Discard, response.Body)

	// Parse success response.
	_, location := path.Split(response.Header.Get("Location"))
	return location, nil
}
Пример #12
0
// This operation retrieves the notification-configuration subresource set on
// the vault. If notification configuration for a vault is not set, the
// operation returns a 404 Not Found error.
func (c *Connection) GetVaultNotifications(name string) (*Notifications, error) {
	// Build request.
	var results Notifications

	request, err := http.NewRequest("GET", "https://"+c.Signature.Region.Glacier+"/-/vaults/"+name+
		"/notification-configuration", nil)
	if err != nil {
		return nil, err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	c.Signature.Sign(request, nil)

	// Perform request.
	response, err := c.client().Do(request)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusOK {
		return nil, aws.ParseError(response)
	}

	// Parse success response.
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(body, &results)
	if err != nil {
		return nil, err
	}

	return &results, nil
}
Пример #13
0
// This operation returns the current data retrieval policy and bytes per hour
// (if applicable).
//
// There is one policy per region for an AWS account.
//
// For more information about data retrieval policies, see DataRetrievalPolicy.
func (c *Connection) GetDataRetrievalPolicy() (DataRetrievalPolicy, int, error) {
	// Build request.
	request, err := http.NewRequest("GET", c.policy("data-retrieval"), nil)
	if err != nil {
		return 0, 0, err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	c.Signature.Sign(request, nil)

	// Perform request.
	response, err := c.client().Do(request)
	if err != nil {
		return 0, 0, err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusOK {
		return 0, 0, aws.ParseError(response)
	}

	// Parse success response.
	var policy dataRetrievalPolicy
	decoder := json.NewDecoder(response.Body)
	err = decoder.Decode(&policy)
	if err != nil {
		return 0, 0, err
	}

	var bytesPerHour int
	if policy.Policy.Rules[0].BytesPerHour != nil {
		bytesPerHour = *policy.Policy.Rules[0].BytesPerHour
	}
	strategy := ToDataRetrievalPolicy(policy.Policy.Rules[0].Strategy)

	return strategy, bytesPerHour, nil
}
Пример #14
0
// This operation sets and then enacts a data retrieval policy.
//
// You can set one policy per region for an AWS account. The policy is enacted
// within a few minutes of a successful call.
//
// The set policy operation does not affect retrieval jobs that were in progress
// before the policy was enacted. For more information about data retrieval
// policies, see DataRetrievalPolicy.
func (c *Connection) SetRetrievalPolicy(drp DataRetrievalPolicy, bytesPerHour int) error {
	// Build request.
	var rules dataRetrievalPolicy
	rules.Policy.Rules[0].Strategy = drp.String()
	if bytesPerHour != 0 {
		rules.Policy.Rules[0].BytesPerHour = &bytesPerHour
	}
	data, err := json.Marshal(rules)
	if err != nil {
		return err
	}
	reader := bytes.NewReader(data)

	request, err := http.NewRequest("PUT", c.policy("data-retrieval"), reader)
	if err != nil {
		return err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	c.Signature.Sign(request, aws.ReadSeekerPayload(reader))

	// Perform request.
	response, err := c.client().Do(request)
	if err != nil {
		return err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusNoContent {
		return aws.ParseError(response)
	}

	io.Copy(ioutil.Discard, response.Body)

	// Parse success response.
	return nil
}
Пример #15
0
// This operation returns information about a job you previously initiated,
// see Job type.
//
// Returns the job and the first error, if any, encountered.
func (c *Connection) DescribeJob(vault, jobId string) (*Job, error) {
	// Build request.
	request, err := http.NewRequest("GET", c.vault(vault)+"/jobs/"+jobId, nil)
	if err != nil {
		return nil, err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	c.Signature.Sign(request, nil)

	// Perform request.
	response, err := c.client().Do(request)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusOK {
		return nil, aws.ParseError(response)
	}

	// Parse success response.
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	var j job
	err = json.Unmarshal(body, &j)
	if err != nil {
		return nil, err
	}

	var result Job
	if j.ArchiveId != nil {
		result.ArchiveId = *j.ArchiveId
	}
	if j.ArchiveSizeInBytes != nil {
		result.ArchiveSizeInBytes = *j.ArchiveSizeInBytes
	}
	result.Completed = j.Completed
	if j.CompletionDate != nil {
		result.CompletionDate, err = time.Parse(time.RFC3339, *j.CompletionDate)
		if err != nil {
			return nil, err
		}
	}
	result.CreationDate, err = time.Parse(time.RFC3339, j.CreationDate)
	if err != nil {
		return nil, err
	}
	if j.InventorySizeInBytes != nil {
		result.InventorySizeInBytes = *j.InventorySizeInBytes
	}
	if j.JobDescription != nil {
		result.JobDescription = *j.JobDescription
	}
	result.JobId = j.JobId
	if j.SHA256TreeHash != nil {
		result.SHA256TreeHash = *j.SHA256TreeHash
	}
	if j.SNSTopic != nil {
		result.SNSTopic = *j.SNSTopic
	}
	result.StatusCode = j.StatusCode
	if j.StatusMessage != nil {
		result.StatusMessage = *j.StatusMessage
	}
	result.VaultARN = j.VaultARN

	return &result, nil
}
Пример #16
0
// This multipart upload operation lists the parts of an archive that have been
// uploaded in a specific multipart upload identified by an upload ID.
//
// You can make this request at any time during an in-progress multipart upload
// before you complete the multipart upload. Amazon Glacier returns the part
// list sorted by range you specified in each part upload. If you send a List
// Parts request after completing the multipart upload, Amazon Glacier returns
// an error.
//
// The List Parts operation supports pagination. By default, this operation
// returns up to 1,000 uploaded parts in the response.You should always check
// the marker field in the response body for a marker at which to continue the
// list; if there are no more items the marker field is null. If the marker is
// not null, to fetch the next set of parts you sent another List Parts request
// with the marker request parameter set to the marker value Amazon Glacier
// returned in response to your previous List Parts request.
//
// You can also limit the number of parts returned in the response by specifying
// the limit parameter in the request.
func (c *Connection) ListMultipartParts(vault, uploadId, marker string, limit int) (*MultipartParts, error) {
	// Build request.
	parameters := parameters{}
	if limit > 0 {
		// TODO validate limit
		parameters.add("limit", strconv.Itoa(limit))
	}
	if marker != "" {
		parameters.add("marker", marker)
	}

	request, err := http.NewRequest("GET", c.vault(vault)+"/multipart-uploads/"+uploadId+parameters.encode(), nil)
	if err != nil {
		return nil, err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	c.Signature.Sign(request, nil)

	// Perform request.
	response, err := c.client().Do(request)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusOK {
		return nil, aws.ParseError(response)
	}

	// Parse success response.
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	var list struct {
		ArchiveDescription string
		CreationDate       string
		Marker             *string
		MultipartUploadId  string
		PartSizeInBytes    int64
		Parts              []MultipartPart
		VaultARN           string
	}
	err = json.Unmarshal(body, &list)
	if err != nil {
		return nil, err
	}

	var result MultipartParts
	result.ArchiveDescription = list.ArchiveDescription
	result.CreationDate, err = time.Parse(time.RFC3339, list.CreationDate)
	if err != nil {
		return nil, err
	}
	if list.Marker != nil {
		result.Marker = *list.Marker
	}
	result.MultipartUploadId = list.MultipartUploadId
	result.PartSizeInBytes = list.PartSizeInBytes
	result.Parts = list.Parts
	result.VaultARN = list.VaultARN

	return &result, nil
}
Пример #17
0
// This operation lists all vaults owned by the calling user’s account. The list
// returned in the response is ASCII-sorted by vault name.
//
// By default, this operation returns up to 1,000 items. If there are more
// vaults to list, the marker field in the response body contains the vault
// Amazon Resource Name (ARN) at which to continue the list with a new List
// Vaults request; otherwise, the marker field is null. In your next List Vaults
// request you set the marker parameter to the value Amazon Glacier returned in
// the responses to your previous List Vaults request.You can also limit the
// number of vaults returned in the response by specifying the limit parameter
// in the request.
func (c *Connection) ListVaults(marker string, limit int) ([]Vault, string, error) {
	// Build request.
	if limit < 0 || limit > 1000 {
		// TODO return predeclared variable
		return nil, "", errors.New("limit must be 1 through 1000")
	}

	request, err := http.NewRequest("GET", "https://"+c.Signature.Region.Glacier+"/-/vaults", nil)
	if err != nil {
		return nil, "", err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	if limit != 0 {
		request.Header.Add("limit", "")
	}
	if marker != "" {
		request.Header.Add("marker", "")
	}

	c.Signature.Sign(request, nil)

	// Perform request.
	response, err := c.client().Do(request)
	if err != nil {
		return nil, "", err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusOK {
		return nil, "", aws.ParseError(response)
	}

	// Parse success response.
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, "", err
	}

	var vaults struct {
		Marker    *string
		VaultList []vault
	}
	err = json.Unmarshal(body, &vaults)
	if err != nil {
		return nil, "", err
	}

	result := make([]Vault, len(vaults.VaultList))
	for i, v := range vaults.VaultList {
		result[i].CreationDate, err = time.Parse(time.RFC3339, v.CreationDate)
		if err != nil {
			return nil, "", err
		}
		if v.LastInventoryDate != nil {
			result[i].LastInventoryDate, err = time.Parse(time.RFC3339, *v.LastInventoryDate)
			if err != nil {
				return nil, "", err
			}
		}
		result[i].NumberOfArchives = v.NumberOfArchives
		result[i].SizeInBytes = v.SizeInBytes
		result[i].VaultARN = v.VaultARN
		result[i].VaultName = v.VaultName
	}

	var resultMarker string
	if vaults.Marker != nil {
		resultMarker = *vaults.Marker
	}

	return result, resultMarker, nil
}
Пример #18
0
// This multipart upload operation lists in-progress multipart uploads for the
// specified vault. An in-progress multipart upload is a multipart upload that
// has been initiated by an Initiate Multipart Upload request, but has not yet
// been completed or aborted. The list returned in the List Multipart Upload
// response has no guaranteed order.
//
// The List Multipart Uploads operation supports pagination. By default, this
// operation returns up to 1,000 multipart uploads in the response.You should
// always check the marker field in the response body for a marker at which to
// continue the list; if there are no more items the marker field is null.
//
// If the marker is not null, to fetch the next set of multipart uploads you
// sent another List Multipart Uploads request with the marker request parameter
// set to the marker value Amazon Glacier returned in response to your previous
// List Multipart Uploads request.
//
// Note the difference between this operation and the List Parts operation.The
// List Multipart Uploads operation lists all multipart uploads for a vault. The
// List Parts operation returns parts of a specific multipart upload identified
// by an Upload ID.
func (c *Connection) ListMultipartUploads(vault, marker string, limit int) ([]Multipart, string, error) {
	// Build request.
	query := url.Values{}
	if limit > 0 {
		// TODO validate limit
		query.Add("limit", fmt.Sprint(limit))
	}
	if marker != "" {
		query.Add("marker", marker)
	}

	request, err := http.NewRequest("GET", c.vault(vault)+"/multipart-uploads"+query.Encode(), nil)
	if err != nil {
		return nil, "", err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	c.Signature.Sign(request, nil)

	// Perform request.
	response, err := c.client().Do(request)
	if err != nil {
		return nil, "", err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusOK {
		return nil, "", aws.ParseError(response)
	}

	// Parse success response.
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, "", err
	}

	var list struct {
		Marker      *string
		UploadsList []struct {
			ArchiveDescription *string
			CreationDate       string
			MultipartUploadId  string
			PartSizeInBytes    int64
			VaultARN           string
		}
	}
	err = json.Unmarshal(body, &list)
	if err != nil {
		return nil, "", err
	}

	parts := make([]Multipart, len(list.UploadsList))
	for i, v := range list.UploadsList {
		if v.ArchiveDescription != nil {
			parts[i].ArchiveDescription = *v.ArchiveDescription
		}
		parts[i].CreationDate, err = time.Parse(time.RFC3339, v.CreationDate)
		if err != nil {
			return nil, "", err
		}
		parts[i].MultipartUploadId = v.MultipartUploadId
		parts[i].PartSizeInBytes = v.PartSizeInBytes
		parts[i].VaultARN = v.VaultARN
	}

	var m string
	if list.Marker != nil {
		m = *list.Marker
	}

	return parts, m, nil
}
Пример #19
0
// This operation lists all vaults owned by the calling user’s account. The list
// returned in the response is ASCII-sorted by vault name.
//
// By default, this operation returns up to 1,000 items. If there are more
// vaults to list, the marker field in the response body contains the vault
// Amazon Resource Name (ARN) at which to continue the list with a new List
// Vaults request; otherwise, the marker field is null. In your next List Vaults
// request you set the marker parameter to the value Amazon Glacier returned in
// the responses to your previous List Vaults request.You can also limit the
// number of vaults returned in the response by specifying the limit parameter
// in the request.
func (c *Connection) ListVaults(marker string, limit int) ([]Vault, string, error) {
	// Build request.
	parameters := parameters{}
	if limit > 0 {
		// TODO validate, 1 - 1000
		parameters.add("limit", strconv.Itoa(limit))
	}
	if marker != "" {
		parameters.add("marker", marker)
	}

	// This is the only case where we don't supply a vault name and will thus
	// need to trim the trailing slash of the generated URL.
	vaultURL := c.vault("")
	vaultURL = vaultURL[:len(vaultURL)-1]

	request, err := http.NewRequest("GET", vaultURL+parameters.encode(), nil)
	if err != nil {
		return nil, "", err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	c.Signature.Sign(request, nil)

	// Perform request.
	response, err := c.client().Do(request)
	if err != nil {
		return nil, "", err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusOK {
		return nil, "", aws.ParseError(response)
	}

	// Parse success response.
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, "", err
	}

	var vaults struct {
		Marker    *string
		VaultList []vault
	}
	err = json.Unmarshal(body, &vaults)
	if err != nil {
		return nil, "", err
	}

	result := make([]Vault, len(vaults.VaultList))
	for i, v := range vaults.VaultList {
		result[i].CreationDate, err = time.Parse(time.RFC3339, v.CreationDate)
		if err != nil {
			return nil, "", err
		}
		if v.LastInventoryDate != nil {
			result[i].LastInventoryDate, err = time.Parse(time.RFC3339, *v.LastInventoryDate)
			if err != nil {
				return nil, "", err
			}
		}
		result[i].NumberOfArchives = v.NumberOfArchives
		result[i].SizeInBytes = v.SizeInBytes
		result[i].VaultARN = v.VaultARN
		result[i].VaultName = v.VaultName
	}

	var resultMarker string
	if vaults.Marker != nil {
		resultMarker = *vaults.Marker
	}

	return result, resultMarker, nil
}
Пример #20
0
// This operation lists jobs for a vault including jobs that are in-progress and
// jobs that have recently finished.
//
// To retrieve an archive or retrieve a vault inventory from Amazon Glacier, you
// first initiate a job, and after the job completes, you download the data. For
// an archive retrieval, the output is the archive data, and for an inventory
// retrieval, it is the inventory list. The List Job operation returns a list of
// these jobs sorted by job initiation time. The List Jobs operation supports
// pagination. By default, this operation returns up to 1,000 jobs in the
// response.You should always check the response marker field for a marker at
// which to continue the list; if there are no more items the marker field is
// null. To return a list of jobs that begins at a specific job, set the marker
// request parameter to the value you obtained from a previous List Jobs
// request.You can also limit the number of jobs returned in the response by
// specifying the limit parameter in the request.
//
// Additionally, you can filter the jobs list returned by specifying an optional
// statuscode (InProgress, Succeeded, or Failed) and completed (true, false)
// parameter. The statuscode allows you to specify that only jobs that match a
// specified status are returned.The completed parameter allows you to specify
// that only jobs in specific completion state are returned.
//
// Amazon Glacier retains recently completed jobs for a period before deleting
// them; however, it eventually removes completed jobs. The output of completed
// jobs can be retrieved. Retaining completed jobs for a period of time after
// they have completed enables you to get a job output in the event you miss the
// job completion notification or your first attempt to download it fails. For
// example, suppose you start an archive retrieval job to download an archive.
// After the job completes, you start to download the archive but encounter a
// network error. In this scenario, you can retry and download the archive while
// the job exists.
func (c *Connection) ListJobs(vault, completed, statusCode, marker string, limit int) ([]Job, string, error) {
	// Build request.
	parameters := parameters{}
	if completed != "" {
		// TODO validate, true or false
		parameters.add("completed", completed)
	}
	if limit > 0 {
		// TODO validate, 1 - 1000
		parameters.add("limit", strconv.Itoa(limit))
	}
	if marker != "" {
		// TODO validate
		parameters.add("marker", marker)
	}
	if statusCode != "" {
		// TODO validate, InProgress, Succeeded, or Failed
		parameters.add("statuscode", statusCode)
	}

	request, err := http.NewRequest("GET", c.vault(vault)+"/jobs"+parameters.encode(), nil)
	if err != nil {
		return nil, "", err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	c.Signature.Sign(request, nil)

	// Perform request.
	response, err := c.client().Do(request)
	if err != nil {
		return nil, "", err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusOK {
		return nil, "", aws.ParseError(response)
	}

	// Parse success response.
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, "", err
	}

	var jl jobList
	err = json.Unmarshal(body, &jl)
	if err != nil {
		return nil, "", err
	}

	jobs := make([]Job, len(jl.JobList))
	for i, v := range jl.JobList {
		jobs[i].Action = v.Action
		if v.ArchiveId != nil {
			jobs[i].ArchiveId = *v.ArchiveId
		}
		if v.ArchiveSizeInBytes != nil {
			jobs[i].ArchiveSizeInBytes = *v.ArchiveSizeInBytes
		}
		jobs[i].Completed = v.Completed
		if v.CompletionDate != nil {
			jobs[i].CompletionDate, err = time.Parse(time.RFC3339, *v.CompletionDate)
			if err != nil {
				return nil, "", err
			}
		}
		jobs[i].CreationDate, err = time.Parse(time.RFC3339, v.CreationDate)
		if err != nil {
			return nil, "", err
		}
		if v.InventorySizeInBytes != nil {
			jobs[i].InventorySizeInBytes = *v.InventorySizeInBytes
		}
		if v.JobDescription != nil {
			jobs[i].JobDescription = *v.JobDescription
		}
		jobs[i].JobId = v.JobId
		if v.SHA256TreeHash != nil {
			jobs[i].SHA256TreeHash = *v.SHA256TreeHash
		}
		if v.SNSTopic != nil {
			jobs[i].SNSTopic = *v.SNSTopic
		}
		jobs[i].StatusCode = v.StatusCode
		if v.StatusMessage != nil {
			jobs[i].StatusMessage = *v.StatusMessage
		}
		jobs[i].VaultARN = v.VaultARN
	}

	var m string
	if jl.Marker != nil {
		m = *jl.Marker
	}

	return jobs, m, nil
}
Пример #21
0
// Amazon Glacier updates a vault inventory approximately once a day, starting
// on the day you first upload an archive to the vault. When you initiate a job
// for a vault inventory, Amazon Glacier returns the last inventory it
// generated, which is a point-in-time snapshot and not realtime data. Note that
// after Amazon Glacier creates the first inventory for the vault, it typically
// takes half a day and up to a day before that inventory is available for
// retrieval.You might not find it useful to retrieve a vault inventory for each
// archive upload. However, suppose you maintain a database on the client-side
// associating metadata about the archives you upload to Amazon Glacier. Then,
// you might find the vault inventory useful to reconcile information, as
// needed, in your database with the actual vault inventory.
func (c *Connection) GetInventoryJob(vault, job string) (*Inventory, error) {
	// Build request.
	request, err := http.NewRequest("GET", c.vault(vault)+"/jobs/"+job+"/output", nil)
	if err != nil {
		return nil, err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	c.Signature.Sign(request, nil)

	// Perform request.
	response, err := c.client().Do(request)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusOK {
		return nil, aws.ParseError(response)
	}

	// Parse success response.
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	var i struct {
		VaultARN      string
		InventoryDate string
		ArchiveList   []struct {
			ArchiveId          string
			ArchiveDescription string
			CreationDate       string
			Size               int64
			SHA256TreeHash     string
		}
	}
	err = json.Unmarshal(body, &i)
	if err != nil {
		return nil, err
	}

	var result Inventory
	result.VaultARN = i.VaultARN
	result.InventoryDate, err = time.Parse(time.RFC3339, i.InventoryDate)
	if err != nil {
		return nil, err
	}
	result.ArchiveList = make([]Archive, len(i.ArchiveList))
	for j, v := range i.ArchiveList {
		result.ArchiveList[j].ArchiveId = v.ArchiveId
		result.ArchiveList[j].ArchiveDescription = v.ArchiveDescription
		result.ArchiveList[j].CreationDate, err = time.Parse(time.RFC3339, v.CreationDate)
		if err != nil {
			return nil, err
		}
		result.ArchiveList[j].Size = v.Size
		result.ArchiveList[j].SHA256TreeHash = v.SHA256TreeHash
	}

	return &result, nil
}