vendor: Updating Gophercloud for OpenStack Provider (#11191)
This commit is contained in:
parent
a2c0b85b2d
commit
7b168604a1
|
@ -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:<my_username>/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!
|
|
@ -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
|
||||
|
||||
|
|
75
vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes/results.go
generated
vendored
75
vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes/results.go
generated
vendored
|
@ -1,12 +1,15 @@
|
|||
package volumes
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/gophercloud/gophercloud"
|
||||
"github.com/gophercloud/gophercloud/pagination"
|
||||
)
|
||||
|
||||
type Attachment struct {
|
||||
AttachedAt gophercloud.JSONRFC3339MilliNoZ `json:"attached_at"`
|
||||
AttachedAt time.Time `json:"-"`
|
||||
AttachmentID string `json:"attachment_id"`
|
||||
Device string `json:"device"`
|
||||
HostName string `json:"host_name"`
|
||||
|
@ -15,6 +18,23 @@ type Attachment struct {
|
|||
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.
|
||||
type Volume struct {
|
||||
// Unique identifier for the 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.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
60
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/results.go
generated
vendored
60
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/results.go
generated
vendored
|
@ -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
|
||||
}
|
||||
|
|
5
vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/results.go
generated
vendored
5
vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/results.go
generated
vendored
|
@ -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 {
|
||||
|
|
43
vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/results.go
generated
vendored
43
vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/results.go
generated
vendored
|
@ -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")
|
||||
}
|
||||
|
|
75
vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts/results.go
generated
vendored
75
vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts/results.go
generated
vendored
|
@ -2,9 +2,9 @@ package accounts
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gophercloud/gophercloud"
|
||||
)
|
||||
|
@ -19,41 +19,44 @@ type UpdateHeader struct {
|
|||
ContentLength int64 `json:"-"`
|
||||
ContentType string `json:"Content-Type"`
|
||||
TransID string `json:"X-Trans-Id"`
|
||||
Date gophercloud.JSONRFC1123 `json:"Date"`
|
||||
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"`
|
||||
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.
|
||||
|
@ -66,67 +69,71 @@ type GetHeader struct {
|
|||
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"`
|
||||
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 {
|
||||
|
|
103
vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers/results.go
generated
vendored
103
vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers/results.go
generated
vendored
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gophercloud/gophercloud"
|
||||
"github.com/gophercloud/gophercloud/pagination"
|
||||
|
@ -92,7 +93,7 @@ type GetHeader struct {
|
|||
BytesUsed int64 `json:"-"`
|
||||
ContentLength int64 `json:"-"`
|
||||
ContentType string `json:"Content-Type"`
|
||||
Date gophercloud.JSONRFC1123 `json:"Date"`
|
||||
Date time.Time `json:"-"`
|
||||
ObjectCount int64 `json:"-"`
|
||||
Read []string `json:"-"`
|
||||
TransID string `json:"X-Trans-Id"`
|
||||
|
@ -100,57 +101,60 @@ type GetHeader struct {
|
|||
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"`
|
||||
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 {
|
||||
|
@ -186,34 +190,37 @@ func (r GetResult) ExtractMetadata() (map[string]string, error) {
|
|||
type CreateHeader struct {
|
||||
ContentLength int64 `json:"-"`
|
||||
ContentType string `json:"Content-Type"`
|
||||
Date gophercloud.JSONRFC1123 `json:"Date"`
|
||||
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"`
|
||||
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
|
||||
|
@ -235,34 +242,37 @@ func (r CreateResult) Extract() (*CreateHeader, error) {
|
|||
type UpdateHeader struct {
|
||||
ContentLength int64 `json:"-"`
|
||||
ContentType string `json:"Content-Type"`
|
||||
Date gophercloud.JSONRFC1123 `json:"Date"`
|
||||
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"`
|
||||
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
|
||||
|
@ -284,34 +294,37 @@ func (r UpdateResult) Extract() (*UpdateHeader, error) {
|
|||
type DeleteHeader struct {
|
||||
ContentLength int64 `json:"-"`
|
||||
ContentType string `json:"Content-Type"`
|
||||
Date gophercloud.JSONRFC1123 `json:"Date"`
|
||||
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"`
|
||||
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
|
||||
|
|
178
vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/results.go
generated
vendored
178
vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects/results.go
generated
vendored
|
@ -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 {
|
||||
|
@ -105,38 +125,45 @@ type DownloadHeader struct {
|
|||
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"`
|
||||
Date time.Time `json:"-"`
|
||||
DeleteAt time.Time `json:"-"`
|
||||
ETag string `json:"Etag"`
|
||||
LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"`
|
||||
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"`
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -176,40 +203,47 @@ func (r *DownloadResult) ExtractContent() ([]byte, error) {
|
|||
type GetHeader struct {
|
||||
ContentDisposition string `json:"Content-Disposition"`
|
||||
ContentEncoding string `json:"Content-Encoding"`
|
||||
ContentLength int64 `json:"Content-Length"`
|
||||
ContentLength int64 `json:"-"`
|
||||
ContentType string `json:"Content-Type"`
|
||||
Date gophercloud.JSONRFC1123 `json:"Date"`
|
||||
DeleteAt gophercloud.JSONUnix `json:"X-Delete-At"`
|
||||
Date time.Time `json:"-"`
|
||||
DeleteAt time.Time `json:"-"`
|
||||
ETag string `json:"Etag"`
|
||||
LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"`
|
||||
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"`
|
||||
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"`
|
||||
ContentLength int64 `json:"-"`
|
||||
ContentType string `json:"Content-Type"`
|
||||
Date gophercloud.JSONRFC1123 `json:"Date"`
|
||||
Date time.Time `json:"-"`
|
||||
ETag string `json:"Etag"`
|
||||
LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"`
|
||||
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"`
|
||||
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"`
|
||||
ContentLength int64 `json:"-"`
|
||||
ContentType string `json:"Content-Type"`
|
||||
Date gophercloud.JSONRFC1123 `json:"Date"`
|
||||
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"`
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -346,33 +388,36 @@ func (r UpdateResult) Extract() (*UpdateHeader, error) {
|
|||
type DeleteHeader struct {
|
||||
ContentLength int64 `json:"Content-Length"`
|
||||
ContentType string `json:"Content-Type"`
|
||||
Date gophercloud.JSONRFC1123 `json:"Date"`
|
||||
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"`
|
||||
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"`
|
||||
ContentLength int64 `json:"-"`
|
||||
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"`
|
||||
CopiedFromLastModified time.Time `json:"-"`
|
||||
Date time.Time `json:"-"`
|
||||
ETag string `json:"Etag"`
|
||||
LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"`
|
||||
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"`
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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=",
|
||||
|
|
Loading…
Reference in New Issue