Move deps from _workspace/ to vendor/
godep restore pushd $GOPATH/src/github.com/appc/spec git co master popd go get go4.org/errorutil rm -rf Godeps godep save ./... git add vendor git add -f $(git ls-files --other vendor/) git co -- Godeps/LICENSES Godeps/.license_file_state Godeps/OWNERS
This commit is contained in:
8
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/doc.go
generated
vendored
Normal file
8
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/doc.go
generated
vendored
Normal file
@@ -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
|
||||
38
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/fixtures.go
generated
vendored
Normal file
38
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/fixtures.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
// +build fixtures
|
||||
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
fake "github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
// HandleGetAccountSuccessfully creates an HTTP handler at `/` on the test handler mux that
|
||||
// responds with a `Get` response.
|
||||
func HandleGetAccountSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "HEAD")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
w.Header().Set("X-Account-Container-Count", "2")
|
||||
w.Header().Set("X-Account-Bytes-Used", "14")
|
||||
w.Header().Set("X-Account-Meta-Subject", "books")
|
||||
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleUpdateAccountSuccessfully creates an HTTP handler at `/` on the test handler mux that
|
||||
// responds with a `Update` response.
|
||||
func HandleUpdateAccountSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "POST")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
th.TestHeader(t, r, "X-Account-Meta-Gophercloud-Test", "accounts")
|
||||
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
})
|
||||
}
|
||||
107
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/requests.go
generated
vendored
Normal file
107
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/requests.go
generated
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
package accounts
|
||||
|
||||
import "github.com/rackspace/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) GetResult {
|
||||
var res GetResult
|
||||
h := c.AuthenticatedHeaders()
|
||||
|
||||
if opts != nil {
|
||||
headers, err := opts.ToAccountGetMap()
|
||||
if err != nil {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
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 {
|
||||
res.Header = resp.Header
|
||||
}
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
// 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) UpdateResult {
|
||||
var res UpdateResult
|
||||
h := make(map[string]string)
|
||||
|
||||
if opts != nil {
|
||||
headers, err := opts.ToAccountUpdateMap()
|
||||
if err != nil {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
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 {
|
||||
res.Header = resp.Header
|
||||
}
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
102
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/results.go
generated
vendored
Normal file
102
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/results.go
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/rackspace/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 string `mapstructure:"Content-Length"`
|
||||
ContentType string `mapstructure:"Content-Type"`
|
||||
Date time.Time `mapstructure:"-"`
|
||||
TransID string `mapstructure:"X-Trans-Id"`
|
||||
}
|
||||
|
||||
// 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
|
||||
if ur.Err != nil {
|
||||
return uh, ur.Err
|
||||
}
|
||||
|
||||
if err := gophercloud.DecodeHeader(ur.Header, &uh); err != nil {
|
||||
return uh, err
|
||||
}
|
||||
|
||||
if date, ok := ur.Header["Date"]; ok && len(date) > 0 {
|
||||
t, err := time.Parse(time.RFC1123, ur.Header["Date"][0])
|
||||
if err != nil {
|
||||
return uh, err
|
||||
}
|
||||
uh.Date = t
|
||||
}
|
||||
|
||||
return uh, nil
|
||||
}
|
||||
|
||||
// GetHeader represents the headers returned in the response from a Get request.
|
||||
type GetHeader struct {
|
||||
BytesUsed int64 `mapstructure:"X-Account-Bytes-Used"`
|
||||
ContainerCount int `mapstructure:"X-Account-Container-Count"`
|
||||
ContentLength int64 `mapstructure:"Content-Length"`
|
||||
ContentType string `mapstructure:"Content-Type"`
|
||||
Date time.Time `mapstructure:"-"`
|
||||
ObjectCount int64 `mapstructure:"X-Account-Object-Count"`
|
||||
TransID string `mapstructure:"X-Trans-Id"`
|
||||
TempURLKey string `mapstructure:"X-Account-Meta-Temp-URL-Key"`
|
||||
TempURLKey2 string `mapstructure:"X-Account-Meta-Temp-URL-Key-2"`
|
||||
}
|
||||
|
||||
// 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 (gr GetResult) Extract() (GetHeader, error) {
|
||||
var gh GetHeader
|
||||
if gr.Err != nil {
|
||||
return gh, gr.Err
|
||||
}
|
||||
|
||||
if err := gophercloud.DecodeHeader(gr.Header, &gh); err != nil {
|
||||
return gh, err
|
||||
}
|
||||
|
||||
if date, ok := gr.Header["Date"]; ok && len(date) > 0 {
|
||||
t, err := time.Parse(time.RFC1123, gr.Header["Date"][0])
|
||||
if err != nil {
|
||||
return gh, err
|
||||
}
|
||||
gh.Date = t
|
||||
}
|
||||
|
||||
return gh, nil
|
||||
}
|
||||
|
||||
// ExtractMetadata is a function that takes a GetResult (of type *http.Response)
|
||||
// and returns the custom metatdata associated with the account.
|
||||
func (gr GetResult) ExtractMetadata() (map[string]string, error) {
|
||||
if gr.Err != nil {
|
||||
return nil, gr.Err
|
||||
}
|
||||
|
||||
metadata := make(map[string]string)
|
||||
for k, v := range gr.Header {
|
||||
if strings.HasPrefix(k, "X-Account-Meta-") {
|
||||
key := strings.TrimPrefix(k, "X-Account-Meta-")
|
||||
metadata[key] = v[0]
|
||||
}
|
||||
}
|
||||
return metadata, nil
|
||||
}
|
||||
11
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/urls.go
generated
vendored
Normal file
11
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts/urls.go
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
package accounts
|
||||
|
||||
import "github.com/rackspace/gophercloud"
|
||||
|
||||
func getURL(c *gophercloud.ServiceClient) string {
|
||||
return c.Endpoint
|
||||
}
|
||||
|
||||
func updateURL(c *gophercloud.ServiceClient) string {
|
||||
return getURL(c)
|
||||
}
|
||||
8
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/doc.go
generated
vendored
Normal file
8
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/doc.go
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
// Package containers contains functionality for working with Object Storage
|
||||
// container resources. A container serves as a logical namespace for objects
|
||||
// that are placed inside it - an object with the same name in two different
|
||||
// containers represents two different objects.
|
||||
//
|
||||
// In addition to containing objects, you can also use the container to control
|
||||
// access to objects by using an access control list (ACL).
|
||||
package containers
|
||||
143
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/fixtures.go
generated
vendored
Normal file
143
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/fixtures.go
generated
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
// +build fixtures
|
||||
|
||||
package containers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
fake "github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
// ExpectedListInfo is the result expected from a call to `List` when full
|
||||
// info is requested.
|
||||
var ExpectedListInfo = []Container{
|
||||
Container{
|
||||
Count: 0,
|
||||
Bytes: 0,
|
||||
Name: "janeausten",
|
||||
},
|
||||
Container{
|
||||
Count: 1,
|
||||
Bytes: 14,
|
||||
Name: "marktwain",
|
||||
},
|
||||
}
|
||||
|
||||
// ExpectedListNames is the result expected from a call to `List` when just
|
||||
// container names are requested.
|
||||
var ExpectedListNames = []string{"janeausten", "marktwain"}
|
||||
|
||||
// HandleListContainerInfoSuccessfully creates an HTTP handler at `/` on the test handler mux that
|
||||
// responds with a `List` response when full info is requested.
|
||||
func HandleListContainerInfoSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
th.TestHeader(t, r, "Accept", "application/json")
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
r.ParseForm()
|
||||
marker := r.Form.Get("marker")
|
||||
switch marker {
|
||||
case "":
|
||||
fmt.Fprintf(w, `[
|
||||
{
|
||||
"count": 0,
|
||||
"bytes": 0,
|
||||
"name": "janeausten"
|
||||
},
|
||||
{
|
||||
"count": 1,
|
||||
"bytes": 14,
|
||||
"name": "marktwain"
|
||||
}
|
||||
]`)
|
||||
case "janeausten":
|
||||
fmt.Fprintf(w, `[
|
||||
{
|
||||
"count": 1,
|
||||
"bytes": 14,
|
||||
"name": "marktwain"
|
||||
}
|
||||
]`)
|
||||
case "marktwain":
|
||||
fmt.Fprintf(w, `[]`)
|
||||
default:
|
||||
t.Fatalf("Unexpected marker: [%s]", marker)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// HandleListContainerNamesSuccessfully creates an HTTP handler at `/` on the test handler mux that
|
||||
// responds with a `ListNames` response when only container names are requested.
|
||||
func HandleListContainerNamesSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
th.TestHeader(t, r, "Accept", "text/plain")
|
||||
|
||||
w.Header().Set("Content-Type", "text/plain")
|
||||
r.ParseForm()
|
||||
marker := r.Form.Get("marker")
|
||||
switch marker {
|
||||
case "":
|
||||
fmt.Fprintf(w, "janeausten\nmarktwain\n")
|
||||
case "janeausten":
|
||||
fmt.Fprintf(w, "marktwain\n")
|
||||
case "marktwain":
|
||||
fmt.Fprintf(w, ``)
|
||||
default:
|
||||
t.Fatalf("Unexpected marker: [%s]", marker)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// HandleCreateContainerSuccessfully creates an HTTP handler at `/testContainer` on the test handler mux that
|
||||
// responds with a `Create` response.
|
||||
func HandleCreateContainerSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/testContainer", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "PUT")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
th.TestHeader(t, r, "Accept", "application/json")
|
||||
|
||||
w.Header().Add("X-Container-Meta-Foo", "bar")
|
||||
w.Header().Add("X-Trans-Id", "1234567")
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleDeleteContainerSuccessfully creates an HTTP handler at `/testContainer` on the test handler mux that
|
||||
// responds with a `Delete` response.
|
||||
func HandleDeleteContainerSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/testContainer", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "DELETE")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
th.TestHeader(t, r, "Accept", "application/json")
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleUpdateContainerSuccessfully creates an HTTP handler at `/testContainer` on the test handler mux that
|
||||
// responds with a `Update` response.
|
||||
func HandleUpdateContainerSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/testContainer", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "POST")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
th.TestHeader(t, r, "Accept", "application/json")
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleGetContainerSuccessfully creates an HTTP handler at `/testContainer` on the test handler mux that
|
||||
// responds with a `Get` response.
|
||||
func HandleGetContainerSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/testContainer", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "HEAD")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
th.TestHeader(t, r, "Accept", "application/json")
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
})
|
||||
}
|
||||
205
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/requests.go
generated
vendored
Normal file
205
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/requests.go
generated
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
package containers
|
||||
|
||||
import (
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// ListOptsBuilder allows extensions to add additional parameters to the List
|
||||
// request.
|
||||
type ListOptsBuilder interface {
|
||||
ToContainerListParams() (bool, string, error)
|
||||
}
|
||||
|
||||
// ListOpts is a structure that holds options for listing containers.
|
||||
type ListOpts struct {
|
||||
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"`
|
||||
}
|
||||
|
||||
// ToContainerListParams formats a ListOpts into a query string and boolean
|
||||
// representing whether to list complete information for each container.
|
||||
func (opts ListOpts) ToContainerListParams() (bool, string, error) {
|
||||
q, err := gophercloud.BuildQueryString(opts)
|
||||
if err != nil {
|
||||
return false, "", err
|
||||
}
|
||||
return opts.Full, q.String(), nil
|
||||
}
|
||||
|
||||
// List is a function that retrieves containers associated with the account as
|
||||
// well as account metadata. It returns a pager which can be iterated with the
|
||||
// EachPage function.
|
||||
func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
|
||||
headers := map[string]string{"Accept": "text/plain", "Content-Type": "text/plain"}
|
||||
|
||||
url := listURL(c)
|
||||
if opts != nil {
|
||||
full, query, err := opts.ToContainerListParams()
|
||||
if err != nil {
|
||||
return pagination.Pager{Err: err}
|
||||
}
|
||||
url += query
|
||||
|
||||
if full {
|
||||
headers = map[string]string{"Accept": "application/json", "Content-Type": "application/json"}
|
||||
}
|
||||
}
|
||||
|
||||
createPage := func(r pagination.PageResult) pagination.Page {
|
||||
p := ContainerPage{pagination.MarkerPageBase{PageResult: r}}
|
||||
p.MarkerPageBase.Owner = p
|
||||
return p
|
||||
}
|
||||
|
||||
pager := pagination.NewPager(c, url, createPage)
|
||||
pager.Headers = headers
|
||||
return pager
|
||||
}
|
||||
|
||||
// CreateOptsBuilder allows extensions to add additional parameters to the
|
||||
// Create request.
|
||||
type CreateOptsBuilder interface {
|
||||
ToContainerCreateMap() (map[string]string, error)
|
||||
}
|
||||
|
||||
// CreateOpts is a structure that holds parameters for creating a container.
|
||||
type CreateOpts struct {
|
||||
Metadata map[string]string
|
||||
ContainerRead string `h:"X-Container-Read"`
|
||||
ContainerSyncTo string `h:"X-Container-Sync-To"`
|
||||
ContainerSyncKey string `h:"X-Container-Sync-Key"`
|
||||
ContainerWrite string `h:"X-Container-Write"`
|
||||
ContentType string `h:"Content-Type"`
|
||||
DetectContentType bool `h:"X-Detect-Content-Type"`
|
||||
IfNoneMatch string `h:"If-None-Match"`
|
||||
VersionsLocation string `h:"X-Versions-Location"`
|
||||
}
|
||||
|
||||
// ToContainerCreateMap formats a CreateOpts into a map of headers.
|
||||
func (opts CreateOpts) ToContainerCreateMap() (map[string]string, error) {
|
||||
h, err := gophercloud.BuildHeaders(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for k, v := range opts.Metadata {
|
||||
h["X-Container-Meta-"+k] = v
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// Create is a function that creates a new container.
|
||||
func Create(c *gophercloud.ServiceClient, containerName string, opts CreateOptsBuilder) CreateResult {
|
||||
var res CreateResult
|
||||
h := c.AuthenticatedHeaders()
|
||||
|
||||
if opts != nil {
|
||||
headers, err := opts.ToContainerCreateMap()
|
||||
if err != nil {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
for k, v := range headers {
|
||||
h[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := c.Request("PUT", createURL(c, containerName), gophercloud.RequestOpts{
|
||||
MoreHeaders: h,
|
||||
OkCodes: []int{201, 202, 204},
|
||||
})
|
||||
if resp != nil {
|
||||
res.Header = resp.Header
|
||||
}
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
// Delete is a function that deletes a container.
|
||||
func Delete(c *gophercloud.ServiceClient, containerName string) DeleteResult {
|
||||
var res DeleteResult
|
||||
_, res.Err = c.Delete(deleteURL(c, containerName), nil)
|
||||
return res
|
||||
}
|
||||
|
||||
// UpdateOptsBuilder allows extensions to add additional parameters to the
|
||||
// Update request.
|
||||
type UpdateOptsBuilder interface {
|
||||
ToContainerUpdateMap() (map[string]string, error)
|
||||
}
|
||||
|
||||
// UpdateOpts is a structure that holds parameters for updating, creating, or
|
||||
// deleting a container's metadata.
|
||||
type UpdateOpts struct {
|
||||
Metadata map[string]string
|
||||
ContainerRead string `h:"X-Container-Read"`
|
||||
ContainerSyncTo string `h:"X-Container-Sync-To"`
|
||||
ContainerSyncKey string `h:"X-Container-Sync-Key"`
|
||||
ContainerWrite string `h:"X-Container-Write"`
|
||||
ContentType string `h:"Content-Type"`
|
||||
DetectContentType bool `h:"X-Detect-Content-Type"`
|
||||
RemoveVersionsLocation string `h:"X-Remove-Versions-Location"`
|
||||
VersionsLocation string `h:"X-Versions-Location"`
|
||||
}
|
||||
|
||||
// ToContainerUpdateMap formats a CreateOpts into a map of headers.
|
||||
func (opts UpdateOpts) ToContainerUpdateMap() (map[string]string, error) {
|
||||
h, err := gophercloud.BuildHeaders(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for k, v := range opts.Metadata {
|
||||
h["X-Container-Meta-"+k] = v
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// Update is a function that creates, updates, or deletes a container's
|
||||
// metadata.
|
||||
func Update(c *gophercloud.ServiceClient, containerName string, opts UpdateOptsBuilder) UpdateResult {
|
||||
var res UpdateResult
|
||||
h := c.AuthenticatedHeaders()
|
||||
|
||||
if opts != nil {
|
||||
headers, err := opts.ToContainerUpdateMap()
|
||||
if err != nil {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
for k, v := range headers {
|
||||
h[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := c.Request("POST", updateURL(c, containerName), gophercloud.RequestOpts{
|
||||
MoreHeaders: h,
|
||||
OkCodes: []int{201, 202, 204},
|
||||
})
|
||||
if resp != nil {
|
||||
res.Header = resp.Header
|
||||
}
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
// Get is a function that retrieves the metadata of a container. To extract just
|
||||
// the custom metadata, pass the GetResult response to the ExtractMetadata
|
||||
// function.
|
||||
func Get(c *gophercloud.ServiceClient, containerName string) GetResult {
|
||||
var res GetResult
|
||||
resp, err := c.Request("HEAD", getURL(c, containerName), gophercloud.RequestOpts{
|
||||
OkCodes: []int{200, 204},
|
||||
})
|
||||
if resp != nil {
|
||||
res.Header = resp.Header
|
||||
}
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
270
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/results.go
generated
vendored
Normal file
270
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/results.go
generated
vendored
Normal file
@@ -0,0 +1,270 @@
|
||||
package containers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
// Container represents a container resource.
|
||||
type Container struct {
|
||||
// The total number of bytes stored in the container.
|
||||
Bytes int `json:"bytes" mapstructure:"bytes"`
|
||||
|
||||
// The total number of objects stored in the container.
|
||||
Count int `json:"count" mapstructure:"count"`
|
||||
|
||||
// The name of the container.
|
||||
Name string `json:"name" mapstructure:"name"`
|
||||
}
|
||||
|
||||
// ContainerPage is the page returned by a pager when traversing over a
|
||||
// collection of containers.
|
||||
type ContainerPage struct {
|
||||
pagination.MarkerPageBase
|
||||
}
|
||||
|
||||
// IsEmpty returns true if a ListResult contains no container names.
|
||||
func (r ContainerPage) IsEmpty() (bool, error) {
|
||||
names, err := ExtractNames(r)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
return len(names) == 0, nil
|
||||
}
|
||||
|
||||
// LastMarker returns the last container name in a ListResult.
|
||||
func (r ContainerPage) 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 ListResult and returns the containers' information.
|
||||
func ExtractInfo(page pagination.Page) ([]Container, error) {
|
||||
untyped := page.(ContainerPage).Body.([]interface{})
|
||||
results := make([]Container, len(untyped))
|
||||
for index, each := range untyped {
|
||||
container := each.(map[string]interface{})
|
||||
err := mapstructure.Decode(container, &results[index])
|
||||
if err != nil {
|
||||
return results, err
|
||||
}
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
// ExtractNames is a function that takes a ListResult and returns the containers' names.
|
||||
func ExtractNames(page pagination.Page) ([]string, error) {
|
||||
casted := page.(ContainerPage)
|
||||
ct := casted.Header.Get("Content-Type")
|
||||
|
||||
switch {
|
||||
case strings.HasPrefix(ct, "application/json"):
|
||||
parsed, err := ExtractInfo(page)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
names := make([]string, 0, len(parsed))
|
||||
for _, container := range parsed {
|
||||
names = append(names, container.Name)
|
||||
}
|
||||
return names, nil
|
||||
case strings.HasPrefix(ct, "text/plain"):
|
||||
names := make([]string, 0, 50)
|
||||
|
||||
body := string(page.(ContainerPage).Body.([]uint8))
|
||||
for _, name := range strings.Split(body, "\n") {
|
||||
if len(name) > 0 {
|
||||
names = append(names, name)
|
||||
}
|
||||
}
|
||||
|
||||
return names, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("Cannot extract names from response with content-type: [%s]", ct)
|
||||
}
|
||||
}
|
||||
|
||||
// GetHeader represents the headers returned in the response from a Get request.
|
||||
type GetHeader struct {
|
||||
AcceptRanges string `mapstructure:"Accept-Ranges"`
|
||||
BytesUsed int64 `mapstructure:"X-Account-Bytes-Used"`
|
||||
ContentLength int64 `mapstructure:"Content-Length"`
|
||||
ContentType string `mapstructure:"Content-Type"`
|
||||
Date time.Time `mapstructure:"-"`
|
||||
ObjectCount int64 `mapstructure:"X-Container-Object-Count"`
|
||||
Read string `mapstructure:"X-Container-Read"`
|
||||
TransID string `mapstructure:"X-Trans-Id"`
|
||||
VersionsLocation string `mapstructure:"X-Versions-Location"`
|
||||
Write string `mapstructure:"X-Container-Write"`
|
||||
}
|
||||
|
||||
// GetResult represents the result of a get operation.
|
||||
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 (gr GetResult) Extract() (GetHeader, error) {
|
||||
var gh GetHeader
|
||||
if gr.Err != nil {
|
||||
return gh, gr.Err
|
||||
}
|
||||
|
||||
if err := gophercloud.DecodeHeader(gr.Header, &gh); err != nil {
|
||||
return gh, err
|
||||
}
|
||||
|
||||
if date, ok := gr.Header["Date"]; ok && len(date) > 0 {
|
||||
t, err := time.Parse(time.RFC1123, gr.Header["Date"][0])
|
||||
if err != nil {
|
||||
return gh, err
|
||||
}
|
||||
gh.Date = t
|
||||
}
|
||||
|
||||
return gh, nil
|
||||
}
|
||||
|
||||
// ExtractMetadata is a function that takes a GetResult (of type *http.Response)
|
||||
// and returns the custom metadata associated with the container.
|
||||
func (gr GetResult) ExtractMetadata() (map[string]string, error) {
|
||||
if gr.Err != nil {
|
||||
return nil, gr.Err
|
||||
}
|
||||
metadata := make(map[string]string)
|
||||
for k, v := range gr.Header {
|
||||
if strings.HasPrefix(k, "X-Container-Meta-") {
|
||||
key := strings.TrimPrefix(k, "X-Container-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 `mapstructure:"Content-Length"`
|
||||
ContentType string `mapstructure:"Content-Type"`
|
||||
Date time.Time `mapstructure:"-"`
|
||||
TransID string `mapstructure:"X-Trans-Id"`
|
||||
}
|
||||
|
||||
// CreateResult represents the result of a create operation. To extract the
|
||||
// the headers from the HTTP response, you can invoke the 'ExtractHeader'
|
||||
// method on the result struct.
|
||||
type CreateResult struct {
|
||||
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 (cr CreateResult) Extract() (CreateHeader, error) {
|
||||
var ch CreateHeader
|
||||
if cr.Err != nil {
|
||||
return ch, cr.Err
|
||||
}
|
||||
|
||||
if err := gophercloud.DecodeHeader(cr.Header, &ch); err != nil {
|
||||
return ch, err
|
||||
}
|
||||
|
||||
if date, ok := cr.Header["Date"]; ok && len(date) > 0 {
|
||||
t, err := time.Parse(time.RFC1123, cr.Header["Date"][0])
|
||||
if err != nil {
|
||||
return ch, err
|
||||
}
|
||||
ch.Date = t
|
||||
}
|
||||
|
||||
return ch, nil
|
||||
}
|
||||
|
||||
// UpdateHeader represents the headers returned in the response from a Update request.
|
||||
type UpdateHeader struct {
|
||||
ContentLength int64 `mapstructure:"Content-Length"`
|
||||
ContentType string `mapstructure:"Content-Type"`
|
||||
Date time.Time `mapstructure:"-"`
|
||||
TransID string `mapstructure:"X-Trans-Id"`
|
||||
}
|
||||
|
||||
// UpdateResult represents the result of an update operation. To extract the
|
||||
// the headers from the HTTP response, you can invoke the 'ExtractHeader'
|
||||
// method on the result struct.
|
||||
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 (ur UpdateResult) Extract() (UpdateHeader, error) {
|
||||
var uh UpdateHeader
|
||||
if ur.Err != nil {
|
||||
return uh, ur.Err
|
||||
}
|
||||
|
||||
if err := gophercloud.DecodeHeader(ur.Header, &uh); err != nil {
|
||||
return uh, err
|
||||
}
|
||||
|
||||
if date, ok := ur.Header["Date"]; ok && len(date) > 0 {
|
||||
t, err := time.Parse(time.RFC1123, ur.Header["Date"][0])
|
||||
if err != nil {
|
||||
return uh, err
|
||||
}
|
||||
uh.Date = t
|
||||
}
|
||||
|
||||
return uh, nil
|
||||
}
|
||||
|
||||
// DeleteHeader represents the headers returned in the response from a Delete request.
|
||||
type DeleteHeader struct {
|
||||
ContentLength int64 `mapstructure:"Content-Length"`
|
||||
ContentType string `mapstructure:"Content-Type"`
|
||||
Date time.Time `mapstructure:"-"`
|
||||
TransID string `mapstructure:"X-Trans-Id"`
|
||||
}
|
||||
|
||||
// DeleteResult represents the result of a delete operation. To extract the
|
||||
// the headers from the HTTP response, you can invoke the 'ExtractHeader'
|
||||
// method on the result struct.
|
||||
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 (dr DeleteResult) Extract() (DeleteHeader, error) {
|
||||
var dh DeleteHeader
|
||||
if dr.Err != nil {
|
||||
return dh, dr.Err
|
||||
}
|
||||
|
||||
if err := gophercloud.DecodeHeader(dr.Header, &dh); err != nil {
|
||||
return dh, err
|
||||
}
|
||||
|
||||
if date, ok := dr.Header["Date"]; ok && len(date) > 0 {
|
||||
t, err := time.Parse(time.RFC1123, dr.Header["Date"][0])
|
||||
if err != nil {
|
||||
return dh, err
|
||||
}
|
||||
dh.Date = t
|
||||
}
|
||||
|
||||
return dh, nil
|
||||
}
|
||||
23
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/urls.go
generated
vendored
Normal file
23
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers/urls.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
package containers
|
||||
|
||||
import "github.com/rackspace/gophercloud"
|
||||
|
||||
func listURL(c *gophercloud.ServiceClient) string {
|
||||
return c.Endpoint
|
||||
}
|
||||
|
||||
func createURL(c *gophercloud.ServiceClient, container string) string {
|
||||
return c.ServiceURL(container)
|
||||
}
|
||||
|
||||
func getURL(c *gophercloud.ServiceClient, container string) string {
|
||||
return createURL(c, container)
|
||||
}
|
||||
|
||||
func deleteURL(c *gophercloud.ServiceClient, container string) string {
|
||||
return createURL(c, container)
|
||||
}
|
||||
|
||||
func updateURL(c *gophercloud.ServiceClient, container string) string {
|
||||
return createURL(c, container)
|
||||
}
|
||||
5
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/doc.go
generated
vendored
Normal file
5
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/doc.go
generated
vendored
Normal file
@@ -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
|
||||
195
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/fixtures.go
generated
vendored
Normal file
195
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/fixtures.go
generated
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
// +build fixtures
|
||||
|
||||
package objects
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
fake "github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
// HandleDownloadObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux that
|
||||
// responds with a `Download` response.
|
||||
func HandleDownloadObjectSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
th.TestHeader(t, r, "Accept", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintf(w, "Successful download with Gophercloud")
|
||||
})
|
||||
}
|
||||
|
||||
// ExpectedListInfo is the result expected from a call to `List` when full
|
||||
// info is requested.
|
||||
var ExpectedListInfo = []Object{
|
||||
Object{
|
||||
Hash: "451e372e48e0f6b1114fa0724aa79fa1",
|
||||
LastModified: "2009-11-10 23:00:00 +0000 UTC",
|
||||
Bytes: 14,
|
||||
Name: "goodbye",
|
||||
ContentType: "application/octet-stream",
|
||||
},
|
||||
Object{
|
||||
Hash: "451e372e48e0f6b1114fa0724aa79fa1",
|
||||
LastModified: "2009-11-10 23:00:00 +0000 UTC",
|
||||
Bytes: 14,
|
||||
Name: "hello",
|
||||
ContentType: "application/octet-stream",
|
||||
},
|
||||
}
|
||||
|
||||
// ExpectedListNames is the result expected from a call to `List` when just
|
||||
// object names are requested.
|
||||
var ExpectedListNames = []string{"hello", "goodbye"}
|
||||
|
||||
// HandleListObjectsInfoSuccessfully creates an HTTP handler at `/testContainer` on the test handler mux that
|
||||
// responds with a `List` response when full info is requested.
|
||||
func HandleListObjectsInfoSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/testContainer", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
th.TestHeader(t, r, "Accept", "application/json")
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
r.ParseForm()
|
||||
marker := r.Form.Get("marker")
|
||||
switch marker {
|
||||
case "":
|
||||
fmt.Fprintf(w, `[
|
||||
{
|
||||
"hash": "451e372e48e0f6b1114fa0724aa79fa1",
|
||||
"last_modified": "2009-11-10 23:00:00 +0000 UTC",
|
||||
"bytes": 14,
|
||||
"name": "goodbye",
|
||||
"content_type": "application/octet-stream"
|
||||
},
|
||||
{
|
||||
"hash": "451e372e48e0f6b1114fa0724aa79fa1",
|
||||
"last_modified": "2009-11-10 23:00:00 +0000 UTC",
|
||||
"bytes": 14,
|
||||
"name": "hello",
|
||||
"content_type": "application/octet-stream"
|
||||
}
|
||||
]`)
|
||||
case "hello":
|
||||
fmt.Fprintf(w, `[]`)
|
||||
default:
|
||||
t.Fatalf("Unexpected marker: [%s]", marker)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// HandleListObjectNamesSuccessfully creates an HTTP handler at `/testContainer` on the test handler mux that
|
||||
// responds with a `List` response when only object names are requested.
|
||||
func HandleListObjectNamesSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/testContainer", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
th.TestHeader(t, r, "Accept", "text/plain")
|
||||
|
||||
w.Header().Set("Content-Type", "text/plain")
|
||||
r.ParseForm()
|
||||
marker := r.Form.Get("marker")
|
||||
switch marker {
|
||||
case "":
|
||||
fmt.Fprintf(w, "hello\ngoodbye\n")
|
||||
case "goodbye":
|
||||
fmt.Fprintf(w, "")
|
||||
default:
|
||||
t.Fatalf("Unexpected marker: [%s]", marker)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// HandleCreateTextObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux
|
||||
// that responds with a `Create` response. A Content-Type of "text/plain" is expected.
|
||||
func HandleCreateTextObjectSuccessfully(t *testing.T, content string) {
|
||||
th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "PUT")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
th.TestHeader(t, r, "Content-Type", "text/plain")
|
||||
th.TestHeader(t, r, "Accept", "application/json")
|
||||
|
||||
hash := md5.New()
|
||||
io.WriteString(hash, content)
|
||||
localChecksum := hash.Sum(nil)
|
||||
|
||||
w.Header().Set("ETag", fmt.Sprintf("%x", localChecksum))
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleCreateTypelessObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler
|
||||
// mux that responds with a `Create` response. No Content-Type header may be present in the request, so that server-
|
||||
// side content-type detection will be triggered properly.
|
||||
func HandleCreateTypelessObjectSuccessfully(t *testing.T, content string) {
|
||||
th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "PUT")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
th.TestHeader(t, r, "Accept", "application/json")
|
||||
|
||||
if contentType, present := r.Header["Content-Type"]; present {
|
||||
t.Errorf("Expected Content-Type header to be omitted, but was %#v", contentType)
|
||||
}
|
||||
|
||||
hash := md5.New()
|
||||
io.WriteString(hash, content)
|
||||
localChecksum := hash.Sum(nil)
|
||||
|
||||
w.Header().Set("ETag", fmt.Sprintf("%x", localChecksum))
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleCopyObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux that
|
||||
// responds with a `Copy` response.
|
||||
func HandleCopyObjectSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "COPY")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
th.TestHeader(t, r, "Accept", "application/json")
|
||||
th.TestHeader(t, r, "Destination", "/newTestContainer/newTestObject")
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleDeleteObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux that
|
||||
// responds with a `Delete` response.
|
||||
func HandleDeleteObjectSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "DELETE")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
th.TestHeader(t, r, "Accept", "application/json")
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleUpdateObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux that
|
||||
// responds with a `Update` response.
|
||||
func HandleUpdateObjectSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "POST")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
th.TestHeader(t, r, "Accept", "application/json")
|
||||
th.TestHeader(t, r, "X-Object-Meta-Gophercloud-Test", "objects")
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleGetObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux that
|
||||
// responds with a `Get` response.
|
||||
func HandleGetObjectSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/testContainer/testObject", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "HEAD")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
th.TestHeader(t, r, "Accept", "application/json")
|
||||
w.Header().Add("X-Object-Meta-Gophercloud-Test", "objects")
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
})
|
||||
}
|
||||
501
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/requests.go
generated
vendored
Normal file
501
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/requests.go
generated
vendored
Normal file
@@ -0,0 +1,501 @@
|
||||
package objects
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/hmac"
|
||||
"crypto/md5"
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts"
|
||||
"github.com/rackspace/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)
|
||||
if err != nil {
|
||||
return false, "", err
|
||||
}
|
||||
return opts.Full, q.String(), nil
|
||||
}
|
||||
|
||||
// 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"}
|
||||
}
|
||||
}
|
||||
|
||||
createPage := func(r pagination.PageResult) pagination.Page {
|
||||
p := ObjectPage{pagination.MarkerPageBase{PageResult: r}}
|
||||
p.MarkerPageBase.Owner = p
|
||||
return p
|
||||
}
|
||||
|
||||
pager := pagination.NewPager(c, url, createPage)
|
||||
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) DownloadResult {
|
||||
var res DownloadResult
|
||||
|
||||
url := downloadURL(c, containerName, objectName)
|
||||
h := c.AuthenticatedHeaders()
|
||||
|
||||
if opts != nil {
|
||||
headers, query, err := opts.ToObjectDownloadParams()
|
||||
if err != nil {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
for k, v := range headers {
|
||||
h[k] = v
|
||||
}
|
||||
|
||||
url += query
|
||||
}
|
||||
|
||||
resp, err := c.Request("GET", url, gophercloud.RequestOpts{
|
||||
MoreHeaders: h,
|
||||
OkCodes: []int{200, 304},
|
||||
})
|
||||
if resp != nil {
|
||||
res.Header = resp.Header
|
||||
res.Body = resp.Body
|
||||
}
|
||||
res.Err = err
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// CreateOptsBuilder allows extensions to add additional parameters to the
|
||||
// Create request.
|
||||
type CreateOptsBuilder interface {
|
||||
ToObjectCreateParams() (map[string]string, string, error)
|
||||
}
|
||||
|
||||
// CreateOpts is a structure that holds parameters for creating an object.
|
||||
type CreateOpts struct {
|
||||
Metadata map[string]string
|
||||
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() (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
|
||||
}
|
||||
|
||||
for k, v := range opts.Metadata {
|
||||
h["X-Object-Meta-"+k] = v
|
||||
}
|
||||
|
||||
return 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, content io.ReadSeeker, opts CreateOptsBuilder) CreateResult {
|
||||
var res CreateResult
|
||||
|
||||
url := createURL(c, containerName, objectName)
|
||||
h := make(map[string]string)
|
||||
|
||||
if opts != nil {
|
||||
headers, query, err := opts.ToObjectCreateParams()
|
||||
if err != nil {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
for k, v := range headers {
|
||||
h[k] = v
|
||||
}
|
||||
|
||||
url += query
|
||||
}
|
||||
|
||||
hash := md5.New()
|
||||
bufioReader := bufio.NewReader(io.TeeReader(content, hash))
|
||||
io.Copy(ioutil.Discard, bufioReader)
|
||||
localChecksum := hash.Sum(nil)
|
||||
|
||||
h["ETag"] = fmt.Sprintf("%x", localChecksum)
|
||||
|
||||
_, err := content.Seek(0, 0)
|
||||
if err != nil {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
ropts := gophercloud.RequestOpts{
|
||||
RawBody: content,
|
||||
MoreHeaders: h,
|
||||
}
|
||||
|
||||
resp, err := c.Request("PUT", url, ropts)
|
||||
if err != nil {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
if resp != nil {
|
||||
res.Header = resp.Header
|
||||
if resp.Header.Get("ETag") == fmt.Sprintf("%x", localChecksum) {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
res.Err = fmt.Errorf("Local checksum does not match API ETag header")
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// 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"`
|
||||
}
|
||||
|
||||
// ToObjectCopyMap formats a CopyOpts into a map of headers.
|
||||
func (opts CopyOpts) ToObjectCopyMap() (map[string]string, error) {
|
||||
if opts.Destination == "" {
|
||||
return nil, fmt.Errorf("Required CopyOpts field 'Destination' not set.")
|
||||
}
|
||||
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) CopyResult {
|
||||
var res CopyResult
|
||||
h := c.AuthenticatedHeaders()
|
||||
|
||||
headers, err := opts.ToObjectCopyMap()
|
||||
if err != nil {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
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 {
|
||||
res.Header = resp.Header
|
||||
}
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return q.String(), nil
|
||||
}
|
||||
|
||||
// Delete is a function that deletes an object.
|
||||
func Delete(c *gophercloud.ServiceClient, containerName, objectName string, opts DeleteOptsBuilder) DeleteResult {
|
||||
var res DeleteResult
|
||||
url := deleteURL(c, containerName, objectName)
|
||||
|
||||
if opts != nil {
|
||||
query, err := opts.ToObjectDeleteQuery()
|
||||
if err != nil {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
url += query
|
||||
}
|
||||
|
||||
resp, err := c.Delete(url, nil)
|
||||
if resp != nil {
|
||||
res.Header = resp.Header
|
||||
}
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return q.String(), nil
|
||||
}
|
||||
|
||||
// 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) GetResult {
|
||||
var res GetResult
|
||||
url := getURL(c, containerName, objectName)
|
||||
|
||||
if opts != nil {
|
||||
query, err := opts.ToObjectGetQuery()
|
||||
if err != nil {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
url += query
|
||||
}
|
||||
|
||||
resp, err := c.Request("HEAD", url, gophercloud.RequestOpts{
|
||||
OkCodes: []int{200, 204},
|
||||
})
|
||||
if resp != nil {
|
||||
res.Header = resp.Header
|
||||
}
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
// 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) UpdateResult {
|
||||
var res UpdateResult
|
||||
h := c.AuthenticatedHeaders()
|
||||
|
||||
if opts != nil {
|
||||
headers, err := opts.ToObjectUpdateMap()
|
||||
if err != nil {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
for k, v := range headers {
|
||||
h[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
url := updateURL(c, containerName, objectName)
|
||||
resp, err := c.Request("POST", url, gophercloud.RequestOpts{
|
||||
MoreHeaders: h,
|
||||
})
|
||||
if resp != nil {
|
||||
res.Header = resp.Header
|
||||
}
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
438
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/results.go
generated
vendored
Normal file
438
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/results.go
generated
vendored
Normal file
@@ -0,0 +1,438 @@
|
||||
package objects
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
// 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" mapstructure:"bytes"`
|
||||
|
||||
// ContentType is the content type of the object.
|
||||
ContentType string `json:"content_type" mapstructure:"content_type"`
|
||||
|
||||
// Hash represents the MD5 checksum value of the object's content.
|
||||
Hash string `json:"hash" mapstructure:"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 string `json:"last_modified" mapstructure:"last_modified"`
|
||||
|
||||
// Name is the unique name for the object.
|
||||
Name string `json:"name" mapstructure:"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)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
return len(names) == 0, nil
|
||||
}
|
||||
|
||||
// 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(page pagination.Page) ([]Object, error) {
|
||||
untyped := page.(ObjectPage).Body.([]interface{})
|
||||
results := make([]Object, len(untyped))
|
||||
for index, each := range untyped {
|
||||
object := each.(map[string]interface{})
|
||||
err := mapstructure.Decode(object, &results[index])
|
||||
if err != nil {
|
||||
return results, err
|
||||
}
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
// ExtractNames is a function that takes a page of objects and returns only their names.
|
||||
func ExtractNames(page pagination.Page) ([]string, error) {
|
||||
casted := page.(ObjectPage)
|
||||
ct := casted.Header.Get("Content-Type")
|
||||
switch {
|
||||
case strings.HasPrefix(ct, "application/json"):
|
||||
parsed, err := ExtractInfo(page)
|
||||
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(page.(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 `mapstructure:"Accept-Ranges"`
|
||||
ContentDisposition string `mapstructure:"Content-Disposition"`
|
||||
ContentEncoding string `mapstructure:"Content-Encoding"`
|
||||
ContentLength int64 `mapstructure:"Content-Length"`
|
||||
ContentType string `mapstructure:"Content-Type"`
|
||||
Date time.Time `mapstructure:"-"`
|
||||
DeleteAt time.Time `mapstructure:"-"`
|
||||
ETag string `mapstructure:"Etag"`
|
||||
LastModified time.Time `mapstructure:"-"`
|
||||
ObjectManifest string `mapstructure:"X-Object-Manifest"`
|
||||
StaticLargeObject bool `mapstructure:"X-Static-Large-Object"`
|
||||
TransID string `mapstructure:"X-Trans-Id"`
|
||||
}
|
||||
|
||||
// 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 (dr DownloadResult) Extract() (DownloadHeader, error) {
|
||||
var dh DownloadHeader
|
||||
if dr.Err != nil {
|
||||
return dh, dr.Err
|
||||
}
|
||||
|
||||
if err := gophercloud.DecodeHeader(dr.Header, &dh); err != nil {
|
||||
return dh, err
|
||||
}
|
||||
|
||||
if date, ok := dr.Header["Date"]; ok && len(date) > 0 {
|
||||
t, err := time.Parse(time.RFC1123, date[0])
|
||||
if err != nil {
|
||||
return dh, err
|
||||
}
|
||||
dh.Date = t
|
||||
}
|
||||
|
||||
if date, ok := dr.Header["Last-Modified"]; ok && len(date) > 0 {
|
||||
t, err := time.Parse(time.RFC1123, date[0])
|
||||
if err != nil {
|
||||
return dh, err
|
||||
}
|
||||
dh.LastModified = t
|
||||
}
|
||||
|
||||
if date, ok := dr.Header["X-Delete-At"]; ok && len(date) > 0 {
|
||||
unix, err := strconv.ParseInt(date[0], 10, 64)
|
||||
if err != nil {
|
||||
return dh, err
|
||||
}
|
||||
dh.DeleteAt = time.Unix(unix, 0)
|
||||
}
|
||||
|
||||
return dh, nil
|
||||
}
|
||||
|
||||
// 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 (dr DownloadResult) ExtractContent() ([]byte, error) {
|
||||
if dr.Err != nil {
|
||||
return nil, dr.Err
|
||||
}
|
||||
body, err := ioutil.ReadAll(dr.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dr.Body.Close()
|
||||
return body, nil
|
||||
}
|
||||
|
||||
// GetHeader represents the headers returned in the response from a Get request.
|
||||
type GetHeader struct {
|
||||
ContentDisposition string `mapstructure:"Content-Disposition"`
|
||||
ContentEncoding string `mapstructure:"Content-Encoding"`
|
||||
ContentLength int64 `mapstructure:"Content-Length"`
|
||||
ContentType string `mapstructure:"Content-Type"`
|
||||
Date time.Time `mapstructure:"-"`
|
||||
DeleteAt time.Time `mapstructure:"-"`
|
||||
ETag string `mapstructure:"Etag"`
|
||||
LastModified time.Time `mapstructure:"-"`
|
||||
ObjectManifest string `mapstructure:"X-Object-Manifest"`
|
||||
StaticLargeObject bool `mapstructure:"X-Static-Large-Object"`
|
||||
TransID string `mapstructure:"X-Trans-Id"`
|
||||
}
|
||||
|
||||
// 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 (gr GetResult) Extract() (GetHeader, error) {
|
||||
var gh GetHeader
|
||||
if gr.Err != nil {
|
||||
return gh, gr.Err
|
||||
}
|
||||
|
||||
if err := gophercloud.DecodeHeader(gr.Header, &gh); err != nil {
|
||||
return gh, err
|
||||
}
|
||||
|
||||
if date, ok := gr.Header["Date"]; ok && len(date) > 0 {
|
||||
t, err := time.Parse(time.RFC1123, gr.Header["Date"][0])
|
||||
if err != nil {
|
||||
return gh, err
|
||||
}
|
||||
gh.Date = t
|
||||
}
|
||||
|
||||
if date, ok := gr.Header["Last-Modified"]; ok && len(date) > 0 {
|
||||
t, err := time.Parse(time.RFC1123, gr.Header["Last-Modified"][0])
|
||||
if err != nil {
|
||||
return gh, err
|
||||
}
|
||||
gh.LastModified = t
|
||||
}
|
||||
|
||||
if date, ok := gr.Header["X-Delete-At"]; ok && len(date) > 0 {
|
||||
unix, err := strconv.ParseInt(date[0], 10, 64)
|
||||
if err != nil {
|
||||
return gh, err
|
||||
}
|
||||
gh.DeleteAt = time.Unix(unix, 0)
|
||||
}
|
||||
|
||||
return gh, nil
|
||||
}
|
||||
|
||||
// ExtractMetadata is a function that takes a GetResult (of type *http.Response)
|
||||
// and returns the custom metadata associated with the object.
|
||||
func (gr GetResult) ExtractMetadata() (map[string]string, error) {
|
||||
if gr.Err != nil {
|
||||
return nil, gr.Err
|
||||
}
|
||||
metadata := make(map[string]string)
|
||||
for k, v := range gr.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 `mapstructure:"Content-Length"`
|
||||
ContentType string `mapstructure:"Content-Type"`
|
||||
Date time.Time `mapstructure:"-"`
|
||||
ETag string `mapstructure:"Etag"`
|
||||
LastModified time.Time `mapstructure:"-"`
|
||||
TransID string `mapstructure:"X-Trans-Id"`
|
||||
}
|
||||
|
||||
// CreateResult represents the result of a create operation.
|
||||
type CreateResult struct {
|
||||
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 (cr CreateResult) Extract() (CreateHeader, error) {
|
||||
var ch CreateHeader
|
||||
if cr.Err != nil {
|
||||
return ch, cr.Err
|
||||
}
|
||||
|
||||
if err := gophercloud.DecodeHeader(cr.Header, &ch); err != nil {
|
||||
return ch, err
|
||||
}
|
||||
|
||||
if date, ok := cr.Header["Date"]; ok && len(date) > 0 {
|
||||
t, err := time.Parse(time.RFC1123, cr.Header["Date"][0])
|
||||
if err != nil {
|
||||
return ch, err
|
||||
}
|
||||
ch.Date = t
|
||||
}
|
||||
|
||||
if date, ok := cr.Header["Last-Modified"]; ok && len(date) > 0 {
|
||||
t, err := time.Parse(time.RFC1123, cr.Header["Last-Modified"][0])
|
||||
if err != nil {
|
||||
return ch, err
|
||||
}
|
||||
ch.LastModified = t
|
||||
}
|
||||
|
||||
return ch, nil
|
||||
}
|
||||
|
||||
// UpdateHeader represents the headers returned in the response from a Update request.
|
||||
type UpdateHeader struct {
|
||||
ContentLength int64 `mapstructure:"Content-Length"`
|
||||
ContentType string `mapstructure:"Content-Type"`
|
||||
Date time.Time `mapstructure:"-"`
|
||||
TransID string `mapstructure:"X-Trans-Id"`
|
||||
}
|
||||
|
||||
// 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 (ur UpdateResult) Extract() (UpdateHeader, error) {
|
||||
var uh UpdateHeader
|
||||
if ur.Err != nil {
|
||||
return uh, ur.Err
|
||||
}
|
||||
|
||||
if err := gophercloud.DecodeHeader(ur.Header, &uh); err != nil {
|
||||
return uh, err
|
||||
}
|
||||
|
||||
if date, ok := ur.Header["Date"]; ok && len(date) > 0 {
|
||||
t, err := time.Parse(time.RFC1123, ur.Header["Date"][0])
|
||||
if err != nil {
|
||||
return uh, err
|
||||
}
|
||||
uh.Date = t
|
||||
}
|
||||
|
||||
return uh, nil
|
||||
}
|
||||
|
||||
// DeleteHeader represents the headers returned in the response from a Delete request.
|
||||
type DeleteHeader struct {
|
||||
ContentLength int64 `mapstructure:"Content-Length"`
|
||||
ContentType string `mapstructure:"Content-Type"`
|
||||
Date time.Time `mapstructure:"-"`
|
||||
TransID string `mapstructure:"X-Trans-Id"`
|
||||
}
|
||||
|
||||
// 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 (dr DeleteResult) Extract() (DeleteHeader, error) {
|
||||
var dh DeleteHeader
|
||||
if dr.Err != nil {
|
||||
return dh, dr.Err
|
||||
}
|
||||
|
||||
if err := gophercloud.DecodeHeader(dr.Header, &dh); err != nil {
|
||||
return dh, err
|
||||
}
|
||||
|
||||
if date, ok := dr.Header["Date"]; ok && len(date) > 0 {
|
||||
t, err := time.Parse(time.RFC1123, dr.Header["Date"][0])
|
||||
if err != nil {
|
||||
return dh, err
|
||||
}
|
||||
dh.Date = t
|
||||
}
|
||||
|
||||
return dh, nil
|
||||
}
|
||||
|
||||
// CopyHeader represents the headers returned in the response from a Copy request.
|
||||
type CopyHeader struct {
|
||||
ContentLength int64 `mapstructure:"Content-Length"`
|
||||
ContentType string `mapstructure:"Content-Type"`
|
||||
CopiedFrom string `mapstructure:"X-Copied-From"`
|
||||
CopiedFromLastModified time.Time `mapstructure:"-"`
|
||||
Date time.Time `mapstructure:"-"`
|
||||
ETag string `mapstructure:"Etag"`
|
||||
LastModified time.Time `mapstructure:"-"`
|
||||
TransID string `mapstructure:"X-Trans-Id"`
|
||||
}
|
||||
|
||||
// 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 (cr CopyResult) Extract() (CopyHeader, error) {
|
||||
var ch CopyHeader
|
||||
if cr.Err != nil {
|
||||
return ch, cr.Err
|
||||
}
|
||||
|
||||
if err := gophercloud.DecodeHeader(cr.Header, &ch); err != nil {
|
||||
return ch, err
|
||||
}
|
||||
|
||||
if date, ok := cr.Header["Date"]; ok && len(date) > 0 {
|
||||
t, err := time.Parse(time.RFC1123, cr.Header["Date"][0])
|
||||
if err != nil {
|
||||
return ch, err
|
||||
}
|
||||
ch.Date = t
|
||||
}
|
||||
|
||||
if date, ok := cr.Header["Last-Modified"]; ok && len(date) > 0 {
|
||||
t, err := time.Parse(time.RFC1123, cr.Header["Last-Modified"][0])
|
||||
if err != nil {
|
||||
return ch, err
|
||||
}
|
||||
ch.LastModified = t
|
||||
}
|
||||
|
||||
if date, ok := cr.Header["X-Copied-From-Last-Modified"]; ok && len(date) > 0 {
|
||||
t, err := time.Parse(time.RFC1123, cr.Header["X-Copied-From-Last-Modified"][0])
|
||||
if err != nil {
|
||||
return ch, err
|
||||
}
|
||||
ch.CopiedFromLastModified = t
|
||||
}
|
||||
|
||||
return ch, nil
|
||||
}
|
||||
33
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/urls.go
generated
vendored
Normal file
33
vendor/github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects/urls.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
package objects
|
||||
|
||||
import (
|
||||
"github.com/rackspace/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)
|
||||
}
|
||||
Reference in New Issue
Block a user