Move deps from _workspace/ to vendor/
godep restore pushd $GOPATH/src/github.com/appc/spec git co master popd go get go4.org/errorutil rm -rf Godeps godep save ./... git add vendor git add -f $(git ls-files --other vendor/) git co -- Godeps/LICENSES Godeps/.license_file_state Godeps/OWNERS
This commit is contained in:
20
vendor/github.com/rackspace/gophercloud/.travis.yml
generated
vendored
Normal file
20
vendor/github.com/rackspace/gophercloud/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
language: go
|
||||
sudo: false
|
||||
install:
|
||||
- go get golang.org/x/crypto/ssh
|
||||
- go get -v -tags 'fixtures acceptance' ./...
|
||||
go:
|
||||
- 1.4
|
||||
- 1.5
|
||||
- tip
|
||||
env:
|
||||
- COVERALLS_TOKEN=2k7PTU3xa474Hymwgdj6XjqenNfGTNkO8
|
||||
before_install:
|
||||
- go get github.com/axw/gocov/gocov
|
||||
- go get github.com/mattn/goveralls
|
||||
- go get github.com/pierrre/gotestcover
|
||||
- if ! go get github.com/golang/tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi
|
||||
script:
|
||||
- $HOME/gopath/bin/gotestcover -v -tags=fixtures -coverprofile=cover.out ./...
|
||||
after_success:
|
||||
- $HOME/gopath/bin/goveralls -service=travis-ci -coverprofile=cover.out
|
275
vendor/github.com/rackspace/gophercloud/CONTRIBUTING.md
generated
vendored
Normal file
275
vendor/github.com/rackspace/gophercloud/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,275 @@
|
||||
# Contributing to gophercloud
|
||||
|
||||
- [Getting started](#getting-started)
|
||||
- [Tests](#tests)
|
||||
- [Style guide](#basic-style-guide)
|
||||
- [5 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.
|
||||
|
||||
2. Move into the directory that houses your local repository:
|
||||
|
||||
```bash
|
||||
cd ${GOPATH}/src/github.com/rackspace/gophercloud
|
||||
```
|
||||
|
||||
3. Fork the `rackspace/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
|
||||
```
|
||||
|
||||
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 behaviour
|
||||
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/rackspace/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/rackspace/gophercloud/testhelper"
|
||||
fake "github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
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 := 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 behaviour. 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 .
|
||||
```
|
||||
|
||||
## Basic style guide
|
||||
|
||||
We follow the standard formatting recommendations and language idioms set out
|
||||
in the [Effective Go](https://golang.org/doc/effective_go.html) guide. It's
|
||||
definitely worth reading - but the relevant sections are
|
||||
[formatting](https://golang.org/doc/effective_go.html#formatting)
|
||||
and [names](https://golang.org/doc/effective_go.html#names).
|
||||
|
||||
## 5 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 `rackspace/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. Providing feedback
|
||||
|
||||
On of the easiest ways to get readily involved in our project is to let us know
|
||||
about your experiences using our SDK. Feedback like this is incredibly useful
|
||||
to us, because it allows us to refine and change features based on what our
|
||||
users want and expect of us. There are a bunch of ways to get in contact! You
|
||||
can [ping us](https://developer.rackspace.com/support/) via e-mail, talk to us on irc
|
||||
(#rackspace-dev on freenode), [tweet us](https://twitter.com/rackspace), or
|
||||
submit an issue on our [bug tracker](/issues). Things you might like to tell us
|
||||
are:
|
||||
|
||||
* how easy was it to start using our SDK?
|
||||
* did it meet your expectations? If not, why not?
|
||||
* did our documentation help or hinder you?
|
||||
* what could we improve in general?
|
||||
|
||||
### 2. 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/rackspace/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.
|
||||
|
||||
### 3. Improving documentation
|
||||
|
||||
We have three forms of documentation:
|
||||
|
||||
* short README documents that briefly introduce a topic
|
||||
* reference documentation on [godoc.org](http://godoc.org) that is automatically
|
||||
generated from source code comments
|
||||
* user documentation on our [homepage](http://gophercloud.io) that includes
|
||||
getting started guides, installation guides and code samples
|
||||
|
||||
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!
|
||||
|
||||
### 4. Optimizing existing features
|
||||
|
||||
If you would like to improve or optimize an existing feature, please be aware
|
||||
that we adhere to [semantic versioning](http://semver.org) - which means that
|
||||
we cannot introduce breaking changes to the API without a major version change
|
||||
(v1.x -> v2.x). Making that leap is a big step, so we encourage contributors to
|
||||
refactor rather than rewrite. Running tests will prevent regression and avoid
|
||||
the possibility of breaking somebody's current implementation.
|
||||
|
||||
Another tip is to keep the focus of your work as small as possible - try not to
|
||||
introduce a change that affects lots and lots of files because it introduces
|
||||
added risk and increases the cognitive load on the reviewers checking your
|
||||
work. Change-sets which are easily understood and will not negatively impact
|
||||
users are more likely to be integrated quickly.
|
||||
|
||||
Lastly, if you're seeking to optimize a particular operation, you should try to
|
||||
demonstrate a negative performance impact - perhaps using go's inbuilt
|
||||
[benchmark capabilities](http://dave.cheney.net/2013/06/30/how-to-write-benchmarks-in-go).
|
||||
|
||||
### 5. 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!
|
13
vendor/github.com/rackspace/gophercloud/CONTRIBUTORS.md
generated
vendored
Normal file
13
vendor/github.com/rackspace/gophercloud/CONTRIBUTORS.md
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
Contributors
|
||||
============
|
||||
|
||||
| Name | Email |
|
||||
| ---- | ----- |
|
||||
| Samuel A. Falvo II | <sam.falvo@rackspace.com>
|
||||
| Glen Campbell | <glen.campbell@rackspace.com>
|
||||
| Jesse Noller | <jesse.noller@rackspace.com>
|
||||
| Jon Perritt | <jon.perritt@rackspace.com>
|
||||
| Ash Wilson | <ash.wilson@rackspace.com>
|
||||
| Jamie Hannaford | <jamie.hannaford@rackspace.com>
|
||||
| Don Schenck | don.schenck@rackspace.com>
|
||||
| Joe Topjian | <joe@topjian.net>
|
191
vendor/github.com/rackspace/gophercloud/LICENSE
generated
vendored
Normal file
191
vendor/github.com/rackspace/gophercloud/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
Copyright 2012-2013 Rackspace, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed
|
||||
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
------
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
160
vendor/github.com/rackspace/gophercloud/README.md
generated
vendored
Normal file
160
vendor/github.com/rackspace/gophercloud/README.md
generated
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
# Gophercloud: an OpenStack SDK for Go
|
||||
[](https://travis-ci.org/rackspace/gophercloud) [](https://coveralls.io/r/rackspace/gophercloud)
|
||||
|
||||
Gophercloud is a flexible SDK that allows you to consume and work with OpenStack
|
||||
clouds in a simple and idiomatic way using golang. Many services are supported,
|
||||
including Compute, Block Storage, Object Storage, Networking, and Identity.
|
||||
Each service API is backed with getting started guides, code samples, reference
|
||||
documentation, unit tests and acceptance tests.
|
||||
|
||||
## Useful links
|
||||
|
||||
* [Gophercloud homepage](http://gophercloud.io)
|
||||
* [Reference documentation](http://godoc.org/github.com/rackspace/gophercloud)
|
||||
* [Getting started guides](http://gophercloud.io/docs)
|
||||
* [Effective Go](https://golang.org/doc/effective_go.html)
|
||||
|
||||
## How to install
|
||||
|
||||
Before installing, you need to ensure that your [GOPATH environment variable](https://golang.org/doc/code.html#GOPATH)
|
||||
is pointing to an appropriate directory where you want to install Gophercloud:
|
||||
|
||||
```bash
|
||||
mkdir $HOME/go
|
||||
export GOPATH=$HOME/go
|
||||
```
|
||||
|
||||
To protect yourself against changes in your dependencies, we highly recommend choosing a
|
||||
[dependency management solution](https://github.com/golang/go/wiki/PackageManagementTools) for
|
||||
your projects, such as [godep](https://github.com/tools/godep). Once this is set up, you can install
|
||||
Gophercloud as a dependency like so:
|
||||
|
||||
```bash
|
||||
go get github.com/rackspace/gophercloud
|
||||
|
||||
# Edit your code to import relevant packages from "github.com/rackspace/gophercloud"
|
||||
|
||||
godep save ./...
|
||||
```
|
||||
|
||||
This will install all the source files you need into a `Godeps/_workspace` directory, which is
|
||||
referenceable from your own source files when you use the `godep go` command.
|
||||
|
||||
## Getting started
|
||||
|
||||
### Credentials
|
||||
|
||||
Because you'll be hitting an API, you will need to retrieve your OpenStack
|
||||
credentials and either store them as environment variables or in your local Go
|
||||
files. The first method is recommended because it decouples credential
|
||||
information from source code, allowing you to push the latter to your version
|
||||
control system without any security risk.
|
||||
|
||||
You will need to retrieve the following:
|
||||
|
||||
* username
|
||||
* password
|
||||
* tenant name or tenant ID
|
||||
* a valid Keystone identity URL
|
||||
|
||||
For users that have the OpenStack dashboard installed, there's a shortcut. If
|
||||
you visit the `project/access_and_security` path in Horizon and click on the
|
||||
"Download OpenStack RC File" button at the top right hand corner, you will
|
||||
download a bash file that exports all of your access details to environment
|
||||
variables. To execute the file, run `source admin-openrc.sh` and you will be
|
||||
prompted for your password.
|
||||
|
||||
### Authentication
|
||||
|
||||
Once you have access to your credentials, you can begin plugging them into
|
||||
Gophercloud. The next step is authentication, and this is handled by a base
|
||||
"Provider" struct. To get one, you can either pass in your credentials
|
||||
explicitly, or tell Gophercloud to use environment variables:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack"
|
||||
"github.com/rackspace/gophercloud/openstack/utils"
|
||||
)
|
||||
|
||||
// Option 1: Pass in the values yourself
|
||||
opts := gophercloud.AuthOptions{
|
||||
IdentityEndpoint: "https://my-openstack.com:5000/v2.0",
|
||||
Username: "{username}",
|
||||
Password: "{password}",
|
||||
TenantID: "{tenant_id}",
|
||||
}
|
||||
|
||||
// Option 2: Use a utility function to retrieve all your environment variables
|
||||
opts, err := openstack.AuthOptionsFromEnv()
|
||||
```
|
||||
|
||||
Once you have the `opts` variable, you can pass it in and get back a
|
||||
`ProviderClient` struct:
|
||||
|
||||
```go
|
||||
provider, err := openstack.AuthenticatedClient(opts)
|
||||
```
|
||||
|
||||
The `ProviderClient` is the top-level client that all of your OpenStack services
|
||||
derive from. The provider contains all of the authentication details that allow
|
||||
your Go code to access the API - such as the base URL and token ID.
|
||||
|
||||
### Provision a server
|
||||
|
||||
Once we have a base Provider, we inject it as a dependency into each OpenStack
|
||||
service. In order to work with the Compute API, we need a Compute service
|
||||
client; which can be created like so:
|
||||
|
||||
```go
|
||||
client, err := openstack.NewComputeV2(provider, gophercloud.EndpointOpts{
|
||||
Region: os.Getenv("OS_REGION_NAME"),
|
||||
})
|
||||
```
|
||||
|
||||
We then use this `client` for any Compute API operation we want. In our case,
|
||||
we want to provision a new server - so we invoke the `Create` method and pass
|
||||
in the flavor ID (hardware specification) and image ID (operating system) we're
|
||||
interested in:
|
||||
|
||||
```go
|
||||
import "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
|
||||
server, err := servers.Create(client, servers.CreateOpts{
|
||||
Name: "My new server!",
|
||||
FlavorRef: "flavor_id",
|
||||
ImageRef: "image_id",
|
||||
}).Extract()
|
||||
```
|
||||
|
||||
If you are unsure about what images and flavors are, you can read our [Compute
|
||||
Getting Started guide](http://gophercloud.io/docs/compute). The above code
|
||||
sample creates a new server with the parameters, and embodies the new resource
|
||||
in the `server` variable (a
|
||||
[`servers.Server`](http://godoc.org/github.com/rackspace/gophercloud) struct).
|
||||
|
||||
### Next steps
|
||||
|
||||
Cool! You've handled authentication, got your `ProviderClient` and provisioned
|
||||
a new server. You're now ready to use more OpenStack services.
|
||||
|
||||
* [Getting started with Compute](http://gophercloud.io/docs/compute)
|
||||
* [Getting started with Object Storage](http://gophercloud.io/docs/object-storage)
|
||||
* [Getting started with Networking](http://gophercloud.io/docs/networking)
|
||||
* [Getting started with Block Storage](http://gophercloud.io/docs/block-storage)
|
||||
* [Getting started with Identity](http://gophercloud.io/docs/identity)
|
||||
|
||||
## Contributing
|
||||
|
||||
Engaging the community and lowering barriers for contributors is something we
|
||||
care a lot about. For this reason, we've taken the time to write a [contributing
|
||||
guide](./CONTRIBUTING.md) for folks interested in getting involved in our project.
|
||||
If you're not sure how you can get involved, feel free to submit an issue or
|
||||
[contact us](https://developer.rackspace.com/support/). You don't need to be a
|
||||
Go expert - all members of the community are welcome!
|
||||
|
||||
## Help and feedback
|
||||
|
||||
If you're struggling with something or have spotted a potential bug, feel free
|
||||
to submit an issue to our [bug tracker](/issues) or [contact us directly](https://developer.rackspace.com/support/).
|
338
vendor/github.com/rackspace/gophercloud/UPGRADING.md
generated
vendored
Normal file
338
vendor/github.com/rackspace/gophercloud/UPGRADING.md
generated
vendored
Normal file
@@ -0,0 +1,338 @@
|
||||
# Upgrading to v1.0.0
|
||||
|
||||
With the arrival of this new major version increment, the unfortunate news is
|
||||
that breaking changes have been introduced to existing services. The API
|
||||
has been completely rewritten from the ground up to make the library more
|
||||
extensible, maintainable and easy-to-use.
|
||||
|
||||
Below we've compiled upgrade instructions for the various services that
|
||||
existed before. If you have a specific issue that is not addressed below,
|
||||
please [submit an issue](/issues/new) or
|
||||
[e-mail our support team](https://developer.rackspace.com/support/).
|
||||
|
||||
* [Authentication](#authentication)
|
||||
* [Servers](#servers)
|
||||
* [List servers](#list-servers)
|
||||
* [Get server details](#get-server-details)
|
||||
* [Create server](#create-server)
|
||||
* [Resize server](#resize-server)
|
||||
* [Reboot server](#reboot-server)
|
||||
* [Update server](#update-server)
|
||||
* [Rebuild server](#rebuild-server)
|
||||
* [Change admin password](#change-admin-password)
|
||||
* [Delete server](#delete-server)
|
||||
* [Rescue server](#rescue-server)
|
||||
* [Images and flavors](#images-and-flavors)
|
||||
* [List images](#list-images)
|
||||
* [List flavors](#list-flavors)
|
||||
* [Create/delete image](#createdelete-image)
|
||||
* [Other](#other)
|
||||
* [List keypairs](#list-keypairs)
|
||||
* [Create/delete keypair](#createdelete-keypair)
|
||||
* [List IP addresses](#list-ip-addresses)
|
||||
|
||||
# Authentication
|
||||
|
||||
One of the major differences that this release introduces is the level of
|
||||
sub-packaging to differentiate between services and providers. You now have
|
||||
the option of authenticating with OpenStack and other providers (like Rackspace).
|
||||
|
||||
To authenticate with a vanilla OpenStack installation, you can either specify
|
||||
your credentials like this:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack"
|
||||
)
|
||||
|
||||
opts := gophercloud.AuthOptions{
|
||||
IdentityEndpoint: "https://my-openstack.com:5000/v2.0",
|
||||
Username: "{username}",
|
||||
Password: "{password}",
|
||||
TenantID: "{tenant_id}",
|
||||
}
|
||||
```
|
||||
|
||||
Or have them pulled in through environment variables, like this:
|
||||
|
||||
```go
|
||||
opts, err := openstack.AuthOptionsFromEnv()
|
||||
```
|
||||
|
||||
Once you have your `AuthOptions` struct, you pass it in to get back a `Provider`,
|
||||
like so:
|
||||
|
||||
```go
|
||||
provider, err := openstack.AuthenticatedClient(opts)
|
||||
```
|
||||
|
||||
This provider is the top-level structure that all services are created from.
|
||||
|
||||
# Servers
|
||||
|
||||
Before you can interact with the Compute API, you need to retrieve a
|
||||
`gophercloud.ServiceClient`. To do this:
|
||||
|
||||
```go
|
||||
// Define your region, etc.
|
||||
opts := gophercloud.EndpointOpts{Region: "RegionOne"}
|
||||
|
||||
client, err := openstack.NewComputeV2(provider, opts)
|
||||
```
|
||||
|
||||
## List servers
|
||||
|
||||
All operations that involve API collections (servers, flavors, images) now use
|
||||
the `pagination.Pager` interface. This interface represents paginated entities
|
||||
that can be iterated over.
|
||||
|
||||
Once you have a Pager, you can then pass a callback function into its `EachPage`
|
||||
method, and this will allow you to traverse over the collection and execute
|
||||
arbitrary functionality. So, an example with list servers:
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
)
|
||||
|
||||
// We have the option of filtering the server list. If we want the full
|
||||
// collection, leave it as an empty struct or nil
|
||||
opts := servers.ListOpts{Name: "server_1"}
|
||||
|
||||
// Retrieve a pager (i.e. a paginated collection)
|
||||
pager := servers.List(client, opts)
|
||||
|
||||
// Define an anonymous function to be executed on each page's iteration
|
||||
err := pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
serverList, err := servers.ExtractServers(page)
|
||||
|
||||
// `s' will be a servers.Server struct
|
||||
for _, s := range serverList {
|
||||
fmt.Printf("We have a server. ID=%s, Name=%s", s.ID, s.Name)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Get server details
|
||||
|
||||
```go
|
||||
import "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
|
||||
// Get the HTTP result
|
||||
response := servers.Get(client, "server_id")
|
||||
|
||||
// Extract a Server struct from the response
|
||||
server, err := response.Extract()
|
||||
```
|
||||
|
||||
## Create server
|
||||
|
||||
```go
|
||||
import "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
|
||||
// Define our options
|
||||
opts := servers.CreateOpts{
|
||||
Name: "new_server",
|
||||
FlavorRef: "flavorID",
|
||||
ImageRef: "imageID",
|
||||
}
|
||||
|
||||
// Get our response
|
||||
response := servers.Create(client, opts)
|
||||
|
||||
// Extract
|
||||
server, err := response.Extract()
|
||||
```
|
||||
|
||||
## Change admin password
|
||||
|
||||
```go
|
||||
import "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
|
||||
result := servers.ChangeAdminPassword(client, "server_id", "newPassword_&123")
|
||||
```
|
||||
|
||||
## Resize server
|
||||
|
||||
```go
|
||||
import "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
|
||||
result := servers.Resize(client, "server_id", "new_flavor_id")
|
||||
```
|
||||
|
||||
## Reboot server
|
||||
|
||||
```go
|
||||
import "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
|
||||
// You have a choice of two reboot methods: servers.SoftReboot or servers.HardReboot
|
||||
result := servers.Reboot(client, "server_id", servers.SoftReboot)
|
||||
```
|
||||
|
||||
## Update server
|
||||
|
||||
```go
|
||||
import "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
|
||||
opts := servers.UpdateOpts{Name: "new_name"}
|
||||
|
||||
server, err := servers.Update(client, "server_id", opts).Extract()
|
||||
```
|
||||
|
||||
## Rebuild server
|
||||
|
||||
```go
|
||||
import "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
|
||||
// You have the option of specifying additional options
|
||||
opts := RebuildOpts{
|
||||
Name: "new_name",
|
||||
AdminPass: "admin_password",
|
||||
ImageID: "image_id",
|
||||
Metadata: map[string]string{"owner": "me"},
|
||||
}
|
||||
|
||||
result := servers.Rebuild(client, "server_id", opts)
|
||||
|
||||
// You can extract a servers.Server struct from the HTTP response
|
||||
server, err := result.Extract()
|
||||
```
|
||||
|
||||
## Delete server
|
||||
|
||||
```go
|
||||
import "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
|
||||
response := servers.Delete(client, "server_id")
|
||||
```
|
||||
|
||||
## Rescue server
|
||||
|
||||
The server rescue extension for Compute is not currently supported.
|
||||
|
||||
# Images and flavors
|
||||
|
||||
## List images
|
||||
|
||||
As with listing servers (see above), you first retrieve a Pager, and then pass
|
||||
in a callback over each page:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/images"
|
||||
)
|
||||
|
||||
// We have the option of filtering the image list. If we want the full
|
||||
// collection, leave it as an empty struct
|
||||
opts := images.ListOpts{ChangesSince: "2014-01-01T01:02:03Z", Name: "Ubuntu 12.04"}
|
||||
|
||||
// Retrieve a pager (i.e. a paginated collection)
|
||||
pager := images.List(client, opts)
|
||||
|
||||
// Define an anonymous function to be executed on each page's iteration
|
||||
err := pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
imageList, err := images.ExtractImages(page)
|
||||
|
||||
for _, i := range imageList {
|
||||
// "i" will be an images.Image
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## List flavors
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/flavors"
|
||||
)
|
||||
|
||||
// We have the option of filtering the flavor list. If we want the full
|
||||
// collection, leave it as an empty struct
|
||||
opts := flavors.ListOpts{ChangesSince: "2014-01-01T01:02:03Z", MinRAM: 4}
|
||||
|
||||
// Retrieve a pager (i.e. a paginated collection)
|
||||
pager := flavors.List(client, opts)
|
||||
|
||||
// Define an anonymous function to be executed on each page's iteration
|
||||
err := pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
flavorList, err := networks.ExtractFlavors(page)
|
||||
|
||||
for _, f := range flavorList {
|
||||
// "f" will be a flavors.Flavor
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Create/delete image
|
||||
|
||||
Image management has been shifted to Glance, but unfortunately this service is
|
||||
not supported as of yet. You can, however, list Compute images like so:
|
||||
|
||||
```go
|
||||
import "github.com/rackspace/gophercloud/openstack/compute/v2/images"
|
||||
|
||||
// Retrieve a pager (i.e. a paginated collection)
|
||||
pager := images.List(client, opts)
|
||||
|
||||
// Define an anonymous function to be executed on each page's iteration
|
||||
err := pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
imageList, err := images.ExtractImages(page)
|
||||
|
||||
for _, i := range imageList {
|
||||
// "i" will be an images.Image
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# Other
|
||||
|
||||
## List keypairs
|
||||
|
||||
```go
|
||||
import "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs"
|
||||
|
||||
// Retrieve a pager (i.e. a paginated collection)
|
||||
pager := keypairs.List(client, opts)
|
||||
|
||||
// Define an anonymous function to be executed on each page's iteration
|
||||
err := pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
keyList, err := keypairs.ExtractKeyPairs(page)
|
||||
|
||||
for _, k := range keyList {
|
||||
// "k" will be a keypairs.KeyPair
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Create/delete keypairs
|
||||
|
||||
To create a new keypair, you need to specify its name and, optionally, a
|
||||
pregenerated OpenSSH-formatted public key.
|
||||
|
||||
```go
|
||||
import "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs"
|
||||
|
||||
opts := keypairs.CreateOpts{
|
||||
Name: "new_key",
|
||||
PublicKey: "...",
|
||||
}
|
||||
|
||||
response := keypairs.Create(client, opts)
|
||||
|
||||
key, err := response.Extract()
|
||||
```
|
||||
|
||||
To delete an existing keypair:
|
||||
|
||||
```go
|
||||
response := keypairs.Delete(client, "keypair_id")
|
||||
```
|
||||
|
||||
## List IP addresses
|
||||
|
||||
This operation is not currently supported.
|
57
vendor/github.com/rackspace/gophercloud/acceptance/README.md
generated
vendored
Normal file
57
vendor/github.com/rackspace/gophercloud/acceptance/README.md
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
# Gophercloud Acceptance tests
|
||||
|
||||
The purpose of these acceptance tests is to validate that SDK features meet
|
||||
the requirements of a contract - to consumers, other parts of the library, and
|
||||
to a remote API.
|
||||
|
||||
> **Note:** Because every test will be run against a real API endpoint, you
|
||||
> may incur bandwidth and service charges for all the resource usage. These
|
||||
> tests *should* remove their remote products automatically. However, there may
|
||||
> be certain cases where this does not happen; always double-check to make sure
|
||||
> you have no stragglers left behind.
|
||||
|
||||
### Step 1. Set environment variables
|
||||
|
||||
A lot of tests rely on environment variables for configuration - so you will need
|
||||
to set them before running the suite. If you're testing against pure OpenStack APIs,
|
||||
you can download a file that contains all of these variables for you: just visit
|
||||
the `project/access_and_security` page in your control panel and click the "Download
|
||||
OpenStack RC File" button at the top right. For all other providers, you will need
|
||||
to set them manually.
|
||||
|
||||
#### Authentication
|
||||
|
||||
|Name|Description|
|
||||
|---|---|
|
||||
|`OS_USERNAME`|Your API username|
|
||||
|`OS_PASSWORD`|Your API password|
|
||||
|`OS_AUTH_URL`|The identity URL you need to authenticate|
|
||||
|`OS_TENANT_NAME`|Your API tenant name|
|
||||
|`OS_TENANT_ID`|Your API tenant ID|
|
||||
|`RS_USERNAME`|Your Rackspace username|
|
||||
|`RS_API_KEY`|Your Rackspace API key|
|
||||
|
||||
#### General
|
||||
|
||||
|Name|Description|
|
||||
|---|---|
|
||||
|`OS_REGION_NAME`|The region you want your resources to reside in|
|
||||
|`RS_REGION`|Rackspace region you want your resource to reside in|
|
||||
|
||||
#### Compute
|
||||
|
||||
|Name|Description|
|
||||
|---|---|
|
||||
|`OS_IMAGE_ID`|The ID of the image your want your server to be based on|
|
||||
|`OS_FLAVOR_ID`|The ID of the flavor you want your server to be based on|
|
||||
|`OS_FLAVOR_ID_RESIZE`|The ID of the flavor you want your server to be resized to|
|
||||
|`RS_IMAGE_ID`|The ID of the image you want servers to be created with|
|
||||
|`RS_FLAVOR_ID`|The ID of the flavor you want your server to be created with|
|
||||
|
||||
### 2. Run the test suite
|
||||
|
||||
From the root directory, run:
|
||||
|
||||
```
|
||||
./script/acceptancetest
|
||||
```
|
3
vendor/github.com/rackspace/gophercloud/acceptance/openstack/blockstorage/v1/pkg.go
generated
vendored
Normal file
3
vendor/github.com/rackspace/gophercloud/acceptance/openstack/blockstorage/v1/pkg.go
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
// The v1 package contains acceptance tests for the Openstack Cinder V1 service.
|
||||
|
||||
package v1
|
3
vendor/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/pkg.go
generated
vendored
Normal file
3
vendor/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/pkg.go
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
// The v2 package contains acceptance tests for the Openstack Compute V2 service.
|
||||
|
||||
package v2
|
70
vendor/github.com/rackspace/gophercloud/acceptance/openstack/db/v1/common.go
generated
vendored
Normal file
70
vendor/github.com/rackspace/gophercloud/acceptance/openstack/db/v1/common.go
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
// +build acceptance db
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack"
|
||||
"github.com/rackspace/gophercloud/openstack/db/v1/instances"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func newClient(t *testing.T) *gophercloud.ServiceClient {
|
||||
ao, err := openstack.AuthOptionsFromEnv()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
client, err := openstack.AuthenticatedClient(ao)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
c, err := openstack.NewDBV1(client, gophercloud.EndpointOpts{
|
||||
Region: os.Getenv("OS_REGION_NAME"),
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
type context struct {
|
||||
test *testing.T
|
||||
client *gophercloud.ServiceClient
|
||||
instanceID string
|
||||
DBIDs []string
|
||||
users []string
|
||||
}
|
||||
|
||||
func newContext(t *testing.T) context {
|
||||
return context{
|
||||
test: t,
|
||||
client: newClient(t),
|
||||
}
|
||||
}
|
||||
|
||||
func (c context) Logf(msg string, args ...interface{}) {
|
||||
if len(args) > 0 {
|
||||
c.test.Logf(msg, args...)
|
||||
} else {
|
||||
c.test.Log(msg)
|
||||
}
|
||||
}
|
||||
|
||||
func (c context) AssertNoErr(err error) {
|
||||
th.AssertNoErr(c.test, err)
|
||||
}
|
||||
|
||||
func (c context) WaitUntilActive(id string) {
|
||||
err := gophercloud.WaitFor(60, func() (bool, error) {
|
||||
inst, err := instances.Get(c.client, id).Extract()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if inst.Status == "ACTIVE" {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
|
||||
c.AssertNoErr(err)
|
||||
}
|
1
vendor/github.com/rackspace/gophercloud/acceptance/openstack/db/v1/pkg.go
generated
vendored
Normal file
1
vendor/github.com/rackspace/gophercloud/acceptance/openstack/db/v1/pkg.go
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
package v1
|
1
vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v2/pkg.go
generated
vendored
Normal file
1
vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v2/pkg.go
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
package v2
|
1
vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v3/pkg.go
generated
vendored
Normal file
1
vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v3/pkg.go
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
package v3
|
39
vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/common.go
generated
vendored
Normal file
39
vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/common.go
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
var Client *gophercloud.ServiceClient
|
||||
|
||||
func NewClient() (*gophercloud.ServiceClient, error) {
|
||||
opts, err := openstack.AuthOptionsFromEnv()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
provider, err := openstack.AuthenticatedClient(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return openstack.NewNetworkV2(provider, gophercloud.EndpointOpts{
|
||||
Name: "neutron",
|
||||
Region: os.Getenv("OS_REGION_NAME"),
|
||||
})
|
||||
}
|
||||
|
||||
func Setup(t *testing.T) {
|
||||
client, err := NewClient()
|
||||
th.AssertNoErr(t, err)
|
||||
Client = client
|
||||
}
|
||||
|
||||
func Teardown() {
|
||||
Client = nil
|
||||
}
|
1
vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/fwaas/pkg.go
generated
vendored
Normal file
1
vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/fwaas/pkg.go
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
package fwaas
|
78
vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/lbaas/common.go
generated
vendored
Normal file
78
vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/lbaas/common.go
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
package lbaas
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/networks"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/subnets"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func SetupTopology(t *testing.T) (string, string) {
|
||||
// create network
|
||||
n, err := networks.Create(base.Client, networks.CreateOpts{Name: "tmp_network"}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Created network %s", n.ID)
|
||||
|
||||
// create subnet
|
||||
s, err := subnets.Create(base.Client, subnets.CreateOpts{
|
||||
NetworkID: n.ID,
|
||||
CIDR: "192.168.199.0/24",
|
||||
IPVersion: subnets.IPv4,
|
||||
Name: "tmp_subnet",
|
||||
}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Created subnet %s", s.ID)
|
||||
|
||||
return n.ID, s.ID
|
||||
}
|
||||
|
||||
func DeleteTopology(t *testing.T, networkID string) {
|
||||
res := networks.Delete(base.Client, networkID)
|
||||
th.AssertNoErr(t, res.Err)
|
||||
t.Logf("Deleted network %s", networkID)
|
||||
}
|
||||
|
||||
func CreatePool(t *testing.T, subnetID string) string {
|
||||
p, err := pools.Create(base.Client, pools.CreateOpts{
|
||||
LBMethod: pools.LBMethodRoundRobin,
|
||||
Protocol: "HTTP",
|
||||
Name: "tmp_pool",
|
||||
SubnetID: subnetID,
|
||||
}).Extract()
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Created pool %s", p.ID)
|
||||
|
||||
return p.ID
|
||||
}
|
||||
|
||||
func DeletePool(t *testing.T, poolID string) {
|
||||
res := pools.Delete(base.Client, poolID)
|
||||
th.AssertNoErr(t, res.Err)
|
||||
t.Logf("Deleted pool %s", poolID)
|
||||
}
|
||||
|
||||
func CreateMonitor(t *testing.T) string {
|
||||
m, err := monitors.Create(base.Client, monitors.CreateOpts{
|
||||
Delay: 10,
|
||||
Timeout: 10,
|
||||
MaxRetries: 3,
|
||||
Type: monitors.TypeHTTP,
|
||||
ExpectedCodes: "200",
|
||||
URLPath: "/login",
|
||||
HTTPMethod: "GET",
|
||||
}).Extract()
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Created monitor ID [%s]", m.ID)
|
||||
|
||||
return m.ID
|
||||
}
|
1
vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/lbaas/pkg.go
generated
vendored
Normal file
1
vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/lbaas/pkg.go
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
package lbaas
|
1
vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/pkg.go
generated
vendored
Normal file
1
vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/pkg.go
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
package extensions
|
1
vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/pkg.go
generated
vendored
Normal file
1
vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/pkg.go
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
package v2
|
28
vendor/github.com/rackspace/gophercloud/acceptance/openstack/objectstorage/v1/common.go
generated
vendored
Normal file
28
vendor/github.com/rackspace/gophercloud/acceptance/openstack/objectstorage/v1/common.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
// +build acceptance
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
var metadata = map[string]string{"gopher": "cloud"}
|
||||
|
||||
func newClient(t *testing.T) *gophercloud.ServiceClient {
|
||||
ao, err := openstack.AuthOptionsFromEnv()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
client, err := openstack.AuthenticatedClient(ao)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
c, err := openstack.NewObjectStorageV1(client, gophercloud.EndpointOpts{
|
||||
Region: os.Getenv("OS_REGION_NAME"),
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
return c
|
||||
}
|
44
vendor/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/common.go
generated
vendored
Normal file
44
vendor/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/common.go
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
// +build acceptance
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
var template = fmt.Sprintf(`
|
||||
{
|
||||
"heat_template_version": "2013-05-23",
|
||||
"description": "Simple template to test heat commands",
|
||||
"parameters": {},
|
||||
"resources": {
|
||||
"hello_world": {
|
||||
"type":"OS::Nova::Server",
|
||||
"properties": {
|
||||
"flavor": "%s",
|
||||
"image": "%s",
|
||||
"user_data": "#!/bin/bash -xv\necho \"hello world\" > /root/hello-world.txt\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
}`, os.Getenv("OS_FLAVOR_ID"), os.Getenv("OS_IMAGE_ID"))
|
||||
|
||||
func newClient(t *testing.T) *gophercloud.ServiceClient {
|
||||
ao, err := openstack.AuthOptionsFromEnv()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
client, err := openstack.AuthenticatedClient(ao)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
c, err := openstack.NewOrchestrationV1(client, gophercloud.EndpointOpts{
|
||||
Region: os.Getenv("OS_REGION_NAME"),
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
return c
|
||||
}
|
13
vendor/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/hello-compute.json
generated
vendored
Normal file
13
vendor/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/hello-compute.json
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"heat_template_version": "2013-05-23",
|
||||
"resources": {
|
||||
"compute_instance": {
|
||||
"type": "OS::Nova::Server",
|
||||
"properties": {
|
||||
"flavor": "m1.small",
|
||||
"image": "cirros-0.3.2-x86_64-disk",
|
||||
"name": "Single Compute Instance"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
4
vendor/github.com/rackspace/gophercloud/acceptance/openstack/pkg.go
generated
vendored
Normal file
4
vendor/github.com/rackspace/gophercloud/acceptance/openstack/pkg.go
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
// +build acceptance
|
||||
|
||||
package openstack
|
||||
|
38
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/blockstorage/v1/common.go
generated
vendored
Normal file
38
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/blockstorage/v1/common.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
// +build acceptance
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/acceptance/tools"
|
||||
"github.com/rackspace/gophercloud/rackspace"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func newClient() (*gophercloud.ServiceClient, error) {
|
||||
opts, err := rackspace.AuthOptionsFromEnv()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opts = tools.OnlyRS(opts)
|
||||
region := os.Getenv("RS_REGION")
|
||||
|
||||
provider, err := rackspace.AuthenticatedClient(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return rackspace.NewBlockStorageV1(provider, gophercloud.EndpointOpts{
|
||||
Region: region,
|
||||
})
|
||||
}
|
||||
|
||||
func setup(t *testing.T) *gophercloud.ServiceClient {
|
||||
client, err := newClient()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
return client
|
||||
}
|
23
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/cdn/v1/common.go
generated
vendored
Normal file
23
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/cdn/v1/common.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
// +build acceptance
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/rackspace"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func newClient(t *testing.T) *gophercloud.ServiceClient {
|
||||
ao, err := rackspace.AuthOptionsFromEnv()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
client, err := rackspace.AuthenticatedClient(ao)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
c, err := rackspace.NewCDNV1(client, gophercloud.EndpointOpts{})
|
||||
th.AssertNoErr(t, err)
|
||||
return c
|
||||
}
|
1
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/compute/v2/pkg.go
generated
vendored
Normal file
1
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/compute/v2/pkg.go
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
package v2
|
73
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/db/v1/common.go
generated
vendored
Normal file
73
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/db/v1/common.go
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
// +build acceptance db rackspace
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/acceptance/tools"
|
||||
"github.com/rackspace/gophercloud/rackspace"
|
||||
"github.com/rackspace/gophercloud/rackspace/db/v1/instances"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func newClient(t *testing.T) *gophercloud.ServiceClient {
|
||||
opts, err := rackspace.AuthOptionsFromEnv()
|
||||
th.AssertNoErr(t, err)
|
||||
opts = tools.OnlyRS(opts)
|
||||
|
||||
client, err := rackspace.AuthenticatedClient(opts)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
c, err := rackspace.NewDBV1(client, gophercloud.EndpointOpts{
|
||||
Region: "IAD",
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
type context struct {
|
||||
test *testing.T
|
||||
client *gophercloud.ServiceClient
|
||||
instanceID string
|
||||
DBIDs []string
|
||||
replicaID string
|
||||
backupID string
|
||||
configGroupID string
|
||||
users []string
|
||||
}
|
||||
|
||||
func newContext(t *testing.T) context {
|
||||
return context{
|
||||
test: t,
|
||||
client: newClient(t),
|
||||
}
|
||||
}
|
||||
|
||||
func (c context) Logf(msg string, args ...interface{}) {
|
||||
if len(args) > 0 {
|
||||
c.test.Logf(msg, args...)
|
||||
} else {
|
||||
c.test.Log(msg)
|
||||
}
|
||||
}
|
||||
|
||||
func (c context) AssertNoErr(err error) {
|
||||
th.AssertNoErr(c.test, err)
|
||||
}
|
||||
|
||||
func (c context) WaitUntilActive(id string) {
|
||||
err := gophercloud.WaitFor(60, func() (bool, error) {
|
||||
inst, err := instances.Get(c.client, id).Extract()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if inst.Status == "ACTIVE" {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
c.AssertNoErr(err)
|
||||
}
|
1
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/db/v1/pkg.go
generated
vendored
Normal file
1
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/db/v1/pkg.go
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
package v1
|
1
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/identity/v2/pkg.go
generated
vendored
Normal file
1
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/identity/v2/pkg.go
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
package v2
|
62
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/lb/v1/common.go
generated
vendored
Normal file
62
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/lb/v1/common.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
// +build acceptance lbs
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/acceptance/tools"
|
||||
"github.com/rackspace/gophercloud/rackspace"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func newProvider() (*gophercloud.ProviderClient, error) {
|
||||
opts, err := rackspace.AuthOptionsFromEnv()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opts = tools.OnlyRS(opts)
|
||||
|
||||
return rackspace.AuthenticatedClient(opts)
|
||||
}
|
||||
|
||||
func newClient() (*gophercloud.ServiceClient, error) {
|
||||
provider, err := newProvider()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return rackspace.NewLBV1(provider, gophercloud.EndpointOpts{
|
||||
Region: os.Getenv("RS_REGION"),
|
||||
})
|
||||
}
|
||||
|
||||
func newComputeClient() (*gophercloud.ServiceClient, error) {
|
||||
provider, err := newProvider()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return rackspace.NewComputeV2(provider, gophercloud.EndpointOpts{
|
||||
Region: os.Getenv("RS_REGION"),
|
||||
})
|
||||
}
|
||||
|
||||
func setup(t *testing.T) *gophercloud.ServiceClient {
|
||||
client, err := newClient()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
func intsToStr(ids []int) string {
|
||||
strIDs := []string{}
|
||||
for _, id := range ids {
|
||||
strIDs = append(strIDs, strconv.Itoa(id))
|
||||
}
|
||||
return strings.Join(strIDs, ", ")
|
||||
}
|
39
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/networking/v2/common.go
generated
vendored
Normal file
39
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/networking/v2/common.go
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/rackspace"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
var Client *gophercloud.ServiceClient
|
||||
|
||||
func NewClient() (*gophercloud.ServiceClient, error) {
|
||||
opts, err := rackspace.AuthOptionsFromEnv()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
provider, err := rackspace.AuthenticatedClient(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return rackspace.NewNetworkV2(provider, gophercloud.EndpointOpts{
|
||||
Name: "cloudNetworks",
|
||||
Region: os.Getenv("RS_REGION"),
|
||||
})
|
||||
}
|
||||
|
||||
func Setup(t *testing.T) {
|
||||
client, err := NewClient()
|
||||
th.AssertNoErr(t, err)
|
||||
Client = client
|
||||
}
|
||||
|
||||
func Teardown() {
|
||||
Client = nil
|
||||
}
|
54
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/objectstorage/v1/common.go
generated
vendored
Normal file
54
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/objectstorage/v1/common.go
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
// +build acceptance rackspace objectstorage v1
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/acceptance/tools"
|
||||
"github.com/rackspace/gophercloud/rackspace"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func rackspaceAuthOptions(t *testing.T) gophercloud.AuthOptions {
|
||||
// Obtain credentials from the environment.
|
||||
options, err := rackspace.AuthOptionsFromEnv()
|
||||
th.AssertNoErr(t, err)
|
||||
options = tools.OnlyRS(options)
|
||||
|
||||
if options.Username == "" {
|
||||
t.Fatal("Please provide a Rackspace username as RS_USERNAME.")
|
||||
}
|
||||
if options.APIKey == "" {
|
||||
t.Fatal("Please provide a Rackspace API key as RS_API_KEY.")
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
func createClient(t *testing.T, cdn bool) (*gophercloud.ServiceClient, error) {
|
||||
region := os.Getenv("RS_REGION")
|
||||
if region == "" {
|
||||
t.Fatal("Please provide a Rackspace region as RS_REGION")
|
||||
}
|
||||
|
||||
ao := rackspaceAuthOptions(t)
|
||||
|
||||
provider, err := rackspace.NewClient(ao.IdentityEndpoint)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
err = rackspace.Authenticate(provider, ao)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
if cdn {
|
||||
return rackspace.NewObjectCDNV1(provider, gophercloud.EndpointOpts{
|
||||
Region: region,
|
||||
})
|
||||
}
|
||||
|
||||
return rackspace.NewObjectStorageV1(provider, gophercloud.EndpointOpts{
|
||||
Region: region,
|
||||
})
|
||||
}
|
45
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/orchestration/v1/common.go
generated
vendored
Normal file
45
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/orchestration/v1/common.go
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
// +build acceptance
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/rackspace"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
var template = fmt.Sprintf(`
|
||||
{
|
||||
"heat_template_version": "2013-05-23",
|
||||
"description": "Simple template to test heat commands",
|
||||
"parameters": {},
|
||||
"resources": {
|
||||
"hello_world": {
|
||||
"type":"OS::Nova::Server",
|
||||
"properties": {
|
||||
"flavor": "%s",
|
||||
"image": "%s",
|
||||
"user_data": "#!/bin/bash -xv\necho \"hello world\" > /root/hello-world.txt\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`, os.Getenv("RS_FLAVOR_ID"), os.Getenv("RS_IMAGE_ID"))
|
||||
|
||||
func newClient(t *testing.T) *gophercloud.ServiceClient {
|
||||
ao, err := rackspace.AuthOptionsFromEnv()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
client, err := rackspace.AuthenticatedClient(ao)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
c, err := rackspace.NewOrchestrationV1(client, gophercloud.EndpointOpts{
|
||||
Region: os.Getenv("RS_REGION_NAME"),
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
return c
|
||||
}
|
1
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/pkg.go
generated
vendored
Normal file
1
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/pkg.go
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
package rackspace
|
26
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/rackconnect/v3/common.go
generated
vendored
Normal file
26
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/rackconnect/v3/common.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
// +build acceptance
|
||||
|
||||
package v3
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/rackspace"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func newClient(t *testing.T) *gophercloud.ServiceClient {
|
||||
ao, err := rackspace.AuthOptionsFromEnv()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
client, err := rackspace.AuthenticatedClient(ao)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
c, err := rackspace.NewRackConnectV3(client, gophercloud.EndpointOpts{
|
||||
Region: os.Getenv("RS_REGION_NAME"),
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
return c
|
||||
}
|
1
vendor/github.com/rackspace/gophercloud/acceptance/tools/pkg.go
generated
vendored
Normal file
1
vendor/github.com/rackspace/gophercloud/acceptance/tools/pkg.go
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
package tools
|
89
vendor/github.com/rackspace/gophercloud/acceptance/tools/tools.go
generated
vendored
Normal file
89
vendor/github.com/rackspace/gophercloud/acceptance/tools/tools.go
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
// +build acceptance common
|
||||
|
||||
package tools
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
mrand "math/rand"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
)
|
||||
|
||||
// ErrTimeout is returned if WaitFor takes longer than 300 second to happen.
|
||||
var ErrTimeout = errors.New("Timed out")
|
||||
|
||||
// OnlyRS overrides the default Gophercloud behavior of using OS_-prefixed environment variables
|
||||
// if RS_ variables aren't present. Otherwise, they'll stomp over each other here in the acceptance
|
||||
// tests, where you need to have both defined.
|
||||
func OnlyRS(original gophercloud.AuthOptions) gophercloud.AuthOptions {
|
||||
if os.Getenv("RS_AUTH_URL") == "" {
|
||||
original.IdentityEndpoint = ""
|
||||
}
|
||||
if os.Getenv("RS_USERNAME") == "" {
|
||||
original.Username = ""
|
||||
}
|
||||
if os.Getenv("RS_PASSWORD") == "" {
|
||||
original.Password = ""
|
||||
}
|
||||
if os.Getenv("RS_API_KEY") == "" {
|
||||
original.APIKey = ""
|
||||
}
|
||||
return original
|
||||
}
|
||||
|
||||
// WaitFor polls a predicate function once per second to wait for a certain state to arrive.
|
||||
func WaitFor(predicate func() (bool, error)) error {
|
||||
for i := 0; i < 300; i++ {
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
satisfied, err := predicate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if satisfied {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return ErrTimeout
|
||||
}
|
||||
|
||||
// MakeNewPassword generates a new string that's guaranteed to be different than the given one.
|
||||
func MakeNewPassword(oldPass string) string {
|
||||
randomPassword := RandomString("", 16)
|
||||
for randomPassword == oldPass {
|
||||
randomPassword = RandomString("", 16)
|
||||
}
|
||||
return randomPassword
|
||||
}
|
||||
|
||||
// RandomString generates a string of given length, but random content.
|
||||
// All content will be within the ASCII graphic character set.
|
||||
// (Implementation from Even Shaw's contribution on
|
||||
// http://stackoverflow.com/questions/12771930/what-is-the-fastest-way-to-generate-a-long-random-string-in-go).
|
||||
func RandomString(prefix string, n int) string {
|
||||
const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||
var bytes = make([]byte, n)
|
||||
rand.Read(bytes)
|
||||
for i, b := range bytes {
|
||||
bytes[i] = alphanum[b%byte(len(alphanum))]
|
||||
}
|
||||
return prefix + string(bytes)
|
||||
}
|
||||
|
||||
// RandomInt will return a random integer between a specified range.
|
||||
func RandomInt(min, max int) int {
|
||||
mrand.Seed(time.Now().Unix())
|
||||
return mrand.Intn(max-min) + min
|
||||
}
|
||||
|
||||
// Elide returns the first bit of its input string with a suffix of "..." if it's longer than
|
||||
// a comfortable 40 characters.
|
||||
func Elide(value string) string {
|
||||
if len(value) > 40 {
|
||||
return value[0:37] + "..."
|
||||
}
|
||||
return value
|
||||
}
|
50
vendor/github.com/rackspace/gophercloud/auth_options.go
generated
vendored
Normal file
50
vendor/github.com/rackspace/gophercloud/auth_options.go
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
package gophercloud
|
||||
|
||||
/*
|
||||
AuthOptions stores information needed to authenticate to an OpenStack cluster.
|
||||
You can populate one manually, or use a provider's AuthOptionsFromEnv() function
|
||||
to read relevant information from the standard environment variables. Pass one
|
||||
to a provider's AuthenticatedClient function to authenticate and obtain a
|
||||
ProviderClient representing an active session on that provider.
|
||||
|
||||
Its fields are the union of those recognized by each identity implementation and
|
||||
provider.
|
||||
*/
|
||||
type AuthOptions struct {
|
||||
// IdentityEndpoint specifies the HTTP endpoint that is required to work with
|
||||
// the Identity API of the appropriate version. While it's ultimately needed by
|
||||
// all of the identity services, it will often be populated by a provider-level
|
||||
// function.
|
||||
IdentityEndpoint string
|
||||
|
||||
// Username is required if using Identity V2 API. Consult with your provider's
|
||||
// control panel to discover your account's username. In Identity V3, either
|
||||
// UserID or a combination of Username and DomainID or DomainName are needed.
|
||||
Username, UserID string
|
||||
|
||||
// Exactly one of Password or APIKey is required for the Identity V2 and V3
|
||||
// APIs. Consult with your provider's control panel to discover your account's
|
||||
// preferred method of authentication.
|
||||
Password, APIKey string
|
||||
|
||||
// At most one of DomainID and DomainName must be provided if using Username
|
||||
// with Identity V3. Otherwise, either are optional.
|
||||
DomainID, DomainName string
|
||||
|
||||
// The TenantID and TenantName fields are optional for the Identity V2 API.
|
||||
// Some providers allow you to specify a TenantName instead of the TenantId.
|
||||
// Some require both. Your provider's authentication policies will determine
|
||||
// how these fields influence authentication.
|
||||
TenantID, TenantName string
|
||||
|
||||
// AllowReauth should be set to true if you grant permission for Gophercloud to
|
||||
// cache your credentials in memory, and to allow Gophercloud to attempt to
|
||||
// re-authenticate automatically if/when your token expires. If you set it to
|
||||
// false, it will not cache these settings, but re-authentication will not be
|
||||
// possible. This setting defaults to false.
|
||||
AllowReauth bool
|
||||
|
||||
// TokenID allows users to authenticate (possibly as another user) with an
|
||||
// authentication token ID.
|
||||
TokenID string
|
||||
}
|
14
vendor/github.com/rackspace/gophercloud/auth_results.go
generated
vendored
Normal file
14
vendor/github.com/rackspace/gophercloud/auth_results.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
package gophercloud
|
||||
|
||||
import "time"
|
||||
|
||||
// AuthResults [deprecated] is a leftover type from the v0.x days. It was
|
||||
// intended to describe common functionality among identity service results, but
|
||||
// is not actually used anywhere.
|
||||
type AuthResults interface {
|
||||
// TokenID returns the token's ID value from the authentication response.
|
||||
TokenID() (string, error)
|
||||
|
||||
// ExpiresAt retrieves the token's expiration time.
|
||||
ExpiresAt() (time.Time, error)
|
||||
}
|
67
vendor/github.com/rackspace/gophercloud/doc.go
generated
vendored
Normal file
67
vendor/github.com/rackspace/gophercloud/doc.go
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
Package gophercloud provides a multi-vendor interface to OpenStack-compatible
|
||||
clouds. The library has a three-level hierarchy: providers, services, and
|
||||
resources.
|
||||
|
||||
Provider structs represent the service providers that offer and manage a
|
||||
collection of services. Examples of providers include: OpenStack, Rackspace,
|
||||
HP. These are defined like so:
|
||||
|
||||
opts := gophercloud.AuthOptions{
|
||||
IdentityEndpoint: "https://my-openstack.com:5000/v2.0",
|
||||
Username: "{username}",
|
||||
Password: "{password}",
|
||||
TenantID: "{tenant_id}",
|
||||
}
|
||||
|
||||
provider, err := openstack.AuthenticatedClient(opts)
|
||||
|
||||
Service structs are specific to a provider and handle all of the logic and
|
||||
operations for a particular OpenStack service. Examples of services include:
|
||||
Compute, Object Storage, Block Storage. In order to define one, you need to
|
||||
pass in the parent provider, like so:
|
||||
|
||||
opts := gophercloud.EndpointOpts{Region: "RegionOne"}
|
||||
|
||||
client := openstack.NewComputeV2(provider, opts)
|
||||
|
||||
Resource structs are the domain models that services make use of in order
|
||||
to work with and represent the state of API resources:
|
||||
|
||||
server, err := servers.Get(client, "{serverId}").Extract()
|
||||
|
||||
Intermediate Result structs are returned for API operations, which allow
|
||||
generic access to the HTTP headers, response body, and any errors associated
|
||||
with the network transaction. To turn a result into a usable resource struct,
|
||||
you must call the Extract method which is chained to the response, or an
|
||||
Extract function from an applicable extension:
|
||||
|
||||
result := servers.Get(client, "{serverId}")
|
||||
|
||||
// Attempt to extract the disk configuration from the OS-DCF disk config
|
||||
// extension:
|
||||
config, err := diskconfig.ExtractGet(result)
|
||||
|
||||
All requests that enumerate a collection return a Pager struct that is used to
|
||||
iterate through the results one page at a time. Use the EachPage method on that
|
||||
Pager to handle each successive Page in a closure, then use the appropriate
|
||||
extraction method from that request's package to interpret that Page as a slice
|
||||
of results:
|
||||
|
||||
err := servers.List(client, nil).EachPage(func (page pagination.Page) (bool, error) {
|
||||
s, err := servers.ExtractServers(page)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Handle the []servers.Server slice.
|
||||
|
||||
// Return "false" or an error to prematurely stop fetching new pages.
|
||||
return true, nil
|
||||
})
|
||||
|
||||
This top-level package contains utility functions and data types that are used
|
||||
throughout the provider and service packages. Of particular note for end users
|
||||
are the AuthOptions and EndpointOpts structs.
|
||||
*/
|
||||
package gophercloud
|
92
vendor/github.com/rackspace/gophercloud/endpoint_search.go
generated
vendored
Normal file
92
vendor/github.com/rackspace/gophercloud/endpoint_search.go
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
package gophercloud
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
// ErrServiceNotFound is returned when no service in a service catalog matches
|
||||
// the provided EndpointOpts. This is generally returned by provider service
|
||||
// factory methods like "NewComputeV2()" and can mean that a service is not
|
||||
// enabled for your account.
|
||||
ErrServiceNotFound = errors.New("No suitable service could be found in the service catalog.")
|
||||
|
||||
// ErrEndpointNotFound is returned when no available endpoints match the
|
||||
// provided EndpointOpts. This is also generally returned by provider service
|
||||
// factory methods, and usually indicates that a region was specified
|
||||
// incorrectly.
|
||||
ErrEndpointNotFound = errors.New("No suitable endpoint could be found in the service catalog.")
|
||||
)
|
||||
|
||||
// Availability indicates to whom a specific service endpoint is accessible:
|
||||
// the internet at large, internal networks only, or only to administrators.
|
||||
// Different identity services use different terminology for these. Identity v2
|
||||
// lists them as different kinds of URLs within the service catalog ("adminURL",
|
||||
// "internalURL", and "publicURL"), while v3 lists them as "Interfaces" in an
|
||||
// endpoint's response.
|
||||
type Availability string
|
||||
|
||||
const (
|
||||
// AvailabilityAdmin indicates that an endpoint is only available to
|
||||
// administrators.
|
||||
AvailabilityAdmin Availability = "admin"
|
||||
|
||||
// AvailabilityPublic indicates that an endpoint is available to everyone on
|
||||
// the internet.
|
||||
AvailabilityPublic Availability = "public"
|
||||
|
||||
// AvailabilityInternal indicates that an endpoint is only available within
|
||||
// the cluster's internal network.
|
||||
AvailabilityInternal Availability = "internal"
|
||||
)
|
||||
|
||||
// EndpointOpts specifies search criteria used by queries against an
|
||||
// OpenStack service catalog. The options must contain enough information to
|
||||
// unambiguously identify one, and only one, endpoint within the catalog.
|
||||
//
|
||||
// Usually, these are passed to service client factory functions in a provider
|
||||
// package, like "rackspace.NewComputeV2()".
|
||||
type EndpointOpts struct {
|
||||
// Type [required] is the service type for the client (e.g., "compute",
|
||||
// "object-store"). Generally, this will be supplied by the service client
|
||||
// function, but a user-given value will be honored if provided.
|
||||
Type string
|
||||
|
||||
// Name [optional] is the service name for the client (e.g., "nova") as it
|
||||
// appears in the service catalog. Services can have the same Type but a
|
||||
// different Name, which is why both Type and Name are sometimes needed.
|
||||
Name string
|
||||
|
||||
// Region [required] is the geographic region in which the endpoint resides,
|
||||
// generally specifying which datacenter should house your resources.
|
||||
// Required only for services that span multiple regions.
|
||||
Region string
|
||||
|
||||
// Availability [optional] is the visibility of the endpoint to be returned.
|
||||
// Valid types include the constants AvailabilityPublic, AvailabilityInternal,
|
||||
// or AvailabilityAdmin from this package.
|
||||
//
|
||||
// Availability is not required, and defaults to AvailabilityPublic. Not all
|
||||
// providers or services offer all Availability options.
|
||||
Availability Availability
|
||||
}
|
||||
|
||||
/*
|
||||
EndpointLocator is an internal function to be used by provider implementations.
|
||||
|
||||
It provides an implementation that locates a single endpoint from a service
|
||||
catalog for a specific ProviderClient based on user-provided EndpointOpts. The
|
||||
provider then uses it to discover related ServiceClients.
|
||||
*/
|
||||
type EndpointLocator func(EndpointOpts) (string, error)
|
||||
|
||||
// ApplyDefaults is an internal method to be used by provider implementations.
|
||||
//
|
||||
// It sets EndpointOpts fields if not already set, including a default type.
|
||||
// Currently, EndpointOpts.Availability defaults to the public endpoint.
|
||||
func (eo *EndpointOpts) ApplyDefaults(t string) {
|
||||
if eo.Type == "" {
|
||||
eo.Type = t
|
||||
}
|
||||
if eo.Availability == "" {
|
||||
eo.Availability = AvailabilityPublic
|
||||
}
|
||||
}
|
58
vendor/github.com/rackspace/gophercloud/openstack/auth_env.go
generated
vendored
Normal file
58
vendor/github.com/rackspace/gophercloud/openstack/auth_env.go
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
package openstack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
)
|
||||
|
||||
var nilOptions = gophercloud.AuthOptions{}
|
||||
|
||||
// ErrNoAuthUrl, ErrNoUsername, and ErrNoPassword errors indicate of the required OS_AUTH_URL, OS_USERNAME, or OS_PASSWORD
|
||||
// environment variables, respectively, remain undefined. See the AuthOptions() function for more details.
|
||||
var (
|
||||
ErrNoAuthURL = fmt.Errorf("Environment variable OS_AUTH_URL needs to be set.")
|
||||
ErrNoUsername = fmt.Errorf("Environment variable OS_USERNAME needs to be set.")
|
||||
ErrNoPassword = fmt.Errorf("Environment variable OS_PASSWORD needs to be set.")
|
||||
)
|
||||
|
||||
// AuthOptions fills out an identity.AuthOptions structure with the settings found on the various OpenStack
|
||||
// OS_* environment variables. The following variables provide sources of truth: OS_AUTH_URL, OS_USERNAME,
|
||||
// OS_PASSWORD, OS_TENANT_ID, and OS_TENANT_NAME. Of these, OS_USERNAME, OS_PASSWORD, and OS_AUTH_URL must
|
||||
// have settings, or an error will result. OS_TENANT_ID and OS_TENANT_NAME are optional.
|
||||
func AuthOptionsFromEnv() (gophercloud.AuthOptions, error) {
|
||||
authURL := os.Getenv("OS_AUTH_URL")
|
||||
username := os.Getenv("OS_USERNAME")
|
||||
userID := os.Getenv("OS_USERID")
|
||||
password := os.Getenv("OS_PASSWORD")
|
||||
tenantID := os.Getenv("OS_TENANT_ID")
|
||||
tenantName := os.Getenv("OS_TENANT_NAME")
|
||||
domainID := os.Getenv("OS_DOMAIN_ID")
|
||||
domainName := os.Getenv("OS_DOMAIN_NAME")
|
||||
|
||||
if authURL == "" {
|
||||
return nilOptions, ErrNoAuthURL
|
||||
}
|
||||
|
||||
if username == "" && userID == "" {
|
||||
return nilOptions, ErrNoUsername
|
||||
}
|
||||
|
||||
if password == "" {
|
||||
return nilOptions, ErrNoPassword
|
||||
}
|
||||
|
||||
ao := gophercloud.AuthOptions{
|
||||
IdentityEndpoint: authURL,
|
||||
UserID: userID,
|
||||
Username: username,
|
||||
Password: password,
|
||||
TenantID: tenantID,
|
||||
TenantName: tenantName,
|
||||
DomainID: domainID,
|
||||
DomainName: domainName,
|
||||
}
|
||||
|
||||
return ao, nil
|
||||
}
|
3
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/doc.go
generated
vendored
Normal file
3
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/doc.go
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
// Package apiversions provides information and interaction with the different
|
||||
// API versions for the OpenStack Block Storage service, code-named Cinder.
|
||||
package apiversions
|
21
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/requests.go
generated
vendored
Normal file
21
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/requests.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
package apiversions
|
||||
|
||||
import (
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// List lists all the Cinder API versions available to end-users.
|
||||
func List(c *gophercloud.ServiceClient) pagination.Pager {
|
||||
return pagination.NewPager(c, listURL(c), func(r pagination.PageResult) pagination.Page {
|
||||
return APIVersionPage{pagination.SinglePageBase(r)}
|
||||
})
|
||||
}
|
||||
|
||||
// Get will retrieve the volume type with the provided ID. To extract the volume
|
||||
// type from the result, call the Extract method on the GetResult.
|
||||
func Get(client *gophercloud.ServiceClient, v string) GetResult {
|
||||
var res GetResult
|
||||
_, res.Err = client.Get(getURL(client, v), &res.Body, nil)
|
||||
return res
|
||||
}
|
58
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/results.go
generated
vendored
Normal file
58
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/results.go
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
package apiversions
|
||||
|
||||
import (
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
// APIVersion represents an API version for Cinder.
|
||||
type APIVersion struct {
|
||||
ID string `json:"id" mapstructure:"id"` // unique identifier
|
||||
Status string `json:"status" mapstructure:"status"` // current status
|
||||
Updated string `json:"updated" mapstructure:"updated"` // date last updated
|
||||
}
|
||||
|
||||
// APIVersionPage is the page returned by a pager when traversing over a
|
||||
// collection of API versions.
|
||||
type APIVersionPage struct {
|
||||
pagination.SinglePageBase
|
||||
}
|
||||
|
||||
// IsEmpty checks whether an APIVersionPage struct is empty.
|
||||
func (r APIVersionPage) IsEmpty() (bool, error) {
|
||||
is, err := ExtractAPIVersions(r)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
return len(is) == 0, nil
|
||||
}
|
||||
|
||||
// ExtractAPIVersions takes a collection page, extracts all of the elements,
|
||||
// and returns them a slice of APIVersion structs. It is effectively a cast.
|
||||
func ExtractAPIVersions(page pagination.Page) ([]APIVersion, error) {
|
||||
var resp struct {
|
||||
Versions []APIVersion `mapstructure:"versions"`
|
||||
}
|
||||
|
||||
err := mapstructure.Decode(page.(APIVersionPage).Body, &resp)
|
||||
|
||||
return resp.Versions, err
|
||||
}
|
||||
|
||||
// GetResult represents the result of a get operation.
|
||||
type GetResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// Extract is a function that accepts a result and extracts an API version resource.
|
||||
func (r GetResult) Extract() (*APIVersion, error) {
|
||||
var resp struct {
|
||||
Version *APIVersion `mapstructure:"version"`
|
||||
}
|
||||
|
||||
err := mapstructure.Decode(r.Body, &resp)
|
||||
|
||||
return resp.Version, err
|
||||
}
|
18
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/urls.go
generated
vendored
Normal file
18
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/apiversions/urls.go
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
package apiversions
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"net/url"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
)
|
||||
|
||||
func getURL(c *gophercloud.ServiceClient, version string) string {
|
||||
return c.ServiceURL(strings.TrimRight(version, "/") + "/")
|
||||
}
|
||||
|
||||
func listURL(c *gophercloud.ServiceClient) string {
|
||||
u, _ := url.Parse(c.ServiceURL(""))
|
||||
u.Path = "/"
|
||||
return u.String()
|
||||
}
|
5
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/doc.go
generated
vendored
Normal file
5
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/doc.go
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
// Package snapshots provides information and interaction with snapshots in the
|
||||
// OpenStack Block Storage service. A snapshot is a point in time copy of the
|
||||
// data contained in an external storage volume, and can be controlled
|
||||
// programmatically.
|
||||
package snapshots
|
114
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/fixtures.go
generated
vendored
Normal file
114
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/fixtures.go
generated
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
package snapshots
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
fake "github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
func MockListResponse(t *testing.T) {
|
||||
th.Mux.HandleFunc("/snapshots", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"snapshots": [
|
||||
{
|
||||
"id": "289da7f8-6440-407c-9fb4-7db01ec49164",
|
||||
"display_name": "snapshot-001"
|
||||
},
|
||||
{
|
||||
"id": "96c3bda7-c82a-4f50-be73-ca7621794835",
|
||||
"display_name": "snapshot-002"
|
||||
}
|
||||
]
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
||||
|
||||
func MockGetResponse(t *testing.T) {
|
||||
th.Mux.HandleFunc("/snapshots/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"snapshot": {
|
||||
"display_name": "snapshot-001",
|
||||
"id": "d32019d3-bc6e-4319-9c1d-6722fc136a22"
|
||||
}
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
||||
|
||||
func MockCreateResponse(t *testing.T) {
|
||||
th.Mux.HandleFunc("/snapshots", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "POST")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
th.TestHeader(t, r, "Content-Type", "application/json")
|
||||
th.TestHeader(t, r, "Accept", "application/json")
|
||||
th.TestJSONRequest(t, r, `
|
||||
{
|
||||
"snapshot": {
|
||||
"volume_id": "1234",
|
||||
"display_name": "snapshot-001"
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"snapshot": {
|
||||
"volume_id": "1234",
|
||||
"display_name": "snapshot-001",
|
||||
"id": "d32019d3-bc6e-4319-9c1d-6722fc136a22"
|
||||
}
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
||||
|
||||
func MockUpdateMetadataResponse(t *testing.T) {
|
||||
th.Mux.HandleFunc("/snapshots/123/metadata", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "PUT")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
th.TestHeader(t, r, "Content-Type", "application/json")
|
||||
th.TestJSONRequest(t, r, `
|
||||
{
|
||||
"metadata": {
|
||||
"key": "v1"
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"metadata": {
|
||||
"key": "v1"
|
||||
}
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
||||
|
||||
func MockDeleteResponse(t *testing.T) {
|
||||
th.Mux.HandleFunc("/snapshots/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "DELETE")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
})
|
||||
}
|
206
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/requests.go
generated
vendored
Normal file
206
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/requests.go
generated
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
package snapshots
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// CreateOptsBuilder allows extensions to add additional parameters to the
|
||||
// Create request.
|
||||
type CreateOptsBuilder interface {
|
||||
ToSnapshotCreateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// CreateOpts contains options for creating a Snapshot. This object is passed to
|
||||
// the snapshots.Create function. For more information about these parameters,
|
||||
// see the Snapshot object.
|
||||
type CreateOpts struct {
|
||||
// OPTIONAL
|
||||
Description string
|
||||
// OPTIONAL
|
||||
Force bool
|
||||
// OPTIONAL
|
||||
Metadata map[string]interface{}
|
||||
// OPTIONAL
|
||||
Name string
|
||||
// REQUIRED
|
||||
VolumeID string
|
||||
}
|
||||
|
||||
// ToSnapshotCreateMap assembles a request body based on the contents of a
|
||||
// CreateOpts.
|
||||
func (opts CreateOpts) ToSnapshotCreateMap() (map[string]interface{}, error) {
|
||||
s := make(map[string]interface{})
|
||||
|
||||
if opts.VolumeID == "" {
|
||||
return nil, fmt.Errorf("Required CreateOpts field 'VolumeID' not set.")
|
||||
}
|
||||
s["volume_id"] = opts.VolumeID
|
||||
|
||||
if opts.Description != "" {
|
||||
s["display_description"] = opts.Description
|
||||
}
|
||||
if opts.Force == true {
|
||||
s["force"] = opts.Force
|
||||
}
|
||||
if opts.Metadata != nil {
|
||||
s["metadata"] = opts.Metadata
|
||||
}
|
||||
if opts.Name != "" {
|
||||
s["display_name"] = opts.Name
|
||||
}
|
||||
|
||||
return map[string]interface{}{"snapshot": s}, nil
|
||||
}
|
||||
|
||||
// Create will create a new Snapshot based on the values in CreateOpts. To
|
||||
// extract the Snapshot object from the response, call the Extract method on the
|
||||
// CreateResult.
|
||||
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
|
||||
var res CreateResult
|
||||
|
||||
reqBody, err := opts.ToSnapshotCreateMap()
|
||||
if err != nil {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
_, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200, 201},
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
// Delete will delete the existing Snapshot with the provided ID.
|
||||
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
|
||||
var res DeleteResult
|
||||
_, res.Err = client.Delete(deleteURL(client, id), nil)
|
||||
return res
|
||||
}
|
||||
|
||||
// Get retrieves the Snapshot with the provided ID. To extract the Snapshot
|
||||
// object from the response, call the Extract method on the GetResult.
|
||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||
var res GetResult
|
||||
_, res.Err = client.Get(getURL(client, id), &res.Body, nil)
|
||||
return res
|
||||
}
|
||||
|
||||
// ListOptsBuilder allows extensions to add additional parameters to the List
|
||||
// request.
|
||||
type ListOptsBuilder interface {
|
||||
ToSnapshotListQuery() (string, error)
|
||||
}
|
||||
|
||||
// ListOpts hold options for listing Snapshots. It is passed to the
|
||||
// snapshots.List function.
|
||||
type ListOpts struct {
|
||||
Name string `q:"display_name"`
|
||||
Status string `q:"status"`
|
||||
VolumeID string `q:"volume_id"`
|
||||
}
|
||||
|
||||
// ToSnapshotListQuery formats a ListOpts into a query string.
|
||||
func (opts ListOpts) ToSnapshotListQuery() (string, error) {
|
||||
q, err := gophercloud.BuildQueryString(opts)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return q.String(), nil
|
||||
}
|
||||
|
||||
// List returns Snapshots optionally limited by the conditions provided in
|
||||
// ListOpts.
|
||||
func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
|
||||
url := listURL(client)
|
||||
if opts != nil {
|
||||
query, err := opts.ToSnapshotListQuery()
|
||||
if err != nil {
|
||||
return pagination.Pager{Err: err}
|
||||
}
|
||||
url += query
|
||||
}
|
||||
|
||||
createPage := func(r pagination.PageResult) pagination.Page {
|
||||
return ListResult{pagination.SinglePageBase(r)}
|
||||
}
|
||||
return pagination.NewPager(client, url, createPage)
|
||||
}
|
||||
|
||||
// UpdateMetadataOptsBuilder allows extensions to add additional parameters to
|
||||
// the Update request.
|
||||
type UpdateMetadataOptsBuilder interface {
|
||||
ToSnapshotUpdateMetadataMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// UpdateMetadataOpts contain options for updating an existing Snapshot. This
|
||||
// object is passed to the snapshots.Update function. For more information
|
||||
// about the parameters, see the Snapshot object.
|
||||
type UpdateMetadataOpts struct {
|
||||
Metadata map[string]interface{}
|
||||
}
|
||||
|
||||
// ToSnapshotUpdateMetadataMap assembles a request body based on the contents of
|
||||
// an UpdateMetadataOpts.
|
||||
func (opts UpdateMetadataOpts) ToSnapshotUpdateMetadataMap() (map[string]interface{}, error) {
|
||||
v := make(map[string]interface{})
|
||||
|
||||
if opts.Metadata != nil {
|
||||
v["metadata"] = opts.Metadata
|
||||
}
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// UpdateMetadata will update the Snapshot with provided information. To
|
||||
// extract the updated Snapshot from the response, call the ExtractMetadata
|
||||
// method on the UpdateMetadataResult.
|
||||
func UpdateMetadata(client *gophercloud.ServiceClient, id string, opts UpdateMetadataOptsBuilder) UpdateMetadataResult {
|
||||
var res UpdateMetadataResult
|
||||
|
||||
reqBody, err := opts.ToSnapshotUpdateMetadataMap()
|
||||
if err != nil {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
_, res.Err = client.Put(updateMetadataURL(client, id), reqBody, &res.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
// IDFromName is a convienience function that returns a snapshot's ID given its name.
|
||||
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
|
||||
snapshotCount := 0
|
||||
snapshotID := ""
|
||||
if name == "" {
|
||||
return "", fmt.Errorf("A snapshot name must be provided.")
|
||||
}
|
||||
pager := List(client, nil)
|
||||
pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
snapshotList, err := ExtractSnapshots(page)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, s := range snapshotList {
|
||||
if s.Name == name {
|
||||
snapshotCount++
|
||||
snapshotID = s.ID
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
|
||||
switch snapshotCount {
|
||||
case 0:
|
||||
return "", fmt.Errorf("Unable to find snapshot: %s", name)
|
||||
case 1:
|
||||
return snapshotID, nil
|
||||
default:
|
||||
return "", fmt.Errorf("Found %d snapshots matching %s", snapshotCount, name)
|
||||
}
|
||||
}
|
123
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/results.go
generated
vendored
Normal file
123
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/results.go
generated
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
package snapshots
|
||||
|
||||
import (
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
// Snapshot contains all the information associated with an OpenStack Snapshot.
|
||||
type Snapshot struct {
|
||||
// Currect status of the Snapshot.
|
||||
Status string `mapstructure:"status"`
|
||||
|
||||
// Display name.
|
||||
Name string `mapstructure:"display_name"`
|
||||
|
||||
// Instances onto which the Snapshot is attached.
|
||||
Attachments []string `mapstructure:"attachments"`
|
||||
|
||||
// Logical group.
|
||||
AvailabilityZone string `mapstructure:"availability_zone"`
|
||||
|
||||
// Is the Snapshot bootable?
|
||||
Bootable string `mapstructure:"bootable"`
|
||||
|
||||
// Date created.
|
||||
CreatedAt string `mapstructure:"created_at"`
|
||||
|
||||
// Display description.
|
||||
Description string `mapstructure:"display_discription"`
|
||||
|
||||
// See VolumeType object for more information.
|
||||
VolumeType string `mapstructure:"volume_type"`
|
||||
|
||||
// ID of the Snapshot from which this Snapshot was created.
|
||||
SnapshotID string `mapstructure:"snapshot_id"`
|
||||
|
||||
// ID of the Volume from which this Snapshot was created.
|
||||
VolumeID string `mapstructure:"volume_id"`
|
||||
|
||||
// User-defined key-value pairs.
|
||||
Metadata map[string]string `mapstructure:"metadata"`
|
||||
|
||||
// Unique identifier.
|
||||
ID string `mapstructure:"id"`
|
||||
|
||||
// Size of the Snapshot, in GB.
|
||||
Size int `mapstructure:"size"`
|
||||
}
|
||||
|
||||
// CreateResult contains the response body and error from a Create request.
|
||||
type CreateResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// GetResult contains the response body and error from a Get request.
|
||||
type GetResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// DeleteResult contains the response body and error from a Delete request.
|
||||
type DeleteResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
|
||||
// ListResult is a pagination.Pager that is returned from a call to the List function.
|
||||
type ListResult struct {
|
||||
pagination.SinglePageBase
|
||||
}
|
||||
|
||||
// IsEmpty returns true if a ListResult contains no Snapshots.
|
||||
func (r ListResult) IsEmpty() (bool, error) {
|
||||
volumes, err := ExtractSnapshots(r)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
return len(volumes) == 0, nil
|
||||
}
|
||||
|
||||
// ExtractSnapshots extracts and returns Snapshots. It is used while iterating over a snapshots.List call.
|
||||
func ExtractSnapshots(page pagination.Page) ([]Snapshot, error) {
|
||||
var response struct {
|
||||
Snapshots []Snapshot `json:"snapshots"`
|
||||
}
|
||||
|
||||
err := mapstructure.Decode(page.(ListResult).Body, &response)
|
||||
return response.Snapshots, err
|
||||
}
|
||||
|
||||
// UpdateMetadataResult contains the response body and error from an UpdateMetadata request.
|
||||
type UpdateMetadataResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// ExtractMetadata returns the metadata from a response from snapshots.UpdateMetadata.
|
||||
func (r UpdateMetadataResult) ExtractMetadata() (map[string]interface{}, error) {
|
||||
if r.Err != nil {
|
||||
return nil, r.Err
|
||||
}
|
||||
|
||||
m := r.Body.(map[string]interface{})["metadata"]
|
||||
return m.(map[string]interface{}), nil
|
||||
}
|
||||
|
||||
type commonResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// Extract will get the Snapshot object out of the commonResult object.
|
||||
func (r commonResult) Extract() (*Snapshot, error) {
|
||||
if r.Err != nil {
|
||||
return nil, r.Err
|
||||
}
|
||||
|
||||
var res struct {
|
||||
Snapshot *Snapshot `json:"snapshot"`
|
||||
}
|
||||
|
||||
err := mapstructure.Decode(r.Body, &res)
|
||||
|
||||
return res.Snapshot, err
|
||||
}
|
27
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/urls.go
generated
vendored
Normal file
27
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/urls.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
package snapshots
|
||||
|
||||
import "github.com/rackspace/gophercloud"
|
||||
|
||||
func createURL(c *gophercloud.ServiceClient) string {
|
||||
return c.ServiceURL("snapshots")
|
||||
}
|
||||
|
||||
func deleteURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return c.ServiceURL("snapshots", id)
|
||||
}
|
||||
|
||||
func getURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return deleteURL(c, id)
|
||||
}
|
||||
|
||||
func listURL(c *gophercloud.ServiceClient) string {
|
||||
return createURL(c)
|
||||
}
|
||||
|
||||
func metadataURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return c.ServiceURL("snapshots", id, "metadata")
|
||||
}
|
||||
|
||||
func updateMetadataURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return metadataURL(c, id)
|
||||
}
|
22
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/util.go
generated
vendored
Normal file
22
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots/util.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
package snapshots
|
||||
|
||||
import (
|
||||
"github.com/rackspace/gophercloud"
|
||||
)
|
||||
|
||||
// WaitForStatus will continually poll the resource, checking for a particular
|
||||
// status. It will do this for the amount of seconds defined.
|
||||
func WaitForStatus(c *gophercloud.ServiceClient, id, status string, secs int) error {
|
||||
return gophercloud.WaitFor(secs, func() (bool, error) {
|
||||
current, err := Get(c, id).Extract()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if current.Status == status {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
})
|
||||
}
|
5
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/doc.go
generated
vendored
Normal file
5
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/doc.go
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
// Package volumes provides information and interaction with volumes in the
|
||||
// OpenStack Block Storage service. A volume is a detachable block storage
|
||||
// device, akin to a USB hard drive. It can only be attached to one instance at
|
||||
// a time.
|
||||
package volumes
|
236
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/requests.go
generated
vendored
Normal file
236
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/requests.go
generated
vendored
Normal file
@@ -0,0 +1,236 @@
|
||||
package volumes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// CreateOptsBuilder allows extensions to add additional parameters to the
|
||||
// Create request.
|
||||
type CreateOptsBuilder interface {
|
||||
ToVolumeCreateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// CreateOpts contains options for creating a Volume. This object is passed to
|
||||
// the volumes.Create function. For more information about these parameters,
|
||||
// see the Volume object.
|
||||
type CreateOpts struct {
|
||||
// OPTIONAL
|
||||
Availability string
|
||||
// OPTIONAL
|
||||
Description string
|
||||
// OPTIONAL
|
||||
Metadata map[string]string
|
||||
// OPTIONAL
|
||||
Name string
|
||||
// REQUIRED
|
||||
Size int
|
||||
// OPTIONAL
|
||||
SnapshotID, SourceVolID, ImageID string
|
||||
// OPTIONAL
|
||||
VolumeType string
|
||||
}
|
||||
|
||||
// ToVolumeCreateMap assembles a request body based on the contents of a
|
||||
// CreateOpts.
|
||||
func (opts CreateOpts) ToVolumeCreateMap() (map[string]interface{}, error) {
|
||||
v := make(map[string]interface{})
|
||||
|
||||
if opts.Size == 0 {
|
||||
return nil, fmt.Errorf("Required CreateOpts field 'Size' not set.")
|
||||
}
|
||||
v["size"] = opts.Size
|
||||
|
||||
if opts.Availability != "" {
|
||||
v["availability_zone"] = opts.Availability
|
||||
}
|
||||
if opts.Description != "" {
|
||||
v["display_description"] = opts.Description
|
||||
}
|
||||
if opts.ImageID != "" {
|
||||
v["imageRef"] = opts.ImageID
|
||||
}
|
||||
if opts.Metadata != nil {
|
||||
v["metadata"] = opts.Metadata
|
||||
}
|
||||
if opts.Name != "" {
|
||||
v["display_name"] = opts.Name
|
||||
}
|
||||
if opts.SourceVolID != "" {
|
||||
v["source_volid"] = opts.SourceVolID
|
||||
}
|
||||
if opts.SnapshotID != "" {
|
||||
v["snapshot_id"] = opts.SnapshotID
|
||||
}
|
||||
if opts.VolumeType != "" {
|
||||
v["volume_type"] = opts.VolumeType
|
||||
}
|
||||
|
||||
return map[string]interface{}{"volume": v}, nil
|
||||
}
|
||||
|
||||
// Create will create a new Volume based on the values in CreateOpts. To extract
|
||||
// the Volume object from the response, call the Extract method on the
|
||||
// CreateResult.
|
||||
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
|
||||
var res CreateResult
|
||||
|
||||
reqBody, err := opts.ToVolumeCreateMap()
|
||||
if err != nil {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
_, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200, 201},
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
// Delete will delete the existing Volume with the provided ID.
|
||||
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
|
||||
var res DeleteResult
|
||||
_, res.Err = client.Delete(deleteURL(client, id), nil)
|
||||
return res
|
||||
}
|
||||
|
||||
// Get retrieves the Volume with the provided ID. To extract the Volume object
|
||||
// from the response, call the Extract method on the GetResult.
|
||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||
var res GetResult
|
||||
_, res.Err = client.Get(getURL(client, id), &res.Body, nil)
|
||||
return res
|
||||
}
|
||||
|
||||
// ListOptsBuilder allows extensions to add additional parameters to the List
|
||||
// request.
|
||||
type ListOptsBuilder interface {
|
||||
ToVolumeListQuery() (string, error)
|
||||
}
|
||||
|
||||
// ListOpts holds options for listing Volumes. It is passed to the volumes.List
|
||||
// function.
|
||||
type ListOpts struct {
|
||||
// admin-only option. Set it to true to see all tenant volumes.
|
||||
AllTenants bool `q:"all_tenants"`
|
||||
// List only volumes that contain Metadata.
|
||||
Metadata map[string]string `q:"metadata"`
|
||||
// List only volumes that have Name as the display name.
|
||||
Name string `q:"name"`
|
||||
// List only volumes that have a status of Status.
|
||||
Status string `q:"status"`
|
||||
}
|
||||
|
||||
// ToVolumeListQuery formats a ListOpts into a query string.
|
||||
func (opts ListOpts) ToVolumeListQuery() (string, error) {
|
||||
q, err := gophercloud.BuildQueryString(opts)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return q.String(), nil
|
||||
}
|
||||
|
||||
// List returns Volumes optionally limited by the conditions provided in ListOpts.
|
||||
func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
|
||||
url := listURL(client)
|
||||
if opts != nil {
|
||||
query, err := opts.ToVolumeListQuery()
|
||||
if err != nil {
|
||||
return pagination.Pager{Err: err}
|
||||
}
|
||||
url += query
|
||||
}
|
||||
createPage := func(r pagination.PageResult) pagination.Page {
|
||||
return ListResult{pagination.SinglePageBase(r)}
|
||||
}
|
||||
|
||||
return pagination.NewPager(client, url, createPage)
|
||||
}
|
||||
|
||||
// UpdateOptsBuilder allows extensions to add additional parameters to the
|
||||
// Update request.
|
||||
type UpdateOptsBuilder interface {
|
||||
ToVolumeUpdateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// UpdateOpts contain options for updating an existing Volume. This object is passed
|
||||
// to the volumes.Update function. For more information about the parameters, see
|
||||
// the Volume object.
|
||||
type UpdateOpts struct {
|
||||
// OPTIONAL
|
||||
Name string
|
||||
// OPTIONAL
|
||||
Description string
|
||||
// OPTIONAL
|
||||
Metadata map[string]string
|
||||
}
|
||||
|
||||
// ToVolumeUpdateMap assembles a request body based on the contents of an
|
||||
// UpdateOpts.
|
||||
func (opts UpdateOpts) ToVolumeUpdateMap() (map[string]interface{}, error) {
|
||||
v := make(map[string]interface{})
|
||||
|
||||
if opts.Description != "" {
|
||||
v["display_description"] = opts.Description
|
||||
}
|
||||
if opts.Metadata != nil {
|
||||
v["metadata"] = opts.Metadata
|
||||
}
|
||||
if opts.Name != "" {
|
||||
v["display_name"] = opts.Name
|
||||
}
|
||||
|
||||
return map[string]interface{}{"volume": v}, nil
|
||||
}
|
||||
|
||||
// Update will update the Volume with provided information. To extract the updated
|
||||
// Volume from the response, call the Extract method on the UpdateResult.
|
||||
func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
|
||||
var res UpdateResult
|
||||
|
||||
reqBody, err := opts.ToVolumeUpdateMap()
|
||||
if err != nil {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
_, res.Err = client.Put(updateURL(client, id), reqBody, &res.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
// IDFromName is a convienience function that returns a server's ID given its name.
|
||||
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
|
||||
volumeCount := 0
|
||||
volumeID := ""
|
||||
if name == "" {
|
||||
return "", fmt.Errorf("A volume name must be provided.")
|
||||
}
|
||||
pager := List(client, nil)
|
||||
pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
volumeList, err := ExtractVolumes(page)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, s := range volumeList {
|
||||
if s.Name == name {
|
||||
volumeCount++
|
||||
volumeID = s.ID
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
|
||||
switch volumeCount {
|
||||
case 0:
|
||||
return "", fmt.Errorf("Unable to find volume: %s", name)
|
||||
case 1:
|
||||
return volumeID, nil
|
||||
default:
|
||||
return "", fmt.Errorf("Found %d volumes matching %s", volumeCount, name)
|
||||
}
|
||||
}
|
113
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/results.go
generated
vendored
Normal file
113
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/results.go
generated
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
package volumes
|
||||
|
||||
import (
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
// Volume contains all the information associated with an OpenStack Volume.
|
||||
type Volume struct {
|
||||
// Current status of the volume.
|
||||
Status string `mapstructure:"status"`
|
||||
|
||||
// Human-readable display name for the volume.
|
||||
Name string `mapstructure:"display_name"`
|
||||
|
||||
// Instances onto which the volume is attached.
|
||||
Attachments []map[string]interface{} `mapstructure:"attachments"`
|
||||
|
||||
// This parameter is no longer used.
|
||||
AvailabilityZone string `mapstructure:"availability_zone"`
|
||||
|
||||
// Indicates whether this is a bootable volume.
|
||||
Bootable string `mapstructure:"bootable"`
|
||||
|
||||
// The date when this volume was created.
|
||||
CreatedAt string `mapstructure:"created_at"`
|
||||
|
||||
// Human-readable description for the volume.
|
||||
Description string `mapstructure:"display_description"`
|
||||
|
||||
// The type of volume to create, either SATA or SSD.
|
||||
VolumeType string `mapstructure:"volume_type"`
|
||||
|
||||
// The ID of the snapshot from which the volume was created
|
||||
SnapshotID string `mapstructure:"snapshot_id"`
|
||||
|
||||
// The ID of another block storage volume from which the current volume was created
|
||||
SourceVolID string `mapstructure:"source_volid"`
|
||||
|
||||
// Arbitrary key-value pairs defined by the user.
|
||||
Metadata map[string]string `mapstructure:"metadata"`
|
||||
|
||||
// Unique identifier for the volume.
|
||||
ID string `mapstructure:"id"`
|
||||
|
||||
// Size of the volume in GB.
|
||||
Size int `mapstructure:"size"`
|
||||
}
|
||||
|
||||
// CreateResult contains the response body and error from a Create request.
|
||||
type CreateResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// GetResult contains the response body and error from a Get request.
|
||||
type GetResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// DeleteResult contains the response body and error from a Delete request.
|
||||
type DeleteResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
|
||||
// ListResult is a pagination.pager that is returned from a call to the List function.
|
||||
type ListResult struct {
|
||||
pagination.SinglePageBase
|
||||
}
|
||||
|
||||
// IsEmpty returns true if a ListResult contains no Volumes.
|
||||
func (r ListResult) IsEmpty() (bool, error) {
|
||||
volumes, err := ExtractVolumes(r)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
return len(volumes) == 0, nil
|
||||
}
|
||||
|
||||
// ExtractVolumes extracts and returns Volumes. It is used while iterating over a volumes.List call.
|
||||
func ExtractVolumes(page pagination.Page) ([]Volume, error) {
|
||||
var response struct {
|
||||
Volumes []Volume `json:"volumes"`
|
||||
}
|
||||
|
||||
err := mapstructure.Decode(page.(ListResult).Body, &response)
|
||||
return response.Volumes, err
|
||||
}
|
||||
|
||||
// UpdateResult contains the response body and error from an Update request.
|
||||
type UpdateResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
type commonResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// Extract will get the Volume object out of the commonResult object.
|
||||
func (r commonResult) Extract() (*Volume, error) {
|
||||
if r.Err != nil {
|
||||
return nil, r.Err
|
||||
}
|
||||
|
||||
var res struct {
|
||||
Volume *Volume `json:"volume"`
|
||||
}
|
||||
|
||||
err := mapstructure.Decode(r.Body, &res)
|
||||
|
||||
return res.Volume, err
|
||||
}
|
7
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/testing/doc.go
generated
vendored
Normal file
7
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/testing/doc.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
This is package created is to hold fixtures (which imports testing),
|
||||
so that importing volumes package does not inadvertently import testing into production code
|
||||
More information here:
|
||||
https://github.com/rackspace/gophercloud/issues/473
|
||||
*/
|
||||
package testing
|
113
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/testing/fixtures.go
generated
vendored
Normal file
113
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/testing/fixtures.go
generated
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
package testing
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
fake "github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
func MockListResponse(t *testing.T) {
|
||||
th.Mux.HandleFunc("/volumes", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"volumes": [
|
||||
{
|
||||
"id": "289da7f8-6440-407c-9fb4-7db01ec49164",
|
||||
"display_name": "vol-001"
|
||||
},
|
||||
{
|
||||
"id": "96c3bda7-c82a-4f50-be73-ca7621794835",
|
||||
"display_name": "vol-002"
|
||||
}
|
||||
]
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
||||
|
||||
func MockGetResponse(t *testing.T) {
|
||||
th.Mux.HandleFunc("/volumes/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"volume": {
|
||||
"display_name": "vol-001",
|
||||
"id": "d32019d3-bc6e-4319-9c1d-6722fc136a22",
|
||||
"attachments": [
|
||||
{
|
||||
"device": "/dev/vde",
|
||||
"server_id": "a740d24b-dc5b-4d59-ac75-53971c2920ba",
|
||||
"id": "d6da11e5-2ed3-413e-88d8-b772ba62193d",
|
||||
"volume_id": "d6da11e5-2ed3-413e-88d8-b772ba62193d"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
||||
|
||||
func MockCreateResponse(t *testing.T) {
|
||||
th.Mux.HandleFunc("/volumes", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "POST")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
th.TestHeader(t, r, "Content-Type", "application/json")
|
||||
th.TestHeader(t, r, "Accept", "application/json")
|
||||
th.TestJSONRequest(t, r, `
|
||||
{
|
||||
"volume": {
|
||||
"size": 75
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"volume": {
|
||||
"size": 4,
|
||||
"id": "d32019d3-bc6e-4319-9c1d-6722fc136a22"
|
||||
}
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
||||
|
||||
func MockDeleteResponse(t *testing.T) {
|
||||
th.Mux.HandleFunc("/volumes/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "DELETE")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
})
|
||||
}
|
||||
|
||||
func MockUpdateResponse(t *testing.T) {
|
||||
th.Mux.HandleFunc("/volumes/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "PUT")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"volume": {
|
||||
"display_name": "vol-002",
|
||||
"id": "d32019d3-bc6e-4319-9c1d-6722fc136a22"
|
||||
}
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
23
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/urls.go
generated
vendored
Normal file
23
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/urls.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
package volumes
|
||||
|
||||
import "github.com/rackspace/gophercloud"
|
||||
|
||||
func createURL(c *gophercloud.ServiceClient) string {
|
||||
return c.ServiceURL("volumes")
|
||||
}
|
||||
|
||||
func listURL(c *gophercloud.ServiceClient) string {
|
||||
return createURL(c)
|
||||
}
|
||||
|
||||
func deleteURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return c.ServiceURL("volumes", id)
|
||||
}
|
||||
|
||||
func getURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return deleteURL(c, id)
|
||||
}
|
||||
|
||||
func updateURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return deleteURL(c, id)
|
||||
}
|
22
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/util.go
generated
vendored
Normal file
22
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/util.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
package volumes
|
||||
|
||||
import (
|
||||
"github.com/rackspace/gophercloud"
|
||||
)
|
||||
|
||||
// WaitForStatus will continually poll the resource, checking for a particular
|
||||
// status. It will do this for the amount of seconds defined.
|
||||
func WaitForStatus(c *gophercloud.ServiceClient, id, status string, secs int) error {
|
||||
return gophercloud.WaitFor(secs, func() (bool, error) {
|
||||
current, err := Get(c, id).Extract()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if current.Status == status {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
})
|
||||
}
|
9
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/doc.go
generated
vendored
Normal file
9
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/doc.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// Package volumetypes provides information and interaction with volume types
|
||||
// in the OpenStack Block Storage service. A volume type indicates the type of
|
||||
// a block storage volume, such as SATA, SCSCI, SSD, etc. These can be
|
||||
// customized or defined by the OpenStack admin.
|
||||
//
|
||||
// You can also define extra_specs associated with your volume types. For
|
||||
// instance, you could have a VolumeType=SATA, with extra_specs (RPM=10000,
|
||||
// RAID-Level=5) . Extra_specs are defined and customized by the admin.
|
||||
package volumetypes
|
60
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/fixtures.go
generated
vendored
Normal file
60
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/fixtures.go
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
package volumetypes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
fake "github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
func MockListResponse(t *testing.T) {
|
||||
th.Mux.HandleFunc("/types", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"volume_types": [
|
||||
{
|
||||
"id": "289da7f8-6440-407c-9fb4-7db01ec49164",
|
||||
"name": "vol-type-001",
|
||||
"extra_specs": {
|
||||
"capabilities": "gpu"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "96c3bda7-c82a-4f50-be73-ca7621794835",
|
||||
"name": "vol-type-002",
|
||||
"extra_specs": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
||||
|
||||
func MockGetResponse(t *testing.T) {
|
||||
th.Mux.HandleFunc("/types/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"volume_type": {
|
||||
"name": "vol-type-001",
|
||||
"id": "d32019d3-bc6e-4319-9c1d-6722fc136a22",
|
||||
"extra_specs": {
|
||||
"serverNumber": "2"
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
76
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/requests.go
generated
vendored
Normal file
76
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/requests.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
package volumetypes
|
||||
|
||||
import (
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// CreateOptsBuilder allows extensions to add additional parameters to the
|
||||
// Create request.
|
||||
type CreateOptsBuilder interface {
|
||||
ToVolumeTypeCreateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// CreateOpts are options for creating a volume type.
|
||||
type CreateOpts struct {
|
||||
// OPTIONAL. See VolumeType.
|
||||
ExtraSpecs map[string]interface{}
|
||||
// OPTIONAL. See VolumeType.
|
||||
Name string
|
||||
}
|
||||
|
||||
// ToVolumeTypeCreateMap casts a CreateOpts struct to a map.
|
||||
func (opts CreateOpts) ToVolumeTypeCreateMap() (map[string]interface{}, error) {
|
||||
vt := make(map[string]interface{})
|
||||
|
||||
if opts.ExtraSpecs != nil {
|
||||
vt["extra_specs"] = opts.ExtraSpecs
|
||||
}
|
||||
if opts.Name != "" {
|
||||
vt["name"] = opts.Name
|
||||
}
|
||||
|
||||
return map[string]interface{}{"volume_type": vt}, nil
|
||||
}
|
||||
|
||||
// Create will create a new volume. To extract the created volume type object,
|
||||
// call the Extract method on the CreateResult.
|
||||
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
|
||||
var res CreateResult
|
||||
|
||||
reqBody, err := opts.ToVolumeTypeCreateMap()
|
||||
if err != nil {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
_, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200, 201},
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
// Delete will delete the volume type with the provided ID.
|
||||
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
|
||||
var res DeleteResult
|
||||
_, res.Err = client.Delete(deleteURL(client, id), nil)
|
||||
return res
|
||||
}
|
||||
|
||||
// Get will retrieve the volume type with the provided ID. To extract the volume
|
||||
// type from the result, call the Extract method on the GetResult.
|
||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||
var res GetResult
|
||||
_, err := client.Get(getURL(client, id), &res.Body, nil)
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
// List returns all volume types.
|
||||
func List(client *gophercloud.ServiceClient) pagination.Pager {
|
||||
createPage := func(r pagination.PageResult) pagination.Page {
|
||||
return ListResult{pagination.SinglePageBase(r)}
|
||||
}
|
||||
|
||||
return pagination.NewPager(client, listURL(client), createPage)
|
||||
}
|
72
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/results.go
generated
vendored
Normal file
72
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/results.go
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
package volumetypes
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// VolumeType contains all information associated with an OpenStack Volume Type.
|
||||
type VolumeType struct {
|
||||
ExtraSpecs map[string]interface{} `json:"extra_specs" mapstructure:"extra_specs"` // user-defined metadata
|
||||
ID string `json:"id" mapstructure:"id"` // unique identifier
|
||||
Name string `json:"name" mapstructure:"name"` // display name
|
||||
}
|
||||
|
||||
// CreateResult contains the response body and error from a Create request.
|
||||
type CreateResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// GetResult contains the response body and error from a Get request.
|
||||
type GetResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// DeleteResult contains the response error from a Delete request.
|
||||
type DeleteResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
|
||||
// ListResult is a pagination.Pager that is returned from a call to the List function.
|
||||
type ListResult struct {
|
||||
pagination.SinglePageBase
|
||||
}
|
||||
|
||||
// IsEmpty returns true if a ListResult contains no Volume Types.
|
||||
func (r ListResult) IsEmpty() (bool, error) {
|
||||
volumeTypes, err := ExtractVolumeTypes(r)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
return len(volumeTypes) == 0, nil
|
||||
}
|
||||
|
||||
// ExtractVolumeTypes extracts and returns Volume Types.
|
||||
func ExtractVolumeTypes(page pagination.Page) ([]VolumeType, error) {
|
||||
var response struct {
|
||||
VolumeTypes []VolumeType `mapstructure:"volume_types"`
|
||||
}
|
||||
|
||||
err := mapstructure.Decode(page.(ListResult).Body, &response)
|
||||
return response.VolumeTypes, err
|
||||
}
|
||||
|
||||
type commonResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// Extract will get the Volume Type object out of the commonResult object.
|
||||
func (r commonResult) Extract() (*VolumeType, error) {
|
||||
if r.Err != nil {
|
||||
return nil, r.Err
|
||||
}
|
||||
|
||||
var res struct {
|
||||
VolumeType *VolumeType `json:"volume_type" mapstructure:"volume_type"`
|
||||
}
|
||||
|
||||
err := mapstructure.Decode(r.Body, &res)
|
||||
|
||||
return res.VolumeType, err
|
||||
}
|
19
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/urls.go
generated
vendored
Normal file
19
vendor/github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes/urls.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
package volumetypes
|
||||
|
||||
import "github.com/rackspace/gophercloud"
|
||||
|
||||
func listURL(c *gophercloud.ServiceClient) string {
|
||||
return c.ServiceURL("types")
|
||||
}
|
||||
|
||||
func createURL(c *gophercloud.ServiceClient) string {
|
||||
return listURL(c)
|
||||
}
|
||||
|
||||
func getURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return c.ServiceURL("types", id)
|
||||
}
|
||||
|
||||
func deleteURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return getURL(c, id)
|
||||
}
|
4
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/doc.go
generated
vendored
Normal file
4
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/doc.go
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
// Package base provides information and interaction with the base API
|
||||
// resource in the OpenStack CDN service. This API resource allows for
|
||||
// retrieving the Home Document and pinging the root URL.
|
||||
package base
|
53
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/fixtures.go
generated
vendored
Normal file
53
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/fixtures.go
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
fake "github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
// HandleGetSuccessfully creates an HTTP handler at `/` on the test handler mux
|
||||
// that responds with a `Get` response.
|
||||
func HandleGetSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
th.TestHeader(t, r, "Accept", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"resources": {
|
||||
"rel/cdn": {
|
||||
"href-template": "services{?marker,limit}",
|
||||
"href-vars": {
|
||||
"marker": "param/marker",
|
||||
"limit": "param/limit"
|
||||
},
|
||||
"hints": {
|
||||
"allow": [
|
||||
"GET"
|
||||
],
|
||||
"formats": {
|
||||
"application/json": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
// HandlePingSuccessfully creates an HTTP handler at `/ping` on the test handler
|
||||
// mux that responds with a `Ping` response.
|
||||
func HandlePingSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
})
|
||||
}
|
21
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/requests.go
generated
vendored
Normal file
21
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/requests.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
package base
|
||||
|
||||
import "github.com/rackspace/gophercloud"
|
||||
|
||||
// Get retrieves the home document, allowing the user to discover the
|
||||
// entire API.
|
||||
func Get(c *gophercloud.ServiceClient) GetResult {
|
||||
var res GetResult
|
||||
_, res.Err = c.Get(getURL(c), &res.Body, nil)
|
||||
return res
|
||||
}
|
||||
|
||||
// Ping retrieves a ping to the server.
|
||||
func Ping(c *gophercloud.ServiceClient) PingResult {
|
||||
var res PingResult
|
||||
_, res.Err = c.Get(pingURL(c), nil, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{204},
|
||||
MoreHeaders: map[string]string{"Accept": ""},
|
||||
})
|
||||
return res
|
||||
}
|
35
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/results.go
generated
vendored
Normal file
35
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/results.go
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
)
|
||||
|
||||
// HomeDocument is a resource that contains all the resources for the CDN API.
|
||||
type HomeDocument map[string]interface{}
|
||||
|
||||
// GetResult represents the result of a Get operation.
|
||||
type GetResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// Extract is a function that accepts a result and extracts a home document resource.
|
||||
func (r GetResult) Extract() (*HomeDocument, error) {
|
||||
if r.Err != nil {
|
||||
return nil, r.Err
|
||||
}
|
||||
|
||||
submap, ok := r.Body.(map[string]interface{})["resources"]
|
||||
if !ok {
|
||||
return nil, errors.New("Unexpected HomeDocument structure")
|
||||
}
|
||||
casted := HomeDocument(submap.(map[string]interface{}))
|
||||
|
||||
return &casted, nil
|
||||
}
|
||||
|
||||
// PingResult represents the result of a Ping operation.
|
||||
type PingResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
11
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/urls.go
generated
vendored
Normal file
11
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/base/urls.go
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
package base
|
||||
|
||||
import "github.com/rackspace/gophercloud"
|
||||
|
||||
func getURL(c *gophercloud.ServiceClient) string {
|
||||
return c.ServiceURL()
|
||||
}
|
||||
|
||||
func pingURL(c *gophercloud.ServiceClient) string {
|
||||
return c.ServiceURL("ping")
|
||||
}
|
6
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/doc.go
generated
vendored
Normal file
6
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/doc.go
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
// Package flavors provides information and interaction with the flavors API
|
||||
// resource in the OpenStack CDN service. This API resource allows for
|
||||
// listing flavors and retrieving a specific flavor.
|
||||
//
|
||||
// A flavor is a mapping configuration to a CDN provider.
|
||||
package flavors
|
82
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/fixtures.go
generated
vendored
Normal file
82
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/fixtures.go
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
package flavors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
fake "github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
// HandleListCDNFlavorsSuccessfully creates an HTTP handler at `/flavors` on the test handler mux
|
||||
// that responds with a `List` response.
|
||||
func HandleListCDNFlavorsSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/flavors", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"flavors": [
|
||||
{
|
||||
"id": "europe",
|
||||
"providers": [
|
||||
{
|
||||
"provider": "Fastly",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://www.fastly.com",
|
||||
"rel": "provider_url"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"href": "https://www.poppycdn.io/v1.0/flavors/europe",
|
||||
"rel": "self"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleGetCDNFlavorSuccessfully creates an HTTP handler at `/flavors/{id}` on the test handler mux
|
||||
// that responds with a `Get` response.
|
||||
func HandleGetCDNFlavorSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/flavors/asia", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"id" : "asia",
|
||||
"providers" : [
|
||||
{
|
||||
"provider" : "ChinaCache",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://www.chinacache.com",
|
||||
"rel": "provider_url"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"href": "https://www.poppycdn.io/v1.0/flavors/asia",
|
||||
"rel": "self"
|
||||
}
|
||||
]
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
22
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/requests.go
generated
vendored
Normal file
22
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/requests.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
package flavors
|
||||
|
||||
import (
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// List returns a single page of CDN flavors.
|
||||
func List(c *gophercloud.ServiceClient) pagination.Pager {
|
||||
url := listURL(c)
|
||||
createPage := func(r pagination.PageResult) pagination.Page {
|
||||
return FlavorPage{pagination.SinglePageBase(r)}
|
||||
}
|
||||
return pagination.NewPager(c, url, createPage)
|
||||
}
|
||||
|
||||
// Get retrieves a specific flavor based on its unique ID.
|
||||
func Get(c *gophercloud.ServiceClient, id string) GetResult {
|
||||
var res GetResult
|
||||
_, res.Err = c.Get(getURL(c, id), &res.Body, nil)
|
||||
return res
|
||||
}
|
71
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/results.go
generated
vendored
Normal file
71
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/results.go
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
package flavors
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// Provider represents a provider for a particular flavor.
|
||||
type Provider struct {
|
||||
// Specifies the name of the provider. The name must not exceed 64 bytes in
|
||||
// length and is limited to unicode, digits, underscores, and hyphens.
|
||||
Provider string `mapstructure:"provider"`
|
||||
// Specifies a list with an href where rel is provider_url.
|
||||
Links []gophercloud.Link `mapstructure:"links"`
|
||||
}
|
||||
|
||||
// Flavor represents a mapping configuration to a CDN provider.
|
||||
type Flavor struct {
|
||||
// Specifies the name of the flavor. The name must not exceed 64 bytes in
|
||||
// length and is limited to unicode, digits, underscores, and hyphens.
|
||||
ID string `mapstructure:"id"`
|
||||
// Specifies the list of providers mapped to this flavor.
|
||||
Providers []Provider `mapstructure:"providers"`
|
||||
// Specifies the self-navigating JSON document paths.
|
||||
Links []gophercloud.Link `mapstructure:"links"`
|
||||
}
|
||||
|
||||
// FlavorPage is the page returned by a pager when traversing over a
|
||||
// collection of CDN flavors.
|
||||
type FlavorPage struct {
|
||||
pagination.SinglePageBase
|
||||
}
|
||||
|
||||
// IsEmpty returns true if a FlavorPage contains no Flavors.
|
||||
func (r FlavorPage) IsEmpty() (bool, error) {
|
||||
flavors, err := ExtractFlavors(r)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
return len(flavors) == 0, nil
|
||||
}
|
||||
|
||||
// ExtractFlavors extracts and returns Flavors. It is used while iterating over
|
||||
// a flavors.List call.
|
||||
func ExtractFlavors(page pagination.Page) ([]Flavor, error) {
|
||||
var response struct {
|
||||
Flavors []Flavor `json:"flavors"`
|
||||
}
|
||||
|
||||
err := mapstructure.Decode(page.(FlavorPage).Body, &response)
|
||||
return response.Flavors, err
|
||||
}
|
||||
|
||||
// GetResult represents the result of a get operation.
|
||||
type GetResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// Extract is a function that extracts a flavor from a GetResult.
|
||||
func (r GetResult) Extract() (*Flavor, error) {
|
||||
if r.Err != nil {
|
||||
return nil, r.Err
|
||||
}
|
||||
|
||||
var res Flavor
|
||||
|
||||
err := mapstructure.Decode(r.Body, &res)
|
||||
|
||||
return &res, err
|
||||
}
|
11
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/urls.go
generated
vendored
Normal file
11
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/urls.go
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
package flavors
|
||||
|
||||
import "github.com/rackspace/gophercloud"
|
||||
|
||||
func listURL(c *gophercloud.ServiceClient) string {
|
||||
return c.ServiceURL("flavors")
|
||||
}
|
||||
|
||||
func getURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return c.ServiceURL("flavors", id)
|
||||
}
|
7
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/doc.go
generated
vendored
Normal file
7
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/doc.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
// Package serviceassets provides information and interaction with the
|
||||
// serviceassets API resource in the OpenStack CDN service. This API resource
|
||||
// allows for deleting cached assets.
|
||||
//
|
||||
// A service distributes assets across the network. Service assets let you
|
||||
// interrogate properties about these assets and perform certain actions on them.
|
||||
package serviceassets
|
19
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/fixtures.go
generated
vendored
Normal file
19
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/fixtures.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
package serviceassets
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
fake "github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
// HandleDeleteCDNAssetSuccessfully creates an HTTP handler at `/services/{id}/assets` on the test handler mux
|
||||
// that responds with a `Delete` response.
|
||||
func HandleDeleteCDNAssetSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0/assets", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "DELETE")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
})
|
||||
}
|
48
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/requests.go
generated
vendored
Normal file
48
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/requests.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
package serviceassets
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
)
|
||||
|
||||
// DeleteOptsBuilder allows extensions to add additional parameters to the Delete
|
||||
// request.
|
||||
type DeleteOptsBuilder interface {
|
||||
ToCDNAssetDeleteParams() (string, error)
|
||||
}
|
||||
|
||||
// DeleteOpts is a structure that holds options for deleting CDN service assets.
|
||||
type DeleteOpts struct {
|
||||
// If all is set to true, specifies that the delete occurs against all of the
|
||||
// assets for the service.
|
||||
All bool `q:"all"`
|
||||
// Specifies the relative URL of the asset to be deleted.
|
||||
URL string `q:"url"`
|
||||
}
|
||||
|
||||
// ToCDNAssetDeleteParams formats a DeleteOpts into a query string.
|
||||
func (opts DeleteOpts) ToCDNAssetDeleteParams() (string, error) {
|
||||
q, err := gophercloud.BuildQueryString(opts)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return q.String(), nil
|
||||
}
|
||||
|
||||
// Delete accepts a unique service ID or URL and deletes the CDN service asset associated with
|
||||
// it. For example, both "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0" and
|
||||
// "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0"
|
||||
// are valid options for idOrURL.
|
||||
func Delete(c *gophercloud.ServiceClient, idOrURL string, opts DeleteOptsBuilder) DeleteResult {
|
||||
var url string
|
||||
if strings.Contains(idOrURL, "/") {
|
||||
url = idOrURL
|
||||
} else {
|
||||
url = deleteURL(c, idOrURL)
|
||||
}
|
||||
|
||||
var res DeleteResult
|
||||
_, res.Err = c.Delete(url, nil)
|
||||
return res
|
||||
}
|
8
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/results.go
generated
vendored
Normal file
8
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/results.go
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
package serviceassets
|
||||
|
||||
import "github.com/rackspace/gophercloud"
|
||||
|
||||
// DeleteResult represents the result of a Delete operation.
|
||||
type DeleteResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
7
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/urls.go
generated
vendored
Normal file
7
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/urls.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
package serviceassets
|
||||
|
||||
import "github.com/rackspace/gophercloud"
|
||||
|
||||
func deleteURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return c.ServiceURL("services", id, "assets")
|
||||
}
|
7
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/doc.go
generated
vendored
Normal file
7
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/doc.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
// Package services provides information and interaction with the services API
|
||||
// resource in the OpenStack CDN service. This API resource allows for
|
||||
// listing, creating, updating, retrieving, and deleting services.
|
||||
//
|
||||
// A service represents an application that has its content cached to the edge
|
||||
// nodes.
|
||||
package services
|
7
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/errors.go
generated
vendored
Normal file
7
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/errors.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
package services
|
||||
|
||||
import "fmt"
|
||||
|
||||
func no(str string) error {
|
||||
return fmt.Errorf("Required parameter %s not provided", str)
|
||||
}
|
372
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/fixtures.go
generated
vendored
Normal file
372
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/fixtures.go
generated
vendored
Normal file
@@ -0,0 +1,372 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
fake "github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
// HandleListCDNServiceSuccessfully creates an HTTP handler at `/services` on the test handler mux
|
||||
// that responds with a `List` response.
|
||||
func HandleListCDNServiceSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/services", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
r.ParseForm()
|
||||
marker := r.Form.Get("marker")
|
||||
switch marker {
|
||||
case "":
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"links": [
|
||||
{
|
||||
"rel": "next",
|
||||
"href": "https://www.poppycdn.io/v1.0/services?marker=96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0&limit=20"
|
||||
}
|
||||
],
|
||||
"services": [
|
||||
{
|
||||
"id": "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0",
|
||||
"name": "mywebsite.com",
|
||||
"domains": [
|
||||
{
|
||||
"domain": "www.mywebsite.com"
|
||||
}
|
||||
],
|
||||
"origins": [
|
||||
{
|
||||
"origin": "mywebsite.com",
|
||||
"port": 80,
|
||||
"ssl": false
|
||||
}
|
||||
],
|
||||
"caching": [
|
||||
{
|
||||
"name": "default",
|
||||
"ttl": 3600
|
||||
},
|
||||
{
|
||||
"name": "home",
|
||||
"ttl": 17200,
|
||||
"rules": [
|
||||
{
|
||||
"name": "index",
|
||||
"request_url": "/index.htm"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "images",
|
||||
"ttl": 12800,
|
||||
"rules": [
|
||||
{
|
||||
"name": "images",
|
||||
"request_url": "*.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"restrictions": [
|
||||
{
|
||||
"name": "website only",
|
||||
"rules": [
|
||||
{
|
||||
"name": "mywebsite.com",
|
||||
"referrer": "www.mywebsite.com"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"flavor_id": "asia",
|
||||
"status": "deployed",
|
||||
"errors" : [],
|
||||
"links": [
|
||||
{
|
||||
"href": "https://www.poppycdn.io/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "mywebsite.com.cdn123.poppycdn.net",
|
||||
"rel": "access_url"
|
||||
},
|
||||
{
|
||||
"href": "https://www.poppycdn.io/v1.0/flavors/asia",
|
||||
"rel": "flavor"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f1",
|
||||
"name": "myothersite.com",
|
||||
"domains": [
|
||||
{
|
||||
"domain": "www.myothersite.com"
|
||||
}
|
||||
],
|
||||
"origins": [
|
||||
{
|
||||
"origin": "44.33.22.11",
|
||||
"port": 80,
|
||||
"ssl": false
|
||||
},
|
||||
{
|
||||
"origin": "77.66.55.44",
|
||||
"port": 80,
|
||||
"ssl": false,
|
||||
"rules": [
|
||||
{
|
||||
"name": "videos",
|
||||
"request_url": "^/videos/*.m3u"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"caching": [
|
||||
{
|
||||
"name": "default",
|
||||
"ttl": 3600
|
||||
}
|
||||
],
|
||||
"restrictions": [
|
||||
{}
|
||||
],
|
||||
"flavor_id": "europe",
|
||||
"status": "deployed",
|
||||
"links": [
|
||||
{
|
||||
"href": "https://www.poppycdn.io/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f1",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "myothersite.com.poppycdn.net",
|
||||
"rel": "access_url"
|
||||
},
|
||||
{
|
||||
"href": "https://www.poppycdn.io/v1.0/flavors/europe",
|
||||
"rel": "flavor"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
`)
|
||||
case "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f1":
|
||||
fmt.Fprintf(w, `{
|
||||
"services": []
|
||||
}`)
|
||||
default:
|
||||
t.Fatalf("Unexpected marker: [%s]", marker)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// HandleCreateCDNServiceSuccessfully creates an HTTP handler at `/services` on the test handler mux
|
||||
// that responds with a `Create` response.
|
||||
func HandleCreateCDNServiceSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/services", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "POST")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
th.TestJSONRequest(t, r, `
|
||||
{
|
||||
"name": "mywebsite.com",
|
||||
"domains": [
|
||||
{
|
||||
"domain": "www.mywebsite.com"
|
||||
},
|
||||
{
|
||||
"domain": "blog.mywebsite.com"
|
||||
}
|
||||
],
|
||||
"origins": [
|
||||
{
|
||||
"origin": "mywebsite.com",
|
||||
"port": 80,
|
||||
"ssl": false
|
||||
}
|
||||
],
|
||||
"restrictions": [
|
||||
{
|
||||
"name": "website only",
|
||||
"rules": [
|
||||
{
|
||||
"name": "mywebsite.com",
|
||||
"referrer": "www.mywebsite.com"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"caching": [
|
||||
{
|
||||
"name": "default",
|
||||
"ttl": 3600
|
||||
}
|
||||
],
|
||||
|
||||
"flavor_id": "cdn"
|
||||
}
|
||||
`)
|
||||
w.Header().Add("Location", "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0")
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleGetCDNServiceSuccessfully creates an HTTP handler at `/services/{id}` on the test handler mux
|
||||
// that responds with a `Get` response.
|
||||
func HandleGetCDNServiceSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"id": "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0",
|
||||
"name": "mywebsite.com",
|
||||
"domains": [
|
||||
{
|
||||
"domain": "www.mywebsite.com",
|
||||
"protocol": "http"
|
||||
}
|
||||
],
|
||||
"origins": [
|
||||
{
|
||||
"origin": "mywebsite.com",
|
||||
"port": 80,
|
||||
"ssl": false
|
||||
}
|
||||
],
|
||||
"caching": [
|
||||
{
|
||||
"name": "default",
|
||||
"ttl": 3600
|
||||
},
|
||||
{
|
||||
"name": "home",
|
||||
"ttl": 17200,
|
||||
"rules": [
|
||||
{
|
||||
"name": "index",
|
||||
"request_url": "/index.htm"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "images",
|
||||
"ttl": 12800,
|
||||
"rules": [
|
||||
{
|
||||
"name": "images",
|
||||
"request_url": "*.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"restrictions": [
|
||||
{
|
||||
"name": "website only",
|
||||
"rules": [
|
||||
{
|
||||
"name": "mywebsite.com",
|
||||
"referrer": "www.mywebsite.com"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"flavor_id": "cdn",
|
||||
"status": "deployed",
|
||||
"errors" : [],
|
||||
"links": [
|
||||
{
|
||||
"href": "https://global.cdn.api.rackspacecloud.com/v1.0/110011/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "blog.mywebsite.com.cdn1.raxcdn.com",
|
||||
"rel": "access_url"
|
||||
},
|
||||
{
|
||||
"href": "https://global.cdn.api.rackspacecloud.com/v1.0/110011/flavors/cdn",
|
||||
"rel": "flavor"
|
||||
}
|
||||
]
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleUpdateCDNServiceSuccessfully creates an HTTP handler at `/services/{id}` on the test handler mux
|
||||
// that responds with a `Update` response.
|
||||
func HandleUpdateCDNServiceSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "PATCH")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
th.TestJSONRequest(t, r, `
|
||||
[
|
||||
{
|
||||
"op": "add",
|
||||
"path": "/domains/-",
|
||||
"value": {"domain": "appended.mocksite4.com"}
|
||||
},
|
||||
{
|
||||
"op": "add",
|
||||
"path": "/domains/4",
|
||||
"value": {"domain": "inserted.mocksite4.com"}
|
||||
},
|
||||
{
|
||||
"op": "add",
|
||||
"path": "/domains",
|
||||
"value": [
|
||||
{"domain": "bulkadded1.mocksite4.com"},
|
||||
{"domain": "bulkadded2.mocksite4.com"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"op": "replace",
|
||||
"path": "/origins/2",
|
||||
"value": {"origin": "44.33.22.11", "port": 80, "ssl": false}
|
||||
},
|
||||
{
|
||||
"op": "replace",
|
||||
"path": "/origins",
|
||||
"value": [
|
||||
{"origin": "44.33.22.11", "port": 80, "ssl": false},
|
||||
{"origin": "55.44.33.22", "port": 443, "ssl": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
"op": "remove",
|
||||
"path": "/caching/8"
|
||||
},
|
||||
{
|
||||
"op": "remove",
|
||||
"path": "/caching"
|
||||
},
|
||||
{
|
||||
"op": "replace",
|
||||
"path": "/name",
|
||||
"value": "differentServiceName"
|
||||
}
|
||||
]
|
||||
`)
|
||||
w.Header().Add("Location", "https://www.poppycdn.io/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0")
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleDeleteCDNServiceSuccessfully creates an HTTP handler at `/services/{id}` on the test handler mux
|
||||
// that responds with a `Delete` response.
|
||||
func HandleDeleteCDNServiceSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "DELETE")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
})
|
||||
}
|
378
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/requests.go
generated
vendored
Normal file
378
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/requests.go
generated
vendored
Normal file
@@ -0,0 +1,378 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// ListOptsBuilder allows extensions to add additional parameters to the
|
||||
// List request.
|
||||
type ListOptsBuilder interface {
|
||||
ToCDNServiceListQuery() (string, error)
|
||||
}
|
||||
|
||||
// ListOpts allows the filtering and sorting of paginated collections through
|
||||
// the API. Marker and Limit are used for pagination.
|
||||
type ListOpts struct {
|
||||
Marker string `q:"marker"`
|
||||
Limit int `q:"limit"`
|
||||
}
|
||||
|
||||
// ToCDNServiceListQuery formats a ListOpts into a query string.
|
||||
func (opts ListOpts) ToCDNServiceListQuery() (string, error) {
|
||||
q, err := gophercloud.BuildQueryString(opts)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return q.String(), nil
|
||||
}
|
||||
|
||||
// List returns a Pager which allows you to iterate over a collection of
|
||||
// CDN services. It accepts a ListOpts struct, which allows for pagination via
|
||||
// marker and limit.
|
||||
func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
|
||||
url := listURL(c)
|
||||
if opts != nil {
|
||||
query, err := opts.ToCDNServiceListQuery()
|
||||
if err != nil {
|
||||
return pagination.Pager{Err: err}
|
||||
}
|
||||
url += query
|
||||
}
|
||||
|
||||
createPage := func(r pagination.PageResult) pagination.Page {
|
||||
p := ServicePage{pagination.MarkerPageBase{PageResult: r}}
|
||||
p.MarkerPageBase.Owner = p
|
||||
return p
|
||||
}
|
||||
|
||||
pager := pagination.NewPager(c, url, createPage)
|
||||
return pager
|
||||
}
|
||||
|
||||
// CreateOptsBuilder is the interface options structs have to satisfy in order
|
||||
// to be used in the main Create operation in this package. Since many
|
||||
// extensions decorate or modify the common logic, it is useful for them to
|
||||
// satisfy a basic interface in order for them to be used.
|
||||
type CreateOptsBuilder interface {
|
||||
ToCDNServiceCreateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// CreateOpts is the common options struct used in this package's Create
|
||||
// operation.
|
||||
type CreateOpts struct {
|
||||
// REQUIRED. Specifies the name of the service. The minimum length for name is
|
||||
// 3. The maximum length is 256.
|
||||
Name string
|
||||
// REQUIRED. Specifies a list of domains used by users to access their website.
|
||||
Domains []Domain
|
||||
// REQUIRED. Specifies a list of origin domains or IP addresses where the
|
||||
// original assets are stored.
|
||||
Origins []Origin
|
||||
// REQUIRED. Specifies the CDN provider flavor ID to use. For a list of
|
||||
// flavors, see the operation to list the available flavors. The minimum
|
||||
// length for flavor_id is 1. The maximum length is 256.
|
||||
FlavorID string
|
||||
// OPTIONAL. Specifies the TTL rules for the assets under this service. Supports wildcards for fine-grained control.
|
||||
Caching []CacheRule
|
||||
// OPTIONAL. Specifies the restrictions that define who can access assets (content from the CDN cache).
|
||||
Restrictions []Restriction
|
||||
}
|
||||
|
||||
// ToCDNServiceCreateMap casts a CreateOpts struct to a map.
|
||||
func (opts CreateOpts) ToCDNServiceCreateMap() (map[string]interface{}, error) {
|
||||
s := make(map[string]interface{})
|
||||
|
||||
if opts.Name == "" {
|
||||
return nil, no("Name")
|
||||
}
|
||||
s["name"] = opts.Name
|
||||
|
||||
if opts.Domains == nil {
|
||||
return nil, no("Domains")
|
||||
}
|
||||
for _, domain := range opts.Domains {
|
||||
if domain.Domain == "" {
|
||||
return nil, no("Domains[].Domain")
|
||||
}
|
||||
}
|
||||
s["domains"] = opts.Domains
|
||||
|
||||
if opts.Origins == nil {
|
||||
return nil, no("Origins")
|
||||
}
|
||||
for _, origin := range opts.Origins {
|
||||
if origin.Origin == "" {
|
||||
return nil, no("Origins[].Origin")
|
||||
}
|
||||
if origin.Rules == nil && len(opts.Origins) > 1 {
|
||||
return nil, no("Origins[].Rules")
|
||||
}
|
||||
for _, rule := range origin.Rules {
|
||||
if rule.Name == "" {
|
||||
return nil, no("Origins[].Rules[].Name")
|
||||
}
|
||||
if rule.RequestURL == "" {
|
||||
return nil, no("Origins[].Rules[].RequestURL")
|
||||
}
|
||||
}
|
||||
}
|
||||
s["origins"] = opts.Origins
|
||||
|
||||
if opts.FlavorID == "" {
|
||||
return nil, no("FlavorID")
|
||||
}
|
||||
s["flavor_id"] = opts.FlavorID
|
||||
|
||||
if opts.Caching != nil {
|
||||
for _, cache := range opts.Caching {
|
||||
if cache.Name == "" {
|
||||
return nil, no("Caching[].Name")
|
||||
}
|
||||
if cache.Rules != nil {
|
||||
for _, rule := range cache.Rules {
|
||||
if rule.Name == "" {
|
||||
return nil, no("Caching[].Rules[].Name")
|
||||
}
|
||||
if rule.RequestURL == "" {
|
||||
return nil, no("Caching[].Rules[].RequestURL")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
s["caching"] = opts.Caching
|
||||
}
|
||||
|
||||
if opts.Restrictions != nil {
|
||||
for _, restriction := range opts.Restrictions {
|
||||
if restriction.Name == "" {
|
||||
return nil, no("Restrictions[].Name")
|
||||
}
|
||||
if restriction.Rules != nil {
|
||||
for _, rule := range restriction.Rules {
|
||||
if rule.Name == "" {
|
||||
return nil, no("Restrictions[].Rules[].Name")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
s["restrictions"] = opts.Restrictions
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Create accepts a CreateOpts struct and creates a new CDN service using the
|
||||
// values provided.
|
||||
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
|
||||
var res CreateResult
|
||||
|
||||
reqBody, err := opts.ToCDNServiceCreateMap()
|
||||
if err != nil {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
// Send request to API
|
||||
resp, err := c.Post(createURL(c), &reqBody, nil, nil)
|
||||
res.Header = resp.Header
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
// Get retrieves a specific service based on its URL or its unique ID. For
|
||||
// example, both "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0" and
|
||||
// "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0"
|
||||
// are valid options for idOrURL.
|
||||
func Get(c *gophercloud.ServiceClient, idOrURL string) GetResult {
|
||||
var url string
|
||||
if strings.Contains(idOrURL, "/") {
|
||||
url = idOrURL
|
||||
} else {
|
||||
url = getURL(c, idOrURL)
|
||||
}
|
||||
|
||||
var res GetResult
|
||||
_, res.Err = c.Get(url, &res.Body, nil)
|
||||
return res
|
||||
}
|
||||
|
||||
// Path is a JSON pointer location that indicates which service parameter is being added, replaced,
|
||||
// or removed.
|
||||
type Path struct {
|
||||
baseElement string
|
||||
}
|
||||
|
||||
func (p Path) renderRoot() string {
|
||||
return "/" + p.baseElement
|
||||
}
|
||||
|
||||
func (p Path) renderDash() string {
|
||||
return fmt.Sprintf("/%s/-", p.baseElement)
|
||||
}
|
||||
|
||||
func (p Path) renderIndex(index int64) string {
|
||||
return fmt.Sprintf("/%s/%d", p.baseElement, index)
|
||||
}
|
||||
|
||||
var (
|
||||
// PathDomains indicates that an update operation is to be performed on a Domain.
|
||||
PathDomains = Path{baseElement: "domains"}
|
||||
|
||||
// PathOrigins indicates that an update operation is to be performed on an Origin.
|
||||
PathOrigins = Path{baseElement: "origins"}
|
||||
|
||||
// PathCaching indicates that an update operation is to be performed on a CacheRule.
|
||||
PathCaching = Path{baseElement: "caching"}
|
||||
)
|
||||
|
||||
type value interface {
|
||||
toPatchValue() interface{}
|
||||
appropriatePath() Path
|
||||
renderRootOr(func(p Path) string) string
|
||||
}
|
||||
|
||||
// Patch represents a single update to an existing Service. Multiple updates to a service can be
|
||||
// submitted at the same time.
|
||||
type Patch interface {
|
||||
ToCDNServiceUpdateMap() map[string]interface{}
|
||||
}
|
||||
|
||||
// Insertion is a Patch that requests the addition of a value (Domain, Origin, or CacheRule) to
|
||||
// a Service at a fixed index. Use an Append instead to append the new value to the end of its
|
||||
// collection. Pass it to the Update function as part of the Patch slice.
|
||||
type Insertion struct {
|
||||
Index int64
|
||||
Value value
|
||||
}
|
||||
|
||||
// ToCDNServiceUpdateMap converts an Insertion into a request body fragment suitable for the
|
||||
// Update call.
|
||||
func (i Insertion) ToCDNServiceUpdateMap() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"op": "add",
|
||||
"path": i.Value.renderRootOr(func(p Path) string { return p.renderIndex(i.Index) }),
|
||||
"value": i.Value.toPatchValue(),
|
||||
}
|
||||
}
|
||||
|
||||
// Append is a Patch that requests the addition of a value (Domain, Origin, or CacheRule) to a
|
||||
// Service at the end of its respective collection. Use an Insertion instead to insert the value
|
||||
// at a fixed index within the collection. Pass this to the Update function as part of its
|
||||
// Patch slice.
|
||||
type Append struct {
|
||||
Value value
|
||||
}
|
||||
|
||||
// ToCDNServiceUpdateMap converts an Append into a request body fragment suitable for the
|
||||
// Update call.
|
||||
func (a Append) ToCDNServiceUpdateMap() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"op": "add",
|
||||
"path": a.Value.renderRootOr(func(p Path) string { return p.renderDash() }),
|
||||
"value": a.Value.toPatchValue(),
|
||||
}
|
||||
}
|
||||
|
||||
// Replacement is a Patch that alters a specific service parameter (Domain, Origin, or CacheRule)
|
||||
// in-place by index. Pass it to the Update function as part of the Patch slice.
|
||||
type Replacement struct {
|
||||
Value value
|
||||
Index int64
|
||||
}
|
||||
|
||||
// ToCDNServiceUpdateMap converts a Replacement into a request body fragment suitable for the
|
||||
// Update call.
|
||||
func (r Replacement) ToCDNServiceUpdateMap() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"op": "replace",
|
||||
"path": r.Value.renderRootOr(func(p Path) string { return p.renderIndex(r.Index) }),
|
||||
"value": r.Value.toPatchValue(),
|
||||
}
|
||||
}
|
||||
|
||||
// NameReplacement specifically updates the Service name. Pass it to the Update function as part
|
||||
// of the Patch slice.
|
||||
type NameReplacement struct {
|
||||
NewName string
|
||||
}
|
||||
|
||||
// ToCDNServiceUpdateMap converts a NameReplacement into a request body fragment suitable for the
|
||||
// Update call.
|
||||
func (r NameReplacement) ToCDNServiceUpdateMap() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"op": "replace",
|
||||
"path": "/name",
|
||||
"value": r.NewName,
|
||||
}
|
||||
}
|
||||
|
||||
// Removal is a Patch that requests the removal of a service parameter (Domain, Origin, or
|
||||
// CacheRule) by index. Pass it to the Update function as part of the Patch slice.
|
||||
type Removal struct {
|
||||
Path Path
|
||||
Index int64
|
||||
All bool
|
||||
}
|
||||
|
||||
// ToCDNServiceUpdateMap converts a Removal into a request body fragment suitable for the
|
||||
// Update call.
|
||||
func (r Removal) ToCDNServiceUpdateMap() map[string]interface{} {
|
||||
result := map[string]interface{}{"op": "remove"}
|
||||
if r.All {
|
||||
result["path"] = r.Path.renderRoot()
|
||||
} else {
|
||||
result["path"] = r.Path.renderIndex(r.Index)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
type UpdateOpts []Patch
|
||||
|
||||
// Update accepts a slice of Patch operations (Insertion, Append, Replacement or Removal) and
|
||||
// updates an existing CDN service using the values provided. idOrURL can be either the service's
|
||||
// URL or its ID. For example, both "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0" and
|
||||
// "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0"
|
||||
// are valid options for idOrURL.
|
||||
func Update(c *gophercloud.ServiceClient, idOrURL string, opts UpdateOpts) UpdateResult {
|
||||
var url string
|
||||
if strings.Contains(idOrURL, "/") {
|
||||
url = idOrURL
|
||||
} else {
|
||||
url = updateURL(c, idOrURL)
|
||||
}
|
||||
|
||||
reqBody := make([]map[string]interface{}, len(opts))
|
||||
for i, patch := range opts {
|
||||
reqBody[i] = patch.ToCDNServiceUpdateMap()
|
||||
}
|
||||
|
||||
resp, err := c.Request("PATCH", url, gophercloud.RequestOpts{
|
||||
JSONBody: &reqBody,
|
||||
OkCodes: []int{202},
|
||||
})
|
||||
var result UpdateResult
|
||||
result.Header = resp.Header
|
||||
result.Err = err
|
||||
return result
|
||||
}
|
||||
|
||||
// Delete accepts a service's ID or its URL and deletes the CDN service
|
||||
// associated with it. For example, both "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0" and
|
||||
// "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0"
|
||||
// are valid options for idOrURL.
|
||||
func Delete(c *gophercloud.ServiceClient, idOrURL string) DeleteResult {
|
||||
var url string
|
||||
if strings.Contains(idOrURL, "/") {
|
||||
url = idOrURL
|
||||
} else {
|
||||
url = deleteURL(c, idOrURL)
|
||||
}
|
||||
|
||||
var res DeleteResult
|
||||
_, res.Err = c.Delete(url, nil)
|
||||
return res
|
||||
}
|
316
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/results.go
generated
vendored
Normal file
316
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/results.go
generated
vendored
Normal file
@@ -0,0 +1,316 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
// Domain represents a domain used by users to access their website.
|
||||
type Domain struct {
|
||||
// Specifies the domain used to access the assets on their website, for which
|
||||
// a CNAME is given to the CDN provider.
|
||||
Domain string `mapstructure:"domain" json:"domain"`
|
||||
// Specifies the protocol used to access the assets on this domain. Only "http"
|
||||
// or "https" are currently allowed. The default is "http".
|
||||
Protocol string `mapstructure:"protocol" json:"protocol,omitempty"`
|
||||
}
|
||||
|
||||
func (d Domain) toPatchValue() interface{} {
|
||||
r := make(map[string]interface{})
|
||||
r["domain"] = d.Domain
|
||||
if d.Protocol != "" {
|
||||
r["protocol"] = d.Protocol
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (d Domain) appropriatePath() Path {
|
||||
return PathDomains
|
||||
}
|
||||
|
||||
func (d Domain) renderRootOr(render func(p Path) string) string {
|
||||
return render(d.appropriatePath())
|
||||
}
|
||||
|
||||
// DomainList provides a useful way to perform bulk operations in a single Patch.
|
||||
type DomainList []Domain
|
||||
|
||||
func (list DomainList) toPatchValue() interface{} {
|
||||
r := make([]interface{}, len(list))
|
||||
for i, domain := range list {
|
||||
r[i] = domain.toPatchValue()
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (list DomainList) appropriatePath() Path {
|
||||
return PathDomains
|
||||
}
|
||||
|
||||
func (list DomainList) renderRootOr(_ func(p Path) string) string {
|
||||
return list.appropriatePath().renderRoot()
|
||||
}
|
||||
|
||||
// OriginRule represents a rule that defines when an origin should be accessed.
|
||||
type OriginRule struct {
|
||||
// Specifies the name of this rule.
|
||||
Name string `mapstructure:"name" json:"name"`
|
||||
// Specifies the request URL this rule should match for this origin to be used. Regex is supported.
|
||||
RequestURL string `mapstructure:"request_url" json:"request_url"`
|
||||
}
|
||||
|
||||
// Origin specifies a list of origin domains or IP addresses where the original assets are stored.
|
||||
type Origin struct {
|
||||
// Specifies the URL or IP address to pull origin content from.
|
||||
Origin string `mapstructure:"origin" json:"origin"`
|
||||
// Specifies the port used to access the origin. The default is port 80.
|
||||
Port int `mapstructure:"port" json:"port,omitempty"`
|
||||
// Specifies whether or not to use HTTPS to access the origin. The default
|
||||
// is false.
|
||||
SSL bool `mapstructure:"ssl" json:"ssl"`
|
||||
// Specifies a collection of rules that define the conditions when this origin
|
||||
// should be accessed. If there is more than one origin, the rules parameter is required.
|
||||
Rules []OriginRule `mapstructure:"rules" json:"rules,omitempty"`
|
||||
}
|
||||
|
||||
func (o Origin) toPatchValue() interface{} {
|
||||
r := make(map[string]interface{})
|
||||
r["origin"] = o.Origin
|
||||
r["port"] = o.Port
|
||||
r["ssl"] = o.SSL
|
||||
if len(o.Rules) > 0 {
|
||||
r["rules"] = make([]map[string]interface{}, len(o.Rules))
|
||||
for index, rule := range o.Rules {
|
||||
submap := r["rules"].([]map[string]interface{})[index]
|
||||
submap["name"] = rule.Name
|
||||
submap["request_url"] = rule.RequestURL
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (o Origin) appropriatePath() Path {
|
||||
return PathOrigins
|
||||
}
|
||||
|
||||
func (o Origin) renderRootOr(render func(p Path) string) string {
|
||||
return render(o.appropriatePath())
|
||||
}
|
||||
|
||||
// OriginList provides a useful way to perform bulk operations in a single Patch.
|
||||
type OriginList []Origin
|
||||
|
||||
func (list OriginList) toPatchValue() interface{} {
|
||||
r := make([]interface{}, len(list))
|
||||
for i, origin := range list {
|
||||
r[i] = origin.toPatchValue()
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (list OriginList) appropriatePath() Path {
|
||||
return PathOrigins
|
||||
}
|
||||
|
||||
func (list OriginList) renderRootOr(_ func(p Path) string) string {
|
||||
return list.appropriatePath().renderRoot()
|
||||
}
|
||||
|
||||
// TTLRule specifies a rule that determines if a TTL should be applied to an asset.
|
||||
type TTLRule struct {
|
||||
// Specifies the name of this rule.
|
||||
Name string `mapstructure:"name" json:"name"`
|
||||
// Specifies the request URL this rule should match for this TTL to be used. Regex is supported.
|
||||
RequestURL string `mapstructure:"request_url" json:"request_url"`
|
||||
}
|
||||
|
||||
// CacheRule specifies the TTL rules for the assets under this service.
|
||||
type CacheRule struct {
|
||||
// Specifies the name of this caching rule. Note: 'default' is a reserved name used for the default TTL setting.
|
||||
Name string `mapstructure:"name" json:"name"`
|
||||
// Specifies the TTL to apply.
|
||||
TTL int `mapstructure:"ttl" json:"ttl"`
|
||||
// Specifies a collection of rules that determine if this TTL should be applied to an asset.
|
||||
Rules []TTLRule `mapstructure:"rules" json:"rules,omitempty"`
|
||||
}
|
||||
|
||||
func (c CacheRule) toPatchValue() interface{} {
|
||||
r := make(map[string]interface{})
|
||||
r["name"] = c.Name
|
||||
r["ttl"] = c.TTL
|
||||
r["rules"] = make([]map[string]interface{}, len(c.Rules))
|
||||
for index, rule := range c.Rules {
|
||||
submap := r["rules"].([]map[string]interface{})[index]
|
||||
submap["name"] = rule.Name
|
||||
submap["request_url"] = rule.RequestURL
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (c CacheRule) appropriatePath() Path {
|
||||
return PathCaching
|
||||
}
|
||||
|
||||
func (c CacheRule) renderRootOr(render func(p Path) string) string {
|
||||
return render(c.appropriatePath())
|
||||
}
|
||||
|
||||
// CacheRuleList provides a useful way to perform bulk operations in a single Patch.
|
||||
type CacheRuleList []CacheRule
|
||||
|
||||
func (list CacheRuleList) toPatchValue() interface{} {
|
||||
r := make([]interface{}, len(list))
|
||||
for i, rule := range list {
|
||||
r[i] = rule.toPatchValue()
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (list CacheRuleList) appropriatePath() Path {
|
||||
return PathCaching
|
||||
}
|
||||
|
||||
func (list CacheRuleList) renderRootOr(_ func(p Path) string) string {
|
||||
return list.appropriatePath().renderRoot()
|
||||
}
|
||||
|
||||
// RestrictionRule specifies a rule that determines if this restriction should be applied to an asset.
|
||||
type RestrictionRule struct {
|
||||
// Specifies the name of this rule.
|
||||
Name string `mapstructure:"name" json:"name"`
|
||||
// Specifies the http host that requests must come from.
|
||||
Referrer string `mapstructure:"referrer" json:"referrer,omitempty"`
|
||||
}
|
||||
|
||||
// Restriction specifies a restriction that defines who can access assets (content from the CDN cache).
|
||||
type Restriction struct {
|
||||
// Specifies the name of this restriction.
|
||||
Name string `mapstructure:"name" json:"name"`
|
||||
// Specifies a collection of rules that determine if this TTL should be applied to an asset.
|
||||
Rules []RestrictionRule `mapstructure:"rules" json:"rules"`
|
||||
}
|
||||
|
||||
// Error specifies an error that occurred during the previous service action.
|
||||
type Error struct {
|
||||
// Specifies an error message detailing why there is an error.
|
||||
Message string `mapstructure:"message"`
|
||||
}
|
||||
|
||||
// Service represents a CDN service resource.
|
||||
type Service struct {
|
||||
// Specifies the service ID that represents distributed content. The value is
|
||||
// a UUID, such as 96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0, that is generated by the server.
|
||||
ID string `mapstructure:"id"`
|
||||
// Specifies the name of the service.
|
||||
Name string `mapstructure:"name"`
|
||||
// Specifies a list of domains used by users to access their website.
|
||||
Domains []Domain `mapstructure:"domains"`
|
||||
// Specifies a list of origin domains or IP addresses where the original assets are stored.
|
||||
Origins []Origin `mapstructure:"origins"`
|
||||
// Specifies the TTL rules for the assets under this service. Supports wildcards for fine grained control.
|
||||
Caching []CacheRule `mapstructure:"caching"`
|
||||
// Specifies the restrictions that define who can access assets (content from the CDN cache).
|
||||
Restrictions []Restriction `mapstructure:"restrictions" json:"restrictions,omitempty"`
|
||||
// Specifies the CDN provider flavor ID to use. For a list of flavors, see the operation to list the available flavors.
|
||||
FlavorID string `mapstructure:"flavor_id"`
|
||||
// Specifies the current status of the service.
|
||||
Status string `mapstructure:"status"`
|
||||
// Specifies the list of errors that occurred during the previous service action.
|
||||
Errors []Error `mapstructure:"errors"`
|
||||
// Specifies the self-navigating JSON document paths.
|
||||
Links []gophercloud.Link `mapstructure:"links"`
|
||||
}
|
||||
|
||||
// ServicePage is the page returned by a pager when traversing over a
|
||||
// collection of CDN services.
|
||||
type ServicePage struct {
|
||||
pagination.MarkerPageBase
|
||||
}
|
||||
|
||||
// IsEmpty returns true if a ListResult contains no services.
|
||||
func (r ServicePage) IsEmpty() (bool, error) {
|
||||
services, err := ExtractServices(r)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
return len(services) == 0, nil
|
||||
}
|
||||
|
||||
// LastMarker returns the last service in a ListResult.
|
||||
func (r ServicePage) LastMarker() (string, error) {
|
||||
services, err := ExtractServices(r)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(services) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
return (services[len(services)-1]).ID, nil
|
||||
}
|
||||
|
||||
// ExtractServices is a function that takes a ListResult and returns the services' information.
|
||||
func ExtractServices(page pagination.Page) ([]Service, error) {
|
||||
var response struct {
|
||||
Services []Service `mapstructure:"services"`
|
||||
}
|
||||
|
||||
err := mapstructure.Decode(page.(ServicePage).Body, &response)
|
||||
return response.Services, err
|
||||
}
|
||||
|
||||
// CreateResult represents the result of a Create operation.
|
||||
type CreateResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// Extract is a method that extracts the location of a newly created service.
|
||||
func (r CreateResult) Extract() (string, error) {
|
||||
if r.Err != nil {
|
||||
return "", r.Err
|
||||
}
|
||||
if l, ok := r.Header["Location"]; ok && len(l) > 0 {
|
||||
return l[0], nil
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// GetResult represents the result of a get operation.
|
||||
type GetResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// Extract is a function that extracts a service from a GetResult.
|
||||
func (r GetResult) Extract() (*Service, error) {
|
||||
if r.Err != nil {
|
||||
return nil, r.Err
|
||||
}
|
||||
|
||||
var res Service
|
||||
|
||||
err := mapstructure.Decode(r.Body, &res)
|
||||
|
||||
return &res, err
|
||||
}
|
||||
|
||||
// UpdateResult represents the result of a Update operation.
|
||||
type UpdateResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// Extract is a method that extracts the location of an updated service.
|
||||
func (r UpdateResult) Extract() (string, error) {
|
||||
if r.Err != nil {
|
||||
return "", r.Err
|
||||
}
|
||||
if l, ok := r.Header["Location"]; ok && len(l) > 0 {
|
||||
return l[0], nil
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// DeleteResult represents the result of a Delete operation.
|
||||
type DeleteResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
23
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/urls.go
generated
vendored
Normal file
23
vendor/github.com/rackspace/gophercloud/openstack/cdn/v1/services/urls.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
package services
|
||||
|
||||
import "github.com/rackspace/gophercloud"
|
||||
|
||||
func listURL(c *gophercloud.ServiceClient) string {
|
||||
return c.ServiceURL("services")
|
||||
}
|
||||
|
||||
func createURL(c *gophercloud.ServiceClient) string {
|
||||
return listURL(c)
|
||||
}
|
||||
|
||||
func getURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return c.ServiceURL("services", id)
|
||||
}
|
||||
|
||||
func updateURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return getURL(c, id)
|
||||
}
|
||||
|
||||
func deleteURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return getURL(c, id)
|
||||
}
|
309
vendor/github.com/rackspace/gophercloud/openstack/client.go
generated
vendored
Normal file
309
vendor/github.com/rackspace/gophercloud/openstack/client.go
generated
vendored
Normal file
@@ -0,0 +1,309 @@
|
||||
package openstack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
tokens2 "github.com/rackspace/gophercloud/openstack/identity/v2/tokens"
|
||||
tokens3 "github.com/rackspace/gophercloud/openstack/identity/v3/tokens"
|
||||
"github.com/rackspace/gophercloud/openstack/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
v20 = "v2.0"
|
||||
v30 = "v3.0"
|
||||
)
|
||||
|
||||
// NewClient prepares an unauthenticated ProviderClient instance.
|
||||
// Most users will probably prefer using the AuthenticatedClient function instead.
|
||||
// This is useful if you wish to explicitly control the version of the identity service that's used for authentication explicitly,
|
||||
// for example.
|
||||
func NewClient(endpoint string) (*gophercloud.ProviderClient, error) {
|
||||
u, err := url.Parse(endpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hadPath := u.Path != ""
|
||||
u.Path, u.RawQuery, u.Fragment = "", "", ""
|
||||
base := u.String()
|
||||
|
||||
endpoint = gophercloud.NormalizeURL(endpoint)
|
||||
base = gophercloud.NormalizeURL(base)
|
||||
|
||||
if hadPath {
|
||||
return &gophercloud.ProviderClient{
|
||||
IdentityBase: base,
|
||||
IdentityEndpoint: endpoint,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &gophercloud.ProviderClient{
|
||||
IdentityBase: base,
|
||||
IdentityEndpoint: "",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// AuthenticatedClient logs in to an OpenStack cloud found at the identity endpoint specified by options, acquires a token, and
|
||||
// returns a Client instance that's ready to operate.
|
||||
// It first queries the root identity endpoint to determine which versions of the identity service are supported, then chooses
|
||||
// the most recent identity service available to proceed.
|
||||
func AuthenticatedClient(options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) {
|
||||
client, err := NewClient(options.IdentityEndpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = Authenticate(client, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// Authenticate or re-authenticate against the most recent identity service supported at the provided endpoint.
|
||||
func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error {
|
||||
versions := []*utils.Version{
|
||||
{ID: v20, Priority: 20, Suffix: "/v2.0/"},
|
||||
{ID: v30, Priority: 30, Suffix: "/v3/"},
|
||||
}
|
||||
|
||||
chosen, endpoint, err := utils.ChooseVersion(client, versions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch chosen.ID {
|
||||
case v20:
|
||||
return v2auth(client, endpoint, options)
|
||||
case v30:
|
||||
return v3auth(client, endpoint, options)
|
||||
default:
|
||||
// The switch statement must be out of date from the versions list.
|
||||
return fmt.Errorf("Unrecognized identity version: %s", chosen.ID)
|
||||
}
|
||||
}
|
||||
|
||||
// AuthenticateV2 explicitly authenticates against the identity v2 endpoint.
|
||||
func AuthenticateV2(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error {
|
||||
return v2auth(client, "", options)
|
||||
}
|
||||
|
||||
func v2auth(client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions) error {
|
||||
v2Client := NewIdentityV2(client)
|
||||
if endpoint != "" {
|
||||
v2Client.Endpoint = endpoint
|
||||
}
|
||||
|
||||
result := tokens2.Create(v2Client, tokens2.AuthOptions{AuthOptions: options})
|
||||
|
||||
token, err := result.ExtractToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
catalog, err := result.ExtractServiceCatalog()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if options.AllowReauth {
|
||||
client.ReauthFunc = func() error {
|
||||
client.TokenID = ""
|
||||
return v2auth(client, endpoint, options)
|
||||
}
|
||||
}
|
||||
client.TokenID = token.ID
|
||||
client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
|
||||
return V2EndpointURL(catalog, opts)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AuthenticateV3 explicitly authenticates against the identity v3 service.
|
||||
func AuthenticateV3(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error {
|
||||
return v3auth(client, "", options)
|
||||
}
|
||||
|
||||
func v3auth(client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions) error {
|
||||
// Override the generated service endpoint with the one returned by the version endpoint.
|
||||
v3Client := NewIdentityV3(client)
|
||||
if endpoint != "" {
|
||||
v3Client.Endpoint = endpoint
|
||||
}
|
||||
|
||||
var scope *tokens3.Scope
|
||||
if options.TenantID != "" {
|
||||
scope = &tokens3.Scope{
|
||||
ProjectID: options.TenantID,
|
||||
}
|
||||
options.TenantID = ""
|
||||
options.TenantName = ""
|
||||
} else {
|
||||
if options.TenantName != "" {
|
||||
scope = &tokens3.Scope{
|
||||
ProjectName: options.TenantName,
|
||||
DomainID: options.DomainID,
|
||||
DomainName: options.DomainName,
|
||||
}
|
||||
options.TenantName = ""
|
||||
}
|
||||
}
|
||||
|
||||
result := tokens3.Create(v3Client, options, scope)
|
||||
|
||||
token, err := result.ExtractToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
catalog, err := result.ExtractServiceCatalog()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client.TokenID = token.ID
|
||||
|
||||
if options.AllowReauth {
|
||||
client.ReauthFunc = func() error {
|
||||
client.TokenID = ""
|
||||
return v3auth(client, endpoint, options)
|
||||
}
|
||||
}
|
||||
client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
|
||||
return V3EndpointURL(catalog, opts)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewIdentityV2 creates a ServiceClient that may be used to interact with the v2 identity service.
|
||||
func NewIdentityV2(client *gophercloud.ProviderClient) *gophercloud.ServiceClient {
|
||||
v2Endpoint := client.IdentityBase + "v2.0/"
|
||||
|
||||
return &gophercloud.ServiceClient{
|
||||
ProviderClient: client,
|
||||
Endpoint: v2Endpoint,
|
||||
}
|
||||
}
|
||||
|
||||
// NewIdentityV3 creates a ServiceClient that may be used to access the v3 identity service.
|
||||
func NewIdentityV3(client *gophercloud.ProviderClient) *gophercloud.ServiceClient {
|
||||
v3Endpoint := client.IdentityBase + "v3/"
|
||||
|
||||
return &gophercloud.ServiceClient{
|
||||
ProviderClient: client,
|
||||
Endpoint: v3Endpoint,
|
||||
}
|
||||
}
|
||||
|
||||
func NewIdentityAdminV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
eo.ApplyDefaults("identity")
|
||||
eo.Availability = gophercloud.AvailabilityAdmin
|
||||
|
||||
url, err := client.EndpointLocator(eo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Force using v2 API
|
||||
if strings.Contains(url, "/v3") {
|
||||
url = strings.Replace(url, "/v3", "/v2.0", -1)
|
||||
}
|
||||
|
||||
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
||||
}
|
||||
|
||||
func NewIdentityAdminV3(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
eo.ApplyDefaults("identity")
|
||||
eo.Availability = gophercloud.AvailabilityAdmin
|
||||
|
||||
url, err := client.EndpointLocator(eo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Force using v3 API
|
||||
if strings.Contains(url, "/v2.0") {
|
||||
url = strings.Replace(url, "/v2.0", "/v3", -1)
|
||||
}
|
||||
|
||||
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
||||
}
|
||||
|
||||
// NewObjectStorageV1 creates a ServiceClient that may be used with the v1 object storage package.
|
||||
func NewObjectStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
eo.ApplyDefaults("object-store")
|
||||
url, err := client.EndpointLocator(eo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
||||
}
|
||||
|
||||
// NewComputeV2 creates a ServiceClient that may be used with the v2 compute package.
|
||||
func NewComputeV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
eo.ApplyDefaults("compute")
|
||||
url, err := client.EndpointLocator(eo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
||||
}
|
||||
|
||||
// NewNetworkV2 creates a ServiceClient that may be used with the v2 network package.
|
||||
func NewNetworkV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
eo.ApplyDefaults("network")
|
||||
url, err := client.EndpointLocator(eo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &gophercloud.ServiceClient{
|
||||
ProviderClient: client,
|
||||
Endpoint: url,
|
||||
ResourceBase: url + "v2.0/",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewBlockStorageV1 creates a ServiceClient that may be used to access the v1 block storage service.
|
||||
func NewBlockStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
eo.ApplyDefaults("volume")
|
||||
url, err := client.EndpointLocator(eo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
||||
}
|
||||
|
||||
// NewCDNV1 creates a ServiceClient that may be used to access the OpenStack v1
|
||||
// CDN service.
|
||||
func NewCDNV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
eo.ApplyDefaults("cdn")
|
||||
url, err := client.EndpointLocator(eo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
||||
}
|
||||
|
||||
// NewOrchestrationV1 creates a ServiceClient that may be used to access the v1 orchestration service.
|
||||
func NewOrchestrationV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
eo.ApplyDefaults("orchestration")
|
||||
url, err := client.EndpointLocator(eo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
||||
}
|
||||
|
||||
// NewDBV1 creates a ServiceClient that may be used to access the v1 DB service.
|
||||
func NewDBV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
eo.ApplyDefaults("database")
|
||||
url, err := client.EndpointLocator(eo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
||||
}
|
3
vendor/github.com/rackspace/gophercloud/openstack/common/README.md
generated
vendored
Normal file
3
vendor/github.com/rackspace/gophercloud/openstack/common/README.md
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# Common Resources
|
||||
|
||||
This directory is for resources that are shared by multiple services.
|
15
vendor/github.com/rackspace/gophercloud/openstack/common/extensions/doc.go
generated
vendored
Normal file
15
vendor/github.com/rackspace/gophercloud/openstack/common/extensions/doc.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// Package extensions provides information and interaction with the different extensions available
|
||||
// for an OpenStack service.
|
||||
//
|
||||
// The purpose of OpenStack API extensions is to:
|
||||
//
|
||||
// - Introduce new features in the API without requiring a version change.
|
||||
// - Introduce vendor-specific niche functionality.
|
||||
// - Act as a proving ground for experimental functionalities that might be included in a future
|
||||
// version of the API.
|
||||
//
|
||||
// Extensions usually have tags that prevent conflicts with other extensions that define attributes
|
||||
// or resources with the same names, and with core resources and attributes.
|
||||
// Because an extension might not be supported by all plug-ins, its availability varies with deployments
|
||||
// and the specific plug-in.
|
||||
package extensions
|
1
vendor/github.com/rackspace/gophercloud/openstack/common/extensions/errors.go
generated
vendored
Normal file
1
vendor/github.com/rackspace/gophercloud/openstack/common/extensions/errors.go
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
package extensions
|
91
vendor/github.com/rackspace/gophercloud/openstack/common/extensions/fixtures.go
generated
vendored
Normal file
91
vendor/github.com/rackspace/gophercloud/openstack/common/extensions/fixtures.go
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
// +build fixtures
|
||||
|
||||
package extensions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
"github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
// ListOutput provides a single page of Extension results.
|
||||
const ListOutput = `
|
||||
{
|
||||
"extensions": [
|
||||
{
|
||||
"updated": "2013-01-20T00:00:00-00:00",
|
||||
"name": "Neutron Service Type Management",
|
||||
"links": [],
|
||||
"namespace": "http://docs.openstack.org/ext/neutron/service-type/api/v1.0",
|
||||
"alias": "service-type",
|
||||
"description": "API for retrieving service providers for Neutron advanced services"
|
||||
}
|
||||
]
|
||||
}`
|
||||
|
||||
// GetOutput provides a single Extension result.
|
||||
const GetOutput = `
|
||||
{
|
||||
"extension": {
|
||||
"updated": "2013-02-03T10:00:00-00:00",
|
||||
"name": "agent",
|
||||
"links": [],
|
||||
"namespace": "http://docs.openstack.org/ext/agent/api/v2.0",
|
||||
"alias": "agent",
|
||||
"description": "The agent management extension."
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
// ListedExtension is the Extension that should be parsed from ListOutput.
|
||||
var ListedExtension = Extension{
|
||||
Updated: "2013-01-20T00:00:00-00:00",
|
||||
Name: "Neutron Service Type Management",
|
||||
Links: []interface{}{},
|
||||
Namespace: "http://docs.openstack.org/ext/neutron/service-type/api/v1.0",
|
||||
Alias: "service-type",
|
||||
Description: "API for retrieving service providers for Neutron advanced services",
|
||||
}
|
||||
|
||||
// ExpectedExtensions is a slice containing the Extension that should be parsed from ListOutput.
|
||||
var ExpectedExtensions = []Extension{ListedExtension}
|
||||
|
||||
// SingleExtension is the Extension that should be parsed from GetOutput.
|
||||
var SingleExtension = &Extension{
|
||||
Updated: "2013-02-03T10:00:00-00:00",
|
||||
Name: "agent",
|
||||
Links: []interface{}{},
|
||||
Namespace: "http://docs.openstack.org/ext/agent/api/v2.0",
|
||||
Alias: "agent",
|
||||
Description: "The agent management extension.",
|
||||
}
|
||||
|
||||
// HandleListExtensionsSuccessfully creates an HTTP handler at `/extensions` on the test handler
|
||||
// mux that response with a list containing a single tenant.
|
||||
func HandleListExtensionsSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/extensions", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
|
||||
fmt.Fprintf(w, ListOutput)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleGetExtensionSuccessfully creates an HTTP handler at `/extensions/agent` that responds with
|
||||
// a JSON payload corresponding to SingleExtension.
|
||||
func HandleGetExtensionSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/extensions/agent", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
fmt.Fprintf(w, GetOutput)
|
||||
})
|
||||
}
|
21
vendor/github.com/rackspace/gophercloud/openstack/common/extensions/requests.go
generated
vendored
Normal file
21
vendor/github.com/rackspace/gophercloud/openstack/common/extensions/requests.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
package extensions
|
||||
|
||||
import (
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// Get retrieves information for a specific extension using its alias.
|
||||
func Get(c *gophercloud.ServiceClient, alias string) GetResult {
|
||||
var res GetResult
|
||||
_, res.Err = c.Get(ExtensionURL(c, alias), &res.Body, nil)
|
||||
return res
|
||||
}
|
||||
|
||||
// List returns a Pager which allows you to iterate over the full collection of extensions.
|
||||
// It does not accept query parameters.
|
||||
func List(c *gophercloud.ServiceClient) pagination.Pager {
|
||||
return pagination.NewPager(c, ListExtensionURL(c), func(r pagination.PageResult) pagination.Page {
|
||||
return ExtensionPage{pagination.SinglePageBase(r)}
|
||||
})
|
||||
}
|
65
vendor/github.com/rackspace/gophercloud/openstack/common/extensions/results.go
generated
vendored
Normal file
65
vendor/github.com/rackspace/gophercloud/openstack/common/extensions/results.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
package extensions
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// GetResult temporarily stores the result of a Get call.
|
||||
// Use its Extract() method to interpret it as an Extension.
|
||||
type GetResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// Extract interprets a GetResult as an Extension.
|
||||
func (r GetResult) Extract() (*Extension, error) {
|
||||
if r.Err != nil {
|
||||
return nil, r.Err
|
||||
}
|
||||
|
||||
var res struct {
|
||||
Extension *Extension `json:"extension"`
|
||||
}
|
||||
|
||||
err := mapstructure.Decode(r.Body, &res)
|
||||
|
||||
return res.Extension, err
|
||||
}
|
||||
|
||||
// Extension is a struct that represents an OpenStack extension.
|
||||
type Extension struct {
|
||||
Updated string `json:"updated" mapstructure:"updated"`
|
||||
Name string `json:"name" mapstructure:"name"`
|
||||
Links []interface{} `json:"links" mapstructure:"links"`
|
||||
Namespace string `json:"namespace" mapstructure:"namespace"`
|
||||
Alias string `json:"alias" mapstructure:"alias"`
|
||||
Description string `json:"description" mapstructure:"description"`
|
||||
}
|
||||
|
||||
// ExtensionPage is the page returned by a pager when traversing over a collection of extensions.
|
||||
type ExtensionPage struct {
|
||||
pagination.SinglePageBase
|
||||
}
|
||||
|
||||
// IsEmpty checks whether an ExtensionPage struct is empty.
|
||||
func (r ExtensionPage) IsEmpty() (bool, error) {
|
||||
is, err := ExtractExtensions(r)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
return len(is) == 0, nil
|
||||
}
|
||||
|
||||
// ExtractExtensions accepts a Page struct, specifically an ExtensionPage struct, and extracts the
|
||||
// elements into a slice of Extension structs.
|
||||
// In other words, a generic collection is mapped into a relevant slice.
|
||||
func ExtractExtensions(page pagination.Page) ([]Extension, error) {
|
||||
var resp struct {
|
||||
Extensions []Extension `mapstructure:"extensions"`
|
||||
}
|
||||
|
||||
err := mapstructure.Decode(page.(ExtensionPage).Body, &resp)
|
||||
|
||||
return resp.Extensions, err
|
||||
}
|
13
vendor/github.com/rackspace/gophercloud/openstack/common/extensions/urls.go
generated
vendored
Normal file
13
vendor/github.com/rackspace/gophercloud/openstack/common/extensions/urls.go
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
package extensions
|
||||
|
||||
import "github.com/rackspace/gophercloud"
|
||||
|
||||
// ExtensionURL generates the URL for an extension resource by name.
|
||||
func ExtensionURL(c *gophercloud.ServiceClient, name string) string {
|
||||
return c.ServiceURL("extensions", name)
|
||||
}
|
||||
|
||||
// ListExtensionURL generates the URL for the extensions resource collection.
|
||||
func ListExtensionURL(c *gophercloud.ServiceClient) string {
|
||||
return c.ServiceURL("extensions")
|
||||
}
|
118
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/requests.go
generated
vendored
Normal file
118
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/requests.go
generated
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
package bootfromvolume
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
)
|
||||
|
||||
// SourceType represents the type of medium being used to create the volume.
|
||||
type SourceType string
|
||||
|
||||
const (
|
||||
Volume SourceType = "volume"
|
||||
Snapshot SourceType = "snapshot"
|
||||
Image SourceType = "image"
|
||||
Blank SourceType = "blank"
|
||||
)
|
||||
|
||||
// BlockDevice is a structure with options for booting a server instance
|
||||
// from a volume. The volume may be created from an image, snapshot, or another
|
||||
// volume.
|
||||
type BlockDevice struct {
|
||||
// BootIndex [optional] is the boot index. It defaults to 0.
|
||||
BootIndex int `json:"boot_index"`
|
||||
|
||||
// DeleteOnTermination [optional] specifies whether or not to delete the attached volume
|
||||
// when the server is deleted. Defaults to `false`.
|
||||
DeleteOnTermination bool `json:"delete_on_termination"`
|
||||
|
||||
// DestinationType [optional] is the type that gets created. Possible values are "volume"
|
||||
// and "local".
|
||||
DestinationType string `json:"destination_type"`
|
||||
|
||||
// GuestFormat [optional] specifies the format of the block device.
|
||||
GuestFormat string `json:"guest_format"`
|
||||
|
||||
// SourceType [required] must be one of: "volume", "snapshot", "image".
|
||||
SourceType SourceType `json:"source_type"`
|
||||
|
||||
// UUID [required] is the unique identifier for the volume, snapshot, or image (see above)
|
||||
UUID string `json:"uuid"`
|
||||
|
||||
// VolumeSize [optional] is the size of the volume to create (in gigabytes).
|
||||
VolumeSize int `json:"volume_size"`
|
||||
}
|
||||
|
||||
// CreateOptsExt is a structure that extends the server `CreateOpts` structure
|
||||
// by allowing for a block device mapping.
|
||||
type CreateOptsExt struct {
|
||||
servers.CreateOptsBuilder
|
||||
BlockDevice []BlockDevice `json:"block_device_mapping_v2,omitempty"`
|
||||
}
|
||||
|
||||
// ToServerCreateMap adds the block device mapping option to the base server
|
||||
// creation options.
|
||||
func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) {
|
||||
base, err := opts.CreateOptsBuilder.ToServerCreateMap()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(opts.BlockDevice) == 0 {
|
||||
return nil, errors.New("Required fields UUID and SourceType not set.")
|
||||
}
|
||||
|
||||
serverMap := base["server"].(map[string]interface{})
|
||||
|
||||
blockDevice := make([]map[string]interface{}, len(opts.BlockDevice))
|
||||
|
||||
for i, bd := range opts.BlockDevice {
|
||||
if string(bd.SourceType) == "" {
|
||||
return nil, errors.New("SourceType must be one of: volume, image, snapshot.")
|
||||
}
|
||||
|
||||
blockDevice[i] = make(map[string]interface{})
|
||||
|
||||
blockDevice[i]["source_type"] = bd.SourceType
|
||||
blockDevice[i]["boot_index"] = strconv.Itoa(bd.BootIndex)
|
||||
blockDevice[i]["delete_on_termination"] = strconv.FormatBool(bd.DeleteOnTermination)
|
||||
blockDevice[i]["volume_size"] = strconv.Itoa(bd.VolumeSize)
|
||||
if bd.UUID != "" {
|
||||
blockDevice[i]["uuid"] = bd.UUID
|
||||
}
|
||||
if bd.DestinationType != "" {
|
||||
blockDevice[i]["destination_type"] = bd.DestinationType
|
||||
}
|
||||
if bd.GuestFormat != "" {
|
||||
blockDevice[i]["guest_format"] = bd.GuestFormat
|
||||
}
|
||||
|
||||
}
|
||||
serverMap["block_device_mapping_v2"] = blockDevice
|
||||
|
||||
return base, nil
|
||||
}
|
||||
|
||||
// Create requests the creation of a server from the given block device mapping.
|
||||
func Create(client *gophercloud.ServiceClient, opts servers.CreateOptsBuilder) servers.CreateResult {
|
||||
var res servers.CreateResult
|
||||
|
||||
reqBody, err := opts.ToServerCreateMap()
|
||||
if err != nil {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
// Delete imageName and flavorName that come from ToServerCreateMap().
|
||||
// As of Liberty, Boot From Volume is failing if they are passed.
|
||||
delete(reqBody["server"].(map[string]interface{}), "imageName")
|
||||
delete(reqBody["server"].(map[string]interface{}), "flavorName")
|
||||
|
||||
_, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200, 202},
|
||||
})
|
||||
return res
|
||||
}
|
10
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/results.go
generated
vendored
Normal file
10
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/results.go
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
package bootfromvolume
|
||||
|
||||
import (
|
||||
os "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
)
|
||||
|
||||
// CreateResult temporarily contains the response from a Create call.
|
||||
type CreateResult struct {
|
||||
os.CreateResult
|
||||
}
|
7
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/urls.go
generated
vendored
Normal file
7
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/urls.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
package bootfromvolume
|
||||
|
||||
import "github.com/rackspace/gophercloud"
|
||||
|
||||
func createURL(c *gophercloud.ServiceClient) string {
|
||||
return c.ServiceURL("os-volumes_boot")
|
||||
}
|
1
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/doc.go
generated
vendored
Normal file
1
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/doc.go
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
package defsecrules
|
143
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/fixtures.go
generated
vendored
Normal file
143
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/fixtures.go
generated
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
package defsecrules
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
fake "github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
const rootPath = "/os-security-group-default-rules"
|
||||
|
||||
func mockListRulesResponse(t *testing.T) {
|
||||
th.Mux.HandleFunc(rootPath, func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"security_group_default_rules": [
|
||||
{
|
||||
"from_port": 80,
|
||||
"id": "{ruleID}",
|
||||
"ip_protocol": "TCP",
|
||||
"ip_range": {
|
||||
"cidr": "10.10.10.0/24"
|
||||
},
|
||||
"to_port": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
||||
|
||||
func mockCreateRuleResponse(t *testing.T) {
|
||||
th.Mux.HandleFunc(rootPath, func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "POST")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
th.TestJSONRequest(t, r, `
|
||||
{
|
||||
"security_group_default_rule": {
|
||||
"ip_protocol": "TCP",
|
||||
"from_port": 80,
|
||||
"to_port": 80,
|
||||
"cidr": "10.10.12.0/24"
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"security_group_default_rule": {
|
||||
"from_port": 80,
|
||||
"id": "{ruleID}",
|
||||
"ip_protocol": "TCP",
|
||||
"ip_range": {
|
||||
"cidr": "10.10.12.0/24"
|
||||
},
|
||||
"to_port": 80
|
||||
}
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
||||
|
||||
func mockCreateRuleResponseICMPZero(t *testing.T) {
|
||||
th.Mux.HandleFunc(rootPath, func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "POST")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
th.TestJSONRequest(t, r, `
|
||||
{
|
||||
"security_group_default_rule": {
|
||||
"ip_protocol": "ICMP",
|
||||
"from_port": 0,
|
||||
"to_port": 0,
|
||||
"cidr": "10.10.12.0/24"
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"security_group_default_rule": {
|
||||
"from_port": 0,
|
||||
"id": "{ruleID}",
|
||||
"ip_protocol": "ICMP",
|
||||
"ip_range": {
|
||||
"cidr": "10.10.12.0/24"
|
||||
},
|
||||
"to_port": 0
|
||||
}
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
||||
|
||||
func mockGetRuleResponse(t *testing.T, ruleID string) {
|
||||
url := rootPath + "/" + ruleID
|
||||
th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"security_group_default_rule": {
|
||||
"id": "{ruleID}",
|
||||
"from_port": 80,
|
||||
"to_port": 80,
|
||||
"ip_protocol": "TCP",
|
||||
"ip_range": {
|
||||
"cidr": "10.10.12.0/24"
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
||||
|
||||
func mockDeleteRuleResponse(t *testing.T, ruleID string) {
|
||||
url := rootPath + "/" + ruleID
|
||||
th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "DELETE")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
})
|
||||
}
|
96
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/requests.go
generated
vendored
Normal file
96
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/requests.go
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
package defsecrules
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// List will return a collection of default rules.
|
||||
func List(client *gophercloud.ServiceClient) pagination.Pager {
|
||||
createPage := func(r pagination.PageResult) pagination.Page {
|
||||
return DefaultRulePage{pagination.SinglePageBase(r)}
|
||||
}
|
||||
|
||||
return pagination.NewPager(client, rootURL(client), createPage)
|
||||
}
|
||||
|
||||
// CreateOpts represents the configuration for adding a new default rule.
|
||||
type CreateOpts struct {
|
||||
// Required - the lower bound of the port range that will be opened.
|
||||
FromPort int `json:"from_port"`
|
||||
|
||||
// Required - the upper bound of the port range that will be opened.
|
||||
ToPort int `json:"to_port"`
|
||||
|
||||
// Required - the protocol type that will be allowed, e.g. TCP.
|
||||
IPProtocol string `json:"ip_protocol"`
|
||||
|
||||
// ONLY required if FromGroupID is blank. This represents the IP range that
|
||||
// will be the source of network traffic to your security group. Use
|
||||
// 0.0.0.0/0 to allow all IP addresses.
|
||||
CIDR string `json:"cidr,omitempty"`
|
||||
}
|
||||
|
||||
// CreateOptsBuilder builds the create rule options into a serializable format.
|
||||
type CreateOptsBuilder interface {
|
||||
ToRuleCreateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// ToRuleCreateMap builds the create rule options into a serializable format.
|
||||
func (opts CreateOpts) ToRuleCreateMap() (map[string]interface{}, error) {
|
||||
rule := make(map[string]interface{})
|
||||
|
||||
if opts.FromPort == 0 && strings.ToUpper(opts.IPProtocol) != "ICMP" {
|
||||
return rule, errors.New("A FromPort must be set")
|
||||
}
|
||||
if opts.ToPort == 0 && strings.ToUpper(opts.IPProtocol) != "ICMP" {
|
||||
return rule, errors.New("A ToPort must be set")
|
||||
}
|
||||
if opts.IPProtocol == "" {
|
||||
return rule, errors.New("A IPProtocol must be set")
|
||||
}
|
||||
if opts.CIDR == "" {
|
||||
return rule, errors.New("A CIDR must be set")
|
||||
}
|
||||
|
||||
rule["from_port"] = opts.FromPort
|
||||
rule["to_port"] = opts.ToPort
|
||||
rule["ip_protocol"] = opts.IPProtocol
|
||||
rule["cidr"] = opts.CIDR
|
||||
|
||||
return map[string]interface{}{"security_group_default_rule": rule}, nil
|
||||
}
|
||||
|
||||
// Create is the operation responsible for creating a new default rule.
|
||||
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
|
||||
var result CreateResult
|
||||
|
||||
reqBody, err := opts.ToRuleCreateMap()
|
||||
if err != nil {
|
||||
result.Err = err
|
||||
return result
|
||||
}
|
||||
|
||||
_, result.Err = client.Post(rootURL(client), reqBody, &result.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Get will return details for a particular default rule.
|
||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||
var result GetResult
|
||||
_, result.Err = client.Get(resourceURL(client, id), &result.Body, nil)
|
||||
return result
|
||||
}
|
||||
|
||||
// Delete will permanently delete a default rule from the project.
|
||||
func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
|
||||
var result gophercloud.ErrResult
|
||||
_, result.Err = client.Delete(resourceURL(client, id), nil)
|
||||
return result
|
||||
}
|
69
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/results.go
generated
vendored
Normal file
69
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/results.go
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
package defsecrules
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/mapstructure"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// DefaultRule represents a default rule - which is identical to a
|
||||
// normal security rule.
|
||||
type DefaultRule secgroups.Rule
|
||||
|
||||
// DefaultRulePage is a single page of a DefaultRule collection.
|
||||
type DefaultRulePage struct {
|
||||
pagination.SinglePageBase
|
||||
}
|
||||
|
||||
// IsEmpty determines whether or not a page of default rules contains any results.
|
||||
func (page DefaultRulePage) IsEmpty() (bool, error) {
|
||||
users, err := ExtractDefaultRules(page)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return len(users) == 0, nil
|
||||
}
|
||||
|
||||
// ExtractDefaultRules returns a slice of DefaultRules contained in a single
|
||||
// page of results.
|
||||
func ExtractDefaultRules(page pagination.Page) ([]DefaultRule, error) {
|
||||
casted := page.(DefaultRulePage).Body
|
||||
var response struct {
|
||||
Rules []DefaultRule `mapstructure:"security_group_default_rules"`
|
||||
}
|
||||
|
||||
err := mapstructure.WeakDecode(casted, &response)
|
||||
|
||||
return response.Rules, err
|
||||
}
|
||||
|
||||
type commonResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// CreateResult represents the result of a create operation.
|
||||
type CreateResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// GetResult represents the result of a get operation.
|
||||
type GetResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// Extract will extract a DefaultRule struct from most responses.
|
||||
func (r commonResult) Extract() (*DefaultRule, error) {
|
||||
if r.Err != nil {
|
||||
return nil, r.Err
|
||||
}
|
||||
|
||||
var response struct {
|
||||
Rule DefaultRule `mapstructure:"security_group_default_rule"`
|
||||
}
|
||||
|
||||
err := mapstructure.WeakDecode(r.Body, &response)
|
||||
|
||||
return &response.Rule, err
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user