rackspace reponse header structs
diff --git a/acceptance/rackspace/objectstorage/v1/accounts_test.go b/acceptance/rackspace/objectstorage/v1/accounts_test.go
index cde534b..8b3cde4 100644
--- a/acceptance/rackspace/objectstorage/v1/accounts_test.go
+++ b/acceptance/rackspace/objectstorage/v1/accounts_test.go
@@ -13,12 +13,11 @@
c, err := createClient(t, false)
th.AssertNoErr(t, err)
- updateres := raxAccounts.Update(c, raxAccounts.UpdateOpts{Metadata: map[string]string{"white": "mountains"}})
- updateHeaders, err := updateres.Extract()
+ updateHeaders, err := raxAccounts.Update(c, raxAccounts.UpdateOpts{Metadata: map[string]string{"white": "mountains"}}).Extract()
th.AssertNoErr(t, err)
t.Logf("Update Account Response Headers: %+v\n", updateHeaders)
defer func() {
- updateres = raxAccounts.Update(c, raxAccounts.UpdateOpts{Metadata: map[string]string{"white": ""}})
+ updateres := raxAccounts.Update(c, raxAccounts.UpdateOpts{Metadata: map[string]string{"white": ""}})
th.AssertNoErr(t, updateres.Err)
metadata, err := raxAccounts.Get(c).ExtractMetadata()
th.AssertNoErr(t, err)
@@ -26,8 +25,13 @@
th.CheckEquals(t, metadata["White"], "")
}()
- metadata, err := raxAccounts.Get(c).ExtractMetadata()
- th.AssertNoErr(t, err)
+ getResp := raxAccounts.Get(c)
+ th.AssertNoErr(t, getResp.Err)
+
+ getHeaders, _ := getResp.Extract()
+ t.Logf("Get Account Response Headers: %+v\n", getHeaders)
+
+ metadata, _ := getResp.ExtractMetadata()
t.Logf("Metadata from Get Account request (after update): %+v\n", metadata)
th.CheckEquals(t, metadata["White"], "mountains")
diff --git a/acceptance/rackspace/objectstorage/v1/cdncontainers_test.go b/acceptance/rackspace/objectstorage/v1/cdncontainers_test.go
index e1bf38b..0f56f49 100644
--- a/acceptance/rackspace/objectstorage/v1/cdncontainers_test.go
+++ b/acceptance/rackspace/objectstorage/v1/cdncontainers_test.go
@@ -26,10 +26,11 @@
raxCDNClient, err := createClient(t, true)
th.AssertNoErr(t, err)
-
- r := raxCDNContainers.Enable(raxCDNClient, "gophercloud-test", raxCDNContainers.EnableOpts{CDNEnabled: true, TTL: 900})
- th.AssertNoErr(t, r.Err)
- t.Logf("Headers from Enable CDN Container request: %+v\n", r.Header)
+ enableRes := raxCDNContainers.Enable(raxCDNClient, "gophercloud-test", raxCDNContainers.EnableOpts{CDNEnabled: true, TTL: 900})
+ t.Logf("Header map from Enable CDN Container request: %+v\n", enableRes.Header)
+ enableHeader, err := enableRes.Extract()
+ th.AssertNoErr(t, err)
+ t.Logf("Headers from Enable CDN Container request: %+v\n", enableHeader)
t.Logf("Container Names available to the currently issued token:")
count := 0
@@ -51,11 +52,15 @@
t.Errorf("No CDN containers listed for your current token.")
}
- updateres := raxCDNContainers.Update(raxCDNClient, "gophercloud-test", raxCDNContainers.UpdateOpts{CDNEnabled: false})
- th.AssertNoErr(t, updateres.Err)
- t.Logf("Headers from Update CDN Container request: %+v\n", updateres.Header)
-
- metadata, err := raxCDNContainers.Get(raxCDNClient, "gophercloud-test").ExtractMetadata()
+ updateOpts := raxCDNContainers.UpdateOpts{XCDNEnabled: raxCDNContainers.Disabled, XLogRetention: raxCDNContainers.Enabled}
+ updateHeader, err := raxCDNContainers.Update(raxCDNClient, "gophercloud-test", updateOpts).Extract()
th.AssertNoErr(t, err)
- t.Logf("Headers from Get CDN Container request (after update): %+v\n", metadata)
+ t.Logf("Headers from Update CDN Container request: %+v\n", updateHeader)
+
+ getRes := raxCDNContainers.Get(raxCDNClient, "gophercloud-test")
+ getHeader, err := getRes.Extract()
+ th.AssertNoErr(t, err)
+ t.Logf("Headers from Get CDN Container request (after update): %+v\n", getHeader)
+ metadata, err := getRes.ExtractMetadata()
+ t.Logf("Metadata from Get CDN Container request (after update): %+v\n", metadata)
}
diff --git a/acceptance/rackspace/objectstorage/v1/containers_test.go b/acceptance/rackspace/objectstorage/v1/containers_test.go
index a7339cf..c895513 100644
--- a/acceptance/rackspace/objectstorage/v1/containers_test.go
+++ b/acceptance/rackspace/objectstorage/v1/containers_test.go
@@ -57,29 +57,34 @@
t.Errorf("No containers listed for your current token.")
}
- createres := raxContainers.Create(c, "gophercloud-test", nil)
- th.AssertNoErr(t, createres.Err)
+ createHeader, err := raxContainers.Create(c, "gophercloud-test", nil).Extract()
+ th.AssertNoErr(t, err)
+ t.Logf("Headers from Create Container request: %+v\n", createHeader)
defer func() {
- res := raxContainers.Delete(c, "gophercloud-test")
- th.AssertNoErr(t, res.Err)
+ deleteres := raxContainers.Delete(c, "gophercloud-test")
+ deleteHeader, err := deleteres.Extract()
+ th.AssertNoErr(t, err)
+ t.Logf("Headers from Delete Container request: %+v\n", deleteres.Header)
+ t.Logf("Headers from Delete Container request: %+v\n", deleteHeader)
}()
- updateres := raxContainers.Update(c, "gophercloud-test", raxContainers.UpdateOpts{Metadata: map[string]string{"white": "mountains"}})
- th.AssertNoErr(t, updateres.Err)
- t.Logf("Headers from Update Account request: %+v\n", updateres.Header)
+ updateHeader, err := raxContainers.Update(c, "gophercloud-test", raxContainers.UpdateOpts{Metadata: map[string]string{"white": "mountains"}}).Extract()
+ th.AssertNoErr(t, err)
+ t.Logf("Headers from Update Container request: %+v\n", updateHeader)
defer func() {
res := raxContainers.Update(c, "gophercloud-test", raxContainers.UpdateOpts{Metadata: map[string]string{"white": ""}})
th.AssertNoErr(t, res.Err)
metadata, err := raxContainers.Get(c, "gophercloud-test").ExtractMetadata()
th.AssertNoErr(t, err)
- t.Logf("Metadata from Get Account request (after update reverted): %+v\n", metadata)
+ t.Logf("Metadata from Get Container request (after update reverted): %+v\n", metadata)
th.CheckEquals(t, metadata["White"], "")
}()
getres := raxContainers.Get(c, "gophercloud-test")
- t.Logf("Headers from Get Account request (after update): %+v\n", getres.Header)
- metadata, err := getres.ExtractMetadata()
+ getHeader, err := getres.Extract()
th.AssertNoErr(t, err)
- t.Logf("Metadata from Get Account request (after update): %+v\n", metadata)
+ t.Logf("Headers from Get Container request (after update): %+v\n", getHeader)
+ metadata, err := getres.ExtractMetadata()
+ t.Logf("Metadata from Get Container request (after update): %+v\n", metadata)
th.CheckEquals(t, metadata["White"], "mountains")
}
diff --git a/rackspace/objectstorage/v1/cdncontainers/delegate.go b/rackspace/objectstorage/v1/cdncontainers/delegate.go
index d7eef20..89adb83 100644
--- a/rackspace/objectstorage/v1/cdncontainers/delegate.go
+++ b/rackspace/objectstorage/v1/cdncontainers/delegate.go
@@ -1,8 +1,6 @@
package cdncontainers
import (
- "strconv"
-
"github.com/rackspace/gophercloud"
os "github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers"
"github.com/rackspace/gophercloud/pagination"
@@ -38,34 +36,3 @@
func List(c *gophercloud.ServiceClient, opts os.ListOptsBuilder) pagination.Pager {
return os.List(c, opts)
}
-
-// 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) os.GetResult {
- return os.Get(c, containerName)
-}
-
-// UpdateOpts is a structure that holds parameters for updating, creating, or
-// deleting a container's metadata.
-type UpdateOpts struct {
- CDNEnabled bool `h:"X-Cdn-Enabled"`
- LogRetention bool `h:"X-Log-Retention"`
- TTL int `h:"X-Ttl"`
-}
-
-// 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
- }
- h["X-Cdn-Enabled"] = strconv.FormatBool(opts.CDNEnabled)
- return h, nil
-}
-
-// Update is a function that creates, updates, or deletes a container's
-// metadata.
-func Update(c *gophercloud.ServiceClient, containerName string, opts os.UpdateOptsBuilder) os.UpdateResult {
- return os.Update(c, containerName, opts)
-}
diff --git a/rackspace/objectstorage/v1/cdncontainers/requests.go b/rackspace/objectstorage/v1/cdncontainers/requests.go
index 0567833..05b1939 100644
--- a/rackspace/objectstorage/v1/cdncontainers/requests.go
+++ b/rackspace/objectstorage/v1/cdncontainers/requests.go
@@ -1,6 +1,8 @@
package cdncontainers
import (
+ "strconv"
+
"github.com/racker/perigee"
"github.com/rackspace/gophercloud"
)
@@ -56,3 +58,100 @@
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 := perigee.Request("HEAD", getURL(c, containerName), perigee.Options{
+ MoreHeaders: c.AuthenticatedHeaders(),
+ OkCodes: []int{200, 204},
+ })
+ res.Header = resp.HttpResponse.Header
+ res.Err = err
+ return res
+}
+
+// State is the state of an option. It is a pointer to a boolean to enable checking for
+// a zero-value of nil instead of false, which is a valid option.
+type State *bool
+
+var (
+ iTrue = true
+ iFalse = false
+
+ // Enabled is used for a true value for options in request bodies.
+ Enabled State = &iTrue
+ // Disabled is used for a false value for options in request bodies.
+ Disabled State = &iFalse
+)
+
+// 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 {
+ // Whether or not to CDN-enable a container. Prefer using XCDNEnabled, which
+ // is of type *bool underneath.
+ // TODO v2.0: change type to Enabled/Disabled (*bool)
+ CDNEnabled bool `h:"X-Cdn-Enabled"`
+ // Whether or not to enable log retention. Prefer using XLogRetention, which
+ // is of type *bool underneath.
+ // TODO v2.0: change type to Enabled/Disabled (*bool)
+ LogRetention bool `h:"X-Log-Retention"`
+ XCDNEnabled *bool
+ XLogRetention *bool
+ TTL int `h:"X-Ttl"`
+}
+
+// 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
+ }
+ h["X-Cdn-Enabled"] = strconv.FormatBool(opts.CDNEnabled)
+ h["X-Log-Retention"] = strconv.FormatBool(opts.LogRetention)
+
+ if opts.XCDNEnabled != nil {
+ h["X-Cdn-Enabled"] = strconv.FormatBool(*opts.XCDNEnabled)
+ }
+
+ if opts.XLogRetention != nil {
+ h["X-Log-Retention"] = strconv.FormatBool(*opts.XLogRetention)
+ }
+
+ 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 := perigee.Request("POST", updateURL(c, containerName), perigee.Options{
+ MoreHeaders: h,
+ OkCodes: []int{202, 204},
+ })
+ res.Header = resp.HttpResponse.Header
+ res.Err = err
+ return res
+}
diff --git a/rackspace/objectstorage/v1/cdncontainers/results.go b/rackspace/objectstorage/v1/cdncontainers/results.go
index a5097ca..cb0ad30 100644
--- a/rackspace/objectstorage/v1/cdncontainers/results.go
+++ b/rackspace/objectstorage/v1/cdncontainers/results.go
@@ -1,8 +1,149 @@
package cdncontainers
-import "github.com/rackspace/gophercloud"
+import (
+ "strings"
+ "time"
-// EnableResult represents the result of a get operation.
+ "github.com/rackspace/gophercloud"
+)
+
+// EnableHeader represents the headers returned in the response from an Enable request.
+type EnableHeader struct {
+ CDNIosURI string `mapstructure:"X-Cdn-Ios-Uri"`
+ CDNSslURI string `mapstructure:"X-Cdn-Ssl-Uri"`
+ CDNStreamingURI string `mapstructure:"X-Cdn-Streaming-Uri"`
+ CDNUri string `mapstructure:"X-Cdn-Uri"`
+ ContentLength int `mapstructure:"Content-Length"`
+ ContentType string `mapstructure:"Content-Type"`
+ Date time.Time `mapstructure:"-"`
+ TransID string `mapstructure:"X-Trans-Id"`
+}
+
+// EnableResult represents the result of an Enable operation.
type EnableResult struct {
gophercloud.HeaderResult
}
+
+// Extract will return extract an EnableHeader from the response to an Enable
+// request. To obtain a map of headers, call the ExtractHeader method on the EnableResult.
+func (er EnableResult) Extract() (EnableHeader, error) {
+ var eh EnableHeader
+ if er.Err != nil {
+ return eh, er.Err
+ }
+
+ if err := gophercloud.DecodeHeader(er.Header, &eh); err != nil {
+ return eh, err
+ }
+
+ if date, ok := er.Header["Date"]; ok && len(date) > 0 {
+ t, err := time.Parse(time.RFC1123, er.Header["Date"][0])
+ if err != nil {
+ return eh, err
+ }
+ eh.Date = t
+ }
+
+ return eh, nil
+}
+
+// GetHeader represents the headers returned in the response from a Get request.
+type GetHeader struct {
+ CDNEnabled bool `mapstructure:"X-Cdn-Enabled"`
+ CDNIosURI string `mapstructure:"X-Cdn-Ios-Uri"`
+ CDNSslURI string `mapstructure:"X-Cdn-Ssl-Uri"`
+ CDNStreamingURI string `mapstructure:"X-Cdn-Streaming-Uri"`
+ CDNUri string `mapstructure:"X-Cdn-Uri"`
+ ContentLength int `mapstructure:"Content-Length"`
+ ContentType string `mapstructure:"Content-Type"`
+ Date time.Time `mapstructure:"-"`
+ LogRetention bool `mapstructure:"X-Log-Retention"`
+ TransID string `mapstructure:"X-Trans-Id"`
+ TTL int `mapstructure:"X-Ttl"`
+}
+
+// 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
+}
+
+// UpdateHeader represents the headers returned in the response from a Update request.
+type UpdateHeader struct {
+ CDNIosURI string `mapstructure:"X-Cdn-Ios-Uri"`
+ CDNSslURI string `mapstructure:"X-Cdn-Ssl-Uri"`
+ CDNStreamingURI string `mapstructure:"X-Cdn-Streaming-Uri"`
+ CDNUri string `mapstructure:"X-Cdn-Uri"`
+ ContentLength int `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
+}
diff --git a/rackspace/objectstorage/v1/cdncontainers/urls.go b/rackspace/objectstorage/v1/cdncontainers/urls.go
index 80653f2..541249a 100644
--- a/rackspace/objectstorage/v1/cdncontainers/urls.go
+++ b/rackspace/objectstorage/v1/cdncontainers/urls.go
@@ -5,3 +5,11 @@
func enableURL(c *gophercloud.ServiceClient, containerName string) string {
return c.ServiceURL(containerName)
}
+
+func getURL(c *gophercloud.ServiceClient, container string) string {
+ return c.ServiceURL(container)
+}
+
+func updateURL(c *gophercloud.ServiceClient, container string) string {
+ return getURL(c, container)
+}