From 2bf054d0d6e407367bd9c3d19f25acd11143f35d Mon Sep 17 00:00:00 2001 From: Gavin Williams Date: Tue, 1 Nov 2016 13:24:00 +0000 Subject: [PATCH] vendor: Updating github.com/gophercloud/gophercloud Add github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects and github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts --- .../objectstorage/v1/accounts/doc.go | 8 + .../objectstorage/v1/accounts/requests.go | 100 ++++ .../objectstorage/v1/accounts/results.go | 160 +++++++ .../objectstorage/v1/accounts/urls.go | 11 + .../openstack/objectstorage/v1/objects/doc.go | 5 + .../objectstorage/v1/objects/errors.go | 13 + .../objectstorage/v1/objects/requests.go | 453 ++++++++++++++++++ .../objectstorage/v1/objects/results.go | 441 +++++++++++++++++ .../objectstorage/v1/objects/urls.go | 33 ++ vendor/vendor.json | 12 + 10 files changed, 1236 insertions(+) create mode 100644 vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts/doc.go create mode 100644 vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts/requests.go create mode 100644 vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts/results.go create mode 100644 vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts/urls.go create mode 100644 vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/doc.go create mode 100644 vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/errors.go create mode 100644 vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/requests.go create mode 100644 vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/results.go create mode 100644 vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/urls.go diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts/doc.go b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts/doc.go new file mode 100644 index 000000000..f5f894a9e --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts/doc.go @@ -0,0 +1,8 @@ +// Package accounts contains functionality for working with Object Storage +// account resources. An account is the top-level resource the object storage +// hierarchy: containers belong to accounts, objects belong to containers. +// +// Another way of thinking of an account is like a namespace for all your +// resources. It is synonymous with a project or tenant in other OpenStack +// services. +package accounts diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts/requests.go new file mode 100644 index 000000000..b5beef28b --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts/requests.go @@ -0,0 +1,100 @@ +package accounts + +import "github.com/gophercloud/gophercloud" + +// GetOptsBuilder allows extensions to add additional headers to the Get +// request. +type GetOptsBuilder interface { + ToAccountGetMap() (map[string]string, error) +} + +// GetOpts is a structure that contains parameters for getting an account's +// metadata. +type GetOpts struct { + Newest bool `h:"X-Newest"` +} + +// ToAccountGetMap formats a GetOpts into a map[string]string of headers. +func (opts GetOpts) ToAccountGetMap() (map[string]string, error) { + return gophercloud.BuildHeaders(opts) +} + +// Get is a function that retrieves an account's metadata. To extract just the +// custom metadata, call the ExtractMetadata method on the GetResult. To extract +// all the headers that are returned (including the metadata), call the +// ExtractHeader method on the GetResult. +func Get(c *gophercloud.ServiceClient, opts GetOptsBuilder) (r GetResult) { + h := make(map[string]string) + if opts != nil { + headers, err := opts.ToAccountGetMap() + if err != nil { + r.Err = err + return + } + for k, v := range headers { + h[k] = v + } + } + resp, err := c.Request("HEAD", getURL(c), &gophercloud.RequestOpts{ + MoreHeaders: h, + OkCodes: []int{204}, + }) + if resp != nil { + r.Header = resp.Header + } + r.Err = err + return +} + +// UpdateOptsBuilder allows extensions to add additional headers to the Update +// request. +type UpdateOptsBuilder interface { + ToAccountUpdateMap() (map[string]string, error) +} + +// UpdateOpts is a structure that contains parameters for updating, creating, or +// deleting an account's metadata. +type UpdateOpts struct { + Metadata map[string]string + ContentType string `h:"Content-Type"` + DetectContentType bool `h:"X-Detect-Content-Type"` + TempURLKey string `h:"X-Account-Meta-Temp-URL-Key"` + TempURLKey2 string `h:"X-Account-Meta-Temp-URL-Key-2"` +} + +// ToAccountUpdateMap formats an UpdateOpts into a map[string]string of headers. +func (opts UpdateOpts) ToAccountUpdateMap() (map[string]string, error) { + headers, err := gophercloud.BuildHeaders(opts) + if err != nil { + return nil, err + } + for k, v := range opts.Metadata { + headers["X-Account-Meta-"+k] = v + } + return headers, err +} + +// Update is a function that creates, updates, or deletes an account's metadata. +// To extract the headers returned, call the Extract method on the UpdateResult. +func Update(c *gophercloud.ServiceClient, opts UpdateOptsBuilder) (r UpdateResult) { + h := make(map[string]string) + if opts != nil { + headers, err := opts.ToAccountUpdateMap() + if err != nil { + r.Err = err + return + } + for k, v := range headers { + h[k] = v + } + } + resp, err := c.Request("POST", updateURL(c), &gophercloud.RequestOpts{ + MoreHeaders: h, + OkCodes: []int{201, 202, 204}, + }) + if resp != nil { + r.Header = resp.Header + } + r.Err = err + return +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts/results.go new file mode 100644 index 000000000..216414b74 --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts/results.go @@ -0,0 +1,160 @@ +package accounts + +import ( + "encoding/json" + "fmt" + "strconv" + "strings" + + "github.com/gophercloud/gophercloud" +) + +// UpdateResult is returned from a call to the Update function. +type UpdateResult struct { + gophercloud.HeaderResult +} + +// UpdateHeader represents the headers returned in the response from an Update request. +type UpdateHeader struct { + ContentLength int64 `json:"-"` + ContentType string `json:"Content-Type"` + TransID string `json:"X-Trans-Id"` + Date gophercloud.JSONRFC1123 `json:"Date"` +} + +func (h *UpdateHeader) UnmarshalJSON(b []byte) error { + type tmp UpdateHeader + var updateHeader *struct { + tmp + ContentLength string `json:"Content-Length"` + } + err := json.Unmarshal(b, &updateHeader) + if err != nil { + return err + } + + *h = UpdateHeader(updateHeader.tmp) + + switch updateHeader.ContentLength { + case "": + h.ContentLength = 0 + default: + h.ContentLength, err = strconv.ParseInt(updateHeader.ContentLength, 10, 64) + if err != nil { + return err + } + } + + return nil +} + +// Extract will return a struct of headers returned from a call to Get. To obtain +// a map of headers, call the ExtractHeader method on the GetResult. +func (ur UpdateResult) Extract() (*UpdateHeader, error) { + var uh *UpdateHeader + err := ur.ExtractInto(&uh) + return uh, err +} + +// GetHeader represents the headers returned in the response from a Get request. +type GetHeader struct { + BytesUsed int64 `json:"-"` + ContainerCount int64 `json:"-"` + ContentLength int64 `json:"-"` + ObjectCount int64 `json:"-"` + ContentType string `json:"Content-Type"` + TransID string `json:"X-Trans-Id"` + TempURLKey string `json:"X-Account-Meta-Temp-URL-Key"` + TempURLKey2 string `json:"X-Account-Meta-Temp-URL-Key-2"` + Date gophercloud.JSONRFC1123 `json:"Date"` +} + +func (h *GetHeader) UnmarshalJSON(b []byte) error { + type tmp GetHeader + var getHeader *struct { + tmp + BytesUsed string `json:"X-Account-Bytes-Used"` + ContentLength string `json:"Content-Length"` + ContainerCount string `json:"X-Account-Container-Count"` + ObjectCount string `json:"X-Account-Object-Count"` + } + err := json.Unmarshal(b, &getHeader) + if err != nil { + return err + } + + *h = GetHeader(getHeader.tmp) + + switch getHeader.BytesUsed { + case "": + h.BytesUsed = 0 + default: + h.BytesUsed, err = strconv.ParseInt(getHeader.BytesUsed, 10, 64) + if err != nil { + return err + } + } + + fmt.Println("getHeader: ", getHeader.ContentLength) + switch getHeader.ContentLength { + case "": + h.ContentLength = 0 + default: + h.ContentLength, err = strconv.ParseInt(getHeader.ContentLength, 10, 64) + if err != nil { + return err + } + } + + switch getHeader.ObjectCount { + case "": + h.ObjectCount = 0 + default: + h.ObjectCount, err = strconv.ParseInt(getHeader.ObjectCount, 10, 64) + if err != nil { + return err + } + } + + switch getHeader.ContainerCount { + case "": + h.ContainerCount = 0 + default: + h.ContainerCount, err = strconv.ParseInt(getHeader.ContainerCount, 10, 64) + if err != nil { + return err + } + } + + return nil +} + +// GetResult is returned from a call to the Get function. +type GetResult struct { + gophercloud.HeaderResult +} + +// Extract will return a struct of headers returned from a call to Get. To obtain +// a map of headers, call the ExtractHeader method on the GetResult. +func (r GetResult) Extract() (*GetHeader, error) { + var s *GetHeader + err := r.ExtractInto(&s) + return s, err +} + +// ExtractMetadata is a function that takes a GetResult (of type *http.Response) +// and returns the custom metatdata associated with the account. +func (r GetResult) ExtractMetadata() (map[string]string, error) { + if r.Err != nil { + return nil, r.Err + } + + metadata := make(map[string]string) + for k, v := range r.Header { + if strings.HasPrefix(k, "X-Account-Meta-") { + key := strings.TrimPrefix(k, "X-Account-Meta-") + metadata[key] = v[0] + } + } + return metadata, nil +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts/urls.go b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts/urls.go new file mode 100644 index 000000000..71540b1da --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts/urls.go @@ -0,0 +1,11 @@ +package accounts + +import "github.com/gophercloud/gophercloud" + +func getURL(c *gophercloud.ServiceClient) string { + return c.Endpoint +} + +func updateURL(c *gophercloud.ServiceClient) string { + return getURL(c) +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/doc.go b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/doc.go new file mode 100644 index 000000000..30a9adde1 --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/doc.go @@ -0,0 +1,5 @@ +// Package objects contains functionality for working with Object Storage +// object resources. An object is a resource that represents and contains data +// - such as documents, images, and so on. You can also store custom metadata +// with an object. +package objects diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/errors.go b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/errors.go new file mode 100644 index 000000000..5c4ae44d3 --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/errors.go @@ -0,0 +1,13 @@ +package objects + +import "github.com/gophercloud/gophercloud" + +// ErrWrongChecksum is the error when the checksum generated for an object +// doesn't match the ETAG header. +type ErrWrongChecksum struct { + gophercloud.BaseError +} + +func (e ErrWrongChecksum) Error() string { + return "Local checksum does not match API ETag header" +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/requests.go new file mode 100644 index 000000000..0ab5e1711 --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/requests.go @@ -0,0 +1,453 @@ +package objects + +import ( + "bytes" + "crypto/hmac" + "crypto/md5" + "crypto/sha1" + "fmt" + "io" + "strings" + "time" + + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts" + "github.com/gophercloud/gophercloud/pagination" +) + +// ListOptsBuilder allows extensions to add additional parameters to the List +// request. +type ListOptsBuilder interface { + ToObjectListParams() (bool, string, error) +} + +// ListOpts is a structure that holds parameters for listing objects. +type ListOpts struct { + // Full is a true/false value that represents the amount of object information + // returned. If Full is set to true, then the content-type, number of bytes, hash + // date last modified, and name are returned. If set to false or not set, then + // only the object names are returned. + Full bool + Limit int `q:"limit"` + Marker string `q:"marker"` + EndMarker string `q:"end_marker"` + Format string `q:"format"` + Prefix string `q:"prefix"` + Delimiter string `q:"delimiter"` + Path string `q:"path"` +} + +// ToObjectListParams formats a ListOpts into a query string and boolean +// representing whether to list complete information for each object. +func (opts ListOpts) ToObjectListParams() (bool, string, error) { + q, err := gophercloud.BuildQueryString(opts) + return opts.Full, q.String(), err +} + +// List is a function that retrieves all objects in a container. It also returns the details +// for the container. To extract only the object information or names, pass the ListResult +// response to the ExtractInfo or ExtractNames function, respectively. +func List(c *gophercloud.ServiceClient, containerName string, opts ListOptsBuilder) pagination.Pager { + headers := map[string]string{"Accept": "text/plain", "Content-Type": "text/plain"} + + url := listURL(c, containerName) + if opts != nil { + full, query, err := opts.ToObjectListParams() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + + if full { + headers = map[string]string{"Accept": "application/json", "Content-Type": "application/json"} + } + } + + pager := pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page { + p := ObjectPage{pagination.MarkerPageBase{PageResult: r}} + p.MarkerPageBase.Owner = p + return p + }) + pager.Headers = headers + return pager +} + +// DownloadOptsBuilder allows extensions to add additional parameters to the +// Download request. +type DownloadOptsBuilder interface { + ToObjectDownloadParams() (map[string]string, string, error) +} + +// DownloadOpts is a structure that holds parameters for downloading an object. +type DownloadOpts struct { + IfMatch string `h:"If-Match"` + IfModifiedSince time.Time `h:"If-Modified-Since"` + IfNoneMatch string `h:"If-None-Match"` + IfUnmodifiedSince time.Time `h:"If-Unmodified-Since"` + Range string `h:"Range"` + Expires string `q:"expires"` + MultipartManifest string `q:"multipart-manifest"` + Signature string `q:"signature"` +} + +// ToObjectDownloadParams formats a DownloadOpts into a query string and map of +// headers. +func (opts DownloadOpts) ToObjectDownloadParams() (map[string]string, string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return nil, "", err + } + h, err := gophercloud.BuildHeaders(opts) + if err != nil { + return nil, q.String(), err + } + return h, q.String(), nil +} + +// Download is a function that retrieves the content and metadata for an object. +// To extract just the content, pass the DownloadResult response to the +// ExtractContent function. +func Download(c *gophercloud.ServiceClient, containerName, objectName string, opts DownloadOptsBuilder) (r DownloadResult) { + url := downloadURL(c, containerName, objectName) + h := make(map[string]string) + if opts != nil { + headers, query, err := opts.ToObjectDownloadParams() + if err != nil { + r.Err = err + return + } + for k, v := range headers { + h[k] = v + } + url += query + } + + resp, err := c.Get(url, nil, &gophercloud.RequestOpts{ + MoreHeaders: h, + OkCodes: []int{200, 304}, + }) + if resp != nil { + r.Header = resp.Header + r.Body = resp.Body + } + r.Err = err + return +} + +// CreateOptsBuilder allows extensions to add additional parameters to the +// Create request. +type CreateOptsBuilder interface { + ToObjectCreateParams() (io.Reader, map[string]string, string, error) +} + +// CreateOpts is a structure that holds parameters for creating an object. +type CreateOpts struct { + Content io.Reader + Metadata map[string]string + CacheControl string `h:"Cache-Control"` + ContentDisposition string `h:"Content-Disposition"` + ContentEncoding string `h:"Content-Encoding"` + ContentLength int64 `h:"Content-Length"` + ContentType string `h:"Content-Type"` + CopyFrom string `h:"X-Copy-From"` + DeleteAfter int `h:"X-Delete-After"` + DeleteAt int `h:"X-Delete-At"` + DetectContentType string `h:"X-Detect-Content-Type"` + ETag string `h:"ETag"` + IfNoneMatch string `h:"If-None-Match"` + ObjectManifest string `h:"X-Object-Manifest"` + TransferEncoding string `h:"Transfer-Encoding"` + Expires string `q:"expires"` + MultipartManifest string `q:"multipart-manifest"` + Signature string `q:"signature"` +} + +// ToObjectCreateParams formats a CreateOpts into a query string and map of +// headers. +func (opts CreateOpts) ToObjectCreateParams() (io.Reader, map[string]string, string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return nil, nil, "", err + } + h, err := gophercloud.BuildHeaders(opts) + if err != nil { + return nil, nil, "", err + } + + for k, v := range opts.Metadata { + h["X-Object-Meta-"+k] = v + } + + hash := md5.New() + buf := bytes.NewBuffer([]byte{}) + _, err = io.Copy(io.MultiWriter(hash, buf), opts.Content) + if err != nil { + return nil, nil, "", err + } + localChecksum := fmt.Sprintf("%x", hash.Sum(nil)) + h["ETag"] = localChecksum + + return buf, h, q.String(), nil +} + +// Create is a function that creates a new object or replaces an existing object. If the returned response's ETag +// header fails to match the local checksum, the failed request will automatically be retried up to a maximum of 3 times. +func Create(c *gophercloud.ServiceClient, containerName, objectName string, opts CreateOptsBuilder) (r CreateResult) { + url := createURL(c, containerName, objectName) + h := make(map[string]string) + var b io.Reader + if opts != nil { + tmpB, headers, query, err := opts.ToObjectCreateParams() + if err != nil { + r.Err = err + return + } + for k, v := range headers { + h[k] = v + } + url += query + b = tmpB + } + + resp, err := c.Put(url, nil, nil, &gophercloud.RequestOpts{ + RawBody: b, + MoreHeaders: h, + }) + r.Err = err + if resp != nil { + r.Header = resp.Header + } + return +} + +// CopyOptsBuilder allows extensions to add additional parameters to the +// Copy request. +type CopyOptsBuilder interface { + ToObjectCopyMap() (map[string]string, error) +} + +// CopyOpts is a structure that holds parameters for copying one object to +// another. +type CopyOpts struct { + Metadata map[string]string + ContentDisposition string `h:"Content-Disposition"` + ContentEncoding string `h:"Content-Encoding"` + ContentType string `h:"Content-Type"` + Destination string `h:"Destination" required:"true"` +} + +// ToObjectCopyMap formats a CopyOpts into a map of headers. +func (opts CopyOpts) ToObjectCopyMap() (map[string]string, error) { + h, err := gophercloud.BuildHeaders(opts) + if err != nil { + return nil, err + } + for k, v := range opts.Metadata { + h["X-Object-Meta-"+k] = v + } + return h, nil +} + +// Copy is a function that copies one object to another. +func Copy(c *gophercloud.ServiceClient, containerName, objectName string, opts CopyOptsBuilder) (r CopyResult) { + h := make(map[string]string) + headers, err := opts.ToObjectCopyMap() + if err != nil { + r.Err = err + return + } + + for k, v := range headers { + h[k] = v + } + + url := copyURL(c, containerName, objectName) + resp, err := c.Request("COPY", url, &gophercloud.RequestOpts{ + MoreHeaders: h, + OkCodes: []int{201}, + }) + if resp != nil { + r.Header = resp.Header + } + r.Err = err + return +} + +// DeleteOptsBuilder allows extensions to add additional parameters to the +// Delete request. +type DeleteOptsBuilder interface { + ToObjectDeleteQuery() (string, error) +} + +// DeleteOpts is a structure that holds parameters for deleting an object. +type DeleteOpts struct { + MultipartManifest string `q:"multipart-manifest"` +} + +// ToObjectDeleteQuery formats a DeleteOpts into a query string. +func (opts DeleteOpts) ToObjectDeleteQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + return q.String(), err +} + +// Delete is a function that deletes an object. +func Delete(c *gophercloud.ServiceClient, containerName, objectName string, opts DeleteOptsBuilder) (r DeleteResult) { + url := deleteURL(c, containerName, objectName) + if opts != nil { + query, err := opts.ToObjectDeleteQuery() + if err != nil { + r.Err = err + return + } + url += query + } + resp, err := c.Delete(url, nil) + if resp != nil { + r.Header = resp.Header + } + r.Err = err + return +} + +// GetOptsBuilder allows extensions to add additional parameters to the +// Get request. +type GetOptsBuilder interface { + ToObjectGetQuery() (string, error) +} + +// GetOpts is a structure that holds parameters for getting an object's metadata. +type GetOpts struct { + Expires string `q:"expires"` + Signature string `q:"signature"` +} + +// ToObjectGetQuery formats a GetOpts into a query string. +func (opts GetOpts) ToObjectGetQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + return q.String(), err +} + +// Get is a function that retrieves the metadata of an object. To extract just the custom +// metadata, pass the GetResult response to the ExtractMetadata function. +func Get(c *gophercloud.ServiceClient, containerName, objectName string, opts GetOptsBuilder) (r GetResult) { + url := getURL(c, containerName, objectName) + if opts != nil { + query, err := opts.ToObjectGetQuery() + if err != nil { + r.Err = err + return + } + url += query + } + resp, err := c.Request("HEAD", url, &gophercloud.RequestOpts{ + OkCodes: []int{200, 204}, + }) + if resp != nil { + r.Header = resp.Header + } + r.Err = err + return +} + +// UpdateOptsBuilder allows extensions to add additional parameters to the +// Update request. +type UpdateOptsBuilder interface { + ToObjectUpdateMap() (map[string]string, error) +} + +// UpdateOpts is a structure that holds parameters for updating, creating, or deleting an +// object's metadata. +type UpdateOpts struct { + Metadata map[string]string + ContentDisposition string `h:"Content-Disposition"` + ContentEncoding string `h:"Content-Encoding"` + ContentType string `h:"Content-Type"` + DeleteAfter int `h:"X-Delete-After"` + DeleteAt int `h:"X-Delete-At"` + DetectContentType bool `h:"X-Detect-Content-Type"` +} + +// ToObjectUpdateMap formats a UpdateOpts into a map of headers. +func (opts UpdateOpts) ToObjectUpdateMap() (map[string]string, error) { + h, err := gophercloud.BuildHeaders(opts) + if err != nil { + return nil, err + } + for k, v := range opts.Metadata { + h["X-Object-Meta-"+k] = v + } + return h, nil +} + +// Update is a function that creates, updates, or deletes an object's metadata. +func Update(c *gophercloud.ServiceClient, containerName, objectName string, opts UpdateOptsBuilder) (r UpdateResult) { + h := make(map[string]string) + if opts != nil { + headers, err := opts.ToObjectUpdateMap() + if err != nil { + r.Err = err + return + } + + for k, v := range headers { + h[k] = v + } + } + url := updateURL(c, containerName, objectName) + resp, err := c.Post(url, nil, nil, &gophercloud.RequestOpts{ + MoreHeaders: h, + }) + if resp != nil { + r.Header = resp.Header + } + r.Err = err + return +} + +// HTTPMethod represents an HTTP method string (e.g. "GET"). +type HTTPMethod string + +var ( + // GET represents an HTTP "GET" method. + GET HTTPMethod = "GET" + // POST represents an HTTP "POST" method. + POST HTTPMethod = "POST" +) + +// CreateTempURLOpts are options for creating a temporary URL for an object. +type CreateTempURLOpts struct { + // (REQUIRED) Method is the HTTP method to allow for users of the temp URL. Valid values + // are "GET" and "POST". + Method HTTPMethod + // (REQUIRED) TTL is the number of seconds the temp URL should be active. + TTL int + // (Optional) Split is the string on which to split the object URL. Since only + // the object path is used in the hash, the object URL needs to be parsed. If + // empty, the default OpenStack URL split point will be used ("/v1/"). + Split string +} + +// CreateTempURL is a function for creating a temporary URL for an object. It +// allows users to have "GET" or "POST" access to a particular tenant's object +// for a limited amount of time. +func CreateTempURL(c *gophercloud.ServiceClient, containerName, objectName string, opts CreateTempURLOpts) (string, error) { + if opts.Split == "" { + opts.Split = "/v1/" + } + duration := time.Duration(opts.TTL) * time.Second + expiry := time.Now().Add(duration).Unix() + getHeader, err := accounts.Get(c, nil).Extract() + if err != nil { + return "", err + } + secretKey := []byte(getHeader.TempURLKey) + url := getURL(c, containerName, objectName) + splitPath := strings.Split(url, opts.Split) + baseURL, objectPath := splitPath[0], splitPath[1] + objectPath = opts.Split + objectPath + body := fmt.Sprintf("%s\n%d\n%s", opts.Method, expiry, objectPath) + hash := hmac.New(sha1.New, secretKey) + hash.Write([]byte(body)) + hexsum := fmt.Sprintf("%x", hash.Sum(nil)) + return fmt.Sprintf("%s%s?temp_url_sig=%s&temp_url_expires=%d", baseURL, objectPath, hexsum, expiry), nil +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/results.go new file mode 100644 index 000000000..4f7020cfd --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/results.go @@ -0,0 +1,441 @@ +package objects + +import ( + "encoding/json" + "fmt" + "io" + "io/ioutil" + "strconv" + "strings" + + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/pagination" +) + +// Object is a structure that holds information related to a storage object. +type Object struct { + // Bytes is the total number of bytes that comprise the object. + Bytes int64 `json:"bytes"` + + // ContentType is the content type of the object. + ContentType string `json:"content_type"` + + // Hash represents the MD5 checksum value of the object's content. + Hash string `json:"hash"` + + // LastModified is the RFC3339Milli time the object was last modified, represented + // as a string. For any given object (obj), this value may be parsed to a time.Time: + // lastModified, err := time.Parse(gophercloud.RFC3339Milli, obj.LastModified) + LastModified gophercloud.JSONRFC3339MilliNoZ `json:"last_modified"` + + // Name is the unique name for the object. + Name string `json:"name"` +} + +// ObjectPage is a single page of objects that is returned from a call to the +// List function. +type ObjectPage struct { + pagination.MarkerPageBase +} + +// IsEmpty returns true if a ListResult contains no object names. +func (r ObjectPage) IsEmpty() (bool, error) { + names, err := ExtractNames(r) + return len(names) == 0, err +} + +// LastMarker returns the last object name in a ListResult. +func (r ObjectPage) LastMarker() (string, error) { + names, err := ExtractNames(r) + if err != nil { + return "", err + } + if len(names) == 0 { + return "", nil + } + return names[len(names)-1], nil +} + +// ExtractInfo is a function that takes a page of objects and returns their full information. +func ExtractInfo(r pagination.Page) ([]Object, error) { + var s []Object + err := (r.(ObjectPage)).ExtractInto(&s) + return s, err +} + +// ExtractNames is a function that takes a page of objects and returns only their names. +func ExtractNames(r pagination.Page) ([]string, error) { + casted := r.(ObjectPage) + ct := casted.Header.Get("Content-Type") + switch { + case strings.HasPrefix(ct, "application/json"): + parsed, err := ExtractInfo(r) + if err != nil { + return nil, err + } + + names := make([]string, 0, len(parsed)) + for _, object := range parsed { + names = append(names, object.Name) + } + + return names, nil + case strings.HasPrefix(ct, "text/plain"): + names := make([]string, 0, 50) + + body := string(r.(ObjectPage).Body.([]uint8)) + for _, name := range strings.Split(body, "\n") { + if len(name) > 0 { + names = append(names, name) + } + } + + return names, nil + case strings.HasPrefix(ct, "text/html"): + return []string{}, nil + default: + return nil, fmt.Errorf("Cannot extract names from response with content-type: [%s]", ct) + } +} + +// DownloadHeader represents the headers returned in the response from a Download request. +type DownloadHeader struct { + AcceptRanges string `json:"Accept-Ranges"` + ContentDisposition string `json:"Content-Disposition"` + ContentEncoding string `json:"Content-Encoding"` + ContentLength int64 `json:"-"` + ContentType string `json:"Content-Type"` + Date gophercloud.JSONRFC1123 `json:"Date"` + DeleteAt gophercloud.JSONUnix `json:"X-Delete-At"` + ETag string `json:"Etag"` + LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"` + ObjectManifest string `json:"X-Object-Manifest"` + StaticLargeObject bool `json:"X-Static-Large-Object"` + TransID string `json:"X-Trans-Id"` +} + +func (h *DownloadHeader) UnmarshalJSON(b []byte) error { + type tmp DownloadHeader + var hTmp *struct { + tmp + ContentLength string `json:"Content-Length"` + } + err := json.Unmarshal(b, &hTmp) + if err != nil { + return err + } + + *h = DownloadHeader(hTmp.tmp) + + switch hTmp.ContentLength { + case "": + h.ContentLength = 0 + default: + h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64) + if err != nil { + return err + } + } + + return nil +} + +// DownloadResult is a *http.Response that is returned from a call to the Download function. +type DownloadResult struct { + gophercloud.HeaderResult + Body io.ReadCloser +} + +// Extract will return a struct of headers returned from a call to Download. To obtain +// a map of headers, call the ExtractHeader method on the DownloadResult. +func (r DownloadResult) Extract() (*DownloadHeader, error) { + var s *DownloadHeader + err := r.ExtractInto(&s) + return s, err +} + +// ExtractContent is a function that takes a DownloadResult's io.Reader body +// and reads all available data into a slice of bytes. Please be aware that due +// the nature of io.Reader is forward-only - meaning that it can only be read +// once and not rewound. You can recreate a reader from the output of this +// function by using bytes.NewReader(downloadBytes) +func (r *DownloadResult) ExtractContent() ([]byte, error) { + if r.Err != nil { + return nil, r.Err + } + defer r.Body.Close() + body, err := ioutil.ReadAll(r.Body) + if err != nil { + return nil, err + } + r.Body.Close() + return body, nil +} + +// GetHeader represents the headers returned in the response from a Get request. +type GetHeader struct { + ContentDisposition string `json:"Content-Disposition"` + ContentEncoding string `json:"Content-Encoding"` + ContentLength int64 `json:"Content-Length"` + ContentType string `json:"Content-Type"` + Date gophercloud.JSONRFC1123 `json:"Date"` + DeleteAt gophercloud.JSONUnix `json:"X-Delete-At"` + ETag string `json:"Etag"` + LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"` + ObjectManifest string `json:"X-Object-Manifest"` + StaticLargeObject bool `json:"X-Static-Large-Object"` + TransID string `json:"X-Trans-Id"` +} + +func (h *GetHeader) UnmarshalJSON(b []byte) error { + type tmp GetHeader + var hTmp *struct { + tmp + ContentLength string `json:"Content-Length"` + } + err := json.Unmarshal(b, &hTmp) + if err != nil { + return err + } + + *h = GetHeader(hTmp.tmp) + + switch hTmp.ContentLength { + case "": + h.ContentLength = 0 + default: + h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64) + if err != nil { + return err + } + } + + return nil +} + +// GetResult is a *http.Response that is returned from a call to the Get function. +type GetResult struct { + gophercloud.HeaderResult +} + +// Extract will return a struct of headers returned from a call to Get. To obtain +// a map of headers, call the ExtractHeader method on the GetResult. +func (r GetResult) Extract() (*GetHeader, error) { + var s *GetHeader + err := r.ExtractInto(&s) + return s, err +} + +// ExtractMetadata is a function that takes a GetResult (of type *http.Response) +// and returns the custom metadata associated with the object. +func (r GetResult) ExtractMetadata() (map[string]string, error) { + if r.Err != nil { + return nil, r.Err + } + metadata := make(map[string]string) + for k, v := range r.Header { + if strings.HasPrefix(k, "X-Object-Meta-") { + key := strings.TrimPrefix(k, "X-Object-Meta-") + metadata[key] = v[0] + } + } + return metadata, nil +} + +// CreateHeader represents the headers returned in the response from a Create request. +type CreateHeader struct { + ContentLength int64 `json:"Content-Length"` + ContentType string `json:"Content-Type"` + Date gophercloud.JSONRFC1123 `json:"Date"` + ETag string `json:"Etag"` + LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"` + TransID string `json:"X-Trans-Id"` +} + +func (h *CreateHeader) UnmarshalJSON(b []byte) error { + type tmp CreateHeader + var hTmp *struct { + tmp + ContentLength string `json:"Content-Length"` + } + err := json.Unmarshal(b, &hTmp) + if err != nil { + return err + } + + *h = CreateHeader(hTmp.tmp) + + switch hTmp.ContentLength { + case "": + h.ContentLength = 0 + default: + h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64) + if err != nil { + return err + } + } + + return nil +} + +// CreateResult represents the result of a create operation. +type CreateResult struct { + checksum string + gophercloud.HeaderResult +} + +// Extract will return a struct of headers returned from a call to Create. To obtain +// a map of headers, call the ExtractHeader method on the CreateResult. +func (r CreateResult) Extract() (*CreateHeader, error) { + //if r.Header.Get("ETag") != fmt.Sprintf("%x", localChecksum) { + // return nil, ErrWrongChecksum{} + //} + var s *CreateHeader + err := r.ExtractInto(&s) + return s, err +} + +// UpdateHeader represents the headers returned in the response from a Update request. +type UpdateHeader struct { + ContentLength int64 `json:"Content-Length"` + ContentType string `json:"Content-Type"` + Date gophercloud.JSONRFC1123 `json:"Date"` + TransID string `json:"X-Trans-Id"` +} + +func (h *UpdateHeader) UnmarshalJSON(b []byte) error { + type tmp UpdateHeader + var hTmp *struct { + tmp + ContentLength string `json:"Content-Length"` + } + err := json.Unmarshal(b, &hTmp) + if err != nil { + return err + } + + *h = UpdateHeader(hTmp.tmp) + + switch hTmp.ContentLength { + case "": + h.ContentLength = 0 + default: + h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64) + if err != nil { + return err + } + } + + return nil +} + +// UpdateResult represents the result of an update operation. +type UpdateResult struct { + gophercloud.HeaderResult +} + +// Extract will return a struct of headers returned from a call to Update. To obtain +// a map of headers, call the ExtractHeader method on the UpdateResult. +func (r UpdateResult) Extract() (*UpdateHeader, error) { + var s *UpdateHeader + err := r.ExtractInto(&s) + return s, err +} + +// DeleteHeader represents the headers returned in the response from a Delete request. +type DeleteHeader struct { + ContentLength int64 `json:"Content-Length"` + ContentType string `json:"Content-Type"` + Date gophercloud.JSONRFC1123 `json:"Date"` + TransID string `json:"X-Trans-Id"` +} + +func (h *DeleteHeader) UnmarshalJSON(b []byte) error { + type tmp DeleteHeader + var hTmp *struct { + tmp + ContentLength string `json:"Content-Length"` + } + err := json.Unmarshal(b, &hTmp) + if err != nil { + return err + } + + *h = DeleteHeader(hTmp.tmp) + + switch hTmp.ContentLength { + case "": + h.ContentLength = 0 + default: + h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64) + if err != nil { + return err + } + } + + return nil +} + +// DeleteResult represents the result of a delete operation. +type DeleteResult struct { + gophercloud.HeaderResult +} + +// Extract will return a struct of headers returned from a call to Delete. To obtain +// a map of headers, call the ExtractHeader method on the DeleteResult. +func (r DeleteResult) Extract() (*DeleteHeader, error) { + var s *DeleteHeader + err := r.ExtractInto(&s) + return s, err +} + +// CopyHeader represents the headers returned in the response from a Copy request. +type CopyHeader struct { + ContentLength int64 `json:"Content-Length"` + ContentType string `json:"Content-Type"` + CopiedFrom string `json:"X-Copied-From"` + CopiedFromLastModified gophercloud.JSONRFC1123 `json:"X-Copied-From-Last-Modified"` + Date gophercloud.JSONRFC1123 `json:"Date"` + ETag string `json:"Etag"` + LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"` + TransID string `json:"X-Trans-Id"` +} + +func (h *CopyHeader) UnmarshalJSON(b []byte) error { + type tmp CopyHeader + var hTmp *struct { + tmp + ContentLength string `json:"Content-Length"` + } + err := json.Unmarshal(b, &hTmp) + if err != nil { + return err + } + + *h = CopyHeader(hTmp.tmp) + + switch hTmp.ContentLength { + case "": + h.ContentLength = 0 + default: + h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64) + if err != nil { + return err + } + } + + return nil +} + +// CopyResult represents the result of a copy operation. +type CopyResult struct { + gophercloud.HeaderResult +} + +// Extract will return a struct of headers returned from a call to Copy. To obtain +// a map of headers, call the ExtractHeader method on the CopyResult. +func (r CopyResult) Extract() (*CopyHeader, error) { + var s *CopyHeader + err := r.ExtractInto(&s) + return s, err +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/urls.go b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/urls.go new file mode 100644 index 000000000..b3ac304b7 --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/urls.go @@ -0,0 +1,33 @@ +package objects + +import ( + "github.com/gophercloud/gophercloud" +) + +func listURL(c *gophercloud.ServiceClient, container string) string { + return c.ServiceURL(container) +} + +func copyURL(c *gophercloud.ServiceClient, container, object string) string { + return c.ServiceURL(container, object) +} + +func createURL(c *gophercloud.ServiceClient, container, object string) string { + return copyURL(c, container, object) +} + +func getURL(c *gophercloud.ServiceClient, container, object string) string { + return copyURL(c, container, object) +} + +func deleteURL(c *gophercloud.ServiceClient, container, object string) string { + return copyURL(c, container, object) +} + +func downloadURL(c *gophercloud.ServiceClient, container, object string) string { + return copyURL(c, container, object) +} + +func updateURL(c *gophercloud.ServiceClient, container, object string) string { + return copyURL(c, container, object) +} diff --git a/vendor/vendor.json b/vendor/vendor.json index 43db85910..d04367d3f 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -1183,12 +1183,24 @@ "revision": "e3d6384a3714b335d075862e6eb0a681180643df", "revisionTime": "2016-10-25T18:03:21Z" }, + { + "checksumSHA1": "yIerdfSMJRUnjh2EZikMhWcgwlY=", + "path": "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts", + "revision": "45720eeefeeeba03b2d7da500297ec68eeee51af", + "revisionTime": "2016-10-31T15:28:56Z" + }, { "checksumSHA1": "5XMyCSYDLmv/b54K3HNNNCJdnBk=", "path": "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers", "revision": "e3d6384a3714b335d075862e6eb0a681180643df", "revisionTime": "2016-10-25T18:03:21Z" }, + { + "checksumSHA1": "CRiIA3oRRlKRDF2ZYnZT8rTlJBU=", + "path": "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects", + "revision": "45720eeefeeeba03b2d7da500297ec68eeee51af", + "revisionTime": "2016-10-31T15:28:56Z" + }, { "checksumSHA1": "TDOZnaS0TO0NirpxV1QwPerAQTY=", "path": "github.com/gophercloud/gophercloud/openstack/utils",