From 7b168604a131f997c27fdbff8f29ca0857333d9a Mon Sep 17 00:00:00 2001 From: Joe Topjian Date: Fri, 13 Jan 2017 03:47:20 -0700 Subject: [PATCH] vendor: Updating Gophercloud for OpenStack Provider (#11191) --- .../gophercloud/gophercloud/CONTRIBUTING.md | 235 ----------------- .../gophercloud/gophercloud/README.md | 2 +- .../blockstorage/v2/volumes/results.go | 87 +++++-- .../gophercloud/openstack/client.go | 12 + .../v2/extensions/secgroups/results.go | 67 ++++- .../openstack/compute/v2/servers/results.go | 60 ++--- .../openstack/identity/v2/tokens/results.go | 5 - .../openstack/identity/v3/tokens/results.go | 43 ++- .../objectstorage/v1/accounts/results.go | 99 +++---- .../objectstorage/v1/containers/results.go | 155 ++++++----- .../objectstorage/v1/objects/results.go | 246 +++++++++++------- .../gophercloud/gophercloud/params.go | 6 +- .../gophercloud/gophercloud/results.go | 74 ++++++ vendor/vendor.json | 196 +++++++------- 14 files changed, 645 insertions(+), 642 deletions(-) delete mode 100644 vendor/github.com/gophercloud/gophercloud/CONTRIBUTING.md diff --git a/vendor/github.com/gophercloud/gophercloud/CONTRIBUTING.md b/vendor/github.com/gophercloud/gophercloud/CONTRIBUTING.md deleted file mode 100644 index e9d5560bc..000000000 --- a/vendor/github.com/gophercloud/gophercloud/CONTRIBUTING.md +++ /dev/null @@ -1,235 +0,0 @@ -# Contributing to Gophercloud - -- [Getting started](#getting-started) -- [Tests](#tests) -- [Style guide](#basic-style-guide) -- [3 ways to get involved](#5-ways-to-get-involved) - -## Setting up your git workspace - -As a contributor you will need to setup your workspace in a slightly different -way than just downloading it. Here are the basic installation instructions: - -1. Configure your `$GOPATH` and run `go get` as described in the main -[README](/README.md#how-to-install) but add `-tags "fixtures acceptance"` to -get dependencies for unit and acceptance tests. - - ```bash - go get -tags "fixtures acceptance" github.com/gophercloud/gophercloud - ``` - -2. Move into the directory that houses your local repository: - - ```bash - cd ${GOPATH}/src/github.com/gophercloud/gophercloud - ``` - -3. Fork the `gophercloud/gophercloud` repository and update your remote refs. You -will need to rename the `origin` remote branch to `upstream`, and add your -fork as `origin` instead: - - ```bash - git remote rename origin upstream - git remote add origin git@github.com:/gophercloud.git - ``` - -4. Checkout the latest development branch: - - ```bash - git checkout master - ``` - -5. If you're working on something (discussed more in detail below), you will -need to checkout a new feature branch: - - ```bash - git checkout -b my-new-feature - ``` - -Another thing to bear in mind is that you will need to add a few extra -environment variables for acceptance tests - this is documented in our -[acceptance tests readme](/acceptance). - -## Tests - -When working on a new or existing feature, testing will be the backbone of your -work since it helps uncover and prevent regressions in the codebase. There are -two types of test we use in Gophercloud: unit tests and acceptance tests, which -are both described below. - -### Unit tests - -Unit tests are the fine-grained tests that establish and ensure the behavior -of individual units of functionality. We usually test on an -operation-by-operation basis (an operation typically being an API action) with -the use of mocking to set up explicit expectations. Each operation will set up -its HTTP response expectation, and then test how the system responds when fed -this controlled, pre-determined input. - -To make life easier, we've introduced a bunch of test helpers to simplify the -process of testing expectations with assertions: - -```go -import ( - "testing" - - "github.com/gophercloud/gophercloud/testhelper" -) - -func TestSomething(t *testing.T) { - result, err := Operation() - - testhelper.AssertEquals(t, "foo", result.Bar) - testhelper.AssertNoErr(t, err) -} - -func TestSomethingElse(t *testing.T) { - testhelper.CheckEquals(t, "expected", "actual") -} -``` - -`AssertEquals` and `AssertNoErr` will throw a fatal error if a value does not -match an expected value or if an error has been declared, respectively. You can -also use `CheckEquals` and `CheckNoErr` for the same purpose; the only difference -being that `t.Errorf` is raised rather than `t.Fatalf`. - -Here is a truncated example of mocked HTTP responses: - -```go -import ( - "testing" - - th "github.com/gophercloud/gophercloud/testhelper" - fake "github.com/gophercloud/gophercloud/testhelper/client" - "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" -) - -func TestGet(t *testing.T) { - // Setup the HTTP request multiplexer and server - th.SetupHTTP() - defer th.TeardownHTTP() - - th.Mux.HandleFunc("/networks/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) { - // Test we're using the correct HTTP method - th.TestMethod(t, r, "GET") - - // Test we're setting the auth token - th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) - - // Set the appropriate headers for our mocked response - w.Header().Add("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - - // Set the HTTP body - fmt.Fprintf(w, ` -{ - "network": { - "status": "ACTIVE", - "name": "private-network", - "admin_state_up": true, - "tenant_id": "4fd44f30292945e481c7b8a0c8908869", - "shared": true, - "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22" - } -} - `) - }) - - // Call our API operation - network, err := networks.Get(fake.ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22").Extract() - - // Assert no errors and equality - th.AssertNoErr(t, err) - th.AssertEquals(t, n.Status, "ACTIVE") -} -``` - -### Acceptance tests - -As we've already mentioned, unit tests have a very narrow and confined focus - -they test small units of behavior. Acceptance tests on the other hand have a -far larger scope: they are fully functional tests that test the entire API of a -service in one fell swoop. They don't care about unit isolation or mocking -expectations, they instead do a full run-through and consequently test how the -entire system _integrates_ together. When an API satisfies expectations, it -proves by default that the requirements for a contract have been met. - -Please be aware that acceptance tests will hit a live API - and may incur -service charges from your provider. Although most tests handle their own -teardown procedures, it is always worth manually checking that resources are -deleted after the test suite finishes. - -### Running tests - -To run all tests: - -```bash -go test -tags fixtures ./... -``` - -To run all tests with verbose output: - -```bash -go test -v -tags fixtures ./... -``` - -To run tests that match certain [build tags](): - -```bash -go test -tags "fixtures foo bar" ./... -``` - -To run tests for a particular sub-package: - -```bash -cd ./path/to/package && go test -tags fixtures . -``` - -## Style guide - -See [here](/STYLEGUIDE.md) - -## 3 ways to get involved - -There are five main ways you can get involved in our open-source project, and -each is described briefly below. Once you've made up your mind and decided on -your fix, you will need to follow the same basic steps that all submissions are -required to adhere to: - -1. [fork](https://help.github.com/articles/fork-a-repo/) the `gophercloud/gophercloud` repository -2. checkout a [new branch](https://github.com/Kunena/Kunena-Forum/wiki/Create-a-new-branch-with-git-and-manage-branches) -3. submit your branch as a [pull request](https://help.github.com/articles/creating-a-pull-request/) - -### 1. Fixing bugs - -If you want to start fixing open bugs, we'd really appreciate that! Bug fixing -is central to any project. The best way to get started is by heading to our -[bug tracker](https://github.com/gophercloud/gophercloud/issues) and finding open -bugs that you think nobody is working on. It might be useful to comment on the -thread to see the current state of the issue and if anybody has made any -breakthroughs on it so far. - -### 2. Improving documentation -The best source of documentation is on [godoc.org](http://godoc.org). It is -automatically generated from the source code. - -If you feel that a certain section could be improved - whether it's to clarify -ambiguity, correct a technical mistake, or to fix a grammatical error - please -feel entitled to do so! We welcome doc pull requests with the same childlike -enthusiasm as any other contribution! - -###3. Working on a new feature - -If you've found something we've left out, definitely feel free to start work on -introducing that feature. It's always useful to open an issue or submit a pull -request early on to indicate your intent to a core contributor - this enables -quick/early feedback and can help steer you in the right direction by avoiding -known issues. It might also help you avoid losing time implementing something -that might not ever work. One tip is to prefix your Pull Request issue title -with [wip] - then people know it's a work in progress. - -You must ensure that all of your work is well tested - both in terms of unit -and acceptance tests. Untested code will not be merged because it introduces -too much of a risk to end-users. - -Happy hacking! diff --git a/vendor/github.com/gophercloud/gophercloud/README.md b/vendor/github.com/gophercloud/gophercloud/README.md index 4d2efaf87..0e1fe0630 100644 --- a/vendor/github.com/gophercloud/gophercloud/README.md +++ b/vendor/github.com/gophercloud/gophercloud/README.md @@ -131,7 +131,7 @@ None. Vendor it and write tests covering the parts you use. ## Contributing -See the [contributing guide](./CONTRIBUTING.md). +See the [contributing guide](./.github/CONTRIBUTING.md). ## Help and feedback diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes/results.go index 2ad94cd9a..674ec3468 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes/results.go @@ -1,18 +1,38 @@ package volumes import ( + "encoding/json" + "time" + "github.com/gophercloud/gophercloud" "github.com/gophercloud/gophercloud/pagination" ) type Attachment struct { - AttachedAt gophercloud.JSONRFC3339MilliNoZ `json:"attached_at"` - AttachmentID string `json:"attachment_id"` - Device string `json:"device"` - HostName string `json:"host_name"` - ID string `json:"id"` - ServerID string `json:"server_id"` - VolumeID string `json:"volume_id"` + AttachedAt time.Time `json:"-"` + AttachmentID string `json:"attachment_id"` + Device string `json:"device"` + HostName string `json:"host_name"` + ID string `json:"id"` + ServerID string `json:"server_id"` + VolumeID string `json:"volume_id"` +} + +func (r *Attachment) UnmarshalJSON(b []byte) error { + type tmp Attachment + var s struct { + tmp + AttachedAt gophercloud.JSONRFC3339MilliNoZ `json:"attached_at"` + } + err := json.Unmarshal(b, &s) + if err != nil { + return err + } + *r = Attachment(s.tmp) + + r.AttachedAt = time.Time(s.AttachedAt) + + return err } // Volume contains all the information associated with an OpenStack Volume. @@ -26,9 +46,9 @@ type Volume struct { // AvailabilityZone is which availability zone the volume is in. AvailabilityZone string `json:"availability_zone"` // The date when this volume was created. - CreatedAt gophercloud.JSONRFC3339MilliNoZ `json:"created_at"` + CreatedAt time.Time `json:"-"` // The date when this volume was last updated - UpdatedAt gophercloud.JSONRFC3339MilliNoZ `json:"updated_at"` + UpdatedAt time.Time `json:"-"` // Instances onto which the volume is attached. Attachments []Attachment `json:"attachments"` // Human-readable display name for the volume. @@ -57,15 +77,24 @@ type Volume struct { Multiattach bool `json:"multiattach"` } -/* -THESE BELONG IN EXTENSIONS: -// ReplicationDriverData contains data about the replication driver. -ReplicationDriverData string `json:"os-volume-replication:driver_data"` -// ReplicationExtendedStatus contains extended status about replication. -ReplicationExtendedStatus string `json:"os-volume-replication:extended_status"` -// TenantID is the id of the project that owns the volume. -TenantID string `json:"os-vol-tenant-attr:tenant_id"` -*/ +func (r *Volume) UnmarshalJSON(b []byte) error { + type tmp Volume + var s struct { + tmp + CreatedAt gophercloud.JSONRFC3339MilliNoZ `json:"created_at"` + UpdatedAt gophercloud.JSONRFC3339MilliNoZ `json:"updated_at"` + } + err := json.Unmarshal(b, &s) + if err != nil { + return err + } + *r = Volume(s.tmp) + + r.CreatedAt = time.Time(s.CreatedAt) + r.UpdatedAt = time.Time(s.UpdatedAt) + + return err +} // VolumePage is a pagination.pager that is returned from a call to the List function. type VolumePage struct { @@ -80,11 +109,9 @@ func (r VolumePage) IsEmpty() (bool, error) { // ExtractVolumes extracts and returns Volumes. It is used while iterating over a volumes.List call. func ExtractVolumes(r pagination.Page) ([]Volume, error) { - var s struct { - Volumes []Volume `json:"volumes"` - } - err := (r.(VolumePage)).ExtractInto(&s) - return s.Volumes, err + var s []Volume + err := ExtractVolumesInto(r, &s) + return s, err } type commonResult struct { @@ -93,11 +120,17 @@ type commonResult struct { // Extract will get the Volume object out of the commonResult object. func (r commonResult) Extract() (*Volume, error) { - var s struct { - Volume *Volume `json:"volume"` - } + var s Volume err := r.ExtractInto(&s) - return s.Volume, err + return &s, err +} + +func (r commonResult) ExtractInto(v interface{}) error { + return r.Result.ExtractIntoStructPtr(v, "volume") +} + +func ExtractVolumesInto(r pagination.Page, v interface{}) error { + return r.(VolumePage).Result.ExtractIntoSlicePtr(v, "volumes") } // CreateResult contains the response body and error from a Create request. diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/client.go b/vendor/github.com/gophercloud/gophercloud/openstack/client.go index 3664cbcbb..6e61944a1 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/client.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/client.go @@ -309,3 +309,15 @@ func NewDBV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (* } return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil } + +// NewImageServiceV2 creates a ServiceClient that may be used to access the v2 image service. +func NewImageServiceV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { + eo.ApplyDefaults("image") + url, err := client.EndpointLocator(eo) + if err != nil { + return nil, err + } + return &gophercloud.ServiceClient{ProviderClient: client, + Endpoint: url, + ResourceBase: url + "v2/"}, nil +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/secgroups/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/secgroups/results.go index 764f5806f..f49338a1d 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/secgroups/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/secgroups/results.go @@ -1,6 +1,9 @@ package secgroups import ( + "encoding/json" + "strconv" + "github.com/gophercloud/gophercloud" "github.com/gophercloud/gophercloud/pagination" ) @@ -10,28 +13,51 @@ type SecurityGroup struct { // The unique ID of the group. If Neutron is installed, this ID will be // represented as a string UUID; if Neutron is not installed, it will be a // numeric ID. For the sake of consistency, we always cast it to a string. - ID string + ID string `json:"-"` // The human-readable name of the group, which needs to be unique. - Name string + Name string `json:"name"` // The human-readable description of the group. - Description string + Description string `json:"description"` // The rules which determine how this security group operates. - Rules []Rule + Rules []Rule `json:"rules"` // The ID of the tenant to which this security group belongs. TenantID string `json:"tenant_id"` } +func (r *SecurityGroup) UnmarshalJSON(b []byte) error { + type tmp SecurityGroup + var s struct { + tmp + ID interface{} `json:"id"` + } + err := json.Unmarshal(b, &s) + if err != nil { + return err + } + + *r = SecurityGroup(s.tmp) + + switch t := s.ID.(type) { + case float64: + r.ID = strconv.FormatFloat(t, 'f', -1, 64) + case string: + r.ID = t + } + + return err +} + // Rule represents a security group rule, a policy which determines how a // security group operates and what inbound traffic it allows in. type Rule struct { // The unique ID. If Neutron is installed, this ID will be // represented as a string UUID; if Neutron is not installed, it will be a // numeric ID. For the sake of consistency, we always cast it to a string. - ID string + ID string `json:"-"` // The lower bound of the port range which this security group should open up FromPort int `json:"from_port"` @@ -52,6 +78,37 @@ type Rule struct { Group Group } +func (r *Rule) UnmarshalJSON(b []byte) error { + type tmp Rule + var s struct { + tmp + ID interface{} `json:"id"` + ParentGroupID interface{} `json:"parent_group_id"` + } + err := json.Unmarshal(b, &s) + if err != nil { + return err + } + + *r = Rule(s.tmp) + + switch t := s.ID.(type) { + case float64: + r.ID = strconv.FormatFloat(t, 'f', -1, 64) + case string: + r.ID = t + } + + switch t := s.ParentGroupID.(type) { + case float64: + r.ParentGroupID = strconv.FormatFloat(t, 'f', -1, 64) + case string: + r.ParentGroupID = t + } + + return err +} + // IPRange represents the IP range whose traffic will be accepted by the // security group. type IPRange struct { diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/results.go index a23923a76..c121a6be7 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/results.go @@ -7,6 +7,7 @@ import ( "fmt" "net/url" "path" + "time" "github.com/gophercloud/gophercloud" "github.com/gophercloud/gophercloud/pagination" @@ -101,12 +102,12 @@ func decryptPassword(encryptedPassword string, privateKey *rsa.PrivateKey) (stri } // ExtractImageID gets the ID of the newly created server image from the header -func (res CreateImageResult) ExtractImageID() (string, error) { - if res.Err != nil { - return "", res.Err +func (r CreateImageResult) ExtractImageID() (string, error) { + if r.Err != nil { + return "", r.Err } // Get the image id from the header - u, err := url.ParseRequestURI(res.Header.Get("Location")) + u, err := url.ParseRequestURI(r.Header.Get("Location")) if err != nil { return "", err } @@ -137,26 +138,27 @@ type Server struct { // Name contains the human-readable name for the server. Name string `json:"name"` // Updated and Created contain ISO-8601 timestamps of when the state of the server last changed, and when it was created. - Updated string - Created string - HostID string + Updated time.Time `json:"updated"` + Created time.Time `json:"created"` + HostID string `json:"hostid"` // Status contains the current operational status of the server, such as IN_PROGRESS or ACTIVE. - Status string + Status string `json:"status"` // Progress ranges from 0..100. // A request made against the server completes only once Progress reaches 100. - Progress int + Progress int `json:"progress"` // AccessIPv4 and AccessIPv6 contain the IP addresses of the server, suitable for remote access for administration. - AccessIPv4, AccessIPv6 string + AccessIPv4 string `json:"accessIPv4"` + AccessIPv6 string `json:"accessIPv6"` // Image refers to a JSON object, which itself indicates the OS image used to deploy the server. - Image map[string]interface{} + Image map[string]interface{} `json:"-"` // Flavor refers to a JSON object, which itself indicates the hardware configuration of the deployed server. - Flavor map[string]interface{} + Flavor map[string]interface{} `json:"flavor"` // Addresses includes a list of all IP addresses assigned to the server, keyed by pool. - Addresses map[string]interface{} + Addresses map[string]interface{} `json:"addresses"` // Metadata includes a list of all user-specified key-value pairs attached to the server. - Metadata map[string]string + Metadata map[string]string `json:"metadata"` // Links includes HTTP references to the itself, useful for passing along to other APIs that might want a server reference. - Links []interface{} + Links []interface{} `json:"links"` // KeyName indicates which public key was injected into the server on launch. KeyName string `json:"key_name"` // AdminPass will generally be empty (""). However, it will contain the administrative password chosen when provisioning a new server without a set AdminPass setting in the first place. @@ -166,30 +168,30 @@ type Server struct { SecurityGroups []map[string]interface{} `json:"security_groups"` } -func (s *Server) UnmarshalJSON(b []byte) error { +func (r *Server) UnmarshalJSON(b []byte) error { type tmp Server - var server *struct { + var s struct { tmp - Image interface{} + Image interface{} `json:"image"` } - err := json.Unmarshal(b, &server) + err := json.Unmarshal(b, &s) if err != nil { return err } - *s = Server(server.tmp) + *r = Server(s.tmp) - switch t := server.Image.(type) { + switch t := s.Image.(type) { case map[string]interface{}: - s.Image = t + r.Image = t case string: switch t { case "": - s.Image = nil + r.Image = nil } } - return nil + return err } // ServerPage abstracts the raw results of making a List() request against the API. @@ -200,17 +202,17 @@ type ServerPage struct { } // IsEmpty returns true if a page contains no Server results. -func (page ServerPage) IsEmpty() (bool, error) { - servers, err := ExtractServers(page) - return len(servers) == 0, err +func (r ServerPage) IsEmpty() (bool, error) { + s, err := ExtractServers(r) + return len(s) == 0, err } // NextPageURL uses the response's embedded link reference to navigate to the next page of results. -func (page ServerPage) NextPageURL() (string, error) { +func (r ServerPage) NextPageURL() (string, error) { var s struct { Links []gophercloud.Link `json:"servers_links"` } - err := page.ExtractInto(&s) + err := r.ExtractInto(&s) if err != nil { return "", err } diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/results.go index 93c0554ae..6b3649370 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/results.go @@ -132,11 +132,6 @@ func (r CreateResult) ExtractServiceCatalog() (*ServiceCatalog, error) { return &ServiceCatalog{Entries: s.Access.Entries}, err } -// createErr quickly packs an error in a CreateResult. -func createErr(err error) CreateResult { - return CreateResult{gophercloud.Result{Err: err}} -} - // ExtractUser returns the User from a GetResult. func (r GetResult) ExtractUser() (*User, error) { var s struct { diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/results.go index 36c9ce619..0f1e8c2ba 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/results.go @@ -1,7 +1,10 @@ package tokens -import "errors" -import "github.com/gophercloud/gophercloud" +import ( + "time" + + "github.com/gophercloud/gophercloud" +) // Endpoint represents a single API endpoint offered by a service. // It matches either a public, internal or admin URL. @@ -35,7 +38,7 @@ type CatalogEntry struct { // ServiceCatalog provides a view into the service catalog from a previous, successful authentication. type ServiceCatalog struct { - Entries []CatalogEntry + Entries []CatalogEntry `json:"catalog"` } // commonResult is the deferred result of a Create or a Get call. @@ -51,34 +54,23 @@ func (r commonResult) Extract() (*Token, error) { // ExtractToken interprets a commonResult as a Token. func (r commonResult) ExtractToken() (*Token, error) { - var s struct { - Token *Token `json:"token"` - } - + var s Token err := r.ExtractInto(&s) if err != nil { return nil, err } - if s.Token == nil { - return nil, errors.New("'token' missing in JSON response") - } - // Parse the token itself from the stored headers. - s.Token.ID = r.Header.Get("X-Subject-Token") + s.ID = r.Header.Get("X-Subject-Token") - return s.Token, err + return &s, err } // ExtractServiceCatalog returns the ServiceCatalog that was generated along with the user's Token. func (r CreateResult) ExtractServiceCatalog() (*ServiceCatalog, error) { - var s struct { - Token struct { - Entries []CatalogEntry `json:"catalog"` - } `json:"token"` - } + var s ServiceCatalog err := r.ExtractInto(&s) - return &ServiceCatalog{Entries: s.Token.Entries}, err + return &s, err } // CreateResult defers the interpretation of a created token. @@ -87,13 +79,6 @@ type CreateResult struct { commonResult } -// createErr quickly creates a CreateResult that reports an error. -func createErr(err error) CreateResult { - return CreateResult{ - commonResult: commonResult{Result: gophercloud.Result{Err: err}}, - } -} - // GetResult is the deferred response from a Get call. type GetResult struct { commonResult @@ -110,5 +95,9 @@ type Token struct { // ID is the issued token. ID string `json:"id"` // ExpiresAt is the timestamp at which this token will no longer be accepted. - ExpiresAt gophercloud.JSONRFC3339Milli `json:"expires_at"` + ExpiresAt time.Time `json:"expires_at"` +} + +func (r commonResult) ExtractInto(v interface{}) error { + return r.ExtractIntoStructPtr(v, "token") } diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts/results.go index 216414b74..9bc834047 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts/results.go @@ -2,9 +2,9 @@ package accounts import ( "encoding/json" - "fmt" "strconv" "strings" + "time" "github.com/gophercloud/gophercloud" ) @@ -16,117 +16,124 @@ type UpdateResult struct { // UpdateHeader represents the headers returned in the response from an Update request. type UpdateHeader struct { - ContentLength int64 `json:"-"` - ContentType string `json:"Content-Type"` - TransID string `json:"X-Trans-Id"` - Date gophercloud.JSONRFC1123 `json:"Date"` + ContentLength int64 `json:"-"` + ContentType string `json:"Content-Type"` + TransID string `json:"X-Trans-Id"` + Date time.Time `json:"-"` } -func (h *UpdateHeader) UnmarshalJSON(b []byte) error { +func (r *UpdateHeader) UnmarshalJSON(b []byte) error { type tmp UpdateHeader - var updateHeader *struct { + var s struct { tmp - ContentLength string `json:"Content-Length"` + ContentLength string `json:"Content-Length"` + Date gophercloud.JSONRFC1123 `json:"Date"` } - err := json.Unmarshal(b, &updateHeader) + err := json.Unmarshal(b, &s) if err != nil { return err } - *h = UpdateHeader(updateHeader.tmp) + *r = UpdateHeader(s.tmp) - switch updateHeader.ContentLength { + switch s.ContentLength { case "": - h.ContentLength = 0 + r.ContentLength = 0 default: - h.ContentLength, err = strconv.ParseInt(updateHeader.ContentLength, 10, 64) + r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64) if err != nil { return err } } - return nil + r.Date = time.Time(s.Date) + + return err } // Extract will return a struct of headers returned from a call to Get. To obtain // a map of headers, call the ExtractHeader method on the GetResult. -func (ur UpdateResult) Extract() (*UpdateHeader, error) { - var uh *UpdateHeader - err := ur.ExtractInto(&uh) - return uh, err +func (r UpdateResult) Extract() (*UpdateHeader, error) { + var s *UpdateHeader + err := r.ExtractInto(&s) + return s, err } // GetHeader represents the headers returned in the response from a Get request. type GetHeader struct { - BytesUsed int64 `json:"-"` - ContainerCount int64 `json:"-"` - ContentLength int64 `json:"-"` - ObjectCount int64 `json:"-"` - ContentType string `json:"Content-Type"` - TransID string `json:"X-Trans-Id"` - TempURLKey string `json:"X-Account-Meta-Temp-URL-Key"` - TempURLKey2 string `json:"X-Account-Meta-Temp-URL-Key-2"` - Date gophercloud.JSONRFC1123 `json:"Date"` + BytesUsed int64 `json:"-"` + ContainerCount int64 `json:"-"` + ContentLength int64 `json:"-"` + ObjectCount int64 `json:"-"` + ContentType string `json:"Content-Type"` + TransID string `json:"X-Trans-Id"` + TempURLKey string `json:"X-Account-Meta-Temp-URL-Key"` + TempURLKey2 string `json:"X-Account-Meta-Temp-URL-Key-2"` + Date time.Time `json:"-"` } -func (h *GetHeader) UnmarshalJSON(b []byte) error { +func (r *GetHeader) UnmarshalJSON(b []byte) error { type tmp GetHeader - var getHeader *struct { + var s struct { tmp BytesUsed string `json:"X-Account-Bytes-Used"` ContentLength string `json:"Content-Length"` ContainerCount string `json:"X-Account-Container-Count"` ObjectCount string `json:"X-Account-Object-Count"` + Date string `json:"Date"` } - err := json.Unmarshal(b, &getHeader) + err := json.Unmarshal(b, &s) if err != nil { return err } - *h = GetHeader(getHeader.tmp) + *r = GetHeader(s.tmp) - switch getHeader.BytesUsed { + switch s.BytesUsed { case "": - h.BytesUsed = 0 + r.BytesUsed = 0 default: - h.BytesUsed, err = strconv.ParseInt(getHeader.BytesUsed, 10, 64) + r.BytesUsed, err = strconv.ParseInt(s.BytesUsed, 10, 64) if err != nil { return err } } - fmt.Println("getHeader: ", getHeader.ContentLength) - switch getHeader.ContentLength { + switch s.ContentLength { case "": - h.ContentLength = 0 + r.ContentLength = 0 default: - h.ContentLength, err = strconv.ParseInt(getHeader.ContentLength, 10, 64) + r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64) if err != nil { return err } } - switch getHeader.ObjectCount { + switch s.ObjectCount { case "": - h.ObjectCount = 0 + r.ObjectCount = 0 default: - h.ObjectCount, err = strconv.ParseInt(getHeader.ObjectCount, 10, 64) + r.ObjectCount, err = strconv.ParseInt(s.ObjectCount, 10, 64) if err != nil { return err } } - switch getHeader.ContainerCount { + switch s.ContainerCount { case "": - h.ContainerCount = 0 + r.ContainerCount = 0 default: - h.ContainerCount, err = strconv.ParseInt(getHeader.ContainerCount, 10, 64) + r.ContainerCount, err = strconv.ParseInt(s.ContainerCount, 10, 64) if err != nil { return err } } - return nil + if s.Date != "" { + r.Date, err = time.Parse(time.RFC1123, s.Date) + } + + return err } // GetResult is returned from a call to the Get function. @@ -142,7 +149,7 @@ func (r GetResult) Extract() (*GetHeader, error) { return s, err } -// ExtractMetadata is a function that takes a GetResult (of type *http.Response) +// ExtractMetadata is a function that takes a GetResult (of type *htts.Response) // and returns the custom metatdata associated with the account. func (r GetResult) ExtractMetadata() (map[string]string, error) { if r.Err != nil { diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers/results.go index ebe6eba52..8c11b8c83 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers/results.go @@ -5,6 +5,7 @@ import ( "fmt" "strconv" "strings" + "time" "github.com/gophercloud/gophercloud" "github.com/gophercloud/gophercloud/pagination" @@ -88,69 +89,72 @@ func ExtractNames(page pagination.Page) ([]string, error) { // GetHeader represents the headers returned in the response from a Get request. type GetHeader struct { - AcceptRanges string `json:"Accept-Ranges"` - BytesUsed int64 `json:"-"` - ContentLength int64 `json:"-"` - ContentType string `json:"Content-Type"` - Date gophercloud.JSONRFC1123 `json:"Date"` - ObjectCount int64 `json:"-"` - Read []string `json:"-"` - TransID string `json:"X-Trans-Id"` - VersionsLocation string `json:"X-Versions-Location"` - Write []string `json:"-"` + AcceptRanges string `json:"Accept-Ranges"` + BytesUsed int64 `json:"-"` + ContentLength int64 `json:"-"` + ContentType string `json:"Content-Type"` + Date time.Time `json:"-"` + ObjectCount int64 `json:"-"` + Read []string `json:"-"` + TransID string `json:"X-Trans-Id"` + VersionsLocation string `json:"X-Versions-Location"` + Write []string `json:"-"` } -func (h *GetHeader) UnmarshalJSON(b []byte) error { +func (r *GetHeader) UnmarshalJSON(b []byte) error { type tmp GetHeader - var getHeader *struct { + var s struct { tmp - BytesUsed string `json:"X-Container-Bytes-Used"` - ContentLength string `json:"Content-Length"` - ObjectCount string `json:"X-Container-Object-Count"` - Write string `json:"X-Container-Write"` - Read string `json:"X-Container-Read"` + BytesUsed string `json:"X-Container-Bytes-Used"` + ContentLength string `json:"Content-Length"` + ObjectCount string `json:"X-Container-Object-Count"` + Write string `json:"X-Container-Write"` + Read string `json:"X-Container-Read"` + Date gophercloud.JSONRFC1123 `json:"Date"` } - err := json.Unmarshal(b, &getHeader) + err := json.Unmarshal(b, &s) if err != nil { return err } - *h = GetHeader(getHeader.tmp) + *r = GetHeader(s.tmp) - switch getHeader.BytesUsed { + switch s.BytesUsed { case "": - h.BytesUsed = 0 + r.BytesUsed = 0 default: - h.BytesUsed, err = strconv.ParseInt(getHeader.BytesUsed, 10, 64) + r.BytesUsed, err = strconv.ParseInt(s.BytesUsed, 10, 64) if err != nil { return err } } - switch getHeader.ContentLength { + switch s.ContentLength { case "": - h.ContentLength = 0 + r.ContentLength = 0 default: - h.ContentLength, err = strconv.ParseInt(getHeader.ContentLength, 10, 64) + r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64) if err != nil { return err } } - switch getHeader.ObjectCount { + switch s.ObjectCount { case "": - h.ObjectCount = 0 + r.ObjectCount = 0 default: - h.ObjectCount, err = strconv.ParseInt(getHeader.ObjectCount, 10, 64) + r.ObjectCount, err = strconv.ParseInt(s.ObjectCount, 10, 64) if err != nil { return err } } - h.Read = strings.Split(getHeader.Read, ",") - h.Write = strings.Split(getHeader.Write, ",") + r.Read = strings.Split(s.Read, ",") + r.Write = strings.Split(s.Write, ",") - return nil + r.Date = time.Time(s.Date) + + return err } // GetResult represents the result of a get operation. @@ -166,7 +170,7 @@ func (r GetResult) Extract() (*GetHeader, error) { return s, err } -// ExtractMetadata is a function that takes a GetResult (of type *http.Response) +// ExtractMetadata is a function that takes a GetResult (of type *stts.Response) // and returns the custom metadata associated with the container. func (r GetResult) ExtractMetadata() (map[string]string, error) { if r.Err != nil { @@ -184,36 +188,39 @@ func (r GetResult) ExtractMetadata() (map[string]string, error) { // CreateHeader represents the headers returned in the response from a Create request. type CreateHeader struct { - ContentLength int64 `json:"-"` - ContentType string `json:"Content-Type"` - Date gophercloud.JSONRFC1123 `json:"Date"` - TransID string `json:"X-Trans-Id"` + ContentLength int64 `json:"-"` + ContentType string `json:"Content-Type"` + Date time.Time `json:"-"` + TransID string `json:"X-Trans-Id"` } -func (h *CreateHeader) UnmarshalJSON(b []byte) error { +func (r *CreateHeader) UnmarshalJSON(b []byte) error { type tmp CreateHeader - var header *struct { + var s struct { tmp - ContentLength string `json:"Content-Length"` + ContentLength string `json:"Content-Length"` + Date gophercloud.JSONRFC1123 `json:"Date"` } - err := json.Unmarshal(b, &header) + err := json.Unmarshal(b, &s) if err != nil { return err } - *h = CreateHeader(header.tmp) + *r = CreateHeader(s.tmp) - switch header.ContentLength { + switch s.ContentLength { case "": - h.ContentLength = 0 + r.ContentLength = 0 default: - h.ContentLength, err = strconv.ParseInt(header.ContentLength, 10, 64) + r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64) if err != nil { return err } } - return nil + r.Date = time.Time(s.Date) + + return err } // CreateResult represents the result of a create operation. To extract the @@ -233,36 +240,39 @@ func (r CreateResult) Extract() (*CreateHeader, error) { // UpdateHeader represents the headers returned in the response from a Update request. type UpdateHeader struct { - ContentLength int64 `json:"-"` - ContentType string `json:"Content-Type"` - Date gophercloud.JSONRFC1123 `json:"Date"` - TransID string `json:"X-Trans-Id"` + ContentLength int64 `json:"-"` + ContentType string `json:"Content-Type"` + Date time.Time `json:"-"` + TransID string `json:"X-Trans-Id"` } -func (h *UpdateHeader) UnmarshalJSON(b []byte) error { +func (r *UpdateHeader) UnmarshalJSON(b []byte) error { type tmp UpdateHeader - var header *struct { + var s struct { tmp - ContentLength string `json:"Content-Length"` + ContentLength string `json:"Content-Length"` + Date gophercloud.JSONRFC1123 `json:"Date"` } - err := json.Unmarshal(b, &header) + err := json.Unmarshal(b, &s) if err != nil { return err } - *h = UpdateHeader(header.tmp) + *r = UpdateHeader(s.tmp) - switch header.ContentLength { + switch s.ContentLength { case "": - h.ContentLength = 0 + r.ContentLength = 0 default: - h.ContentLength, err = strconv.ParseInt(header.ContentLength, 10, 64) + r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64) if err != nil { return err } } - return nil + r.Date = time.Time(s.Date) + + return err } // UpdateResult represents the result of an update operation. To extract the @@ -282,36 +292,39 @@ func (r UpdateResult) Extract() (*UpdateHeader, error) { // DeleteHeader represents the headers returned in the response from a Delete request. type DeleteHeader struct { - ContentLength int64 `json:"-"` - ContentType string `json:"Content-Type"` - Date gophercloud.JSONRFC1123 `json:"Date"` - TransID string `json:"X-Trans-Id"` + ContentLength int64 `json:"-"` + ContentType string `json:"Content-Type"` + Date time.Time `json:"-"` + TransID string `json:"X-Trans-Id"` } -func (h *DeleteHeader) UnmarshalJSON(b []byte) error { +func (r *DeleteHeader) UnmarshalJSON(b []byte) error { type tmp DeleteHeader - var header *struct { + var s struct { tmp - ContentLength string `json:"Content-Length"` + ContentLength string `json:"Content-Length"` + Date gophercloud.JSONRFC1123 `json:"Date"` } - err := json.Unmarshal(b, &header) + err := json.Unmarshal(b, &s) if err != nil { return err } - *h = DeleteHeader(header.tmp) + *r = DeleteHeader(s.tmp) - switch header.ContentLength { + switch s.ContentLength { case "": - h.ContentLength = 0 + r.ContentLength = 0 default: - h.ContentLength, err = strconv.ParseInt(header.ContentLength, 10, 64) + r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64) if err != nil { return err } } - return nil + r.Date = time.Time(s.Date) + + return err } // DeleteResult represents the result of a delete operation. To extract the diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/results.go index 4f7020cfd..0dcdbe2fb 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/results.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "strconv" "strings" + "time" "github.com/gophercloud/gophercloud" "github.com/gophercloud/gophercloud/pagination" @@ -23,15 +24,34 @@ type Object struct { // Hash represents the MD5 checksum value of the object's content. Hash string `json:"hash"` - // LastModified is the RFC3339Milli time the object was last modified, represented - // as a string. For any given object (obj), this value may be parsed to a time.Time: - // lastModified, err := time.Parse(gophercloud.RFC3339Milli, obj.LastModified) - LastModified gophercloud.JSONRFC3339MilliNoZ `json:"last_modified"` + // LastModified is the time the object was last modified, represented + // as a string. + LastModified time.Time `json:"-"` // Name is the unique name for the object. Name string `json:"name"` } +func (r *Object) UnmarshalJSON(b []byte) error { + type tmp Object + var s *struct { + tmp + LastModified gophercloud.JSONRFC3339MilliNoZ `json:"last_modified"` + } + + err := json.Unmarshal(b, &s) + if err != nil { + return err + } + + *r = Object(s.tmp) + + r.LastModified = time.Time(s.LastModified) + + return nil + +} + // ObjectPage is a single page of objects that is returned from a call to the // List function. type ObjectPage struct { @@ -100,43 +120,50 @@ func ExtractNames(r pagination.Page) ([]string, error) { // DownloadHeader represents the headers returned in the response from a Download request. type DownloadHeader struct { - AcceptRanges string `json:"Accept-Ranges"` - ContentDisposition string `json:"Content-Disposition"` - ContentEncoding string `json:"Content-Encoding"` - ContentLength int64 `json:"-"` - ContentType string `json:"Content-Type"` - Date gophercloud.JSONRFC1123 `json:"Date"` - DeleteAt gophercloud.JSONUnix `json:"X-Delete-At"` - ETag string `json:"Etag"` - LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"` - ObjectManifest string `json:"X-Object-Manifest"` - StaticLargeObject bool `json:"X-Static-Large-Object"` - TransID string `json:"X-Trans-Id"` + AcceptRanges string `json:"Accept-Ranges"` + ContentDisposition string `json:"Content-Disposition"` + ContentEncoding string `json:"Content-Encoding"` + ContentLength int64 `json:"-"` + ContentType string `json:"Content-Type"` + Date time.Time `json:"-"` + DeleteAt time.Time `json:"-"` + ETag string `json:"Etag"` + LastModified time.Time `json:"-"` + ObjectManifest string `json:"X-Object-Manifest"` + StaticLargeObject bool `json:"X-Static-Large-Object"` + TransID string `json:"X-Trans-Id"` } -func (h *DownloadHeader) UnmarshalJSON(b []byte) error { +func (r *DownloadHeader) UnmarshalJSON(b []byte) error { type tmp DownloadHeader - var hTmp *struct { + var s struct { tmp - ContentLength string `json:"Content-Length"` + ContentLength string `json:"Content-Length"` + Date gophercloud.JSONRFC1123 `json:"Date"` + DeleteAt gophercloud.JSONUnix `json:"X-Delete-At"` + LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"` } - err := json.Unmarshal(b, &hTmp) + err := json.Unmarshal(b, &s) if err != nil { return err } - *h = DownloadHeader(hTmp.tmp) + *r = DownloadHeader(s.tmp) - switch hTmp.ContentLength { + switch s.ContentLength { case "": - h.ContentLength = 0 + r.ContentLength = 0 default: - h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64) + r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64) if err != nil { return err } } + r.Date = time.Time(s.Date) + r.DeleteAt = time.Time(s.DeleteAt) + r.LastModified = time.Time(s.LastModified) + return nil } @@ -174,42 +201,49 @@ func (r *DownloadResult) ExtractContent() ([]byte, error) { // GetHeader represents the headers returned in the response from a Get request. type GetHeader struct { - ContentDisposition string `json:"Content-Disposition"` - ContentEncoding string `json:"Content-Encoding"` - ContentLength int64 `json:"Content-Length"` - ContentType string `json:"Content-Type"` - Date gophercloud.JSONRFC1123 `json:"Date"` - DeleteAt gophercloud.JSONUnix `json:"X-Delete-At"` - ETag string `json:"Etag"` - LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"` - ObjectManifest string `json:"X-Object-Manifest"` - StaticLargeObject bool `json:"X-Static-Large-Object"` - TransID string `json:"X-Trans-Id"` + ContentDisposition string `json:"Content-Disposition"` + ContentEncoding string `json:"Content-Encoding"` + ContentLength int64 `json:"-"` + ContentType string `json:"Content-Type"` + Date time.Time `json:"-"` + DeleteAt time.Time `json:"-"` + ETag string `json:"Etag"` + LastModified time.Time `json:"-"` + ObjectManifest string `json:"X-Object-Manifest"` + StaticLargeObject bool `json:"X-Static-Large-Object"` + TransID string `json:"X-Trans-Id"` } -func (h *GetHeader) UnmarshalJSON(b []byte) error { +func (r *GetHeader) UnmarshalJSON(b []byte) error { type tmp GetHeader - var hTmp *struct { + var s struct { tmp - ContentLength string `json:"Content-Length"` + ContentLength string `json:"Content-Length"` + Date gophercloud.JSONRFC1123 `json:"Date"` + DeleteAt gophercloud.JSONUnix `json:"X-Delete-At"` + LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"` } - err := json.Unmarshal(b, &hTmp) + err := json.Unmarshal(b, &s) if err != nil { return err } - *h = GetHeader(hTmp.tmp) + *r = GetHeader(s.tmp) - switch hTmp.ContentLength { + switch s.ContentLength { case "": - h.ContentLength = 0 + r.ContentLength = 0 default: - h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64) + r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64) if err != nil { return err } } + r.Date = time.Time(s.Date) + r.DeleteAt = time.Time(s.DeleteAt) + r.LastModified = time.Time(s.LastModified) + return nil } @@ -244,37 +278,42 @@ func (r GetResult) ExtractMetadata() (map[string]string, error) { // CreateHeader represents the headers returned in the response from a Create request. type CreateHeader struct { - ContentLength int64 `json:"Content-Length"` - ContentType string `json:"Content-Type"` - Date gophercloud.JSONRFC1123 `json:"Date"` - ETag string `json:"Etag"` - LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"` - TransID string `json:"X-Trans-Id"` + ContentLength int64 `json:"-"` + ContentType string `json:"Content-Type"` + Date time.Time `json:"-"` + ETag string `json:"Etag"` + LastModified time.Time `json:"-"` + TransID string `json:"X-Trans-Id"` } -func (h *CreateHeader) UnmarshalJSON(b []byte) error { +func (r *CreateHeader) UnmarshalJSON(b []byte) error { type tmp CreateHeader - var hTmp *struct { + var s struct { tmp - ContentLength string `json:"Content-Length"` + ContentLength string `json:"Content-Length"` + Date gophercloud.JSONRFC1123 `json:"Date"` + LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"` } - err := json.Unmarshal(b, &hTmp) + err := json.Unmarshal(b, &s) if err != nil { return err } - *h = CreateHeader(hTmp.tmp) + *r = CreateHeader(s.tmp) - switch hTmp.ContentLength { + switch s.ContentLength { case "": - h.ContentLength = 0 + r.ContentLength = 0 default: - h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64) + r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64) if err != nil { return err } } + r.Date = time.Time(s.Date) + r.LastModified = time.Time(s.LastModified) + return nil } @@ -297,35 +336,38 @@ func (r CreateResult) Extract() (*CreateHeader, error) { // UpdateHeader represents the headers returned in the response from a Update request. type UpdateHeader struct { - ContentLength int64 `json:"Content-Length"` - ContentType string `json:"Content-Type"` - Date gophercloud.JSONRFC1123 `json:"Date"` - TransID string `json:"X-Trans-Id"` + ContentLength int64 `json:"-"` + ContentType string `json:"Content-Type"` + Date time.Time `json:"-"` + TransID string `json:"X-Trans-Id"` } -func (h *UpdateHeader) UnmarshalJSON(b []byte) error { +func (r *UpdateHeader) UnmarshalJSON(b []byte) error { type tmp UpdateHeader - var hTmp *struct { + var s struct { tmp - ContentLength string `json:"Content-Length"` + ContentLength string `json:"Content-Length"` + Date gophercloud.JSONRFC1123 `json:"Date"` } - err := json.Unmarshal(b, &hTmp) + err := json.Unmarshal(b, &s) if err != nil { return err } - *h = UpdateHeader(hTmp.tmp) + *r = UpdateHeader(s.tmp) - switch hTmp.ContentLength { + switch s.ContentLength { case "": - h.ContentLength = 0 + r.ContentLength = 0 default: - h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64) + r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64) if err != nil { return err } } + r.Date = time.Time(s.Date) + return nil } @@ -344,35 +386,38 @@ func (r UpdateResult) Extract() (*UpdateHeader, error) { // DeleteHeader represents the headers returned in the response from a Delete request. type DeleteHeader struct { - ContentLength int64 `json:"Content-Length"` - ContentType string `json:"Content-Type"` - Date gophercloud.JSONRFC1123 `json:"Date"` - TransID string `json:"X-Trans-Id"` + ContentLength int64 `json:"Content-Length"` + ContentType string `json:"Content-Type"` + Date time.Time `json:"-"` + TransID string `json:"X-Trans-Id"` } -func (h *DeleteHeader) UnmarshalJSON(b []byte) error { +func (r *DeleteHeader) UnmarshalJSON(b []byte) error { type tmp DeleteHeader - var hTmp *struct { + var s struct { tmp - ContentLength string `json:"Content-Length"` + ContentLength string `json:"Content-Length"` + Date gophercloud.JSONRFC1123 `json:"Date"` } - err := json.Unmarshal(b, &hTmp) + err := json.Unmarshal(b, &s) if err != nil { return err } - *h = DeleteHeader(hTmp.tmp) + *r = DeleteHeader(s.tmp) - switch hTmp.ContentLength { + switch s.ContentLength { case "": - h.ContentLength = 0 + r.ContentLength = 0 default: - h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64) + r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64) if err != nil { return err } } + r.Date = time.Time(s.Date) + return nil } @@ -391,39 +436,46 @@ func (r DeleteResult) Extract() (*DeleteHeader, error) { // CopyHeader represents the headers returned in the response from a Copy request. type CopyHeader struct { - ContentLength int64 `json:"Content-Length"` - ContentType string `json:"Content-Type"` - CopiedFrom string `json:"X-Copied-From"` - CopiedFromLastModified gophercloud.JSONRFC1123 `json:"X-Copied-From-Last-Modified"` - Date gophercloud.JSONRFC1123 `json:"Date"` - ETag string `json:"Etag"` - LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"` - TransID string `json:"X-Trans-Id"` + ContentLength int64 `json:"-"` + ContentType string `json:"Content-Type"` + CopiedFrom string `json:"X-Copied-From"` + CopiedFromLastModified time.Time `json:"-"` + Date time.Time `json:"-"` + ETag string `json:"Etag"` + LastModified time.Time `json:"-"` + TransID string `json:"X-Trans-Id"` } -func (h *CopyHeader) UnmarshalJSON(b []byte) error { +func (r *CopyHeader) UnmarshalJSON(b []byte) error { type tmp CopyHeader - var hTmp *struct { + var s struct { tmp - ContentLength string `json:"Content-Length"` + ContentLength string `json:"Content-Length"` + CopiedFromLastModified gophercloud.JSONRFC1123 `json:"X-Copied-From-Last-Modified"` + Date gophercloud.JSONRFC1123 `json:"Date"` + LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"` } - err := json.Unmarshal(b, &hTmp) + err := json.Unmarshal(b, &s) if err != nil { return err } - *h = CopyHeader(hTmp.tmp) + *r = CopyHeader(s.tmp) - switch hTmp.ContentLength { + switch s.ContentLength { case "": - h.ContentLength = 0 + r.ContentLength = 0 default: - h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64) + r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64) if err != nil { return err } } + r.Date = time.Time(s.Date) + r.CopiedFromLastModified = time.Time(s.CopiedFromLastModified) + r.LastModified = time.Time(s.LastModified) + return nil } diff --git a/vendor/github.com/gophercloud/gophercloud/params.go b/vendor/github.com/gophercloud/gophercloud/params.go index b7f95083f..e484fe1c1 100644 --- a/vendor/github.com/gophercloud/gophercloud/params.go +++ b/vendor/github.com/gophercloud/gophercloud/params.go @@ -232,7 +232,7 @@ func isZero(v reflect.Value) bool { if v.IsNil() { return true } - return isZero(v.Elem()) + return false case reflect.Func, reflect.Map, reflect.Slice: return v.IsNil() case reflect.Array: @@ -307,7 +307,11 @@ func BuildQueryString(opts interface{}) (*url.URL, error) { // if the field is set, add it to the slice of query pieces if !isZero(v) { + loop: switch v.Kind() { + case reflect.Ptr: + v = v.Elem() + goto loop case reflect.String: params.Add(tags[0], v.String()) case reflect.Int: diff --git a/vendor/github.com/gophercloud/gophercloud/results.go b/vendor/github.com/gophercloud/gophercloud/results.go index 8cca42158..76c16ef8f 100644 --- a/vendor/github.com/gophercloud/gophercloud/results.go +++ b/vendor/github.com/gophercloud/gophercloud/results.go @@ -3,8 +3,10 @@ package gophercloud import ( "bytes" "encoding/json" + "fmt" "io" "net/http" + "reflect" "strconv" "time" ) @@ -60,6 +62,78 @@ func (r Result) ExtractInto(to interface{}) error { return err } +func (r Result) extractIntoPtr(to interface{}, label string) error { + if label == "" { + return r.ExtractInto(&to) + } + + var m map[string]interface{} + err := r.ExtractInto(&m) + if err != nil { + return err + } + + b, err := json.Marshal(m[label]) + if err != nil { + return err + } + + err = json.Unmarshal(b, &to) + return err +} + +// ExtractIntoStructPtr will unmarshal the Result (r) into the provided +// interface{} (to). +// +// NOTE: For internal use only +// +// `to` must be a pointer to an underlying struct type +// +// If provided, `label` will be filtered out of the response +// body prior to `r` being unmarshalled into `to`. +func (r Result) ExtractIntoStructPtr(to interface{}, label string) error { + if r.Err != nil { + return r.Err + } + + t := reflect.TypeOf(to) + if k := t.Kind(); k != reflect.Ptr { + return fmt.Errorf("Expected pointer, got %v", k) + } + switch t.Elem().Kind() { + case reflect.Struct: + return r.extractIntoPtr(to, label) + default: + return fmt.Errorf("Expected pointer to struct, got: %v", t) + } +} + +// ExtractIntoSlicePtr will unmarshal the Result (r) into the provided +// interface{} (to). +// +// NOTE: For internal use only +// +// `to` must be a pointer to an underlying slice type +// +// If provided, `label` will be filtered out of the response +// body prior to `r` being unmarshalled into `to`. +func (r Result) ExtractIntoSlicePtr(to interface{}, label string) error { + if r.Err != nil { + return r.Err + } + + t := reflect.TypeOf(to) + if k := t.Kind(); k != reflect.Ptr { + return fmt.Errorf("Expected pointer, got %v", k) + } + switch t.Elem().Kind() { + case reflect.Slice: + return r.extractIntoPtr(to, label) + default: + return fmt.Errorf("Expected pointer to slice, got: %v", t) + } +} + // PrettyPrintJSON creates a string containing the full response body as // pretty-printed JSON. It's useful for capturing test fixtures and for // debugging extraction bugs. If you include its output in an issue related to diff --git a/vendor/vendor.json b/vendor/vendor.json index adff57916..bc60573b5 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -1282,268 +1282,268 @@ "revision": "2a60fc2ba6c19de80291203597d752e9ba58e4c0" }, { - "checksumSHA1": "WJ/6nt4LiRCzFQcaxfc/iodURPM=", + "checksumSHA1": "DkbpYqirk9i+2YDR5Ujzpot/oAg=", "path": "github.com/gophercloud/gophercloud", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { - "checksumSHA1": "KHRGRGaThzPw7fpZ+h6enJbSyDY=", + "checksumSHA1": "S3zTth9INyj1RfyHkQEvJAvRWvw=", "path": "github.com/gophercloud/gophercloud/openstack", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "XAKLUSwXSMGtbp+U874qU4MzT/A=", "path": "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions", - "revision": "d5eda9707e146108e4d424062b602fd97a71c2e6", - "revisionTime": "2016-11-14T18:28:31Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "PFD8SEqhArAy/6jRbIlYb5lp64k=", "path": "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { - "checksumSHA1": "Ucc8dbvgihRt/2YqLhBkBYXF8v0=", + "checksumSHA1": "B4IXSmq364HcBruvvV0QjDFxZgc=", "path": "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "w2wHF5eEBE89ZYlkS9GAJsSIq9U=", "path": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/bootfromvolume", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "pUlKsepGmWDd4PqPaK4W85pHsRU=", "path": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/floatingips", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "RWwUliHD65cWApdEo4ckOcPSArg=", "path": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "tOmntqlmZ/r8aObUChNloddLhwk=", "path": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { - "checksumSHA1": "IZQJSUx3hRGbhGrkm9Vtk1GP5XY=", + "checksumSHA1": "jNrUTQf+9dYfaD7YqvKwC+kGvyY=", "path": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/secgroups", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "ci4gzd7Uy9JC4NcQ2ms19pjtW6s=", "path": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "qBpGbX7LQMPATdO8XyQmU7IXDiI=", "path": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/startstop", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "5JuziAp9BSRA/z+8pTjVLTWeTw4=", "path": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/tenantnetworks", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "2VNgU0F9PDax5VKClvMLmbzuksw=", "path": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "a9xDFPigDjHlPlthknKlBduGvKY=", "path": "github.com/gophercloud/gophercloud/openstack/compute/v2/flavors", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "UGeqrw3KdPNRwDxl315MAYyy/uY=", "path": "github.com/gophercloud/gophercloud/openstack/compute/v2/images", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { - "checksumSHA1": "8rOLNDSqwz/DSKL1BoPqjtWSWAE=", + "checksumSHA1": "efmzF4m/gZ8nKJ5B9RcdQfgCy/o=", "path": "github.com/gophercloud/gophercloud/openstack/compute/v2/servers", - "revision": "21a44e132331d6d46ab4187411c85ced6b1a9963", - "revisionTime": "2016-11-08T07:34:31Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "1sVqsZBZBNhDXLY9XzjMkcOkcbg=", "path": "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { - "checksumSHA1": "q1VGeltZl57OidZ5UDxbMsnyV2g=", + "checksumSHA1": "AvUU5En9YpG25iLlcAPDgcQODjI=", "path": "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { - "checksumSHA1": "6M6ofb8ri5G+sZ8OiExLi7irdx8=", + "checksumSHA1": "ZKyEbJuIlvuZ9aUushINCXJHF4w=", "path": "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "aTHxjMlfNXFJ3l2TZyvIwqt/3kM=", "path": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "14ZhP0wE/WCL/6oujcML755AaH4=", "path": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/policies", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "sYET5A7WTyJ7dpuxR/VXYoReldw=", "path": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/rules", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "0UcU/7oQbhlnYKoT+I+T403U8MQ=", "path": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "Mjt7GwFygyqPxygY8xZZnUasHmk=", "path": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "mCTz2rnyVfhjJ+AD/WihCNcYWiY=", "path": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/members", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "B2mtHvADREtFLam72wyijyQh/Ds=", "path": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/monitors", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "pTr22CKKJ26yvhgd0SRxFF4jkEs=", "path": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/pools", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "E7/Z7g5O9o+ge+8YklheTpKgWNw=", "path": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/vips", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "mhpwj5tPv7Uw5aUfC55fhLPBcKo=", "path": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "5efJz6UH7JCFeav5ZCCzicXCFTU=", "path": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "TVFgBTz7B6bb1R4TWdgAkbE1/fk=", "path": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "xirjw9vJIN6rmkT3T56bfPfOLUM=", "path": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "FKwSMrpQf7b3TcCOQfh+ovoBShA=", "path": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "CsS/kI3VeLcSHzMKviFVDwqwgvk=", "path": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "zKOhFTL5BDZPMC58ZzZkryjskno=", "path": "github.com/gophercloud/gophercloud/openstack/networking/v2/networks", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "BE+CO3QrEGpIgv3Ee2ANZp1WtSo=", "path": "github.com/gophercloud/gophercloud/openstack/networking/v2/ports", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "wY0MY7RpX0Z2Y0rMmrAuYS6cHYA=", "path": "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { - "checksumSHA1": "yIerdfSMJRUnjh2EZikMhWcgwlY=", + "checksumSHA1": "LtdQKIKKRKe6FOGdBvrBz/bg1Gc=", "path": "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts", - "revision": "45720eeefeeeba03b2d7da500297ec68eeee51af", - "revisionTime": "2016-10-31T15:28:56Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { - "checksumSHA1": "5XMyCSYDLmv/b54K3HNNNCJdnBk=", + "checksumSHA1": "1lwXcRrM5A7iCfekbn3bpfNLe3g=", "path": "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { - "checksumSHA1": "CRiIA3oRRlKRDF2ZYnZT8rTlJBU=", + "checksumSHA1": "dotTh+ZsNiyv8e9Z4e0chPEZDKE=", "path": "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects", - "revision": "45720eeefeeeba03b2d7da500297ec68eeee51af", - "revisionTime": "2016-10-31T15:28:56Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "roxPPVwS2CjJhf0CApHNQxAX7EA=", "path": "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/swauth", - "revision": "d5eda9707e146108e4d424062b602fd97a71c2e6", - "revisionTime": "2016-11-14T18:28:31Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "TDOZnaS0TO0NirpxV1QwPerAQTY=", "path": "github.com/gophercloud/gophercloud/openstack/utils", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "pmpLcbUZ+EgLUmTbzMtGRq3haOU=", "path": "github.com/gophercloud/gophercloud/pagination", - "revision": "e3d6384a3714b335d075862e6eb0a681180643df", - "revisionTime": "2016-10-25T18:03:21Z" + "revision": "368deee20062b2c7a043f792d7d998abe621872e", + "revisionTime": "2017-01-12T21:19:23Z" }, { "checksumSHA1": "6tvhO5ieOvX9R6o0vtl19s0lr8E=",