change 'XXXXOpts' to pointers; return url.URL from BuildQueryString
diff --git a/openstack/objectstorage/v1/containers/requests.go b/openstack/objectstorage/v1/containers/requests.go
index 013c6ff..8b54c81 100644
--- a/openstack/objectstorage/v1/containers/requests.go
+++ b/openstack/objectstorage/v1/containers/requests.go
@@ -20,15 +20,20 @@
// List is a function that retrieves all objects in a container. It also returns the details
// for the account. To extract just the container information or names, pass the ListResult
// response to the ExtractInfo or ExtractNames function, respectively.
-func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
+func List(c *gophercloud.ServiceClient, opts *ListOpts) pagination.Pager {
var headers map[string]string
- query, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return pagination.Pager{Err: err}
- }
- if !opts.Full {
- headers = map[string]string{"Accept": "text/plain", "Content-Type": "text/plain"}
+ url := accountURL(c)
+ if opts != nil {
+ query, err := gophercloud.BuildQueryString(opts)
+ if err != nil {
+ return pagination.Pager{Err: err}
+ }
+ url += query.String()
+
+ if !opts.Full {
+ headers = map[string]string{"Accept": "text/plain", "Content-Type": "text/plain"}
+ }
}
createPage := func(r pagination.LastHTTPResponse) pagination.Page {
@@ -37,7 +42,6 @@
return p
}
- url := accountURL(c) + query
pager := pagination.NewPager(c, url, createPage)
pager.Headers = headers
return pager
@@ -57,24 +61,26 @@
}
// Create is a function that creates a new container.
-func Create(c *gophercloud.ServiceClient, containerName string, opts CreateOpts) (Container, error) {
+func Create(c *gophercloud.ServiceClient, containerName string, opts *CreateOpts) (Container, error) {
var container Container
h := c.Provider.AuthenticatedHeaders()
- headers, err := gophercloud.BuildHeaders(opts)
- if err != nil {
- return container, err
+ if opts != nil {
+ headers, err := gophercloud.BuildHeaders(opts)
+ if err != nil {
+ return container, err
+ }
+
+ for k, v := range headers {
+ h[k] = v
+ }
+
+ for k, v := range opts.Metadata {
+ h["X-Container-Meta-"+k] = v
+ }
}
- for k, v := range headers {
- h[k] = v
- }
-
- for k, v := range opts.Metadata {
- h["X-Container-Meta-"+k] = v
- }
-
- _, err = perigee.Request("PUT", containerURL(c, containerName), perigee.Options{
+ _, err := perigee.Request("PUT", containerURL(c, containerName), perigee.Options{
MoreHeaders: h,
OkCodes: []int{201, 204},
})
@@ -108,24 +114,25 @@
}
// Update is a function that creates, updates, or deletes a container's metadata.
-func Update(c *gophercloud.ServiceClient, containerName string, opts UpdateOpts) error {
+func Update(c *gophercloud.ServiceClient, containerName string, opts *UpdateOpts) error {
h := c.Provider.AuthenticatedHeaders()
- headers, err := gophercloud.BuildHeaders(opts)
- if err != nil {
- return err
+ if opts != nil {
+ headers, err := gophercloud.BuildHeaders(opts)
+ if err != nil {
+ return err
+ }
+
+ for k, v := range headers {
+ h[k] = v
+ }
+
+ for k, v := range opts.Metadata {
+ h["X-Container-Meta-"+k] = v
+ }
}
- for k, v := range headers {
- h[k] = v
- }
-
- for k, v := range opts.Metadata {
- h["X-Container-Meta-"+k] = v
- }
-
- url := containerURL(c, containerName)
- _, err = perigee.Request("POST", url, perigee.Options{
+ _, err := perigee.Request("POST", containerURL(c, containerName), perigee.Options{
MoreHeaders: h,
OkCodes: []int{204},
})
diff --git a/openstack/objectstorage/v1/containers/requests_test.go b/openstack/objectstorage/v1/containers/requests_test.go
index 1c9ee11..d58ebeb 100644
--- a/openstack/objectstorage/v1/containers/requests_test.go
+++ b/openstack/objectstorage/v1/containers/requests_test.go
@@ -34,7 +34,6 @@
w.Header().Add("Content-Type", "application/json")
r.ParseForm()
- fmt.Printf("r: %+v\n", r)
marker := r.Form.Get("marker")
switch marker {
case "":
@@ -58,7 +57,9 @@
})
client := serviceClient()
- List(client, ListOpts{Full: true}).EachPage(func(page pagination.Page) (bool, error) {
+ count := 0
+ List(client, &ListOpts{Full: true}).EachPage(func(page pagination.Page) (bool, error) {
+ count++
actual, err := ExtractInfo(page)
if err != nil {
t.Errorf("Failed to extract container info: %v", err)
@@ -78,10 +79,16 @@
},
}
+ t.Logf("actual: %+v/n", actual)
+
testhelper.CheckDeepEquals(t, expected, actual)
return true, nil
})
+
+ if count != 1 {
+ t.Errorf("Expected 1 page, got %d", count)
+ }
}
func TestListContainerNames(t *testing.T) {
@@ -107,7 +114,9 @@
})
client := serviceClient()
- List(client, ListOpts{Full: false}).EachPage(func(page pagination.Page) (bool, error) {
+ count := 0
+ List(client, &ListOpts{Full: false}).EachPage(func(page pagination.Page) (bool, error) {
+ count++
actual, err := ExtractNames(page)
if err != nil {
t.Errorf("Failed to extract container names: %v", err)
@@ -120,6 +129,10 @@
return true, nil
})
+
+ if count != 1 {
+ t.Errorf("Expected 1 page, got %d", count)
+ }
}
func TestCreateContainer(t *testing.T) {
@@ -134,7 +147,7 @@
})
client := serviceClient()
- _, err := Create(client, "testContainer", CreateOpts{})
+ _, err := Create(client, "testContainer", nil)
if err != nil {
t.Fatalf("Unexpected error creating container: %v", err)
}
@@ -170,7 +183,7 @@
})
client := serviceClient()
- err := Update(client, "testContainer", UpdateOpts{})
+ err := Update(client, "testContainer", nil)
if err != nil {
t.Fatalf("Unexpected error updating container metadata: %v", err)
}
@@ -185,9 +198,6 @@
testhelper.TestHeader(t, r, "X-Auth-Token", tokenId)
testhelper.TestHeader(t, r, "Accept", "application/json")
w.WriteHeader(http.StatusNoContent)
- fmt.Fprintf(w, `
-
- `)
})
client := serviceClient()
diff --git a/openstack/objectstorage/v1/objects/requests.go b/openstack/objectstorage/v1/objects/requests.go
index 1622ff7..900290c 100644
--- a/openstack/objectstorage/v1/objects/requests.go
+++ b/openstack/objectstorage/v1/objects/requests.go
@@ -25,17 +25,21 @@
// 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 ListOpts) pagination.Pager {
+func List(c *gophercloud.ServiceClient, containerName string, opts *ListOpts) pagination.Pager {
var headers map[string]string
- query, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- fmt.Printf("Error building query string: %v", err)
- return pagination.Pager{Err: err}
- }
+ url := containerURL(c, containerName)
+ if opts != nil {
+ query, err := gophercloud.BuildQueryString(opts)
+ if err != nil {
+ fmt.Printf("Error building query string: %v", err)
+ return pagination.Pager{Err: err}
+ }
+ url += query.String()
- if !opts.Full {
- headers = map[string]string{"Accept": "text/plain", "Content-Type": "text/plain"}
+ if !opts.Full {
+ headers = map[string]string{"Accept": "text/plain", "Content-Type": "text/plain"}
+ }
}
createPage := func(r pagination.LastHTTPResponse) pagination.Page {
@@ -44,7 +48,6 @@
return p
}
- url := containerURL(c, containerName) + query
pager := pagination.NewPager(c, url, createPage)
pager.Headers = headers
return pager
@@ -65,28 +68,31 @@
// 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 DownloadOpts) DownloadResult {
+func Download(c *gophercloud.ServiceClient, containerName, objectName string, opts *DownloadOpts) DownloadResult {
var dr DownloadResult
+ url := objectURL(c, containerName, objectName)
h := c.Provider.AuthenticatedHeaders()
- headers, err := gophercloud.BuildHeaders(opts)
- if err != nil {
- dr.Err = err
- return dr
+ if opts != nil {
+ headers, err := gophercloud.BuildHeaders(opts)
+ if err != nil {
+ dr.Err = err
+ return dr
+ }
+
+ for k, v := range headers {
+ h[k] = v
+ }
+
+ query, err := gophercloud.BuildQueryString(opts)
+ if err != nil {
+ dr.Err = err
+ return dr
+ }
+ url += query.String()
}
- for k, v := range headers {
- h[k] = v
- }
-
- query, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- dr.Err = err
- return dr
- }
-
- url := objectURL(c, containerName, objectName) + query
resp, err := perigee.Request("GET", url, perigee.Options{
MoreHeaders: h,
OkCodes: []int{200},
@@ -117,27 +123,31 @@
}
// Create is a function that creates a new object or replaces an existing object.
-func Create(c *gophercloud.ServiceClient, containerName, objectName string, content io.Reader, opts CreateOpts) error {
+func Create(c *gophercloud.ServiceClient, containerName, objectName string, content io.Reader, opts *CreateOpts) error {
var reqBody []byte
+ url := objectURL(c, containerName, objectName)
h := c.Provider.AuthenticatedHeaders()
- headers, err := gophercloud.BuildHeaders(opts)
- if err != nil {
- return nil
- }
+ if opts != nil {
+ headers, err := gophercloud.BuildHeaders(opts)
+ if err != nil {
+ return nil
+ }
- for k, v := range headers {
- h[k] = v
- }
+ for k, v := range headers {
+ h[k] = v
+ }
- for k, v := range opts.Metadata {
- h["X-Object-Meta-"+k] = v
- }
+ for k, v := range opts.Metadata {
+ h["X-Object-Meta-"+k] = v
+ }
- query, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return err
+ query, err := gophercloud.BuildQueryString(opts)
+ if err != nil {
+ return err
+ }
+ url += query.String()
}
if content != nil {
@@ -148,8 +158,7 @@
}
}
- url := objectURL(c, containerName, objectName) + query
- _, err = perigee.Request("PUT", url, perigee.Options{
+ _, err := perigee.Request("PUT", url, perigee.Options{
ReqBody: reqBody,
MoreHeaders: h,
OkCodes: []int{201},
@@ -167,9 +176,12 @@
}
// Copy is a function that copies one object to another.
-func Copy(c *gophercloud.ServiceClient, containerName, objectName string, opts CopyOpts) error {
+func Copy(c *gophercloud.ServiceClient, containerName, objectName string, opts *CopyOpts) error {
h := c.Provider.AuthenticatedHeaders()
+ if opts == nil {
+ return fmt.Errorf("Required CopyOpts field 'Destination' not set.")
+ }
headers, err := gophercloud.BuildHeaders(opts)
if err != nil {
return err
@@ -196,17 +208,19 @@
}
// Delete is a function that deletes an object.
-func Delete(c *gophercloud.ServiceClient, containerName, objectName string, opts DeleteOpts) error {
- h := c.Provider.AuthenticatedHeaders()
+func Delete(c *gophercloud.ServiceClient, containerName, objectName string, opts *DeleteOpts) error {
+ url := objectURL(c, containerName, objectName)
- query, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return err
+ if opts != nil {
+ query, err := gophercloud.BuildQueryString(opts)
+ if err != nil {
+ return err
+ }
+ url += query.String()
}
- url := objectURL(c, containerName, objectName) + query
- _, err = perigee.Request("DELETE", url, perigee.Options{
- MoreHeaders: h,
+ _, err := perigee.Request("DELETE", url, perigee.Options{
+ MoreHeaders: c.Provider.AuthenticatedHeaders(),
OkCodes: []int{204},
})
return err
@@ -220,15 +234,19 @@
// 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 GetOpts) GetResult {
+func Get(c *gophercloud.ServiceClient, containerName, objectName string, opts *GetOpts) GetResult {
var gr GetResult
- query, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- gr.Err = err
- return gr
+ url := objectURL(c, containerName, objectName)
+
+ if opts != nil {
+ query, err := gophercloud.BuildQueryString(opts)
+ if err != nil {
+ gr.Err = err
+ return gr
+ }
+ url += query.String()
}
- url := objectURL(c, containerName, objectName) + query
resp, err := perigee.Request("HEAD", url, perigee.Options{
MoreHeaders: c.Provider.AuthenticatedHeaders(),
OkCodes: []int{200, 204},
@@ -251,24 +269,26 @@
}
// Update is a function that creates, updates, or deletes an object's metadata.
-func Update(c *gophercloud.ServiceClient, containerName, objectName string, opts UpdateOpts) error {
+func Update(c *gophercloud.ServiceClient, containerName, objectName string, opts *UpdateOpts) error {
h := c.Provider.AuthenticatedHeaders()
- headers, err := gophercloud.BuildHeaders(opts)
- if err != nil {
- return nil
- }
+ if opts != nil {
+ headers, err := gophercloud.BuildHeaders(opts)
+ if err != nil {
+ return nil
+ }
- for k, v := range headers {
- h[k] = v
- }
+ for k, v := range headers {
+ h[k] = v
+ }
- for k, v := range opts.Metadata {
- h["X-Object-Meta-"+k] = v
+ for k, v := range opts.Metadata {
+ h["X-Object-Meta-"+k] = v
+ }
}
url := objectURL(c, containerName, objectName)
- _, err = perigee.Request("POST", url, perigee.Options{
+ _, err := perigee.Request("POST", url, perigee.Options{
MoreHeaders: h,
OkCodes: []int{202},
})
diff --git a/openstack/objectstorage/v1/objects/requests_test.go b/openstack/objectstorage/v1/objects/requests_test.go
index 0c61550..00d2c0f 100644
--- a/openstack/objectstorage/v1/objects/requests_test.go
+++ b/openstack/objectstorage/v1/objects/requests_test.go
@@ -37,7 +37,7 @@
})
client := serviceClient()
- content, err := Download(client, "testContainer", "testObject", DownloadOpts{}).ExtractContent()
+ content, err := Download(client, "testContainer", "testObject", nil).ExtractContent()
if err != nil {
t.Fatalf("Unexpected error downloading object: %v", err)
}
@@ -53,20 +53,40 @@
testhelper.Mux.HandleFunc("/testContainer", func(w http.ResponseWriter, r *http.Request) {
testhelper.TestMethod(t, r, "GET")
testhelper.TestHeader(t, r, "X-Auth-Token", tokenId)
+ testhelper.TestHeader(t, r, "Accept", "application/json")
- w.Header().Set("Content-Type", "application/json")
+ w.Header().Add("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'}]`)
+ 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)
}
})
client := serviceClient()
- List(client, "testContainer", ListOpts{Full: true}).EachPage(func(page pagination.Page) (bool, error) {
+ count := 0
+ List(client, "testContainer", &ListOpts{Full: true}).EachPage(func(page pagination.Page) (bool, error) {
+ count++
actual, err := ExtractInfo(page)
if err != nil {
t.Errorf("Failed to extract object info: %v", err)
@@ -81,12 +101,23 @@
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",
+ },
}
testhelper.CheckDeepEquals(t, expected, actual)
return true, nil
})
+
+ if count != 1 {
+ t.Errorf("Expected 1 page, got %d", count)
+ }
}
func TestListObjectNames(t *testing.T) {
@@ -103,7 +134,7 @@
marker := r.Form.Get("marker")
switch marker {
case "":
- fmt.Fprintf(w, "goodbye\n")
+ fmt.Fprintf(w, "hello\ngoodbye\n")
case "goodbye":
fmt.Fprintf(w, "")
default:
@@ -112,19 +143,25 @@
})
client := serviceClient()
- List(client, "testContainer", ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
+ count := 0
+ List(client, "testContainer", nil).EachPage(func(page pagination.Page) (bool, error) {
+ count++
actual, err := ExtractNames(page)
if err != nil {
t.Errorf("Failed to extract object names: %v", err)
return false, err
}
- expected := []string{"goodbye"}
+ expected := []string{"hello", "goodbye"}
testhelper.CheckDeepEquals(t, expected, actual)
return true, nil
})
+
+ if count != 1 {
+ t.Errorf("Expected 1 page, got %d", count)
+ }
}
func TestCreateObject(t *testing.T) {
@@ -140,7 +177,7 @@
client := serviceClient()
content := bytes.NewBufferString("Did gyre and gimble in the wabe")
- err := Create(client, "testContainer", "testObject", content, CreateOpts{})
+ err := Create(client, "testContainer", "testObject", content, nil)
if err != nil {
t.Fatalf("Unexpected error creating object: %v", err)
}
@@ -159,7 +196,7 @@
})
client := serviceClient()
- err := Copy(client, "testContainer", "testObject", CopyOpts{Destination: "/newTestContainer/newTestObject"})
+ err := Copy(client, "testContainer", "testObject", &CopyOpts{Destination: "/newTestContainer/newTestObject"})
if err != nil {
t.Fatalf("Unexpected error copying object: %v", err)
}
@@ -177,7 +214,7 @@
})
client := serviceClient()
- err := Delete(client, "testContainer", "testObject", DeleteOpts{})
+ err := Delete(client, "testContainer", "testObject", nil)
if err != nil {
t.Fatalf("Unexpected error deleting object: %v", err)
}
@@ -196,7 +233,7 @@
})
client := serviceClient()
- err := Update(client, "testContainer", "testObject", UpdateOpts{Metadata: metadata})
+ err := Update(client, "testContainer", "testObject", &UpdateOpts{Metadata: metadata})
if err != nil {
t.Fatalf("Unexpected error updating object metadata: %v", err)
}
@@ -216,7 +253,7 @@
client := serviceClient()
expected := metadata
- actual, err := Get(client, "testContainer", "testObject", GetOpts{}).ExtractMetadata()
+ actual, err := Get(client, "testContainer", "testObject", nil).ExtractMetadata()
if err != nil {
t.Fatalf("Unexpected error getting object metadata: %v", err)
}