// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }