mirror of https://github.com/docker/docs.git
Merge pull request #562 from smashwilson/openstack-insecure
Allow insecure connections in the Openstack driver.
This commit is contained in:
commit
1e716a96ad
|
@ -123,15 +123,10 @@
|
||||||
"ImportPath": "github.com/mitchellh/mapstructure",
|
"ImportPath": "github.com/mitchellh/mapstructure",
|
||||||
"Rev": "740c764bc6149d3f1806231418adb9f52c11bcbf"
|
"Rev": "740c764bc6149d3f1806231418adb9f52c11bcbf"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"ImportPath": "github.com/racker/perigee",
|
|
||||||
"Comment": "v0.0.0-18-g0c00cb0",
|
|
||||||
"Rev": "0c00cb0a026b71034ebc8205263c77dad3577db5"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud",
|
"ImportPath": "github.com/rackspace/gophercloud",
|
||||||
"Comment": "v1.0.0-232-g2e7ab37",
|
"Comment": "v1.0.0-473-g7ca169d",
|
||||||
"Rev": "2e7ab378257b8723e02cbceac7410be4db286436"
|
"Rev": "7ca169d371b29e3dbab9e631c3a6151896b06330"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/smartystreets/go-aws-auth",
|
"ImportPath": "github.com/smartystreets/go-aws-auth",
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
bin/*
|
|
||||||
pkg/*
|
|
|
@ -1,202 +0,0 @@
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
|
||||||
|
|
||||||
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.
|
|
|
@ -1,120 +0,0 @@
|
||||||
# perigee
|
|
||||||
|
|
||||||
Perigee provides a REST client that, while it should be generic enough to use with most any RESTful API, is nonetheless optimized to the needs of the OpenStack APIs.
|
|
||||||
Perigee grew out of the need to refactor out common API access code from the [gorax](http://github.com/racker/gorax) project.
|
|
||||||
|
|
||||||
Several things influenced the name of the project.
|
|
||||||
Numerous elements of the OpenStack ecosystem are named after astronomical artifacts.
|
|
||||||
Additionally, perigee occurs when two orbiting bodies are closest to each other.
|
|
||||||
Perigee seemed appropriate for something aiming to bring OpenStack and other RESTful services closer to the end-user.
|
|
||||||
|
|
||||||
**This library is still in the very early stages of development. Unless you want to contribute, it probably isn't what you want**
|
|
||||||
|
|
||||||
## Installation and Testing
|
|
||||||
|
|
||||||
To install:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go get github.com/racker/perigee
|
|
||||||
```
|
|
||||||
|
|
||||||
To run unit tests:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go test github.com/racker/perigee
|
|
||||||
```
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
The following guidelines are preliminary, as this project is just starting out.
|
|
||||||
However, this should serve as a working first-draft.
|
|
||||||
|
|
||||||
### Branching
|
|
||||||
|
|
||||||
The master branch must always be a valid build.
|
|
||||||
The `go get` command will not work otherwise.
|
|
||||||
Therefore, development must occur on a different branch.
|
|
||||||
|
|
||||||
When creating a feature branch, do so off the master branch:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git checkout master
|
|
||||||
git pull
|
|
||||||
git checkout -b featureBranch
|
|
||||||
git checkout -b featureBranch-wip # optional
|
|
||||||
```
|
|
||||||
|
|
||||||
Perform all your editing and testing in the WIP-branch.
|
|
||||||
Feel free to make as many commits as you see fit.
|
|
||||||
You may even open "WIP" pull requests from your feature branch to seek feedback.
|
|
||||||
WIP pull requests will **never** be merged, however.
|
|
||||||
|
|
||||||
To get code merged, you'll need to "squash" your changes into one or more clean commits in the feature branch.
|
|
||||||
These steps should be followed:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git checkout featureBranch
|
|
||||||
git merge --squash featureBranch-wip
|
|
||||||
git commit -a
|
|
||||||
git push origin featureBranch
|
|
||||||
```
|
|
||||||
|
|
||||||
You may now open a nice, clean, self-contained pull request from featureBranch to master.
|
|
||||||
|
|
||||||
The `git commit -a` command above will open a text editor so that
|
|
||||||
you may provide a comprehensive description of the changes.
|
|
||||||
|
|
||||||
In general, when submitting a pull request against master,
|
|
||||||
be sure to answer the following questions:
|
|
||||||
|
|
||||||
- What is the problem?
|
|
||||||
- Why is it a problem?
|
|
||||||
- What is your solution?
|
|
||||||
- How does your solution work? (Recommended for non-trivial changes.)
|
|
||||||
- Why should we use your solution over someone elses? (Recommended especially if multiple solutions being discussed.)
|
|
||||||
|
|
||||||
Remember that monster-sized pull requests are a bear to code-review,
|
|
||||||
so having helpful commit logs are an absolute must to review changes as quickly as possible.
|
|
||||||
|
|
||||||
Finally, (s)he who breaks master is ultimately responsible for fixing master.
|
|
||||||
|
|
||||||
### Source Representation
|
|
||||||
|
|
||||||
The Go community firmly believes in a consistent representation for all Go source code.
|
|
||||||
We do too.
|
|
||||||
Make sure all source code is passed through "go fmt" *before* you create your pull request.
|
|
||||||
|
|
||||||
Please note, however, that we fully acknowledge and recognize that we no longer rely upon punch-cards for representing source files.
|
|
||||||
Therefore, no 80-column limit exists.
|
|
||||||
However, if a line exceeds 132 columns, you may want to consider splitting the line.
|
|
||||||
|
|
||||||
### Unit and Integration Tests
|
|
||||||
|
|
||||||
Pull requests that include non-trivial code changes without accompanying unit tests will be flatly rejected.
|
|
||||||
While we have no way of enforcing this practice,
|
|
||||||
you can ensure your code is thoroughly tested by always [writing tests first by intention.](http://en.wikipedia.org/wiki/Test-driven_development)
|
|
||||||
|
|
||||||
When creating a pull request, if even one test fails, the PR will be rejected.
|
|
||||||
Make sure all unit tests pass.
|
|
||||||
Make sure all integration tests pass.
|
|
||||||
|
|
||||||
### Documentation
|
|
||||||
|
|
||||||
Private functions and methods which are obvious to anyone unfamiliar with gorax needn't be accompanied by documentation.
|
|
||||||
However, this is a code-smell; if submitting a PR, expect to justify your decision.
|
|
||||||
|
|
||||||
Public functions, regardless of how obvious, **must** have accompanying godoc-style documentation.
|
|
||||||
This is not to suggest you should provide a tome for each function, however.
|
|
||||||
Sometimes a link to more information is more appropriate, provided the link is stable, reliable, and pertinent.
|
|
||||||
|
|
||||||
Changing documentation often results in bizarre diffs in pull requests, due to text often spanning multiple lines.
|
|
||||||
To work around this, put [one logical thought or sentence on a single line.](http://rhodesmill.org/brandon/2012/one-sentence-per-line/)
|
|
||||||
While this looks weird in a plain-text editor,
|
|
||||||
remember that both godoc and HTML viewers will reflow text.
|
|
||||||
The source code and its comments should be easy to edit with minimal diff pollution.
|
|
||||||
Let software dedicated to presenting the documentation to human readers deal with its presentation.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
t.b.d.
|
|
||||||
|
|
|
@ -1,269 +0,0 @@
|
||||||
// vim: ts=8 sw=8 noet ai
|
|
||||||
|
|
||||||
package perigee
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// The UnexpectedResponseCodeError structure represents a mismatch in understanding between server and client in terms of response codes.
|
|
||||||
// Most often, this is due to an actual error condition (e.g., getting a 404 for a resource when you expect a 200).
|
|
||||||
// However, it needn't always be the case (e.g., getting a 204 (No Content) response back when a 200 is expected).
|
|
||||||
type UnexpectedResponseCodeError struct {
|
|
||||||
Url string
|
|
||||||
Expected []int
|
|
||||||
Actual int
|
|
||||||
Body []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err *UnexpectedResponseCodeError) Error() string {
|
|
||||||
return fmt.Sprintf("Expected HTTP response code %d when accessing URL(%s); got %d instead with the following body:\n%s", err.Expected, err.Url, err.Actual, string(err.Body))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Request issues an HTTP request, marshaling parameters, and unmarshaling results, as configured in the provided Options parameter.
|
|
||||||
// The Response structure returned, if any, will include accumulated results recovered from the HTTP server.
|
|
||||||
// See the Response structure for more details.
|
|
||||||
func Request(method string, url string, opts Options) (*Response, error) {
|
|
||||||
var body io.Reader
|
|
||||||
var response Response
|
|
||||||
|
|
||||||
client := opts.CustomClient
|
|
||||||
if client == nil {
|
|
||||||
client = new(http.Client)
|
|
||||||
}
|
|
||||||
|
|
||||||
contentType := opts.ContentType
|
|
||||||
|
|
||||||
body = nil
|
|
||||||
if opts.ReqBody != nil {
|
|
||||||
if contentType == "" {
|
|
||||||
contentType = "application/json"
|
|
||||||
}
|
|
||||||
|
|
||||||
if contentType == "application/json" {
|
|
||||||
bodyText, err := json.Marshal(opts.ReqBody)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
body = strings.NewReader(string(bodyText))
|
|
||||||
if opts.DumpReqJson {
|
|
||||||
log.Printf("Making request:\n%#v\n", string(bodyText))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// assume opts.ReqBody implements the correct interface
|
|
||||||
body = opts.ReqBody.(io.Reader)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req, err := http.NewRequest(method, url, body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if contentType != "" {
|
|
||||||
req.Header.Add("Content-Type", contentType)
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.ContentLength > 0 {
|
|
||||||
req.ContentLength = opts.ContentLength
|
|
||||||
req.Header.Add("Content-Length", string(opts.ContentLength))
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.MoreHeaders != nil {
|
|
||||||
for k, v := range opts.MoreHeaders {
|
|
||||||
req.Header.Add(k, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if accept := req.Header.Get("Accept"); accept == "" {
|
|
||||||
accept = opts.Accept
|
|
||||||
if accept == "" {
|
|
||||||
accept = "application/json"
|
|
||||||
}
|
|
||||||
req.Header.Add("Accept", accept)
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.SetHeaders != nil {
|
|
||||||
err = opts.SetHeaders(req)
|
|
||||||
if err != nil {
|
|
||||||
return &response, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
httpResponse, err := client.Do(req)
|
|
||||||
if httpResponse != nil {
|
|
||||||
response.HttpResponse = *httpResponse
|
|
||||||
response.StatusCode = httpResponse.StatusCode
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return &response, err
|
|
||||||
}
|
|
||||||
// This if-statement is legacy code, preserved for backward compatibility.
|
|
||||||
if opts.StatusCode != nil {
|
|
||||||
*opts.StatusCode = httpResponse.StatusCode
|
|
||||||
}
|
|
||||||
|
|
||||||
acceptableResponseCodes := opts.OkCodes
|
|
||||||
if len(acceptableResponseCodes) != 0 {
|
|
||||||
if not_in(httpResponse.StatusCode, acceptableResponseCodes) {
|
|
||||||
b, _ := ioutil.ReadAll(httpResponse.Body)
|
|
||||||
httpResponse.Body.Close()
|
|
||||||
return &response, &UnexpectedResponseCodeError{
|
|
||||||
Url: url,
|
|
||||||
Expected: acceptableResponseCodes,
|
|
||||||
Actual: httpResponse.StatusCode,
|
|
||||||
Body: b,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if opts.Results != nil {
|
|
||||||
defer httpResponse.Body.Close()
|
|
||||||
jsonResult, err := ioutil.ReadAll(httpResponse.Body)
|
|
||||||
response.JsonResult = jsonResult
|
|
||||||
if err != nil {
|
|
||||||
return &response, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = json.Unmarshal(jsonResult, opts.Results)
|
|
||||||
// This if-statement is legacy code, preserved for backward compatibility.
|
|
||||||
if opts.ResponseJson != nil {
|
|
||||||
*opts.ResponseJson = jsonResult
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &response, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// not_in returns false if, and only if, the provided needle is _not_
|
|
||||||
// in the given set of integers.
|
|
||||||
func not_in(needle int, haystack []int) bool {
|
|
||||||
for _, straw := range haystack {
|
|
||||||
if needle == straw {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Post makes a POST request against a server using the provided HTTP client.
|
|
||||||
// The url must be a fully-formed URL string.
|
|
||||||
// DEPRECATED. Use Request() instead.
|
|
||||||
func Post(url string, opts Options) error {
|
|
||||||
r, err := Request("POST", url, opts)
|
|
||||||
if opts.Response != nil {
|
|
||||||
*opts.Response = r
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get makes a GET request against a server using the provided HTTP client.
|
|
||||||
// The url must be a fully-formed URL string.
|
|
||||||
// DEPRECATED. Use Request() instead.
|
|
||||||
func Get(url string, opts Options) error {
|
|
||||||
r, err := Request("GET", url, opts)
|
|
||||||
if opts.Response != nil {
|
|
||||||
*opts.Response = r
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete makes a DELETE request against a server using the provided HTTP client.
|
|
||||||
// The url must be a fully-formed URL string.
|
|
||||||
// DEPRECATED. Use Request() instead.
|
|
||||||
func Delete(url string, opts Options) error {
|
|
||||||
r, err := Request("DELETE", url, opts)
|
|
||||||
if opts.Response != nil {
|
|
||||||
*opts.Response = r
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Put makes a PUT request against a server using the provided HTTP client.
|
|
||||||
// The url must be a fully-formed URL string.
|
|
||||||
// DEPRECATED. Use Request() instead.
|
|
||||||
func Put(url string, opts Options) error {
|
|
||||||
r, err := Request("PUT", url, opts)
|
|
||||||
if opts.Response != nil {
|
|
||||||
*opts.Response = r
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Options describes a set of optional parameters to the various request calls.
|
|
||||||
//
|
|
||||||
// The custom client can be used for a variety of purposes beyond selecting encrypted versus unencrypted channels.
|
|
||||||
// Transports can be defined to provide augmented logging, header manipulation, et. al.
|
|
||||||
//
|
|
||||||
// If the ReqBody field is provided, it will be embedded as a JSON object.
|
|
||||||
// Otherwise, provide nil.
|
|
||||||
//
|
|
||||||
// If JSON output is to be expected from the response,
|
|
||||||
// provide either a pointer to the container structure in Results,
|
|
||||||
// or a pointer to a nil-initialized pointer variable.
|
|
||||||
// The latter method will cause the unmarshaller to allocate the container type for you.
|
|
||||||
// If no response is expected, provide a nil Results value.
|
|
||||||
//
|
|
||||||
// The MoreHeaders map, if non-nil or empty, provides a set of headers to add to those
|
|
||||||
// already present in the request. At present, only Accepted and Content-Type are set
|
|
||||||
// by default.
|
|
||||||
//
|
|
||||||
// OkCodes provides a set of acceptable, positive responses.
|
|
||||||
//
|
|
||||||
// If provided, StatusCode specifies a pointer to an integer, which will receive the
|
|
||||||
// returned HTTP status code, successful or not. DEPRECATED; use the Response.StatusCode field instead for new software.
|
|
||||||
//
|
|
||||||
// ResponseJson, if specified, provides a means for returning the raw JSON. This is
|
|
||||||
// most useful for diagnostics. DEPRECATED; use the Response.JsonResult field instead for new software.
|
|
||||||
//
|
|
||||||
// DumpReqJson, if set to true, will cause the request to appear to stdout for debugging purposes.
|
|
||||||
// This attribute may be removed at any time in the future; DO NOT use this attribute in production software.
|
|
||||||
//
|
|
||||||
// Response, if set, provides a way to communicate the complete set of HTTP response, raw JSON, status code, and
|
|
||||||
// other useful attributes back to the caller. Note that the Request() method returns a Response structure as part
|
|
||||||
// of its public interface; you don't need to set the Response field here to use this structure. The Response field
|
|
||||||
// exists primarily for legacy or deprecated functions.
|
|
||||||
//
|
|
||||||
// SetHeaders allows the caller to provide code to set any custom headers programmatically. Typically, this
|
|
||||||
// facility can invoke, e.g., SetBasicAuth() on the request to easily set up authentication.
|
|
||||||
// Any error generated will terminate the request and will propegate back to the caller.
|
|
||||||
type Options struct {
|
|
||||||
CustomClient *http.Client
|
|
||||||
ReqBody interface{}
|
|
||||||
Results interface{}
|
|
||||||
MoreHeaders map[string]string
|
|
||||||
OkCodes []int
|
|
||||||
StatusCode *int `DEPRECATED`
|
|
||||||
DumpReqJson bool `UNSUPPORTED`
|
|
||||||
ResponseJson *[]byte `DEPRECATED`
|
|
||||||
Response **Response
|
|
||||||
ContentType string `json:"Content-Type,omitempty"`
|
|
||||||
ContentLength int64 `json:"Content-Length,omitempty"`
|
|
||||||
Accept string `json:"Accept,omitempty"`
|
|
||||||
SetHeaders func(r *http.Request) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Response contains return values from the various request calls.
|
|
||||||
//
|
|
||||||
// HttpResponse will return the http response from the request call.
|
|
||||||
// Note: HttpResponse.Body is always closed and will not be available from this return value.
|
|
||||||
//
|
|
||||||
// StatusCode specifies the returned HTTP status code, successful or not.
|
|
||||||
//
|
|
||||||
// If Results is specified in the Options:
|
|
||||||
// - JsonResult will contain the raw return from the request call
|
|
||||||
// This is most useful for diagnostics.
|
|
||||||
// - Result will contain the unmarshalled json either in the Result passed in
|
|
||||||
// or the unmarshaller will allocate the container type for you.
|
|
||||||
|
|
||||||
type Response struct {
|
|
||||||
HttpResponse http.Response
|
|
||||||
JsonResult []byte
|
|
||||||
Results interface{}
|
|
||||||
StatusCode int
|
|
||||||
}
|
|
|
@ -1,226 +0,0 @@
|
||||||
package perigee
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestNormal(t *testing.T) {
|
|
||||||
handler := http.HandlerFunc(
|
|
||||||
func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.Write([]byte("testing"))
|
|
||||||
})
|
|
||||||
ts := httptest.NewServer(handler)
|
|
||||||
defer ts.Close()
|
|
||||||
|
|
||||||
response, err := Request("GET", ts.URL, Options{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("should not have error: %s", err)
|
|
||||||
}
|
|
||||||
if response.StatusCode != 200 {
|
|
||||||
t.Fatalf("response code %d is not 200", response.StatusCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOKCodes(t *testing.T) {
|
|
||||||
expectCode := 201
|
|
||||||
handler := http.HandlerFunc(
|
|
||||||
func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.WriteHeader(expectCode)
|
|
||||||
w.Write([]byte("testing"))
|
|
||||||
})
|
|
||||||
ts := httptest.NewServer(handler)
|
|
||||||
defer ts.Close()
|
|
||||||
|
|
||||||
options := Options{
|
|
||||||
OkCodes: []int{expectCode},
|
|
||||||
}
|
|
||||||
results, err := Request("GET", ts.URL, options)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("should not have error: %s", err)
|
|
||||||
}
|
|
||||||
if results.StatusCode != expectCode {
|
|
||||||
t.Fatalf("response code %d is not %d", results.StatusCode, expectCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLocation(t *testing.T) {
|
|
||||||
newLocation := "http://www.example.com"
|
|
||||||
handler := http.HandlerFunc(
|
|
||||||
func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.Header().Set("Location", newLocation)
|
|
||||||
w.Write([]byte("testing"))
|
|
||||||
})
|
|
||||||
ts := httptest.NewServer(handler)
|
|
||||||
defer ts.Close()
|
|
||||||
|
|
||||||
response, err := Request("GET", ts.URL, Options{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("should not have error: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
location, err := response.HttpResponse.Location()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("should not have error: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if location.String() != newLocation {
|
|
||||||
t.Fatalf("location returned \"%s\" is not \"%s\"", location.String(), newLocation)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHeaders(t *testing.T) {
|
|
||||||
newLocation := "http://www.example.com"
|
|
||||||
handler := http.HandlerFunc(
|
|
||||||
func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.Header().Set("Location", newLocation)
|
|
||||||
w.Write([]byte("testing"))
|
|
||||||
})
|
|
||||||
ts := httptest.NewServer(handler)
|
|
||||||
defer ts.Close()
|
|
||||||
|
|
||||||
response, err := Request("GET", ts.URL, Options{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("should not have error: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
location := response.HttpResponse.Header.Get("Location")
|
|
||||||
if location == "" {
|
|
||||||
t.Fatalf("Location should not empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
if location != newLocation {
|
|
||||||
t.Fatalf("location returned \"%s\" is not \"%s\"", location, newLocation)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCustomHeaders(t *testing.T) {
|
|
||||||
var contentType, accept, contentLength string
|
|
||||||
|
|
||||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
m := map[string][]string(r.Header)
|
|
||||||
contentType = m["Content-Type"][0]
|
|
||||||
accept = m["Accept"][0]
|
|
||||||
contentLength = m["Content-Length"][0]
|
|
||||||
})
|
|
||||||
ts := httptest.NewServer(handler)
|
|
||||||
defer ts.Close()
|
|
||||||
|
|
||||||
_, err := Request("GET", ts.URL, Options{
|
|
||||||
ContentLength: 5,
|
|
||||||
ContentType: "x-application/vb",
|
|
||||||
Accept: "x-application/c",
|
|
||||||
ReqBody: strings.NewReader("Hello"),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
if contentType != "x-application/vb" {
|
|
||||||
t.Fatalf("I expected x-application/vb; got ", contentType)
|
|
||||||
}
|
|
||||||
|
|
||||||
if contentLength != "5" {
|
|
||||||
t.Fatalf("I expected 5 byte content length; got ", contentLength)
|
|
||||||
}
|
|
||||||
|
|
||||||
if accept != "x-application/c" {
|
|
||||||
t.Fatalf("I expected x-application/c; got ", accept)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestJson(t *testing.T) {
|
|
||||||
newLocation := "http://www.example.com"
|
|
||||||
jsonBytes := []byte(`{"foo": {"bar": "baz"}}`)
|
|
||||||
handler := http.HandlerFunc(
|
|
||||||
func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.Header().Set("Location", newLocation)
|
|
||||||
w.Write(jsonBytes)
|
|
||||||
})
|
|
||||||
ts := httptest.NewServer(handler)
|
|
||||||
defer ts.Close()
|
|
||||||
|
|
||||||
type Data struct {
|
|
||||||
Foo struct {
|
|
||||||
Bar string `json:"bar"`
|
|
||||||
} `json:"foo"`
|
|
||||||
}
|
|
||||||
var data Data
|
|
||||||
|
|
||||||
response, err := Request("GET", ts.URL, Options{Results: &data})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("should not have error: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if bytes.Compare(jsonBytes, response.JsonResult) != 0 {
|
|
||||||
t.Fatalf("json returned \"%s\" is not \"%s\"", response.JsonResult, jsonBytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
if data.Foo.Bar != "baz" {
|
|
||||||
t.Fatalf("Results returned %v", data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSetHeaders(t *testing.T) {
|
|
||||||
var wasCalled bool
|
|
||||||
handler := http.HandlerFunc(
|
|
||||||
func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.Write([]byte("Hi"))
|
|
||||||
})
|
|
||||||
ts := httptest.NewServer(handler)
|
|
||||||
defer ts.Close()
|
|
||||||
|
|
||||||
_, err := Request("GET", ts.URL, Options{
|
|
||||||
SetHeaders: func(r *http.Request) error {
|
|
||||||
wasCalled = true
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !wasCalled {
|
|
||||||
t.Fatal("I expected header setter callback to be called, but it wasn't")
|
|
||||||
}
|
|
||||||
|
|
||||||
myError := fmt.Errorf("boo")
|
|
||||||
|
|
||||||
_, err = Request("GET", ts.URL, Options{
|
|
||||||
SetHeaders: func(r *http.Request) error {
|
|
||||||
return myError
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != myError {
|
|
||||||
t.Fatal("I expected errors to propegate back to the caller.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBodilessMethodsAreSentWithoutContentHeaders(t *testing.T) {
|
|
||||||
var h map[string][]string
|
|
||||||
|
|
||||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
h = r.Header
|
|
||||||
})
|
|
||||||
ts := httptest.NewServer(handler)
|
|
||||||
defer ts.Close()
|
|
||||||
|
|
||||||
_, err := Request("GET", ts.URL, Options{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(h["Content-Type"]) != 0 {
|
|
||||||
t.Fatalf("I expected nothing for Content-Type but got ", h["Content-Type"])
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(h["Content-Length"]) != 0 {
|
|
||||||
t.Fatalf("I expected nothing for Content-Length but got ", h["Content-Length"])
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,6 +4,8 @@ install:
|
||||||
go:
|
go:
|
||||||
- 1.1
|
- 1.1
|
||||||
- 1.2
|
- 1.2
|
||||||
|
- 1.3
|
||||||
|
- 1.4
|
||||||
- tip
|
- tip
|
||||||
script: script/cibuild
|
script: script/cibuild
|
||||||
after_success:
|
after_success:
|
||||||
|
@ -12,3 +14,4 @@ after_success:
|
||||||
- go get github.com/mattn/goveralls
|
- go get github.com/mattn/goveralls
|
||||||
- export PATH=$PATH:$HOME/gopath/bin/
|
- export PATH=$PATH:$HOME/gopath/bin/
|
||||||
- goveralls 2k7PTU3xa474Hymwgdj6XjqenNfGTNkO8
|
- goveralls 2k7PTU3xa474Hymwgdj6XjqenNfGTNkO8
|
||||||
|
sudo: false
|
||||||
|
|
|
@ -10,3 +10,4 @@ Contributors
|
||||||
| Ash Wilson | <ash.wilson@rackspace.com>
|
| Ash Wilson | <ash.wilson@rackspace.com>
|
||||||
| Jamie Hannaford | <jamie.hannaford@rackspace.com>
|
| Jamie Hannaford | <jamie.hannaford@rackspace.com>
|
||||||
| Don Schenck | don.schenck@rackspace.com>
|
| Don Schenck | don.schenck@rackspace.com>
|
||||||
|
| Joe Topjian | <joe@topjian.net>
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
"ImportPath": "github.com/rackspace/gophercloud",
|
|
||||||
"GoVersion": "go1.3.3",
|
|
||||||
"Deps": []
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
This directory tree is generated automatically by godep.
|
|
||||||
|
|
||||||
Please do not edit.
|
|
||||||
|
|
||||||
See https://github.com/tools/godep for more information.
|
|
107
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/floatingip_test.go
generated
vendored
Normal file
107
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/floatingip_test.go
generated
vendored
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
// +build acceptance compute servers
|
||||||
|
|
||||||
|
package v2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
"github.com/rackspace/gophercloud/acceptance/tools"
|
||||||
|
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip"
|
||||||
|
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func createFIPServer(t *testing.T, client *gophercloud.ServiceClient, choices *ComputeChoices) (*servers.Server, error) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("Skipping test that requires server creation in short mode.")
|
||||||
|
}
|
||||||
|
|
||||||
|
name := tools.RandomString("ACPTTEST", 16)
|
||||||
|
t.Logf("Attempting to create server: %s\n", name)
|
||||||
|
|
||||||
|
pwd := tools.MakeNewPassword("")
|
||||||
|
|
||||||
|
server, err := servers.Create(client, servers.CreateOpts{
|
||||||
|
Name: name,
|
||||||
|
FlavorRef: choices.FlavorID,
|
||||||
|
ImageRef: choices.ImageID,
|
||||||
|
AdminPass: pwd,
|
||||||
|
}).Extract()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unable to create server: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
th.AssertEquals(t, pwd, server.AdminPass)
|
||||||
|
|
||||||
|
return server, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func createFloatingIP(t *testing.T, client *gophercloud.ServiceClient) (*floatingip.FloatingIP, error) {
|
||||||
|
pool := os.Getenv("OS_POOL_NAME")
|
||||||
|
fip, err := floatingip.Create(client, &floatingip.CreateOpts{
|
||||||
|
Pool: pool,
|
||||||
|
}).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Obtained Floating IP: %v", fip.IP)
|
||||||
|
|
||||||
|
return fip, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func associateFloatingIP(t *testing.T, client *gophercloud.ServiceClient, serverId string, fip *floatingip.FloatingIP) {
|
||||||
|
err := floatingip.Associate(client, serverId, fip.IP).ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Associated floating IP %v from instance %v", fip.IP, serverId)
|
||||||
|
defer func() {
|
||||||
|
err = floatingip.Disassociate(client, serverId, fip.IP).ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Disassociated floating IP %v from instance %v", fip.IP, serverId)
|
||||||
|
}()
|
||||||
|
floatingIp, err := floatingip.Get(client, fip.ID).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Floating IP %v is associated with Fixed IP %v", fip.IP, floatingIp.FixedIP)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFloatingIP(t *testing.T) {
|
||||||
|
pool := os.Getenv("OS_POOL_NAME")
|
||||||
|
if pool == "" {
|
||||||
|
t.Fatalf("OS_POOL_NAME must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
choices, err := ComputeChoicesFromEnv()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := newClient()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unable to create a compute client: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
server, err := createFIPServer(t, client, choices)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unable to create server: %v", err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
servers.Delete(client, server.ID)
|
||||||
|
t.Logf("Server deleted.")
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err = waitForStatus(client, server, "ACTIVE"); err != nil {
|
||||||
|
t.Fatalf("Unable to wait for server: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fip, err := createFloatingIP(t, client)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unable to create floating IP: %v", err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
err = floatingip.Delete(client, fip.ID).ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Floating IP deleted.")
|
||||||
|
}()
|
||||||
|
|
||||||
|
associateFloatingIP(t, client, server.ID, fip)
|
||||||
|
|
||||||
|
}
|
125
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/volumeattach_test.go
generated
vendored
Normal file
125
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/volumeattach_test.go
generated
vendored
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
// +build acceptance compute servers
|
||||||
|
|
||||||
|
package v2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
"github.com/rackspace/gophercloud/acceptance/tools"
|
||||||
|
"github.com/rackspace/gophercloud/openstack"
|
||||||
|
"github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes"
|
||||||
|
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach"
|
||||||
|
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newBlockClient(t *testing.T) (*gophercloud.ServiceClient, error) {
|
||||||
|
ao, err := openstack.AuthOptionsFromEnv()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
|
||||||
|
client, err := openstack.AuthenticatedClient(ao)
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
|
||||||
|
return openstack.NewBlockStorageV1(client, gophercloud.EndpointOpts{
|
||||||
|
Region: os.Getenv("OS_REGION_NAME"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func createVAServer(t *testing.T, computeClient *gophercloud.ServiceClient, choices *ComputeChoices) (*servers.Server, error) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("Skipping test that requires server creation in short mode.")
|
||||||
|
}
|
||||||
|
|
||||||
|
name := tools.RandomString("ACPTTEST", 16)
|
||||||
|
t.Logf("Attempting to create server: %s\n", name)
|
||||||
|
|
||||||
|
pwd := tools.MakeNewPassword("")
|
||||||
|
|
||||||
|
server, err := servers.Create(computeClient, servers.CreateOpts{
|
||||||
|
Name: name,
|
||||||
|
FlavorRef: choices.FlavorID,
|
||||||
|
ImageRef: choices.ImageID,
|
||||||
|
AdminPass: pwd,
|
||||||
|
}).Extract()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unable to create server: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
th.AssertEquals(t, pwd, server.AdminPass)
|
||||||
|
|
||||||
|
return server, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func createVAVolume(t *testing.T, blockClient *gophercloud.ServiceClient) (*volumes.Volume, error) {
|
||||||
|
volume, err := volumes.Create(blockClient, &volumes.CreateOpts{
|
||||||
|
Size: 1,
|
||||||
|
Name: "gophercloud-test-volume",
|
||||||
|
}).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
defer func() {
|
||||||
|
err = volumes.WaitForStatus(blockClient, volume.ID, "available", 60)
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return volume, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func createVolumeAttachment(t *testing.T, computeClient *gophercloud.ServiceClient, blockClient *gophercloud.ServiceClient, serverId string, volumeId string) {
|
||||||
|
va, err := volumeattach.Create(computeClient, serverId, &volumeattach.CreateOpts{
|
||||||
|
VolumeID: volumeId,
|
||||||
|
}).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
defer func() {
|
||||||
|
err = volumes.WaitForStatus(blockClient, volumeId, "in-use", 60)
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
err = volumeattach.Delete(computeClient, serverId, va.ID).ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
err = volumes.WaitForStatus(blockClient, volumeId, "available", 60)
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAttachVolume(t *testing.T) {
|
||||||
|
choices, err := ComputeChoicesFromEnv()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
computeClient, err := newClient()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unable to create a compute client: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
blockClient, err := newBlockClient(t)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unable to create a blockstorage client: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
server, err := createVAServer(t, computeClient, choices)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unable to create server: %v", err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
servers.Delete(computeClient, server.ID)
|
||||||
|
t.Logf("Server deleted.")
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err = waitForStatus(computeClient, server, "ACTIVE"); err != nil {
|
||||||
|
t.Fatalf("Unable to wait for server: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
volume, err := createVAVolume(t, blockClient)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unable to create volume: %v", err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
err = volumes.Delete(blockClient, volume.ID).ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Volume deleted.")
|
||||||
|
}()
|
||||||
|
|
||||||
|
createVolumeAttachment(t, computeClient, blockClient, server.ID, volume.ID)
|
||||||
|
|
||||||
|
}
|
116
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/fwaas/firewall_test.go
generated
vendored
Normal file
116
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/fwaas/firewall_test.go
generated
vendored
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
// +build acceptance networking fwaas
|
||||||
|
|
||||||
|
package fwaas
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
|
||||||
|
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls"
|
||||||
|
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/policies"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func firewallSetup(t *testing.T) string {
|
||||||
|
base.Setup(t)
|
||||||
|
return createPolicy(t, &policies.CreateOpts{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func firewallTeardown(t *testing.T, policyID string) {
|
||||||
|
defer base.Teardown()
|
||||||
|
deletePolicy(t, policyID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFirewall(t *testing.T) {
|
||||||
|
policyID := firewallSetup(t)
|
||||||
|
defer firewallTeardown(t, policyID)
|
||||||
|
|
||||||
|
firewallID := createFirewall(t, &firewalls.CreateOpts{
|
||||||
|
Name: "gophercloud test",
|
||||||
|
Description: "acceptance test",
|
||||||
|
PolicyID: policyID,
|
||||||
|
})
|
||||||
|
|
||||||
|
waitForFirewallToBeActive(t, firewallID)
|
||||||
|
|
||||||
|
listFirewalls(t)
|
||||||
|
|
||||||
|
updateFirewall(t, firewallID, &firewalls.UpdateOpts{
|
||||||
|
Description: "acceptance test updated",
|
||||||
|
})
|
||||||
|
|
||||||
|
waitForFirewallToBeActive(t, firewallID)
|
||||||
|
|
||||||
|
deleteFirewall(t, firewallID)
|
||||||
|
|
||||||
|
waitForFirewallToBeDeleted(t, firewallID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createFirewall(t *testing.T, opts *firewalls.CreateOpts) string {
|
||||||
|
f, err := firewalls.Create(base.Client, *opts).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Created firewall: %#v", opts)
|
||||||
|
return f.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
func listFirewalls(t *testing.T) {
|
||||||
|
err := firewalls.List(base.Client, firewalls.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
|
||||||
|
firewallList, err := firewalls.ExtractFirewalls(page)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to extract firewalls: %v", err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, r := range firewallList {
|
||||||
|
t.Logf("Listing firewalls: ID [%s]", r.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
})
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateFirewall(t *testing.T, firewallID string, opts *firewalls.UpdateOpts) {
|
||||||
|
f, err := firewalls.Update(base.Client, firewallID, *opts).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Updated firewall ID [%s]", f.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFirewall(t *testing.T, firewallID string) *firewalls.Firewall {
|
||||||
|
f, err := firewalls.Get(base.Client, firewallID).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Getting firewall ID [%s]", f.ID)
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteFirewall(t *testing.T, firewallID string) {
|
||||||
|
res := firewalls.Delete(base.Client, firewallID)
|
||||||
|
th.AssertNoErr(t, res.Err)
|
||||||
|
t.Logf("Deleted firewall %s", firewallID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func waitForFirewallToBeActive(t *testing.T, firewallID string) {
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
fw := getFirewall(t, firewallID)
|
||||||
|
if fw.Status == "ACTIVE" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func waitForFirewallToBeDeleted(t *testing.T, firewallID string) {
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
err := firewalls.Get(base.Client, firewallID).Err
|
||||||
|
if err != nil {
|
||||||
|
httpStatus := err.(*gophercloud.UnexpectedResponseCodeError)
|
||||||
|
if httpStatus.Actual == 404 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
}
|
1
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/fwaas/pkg.go
generated
vendored
Normal file
1
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/fwaas/pkg.go
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
package fwaas
|
107
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/fwaas/policy_test.go
generated
vendored
Normal file
107
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/fwaas/policy_test.go
generated
vendored
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
// +build acceptance networking fwaas
|
||||||
|
|
||||||
|
package fwaas
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
|
||||||
|
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/policies"
|
||||||
|
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/rules"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func firewallPolicySetup(t *testing.T) string {
|
||||||
|
base.Setup(t)
|
||||||
|
return createRule(t, &rules.CreateOpts{
|
||||||
|
Protocol: "tcp",
|
||||||
|
Action: "allow",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func firewallPolicyTeardown(t *testing.T, ruleID string) {
|
||||||
|
defer base.Teardown()
|
||||||
|
deleteRule(t, ruleID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFirewallPolicy(t *testing.T) {
|
||||||
|
ruleID := firewallPolicySetup(t)
|
||||||
|
defer firewallPolicyTeardown(t, ruleID)
|
||||||
|
|
||||||
|
policyID := createPolicy(t, &policies.CreateOpts{
|
||||||
|
Name: "gophercloud test",
|
||||||
|
Description: "acceptance test",
|
||||||
|
Rules: []string{
|
||||||
|
ruleID,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
listPolicies(t)
|
||||||
|
|
||||||
|
updatePolicy(t, policyID, &policies.UpdateOpts{
|
||||||
|
Description: "acceptance test updated",
|
||||||
|
})
|
||||||
|
|
||||||
|
getPolicy(t, policyID)
|
||||||
|
|
||||||
|
removeRuleFromPolicy(t, policyID, ruleID)
|
||||||
|
|
||||||
|
addRuleToPolicy(t, policyID, ruleID)
|
||||||
|
|
||||||
|
deletePolicy(t, policyID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createPolicy(t *testing.T, opts *policies.CreateOpts) string {
|
||||||
|
p, err := policies.Create(base.Client, *opts).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Created policy: %#v", opts)
|
||||||
|
return p.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
func listPolicies(t *testing.T) {
|
||||||
|
err := policies.List(base.Client, policies.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
|
||||||
|
policyList, err := policies.ExtractPolicies(page)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to extract policies: %v", err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range policyList {
|
||||||
|
t.Logf("Listing policies: ID [%s]", p.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
})
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func updatePolicy(t *testing.T, policyID string, opts *policies.UpdateOpts) {
|
||||||
|
p, err := policies.Update(base.Client, policyID, *opts).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Updated policy ID [%s]", p.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeRuleFromPolicy(t *testing.T, policyID string, ruleID string) {
|
||||||
|
err := policies.RemoveRule(base.Client, policyID, ruleID)
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Removed rule [%s] from policy ID [%s]", ruleID, policyID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func addRuleToPolicy(t *testing.T, policyID string, ruleID string) {
|
||||||
|
err := policies.InsertRule(base.Client, policyID, ruleID, "", "")
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Inserted rule [%s] into policy ID [%s]", ruleID, policyID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPolicy(t *testing.T, policyID string) {
|
||||||
|
p, err := policies.Get(base.Client, policyID).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Getting policy ID [%s]", p.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func deletePolicy(t *testing.T, policyID string) {
|
||||||
|
res := policies.Delete(base.Client, policyID)
|
||||||
|
th.AssertNoErr(t, res.Err)
|
||||||
|
t.Logf("Deleted policy %s", policyID)
|
||||||
|
}
|
84
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/fwaas/rule_test.go
generated
vendored
Normal file
84
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/extensions/fwaas/rule_test.go
generated
vendored
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
// +build acceptance networking fwaas
|
||||||
|
|
||||||
|
package fwaas
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
|
||||||
|
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/rules"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFirewallRules(t *testing.T) {
|
||||||
|
base.Setup(t)
|
||||||
|
defer base.Teardown()
|
||||||
|
|
||||||
|
ruleID := createRule(t, &rules.CreateOpts{
|
||||||
|
Name: "gophercloud_test",
|
||||||
|
Description: "acceptance test",
|
||||||
|
Protocol: "tcp",
|
||||||
|
Action: "allow",
|
||||||
|
DestinationIPAddress: "192.168.0.0/24",
|
||||||
|
DestinationPort: "22",
|
||||||
|
})
|
||||||
|
|
||||||
|
listRules(t)
|
||||||
|
|
||||||
|
destinationIPAddress := "192.168.1.0/24"
|
||||||
|
destinationPort := ""
|
||||||
|
sourcePort := "1234"
|
||||||
|
|
||||||
|
updateRule(t, ruleID, &rules.UpdateOpts{
|
||||||
|
DestinationIPAddress: &destinationIPAddress,
|
||||||
|
DestinationPort: &destinationPort,
|
||||||
|
SourcePort: &sourcePort,
|
||||||
|
})
|
||||||
|
|
||||||
|
getRule(t, ruleID)
|
||||||
|
|
||||||
|
deleteRule(t, ruleID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createRule(t *testing.T, opts *rules.CreateOpts) string {
|
||||||
|
r, err := rules.Create(base.Client, *opts).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Created rule: %#v", opts)
|
||||||
|
return r.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
func listRules(t *testing.T) {
|
||||||
|
err := rules.List(base.Client, rules.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
|
||||||
|
ruleList, err := rules.ExtractRules(page)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to extract rules: %v", err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, r := range ruleList {
|
||||||
|
t.Logf("Listing rules: ID [%s]", r.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
})
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateRule(t *testing.T, ruleID string, opts *rules.UpdateOpts) {
|
||||||
|
r, err := rules.Update(base.Client, ruleID, *opts).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Updated rule ID [%s]", r.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getRule(t *testing.T, ruleID string) {
|
||||||
|
r, err := rules.Get(base.Client, ruleID).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Getting rule ID [%s]", r.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteRule(t *testing.T, ruleID string) {
|
||||||
|
res := rules.Delete(base.Client, ruleID)
|
||||||
|
th.AssertNoErr(t, res.Err)
|
||||||
|
t.Logf("Deleted rule %s", ruleID)
|
||||||
|
}
|
|
@ -17,7 +17,10 @@ func TestAccounts(t *testing.T) {
|
||||||
|
|
||||||
// Update an account's metadata.
|
// Update an account's metadata.
|
||||||
updateres := accounts.Update(client, accounts.UpdateOpts{Metadata: metadata})
|
updateres := accounts.Update(client, accounts.UpdateOpts{Metadata: metadata})
|
||||||
th.AssertNoErr(t, updateres.Err)
|
t.Logf("Update Account Response: %+v\n", updateres)
|
||||||
|
updateHeaders, err := updateres.Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Update Account Response Headers: %+v\n", updateHeaders)
|
||||||
|
|
||||||
// Defer the deletion of the metadata set above.
|
// Defer the deletion of the metadata set above.
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -29,11 +32,14 @@ func TestAccounts(t *testing.T) {
|
||||||
th.AssertNoErr(t, updateres.Err)
|
th.AssertNoErr(t, updateres.Err)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Retrieve account metadata.
|
|
||||||
getres := accounts.Get(client, nil)
|
|
||||||
th.AssertNoErr(t, getres.Err)
|
|
||||||
// Extract the custom metadata from the 'Get' response.
|
// Extract the custom metadata from the 'Get' response.
|
||||||
am, err := getres.ExtractMetadata()
|
res := accounts.Get(client, nil)
|
||||||
|
|
||||||
|
h, err := res.Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Get Account Response Headers: %+v\n", h)
|
||||||
|
|
||||||
|
am, err := res.ExtractMetadata()
|
||||||
th.AssertNoErr(t, err)
|
th.AssertNoErr(t, err)
|
||||||
for k := range metadata {
|
for k := range metadata {
|
||||||
if am[k] != metadata[strings.Title(k)] {
|
if am[k] != metadata[strings.Title(k)] {
|
||||||
|
|
20
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/buildinfo_test.go
generated
vendored
Normal file
20
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/buildinfo_test.go
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// +build acceptance
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo"
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBuildInfo(t *testing.T) {
|
||||||
|
// Create a provider client for making the HTTP requests.
|
||||||
|
// See common.go in this directory for more information.
|
||||||
|
client := newClient(t)
|
||||||
|
|
||||||
|
bi, err := buildinfo.Get(client).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("retrieved build info: %+v\n", bi)
|
||||||
|
}
|
44
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/common.go
generated
vendored
Normal file
44
Godeps/_workspace/src/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
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/hello-compute.json
generated
vendored
Normal file
13
Godeps/_workspace/src/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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
68
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/stackevents_test.go
generated
vendored
Normal file
68
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/stackevents_test.go
generated
vendored
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
// +build acceptance
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
"github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents"
|
||||||
|
"github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStackEvents(t *testing.T) {
|
||||||
|
// Create a provider client for making the HTTP requests.
|
||||||
|
// See common.go in this directory for more information.
|
||||||
|
client := newClient(t)
|
||||||
|
|
||||||
|
stackName := "postman_stack_2"
|
||||||
|
resourceName := "hello_world"
|
||||||
|
var eventID string
|
||||||
|
|
||||||
|
createOpts := stacks.CreateOpts{
|
||||||
|
Name: stackName,
|
||||||
|
Template: template,
|
||||||
|
Timeout: 5,
|
||||||
|
}
|
||||||
|
stack, err := stacks.Create(client, createOpts).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Created stack: %+v\n", stack)
|
||||||
|
defer func() {
|
||||||
|
err := stacks.Delete(client, stackName, stack.ID).ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Deleted stack (%s)", stackName)
|
||||||
|
}()
|
||||||
|
err = gophercloud.WaitFor(60, func() (bool, error) {
|
||||||
|
getStack, err := stacks.Get(client, stackName, stack.ID).Extract()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if getStack.Status == "CREATE_COMPLETE" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
err = stackevents.List(client, stackName, stack.ID, nil).EachPage(func(page pagination.Page) (bool, error) {
|
||||||
|
events, err := stackevents.ExtractEvents(page)
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("listed events: %+v\n", events)
|
||||||
|
eventID = events[0].ID
|
||||||
|
return false, nil
|
||||||
|
})
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
|
||||||
|
err = stackevents.ListResourceEvents(client, stackName, stack.ID, resourceName, nil).EachPage(func(page pagination.Page) (bool, error) {
|
||||||
|
resourceEvents, err := stackevents.ExtractEvents(page)
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("listed resource events: %+v\n", resourceEvents)
|
||||||
|
return false, nil
|
||||||
|
})
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
|
||||||
|
event, err := stackevents.Get(client, stackName, stack.ID, resourceName, eventID).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("retrieved event: %+v\n", event)
|
||||||
|
}
|
62
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/stackresources_test.go
generated
vendored
Normal file
62
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/stackresources_test.go
generated
vendored
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
// +build acceptance
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
"github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources"
|
||||||
|
"github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStackResources(t *testing.T) {
|
||||||
|
// Create a provider client for making the HTTP requests.
|
||||||
|
// See common.go in this directory for more information.
|
||||||
|
client := newClient(t)
|
||||||
|
|
||||||
|
stackName := "postman_stack_2"
|
||||||
|
|
||||||
|
createOpts := stacks.CreateOpts{
|
||||||
|
Name: stackName,
|
||||||
|
Template: template,
|
||||||
|
Timeout: 5,
|
||||||
|
}
|
||||||
|
stack, err := stacks.Create(client, createOpts).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Created stack: %+v\n", stack)
|
||||||
|
defer func() {
|
||||||
|
err := stacks.Delete(client, stackName, stack.ID).ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Deleted stack (%s)", stackName)
|
||||||
|
}()
|
||||||
|
err = gophercloud.WaitFor(60, func() (bool, error) {
|
||||||
|
getStack, err := stacks.Get(client, stackName, stack.ID).Extract()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if getStack.Status == "CREATE_COMPLETE" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
resourceName := "hello_world"
|
||||||
|
resource, err := stackresources.Get(client, stackName, stack.ID, resourceName).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Got stack resource: %+v\n", resource)
|
||||||
|
|
||||||
|
metadata, err := stackresources.Metadata(client, stackName, stack.ID, resourceName).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Got stack resource metadata: %+v\n", metadata)
|
||||||
|
|
||||||
|
err = stackresources.List(client, stackName, stack.ID, stackresources.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
|
||||||
|
resources, err := stackresources.ExtractResources(page)
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("resources: %+v\n", resources)
|
||||||
|
return false, nil
|
||||||
|
})
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
}
|
81
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/stacks_test.go
generated
vendored
Normal file
81
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/stacks_test.go
generated
vendored
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
// +build acceptance
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
"github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStacks(t *testing.T) {
|
||||||
|
// Create a provider client for making the HTTP requests.
|
||||||
|
// See common.go in this directory for more information.
|
||||||
|
client := newClient(t)
|
||||||
|
|
||||||
|
stackName1 := "gophercloud-test-stack-2"
|
||||||
|
createOpts := stacks.CreateOpts{
|
||||||
|
Name: stackName1,
|
||||||
|
Template: template,
|
||||||
|
Timeout: 5,
|
||||||
|
}
|
||||||
|
stack, err := stacks.Create(client, createOpts).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Created stack: %+v\n", stack)
|
||||||
|
defer func() {
|
||||||
|
err := stacks.Delete(client, stackName1, stack.ID).ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Deleted stack (%s)", stackName1)
|
||||||
|
}()
|
||||||
|
err = gophercloud.WaitFor(60, func() (bool, error) {
|
||||||
|
getStack, err := stacks.Get(client, stackName1, stack.ID).Extract()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if getStack.Status == "CREATE_COMPLETE" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
updateOpts := stacks.UpdateOpts{
|
||||||
|
Template: template,
|
||||||
|
Timeout: 20,
|
||||||
|
}
|
||||||
|
err = stacks.Update(client, stackName1, stack.ID, updateOpts).ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
err = gophercloud.WaitFor(60, func() (bool, error) {
|
||||||
|
getStack, err := stacks.Get(client, stackName1, stack.ID).Extract()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if getStack.Status == "UPDATE_COMPLETE" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Logf("Updated stack")
|
||||||
|
|
||||||
|
err = stacks.List(client, nil).EachPage(func(page pagination.Page) (bool, error) {
|
||||||
|
stackList, err := stacks.ExtractStacks(page)
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
|
||||||
|
t.Logf("Got stack list: %+v\n", stackList)
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
})
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
|
||||||
|
getStack, err := stacks.Get(client, stackName1, stack.ID).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Got stack: %+v\n", getStack)
|
||||||
|
|
||||||
|
abandonedStack, err := stacks.Abandon(client, stackName1, stack.ID).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Abandonded stack %+v\n", abandonedStack)
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
}
|
77
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/stacktemplates_test.go
generated
vendored
Normal file
77
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/openstack/orchestration/v1/stacktemplates_test.go
generated
vendored
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
// +build acceptance
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
"github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks"
|
||||||
|
"github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates"
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStackTemplates(t *testing.T) {
|
||||||
|
// Create a provider client for making the HTTP requests.
|
||||||
|
// See common.go in this directory for more information.
|
||||||
|
client := newClient(t)
|
||||||
|
|
||||||
|
stackName := "postman_stack_2"
|
||||||
|
|
||||||
|
createOpts := stacks.CreateOpts{
|
||||||
|
Name: stackName,
|
||||||
|
Template: template,
|
||||||
|
Timeout: 5,
|
||||||
|
}
|
||||||
|
stack, err := stacks.Create(client, createOpts).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Created stack: %+v\n", stack)
|
||||||
|
defer func() {
|
||||||
|
err := stacks.Delete(client, stackName, stack.ID).ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Deleted stack (%s)", stackName)
|
||||||
|
}()
|
||||||
|
err = gophercloud.WaitFor(60, func() (bool, error) {
|
||||||
|
getStack, err := stacks.Get(client, stackName, stack.ID).Extract()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if getStack.Status == "CREATE_COMPLETE" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
tmpl, err := stacktemplates.Get(client, stackName, stack.ID).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("retrieved template: %+v\n", tmpl)
|
||||||
|
|
||||||
|
validateOpts := stacktemplates.ValidateOpts{
|
||||||
|
Template: map[string]interface{}{
|
||||||
|
"heat_template_version": "2013-05-23",
|
||||||
|
"description": "Simple template to test heat commands",
|
||||||
|
"parameters": map[string]interface{}{
|
||||||
|
"flavor": map[string]interface{}{
|
||||||
|
"default": "m1.tiny",
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"resources": map[string]interface{}{
|
||||||
|
"hello_world": map[string]interface{}{
|
||||||
|
"type": "OS::Nova::Server",
|
||||||
|
"properties": map[string]interface{}{
|
||||||
|
"key_name": "heat_key",
|
||||||
|
"flavor": map[string]interface{}{
|
||||||
|
"get_param": "flavor",
|
||||||
|
},
|
||||||
|
"image": "ad091b52-742f-469e-8f3c-fd81cadf0743",
|
||||||
|
"user_data": "#!/bin/bash -xv\necho \"hello world\" > /root/hello-world.txt\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
validatedTemplate, err := stacktemplates.Validate(client, validateOpts).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("validated template: %+v\n", validatedTemplate)
|
||||||
|
}
|
32
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/rackspace/cdn/v1/base_test.go
generated
vendored
Normal file
32
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/rackspace/cdn/v1/base_test.go
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
// +build acceptance
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
"github.com/rackspace/gophercloud/rackspace/cdn/v1/base"
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBaseOps(t *testing.T) {
|
||||||
|
client := newClient(t)
|
||||||
|
t.Log("Retrieving Home Document")
|
||||||
|
testHomeDocumentGet(t, client)
|
||||||
|
|
||||||
|
t.Log("Pinging root URL")
|
||||||
|
testPing(t, client)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testHomeDocumentGet(t *testing.T, client *gophercloud.ServiceClient) {
|
||||||
|
hd, err := base.Get(client).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Retrieved home document: %+v", *hd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPing(t *testing.T, client *gophercloud.ServiceClient) {
|
||||||
|
err := base.Ping(client).ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Successfully pinged root URL")
|
||||||
|
}
|
23
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/rackspace/cdn/v1/common.go
generated
vendored
Normal file
23
Godeps/_workspace/src/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
|
||||||
|
}
|
47
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/rackspace/cdn/v1/flavor_test.go
generated
vendored
Normal file
47
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/rackspace/cdn/v1/flavor_test.go
generated
vendored
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
// +build acceptance
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
os "github.com/rackspace/gophercloud/openstack/cdn/v1/flavors"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
"github.com/rackspace/gophercloud/rackspace/cdn/v1/flavors"
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFlavor(t *testing.T) {
|
||||||
|
client := newClient(t)
|
||||||
|
|
||||||
|
t.Log("Listing Flavors")
|
||||||
|
id := testFlavorsList(t, client)
|
||||||
|
|
||||||
|
t.Log("Retrieving Flavor")
|
||||||
|
testFlavorGet(t, client, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFlavorsList(t *testing.T, client *gophercloud.ServiceClient) string {
|
||||||
|
var id string
|
||||||
|
err := flavors.List(client).EachPage(func(page pagination.Page) (bool, error) {
|
||||||
|
flavorList, err := os.ExtractFlavors(page)
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
|
||||||
|
for _, flavor := range flavorList {
|
||||||
|
t.Logf("Listing flavor: ID [%s] Providers [%+v]", flavor.ID, flavor.Providers)
|
||||||
|
id = flavor.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFlavorGet(t *testing.T, client *gophercloud.ServiceClient, id string) {
|
||||||
|
flavor, err := flavors.Get(client, id).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Retrieved Flavor: %+v", *flavor)
|
||||||
|
}
|
93
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/rackspace/cdn/v1/service_test.go
generated
vendored
Normal file
93
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/rackspace/cdn/v1/service_test.go
generated
vendored
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
// +build acceptance
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
os "github.com/rackspace/gophercloud/openstack/cdn/v1/services"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
"github.com/rackspace/gophercloud/rackspace/cdn/v1/services"
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestService(t *testing.T) {
|
||||||
|
client := newClient(t)
|
||||||
|
|
||||||
|
t.Log("Creating Service")
|
||||||
|
loc := testServiceCreate(t, client, "test-site-1")
|
||||||
|
t.Logf("Created service at location: %s", loc)
|
||||||
|
|
||||||
|
defer testServiceDelete(t, client, loc)
|
||||||
|
|
||||||
|
t.Log("Updating Service")
|
||||||
|
testServiceUpdate(t, client, loc)
|
||||||
|
|
||||||
|
t.Log("Retrieving Service")
|
||||||
|
testServiceGet(t, client, loc)
|
||||||
|
|
||||||
|
t.Log("Listing Services")
|
||||||
|
testServiceList(t, client)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testServiceCreate(t *testing.T, client *gophercloud.ServiceClient, name string) string {
|
||||||
|
createOpts := os.CreateOpts{
|
||||||
|
Name: name,
|
||||||
|
Domains: []os.Domain{
|
||||||
|
os.Domain{
|
||||||
|
Domain: "www." + name + ".com",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Origins: []os.Origin{
|
||||||
|
os.Origin{
|
||||||
|
Origin: name + ".com",
|
||||||
|
Port: 80,
|
||||||
|
SSL: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
FlavorID: "cdn",
|
||||||
|
}
|
||||||
|
l, err := services.Create(client, createOpts).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func testServiceGet(t *testing.T, client *gophercloud.ServiceClient, id string) {
|
||||||
|
s, err := services.Get(client, id).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Retrieved service: %+v", *s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testServiceUpdate(t *testing.T, client *gophercloud.ServiceClient, id string) {
|
||||||
|
opts := os.UpdateOpts{
|
||||||
|
os.Append{
|
||||||
|
Value: os.Domain{Domain: "newDomain.com", Protocol: "http"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
loc, err := services.Update(client, id, opts).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Successfully updated service at location: %s", loc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testServiceList(t *testing.T, client *gophercloud.ServiceClient) {
|
||||||
|
err := services.List(client, nil).EachPage(func(page pagination.Page) (bool, error) {
|
||||||
|
serviceList, err := os.ExtractServices(page)
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
|
||||||
|
for _, service := range serviceList {
|
||||||
|
t.Logf("Listing service: %+v", service)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testServiceDelete(t *testing.T, client *gophercloud.ServiceClient, id string) {
|
||||||
|
err := services.Delete(client, id).ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Successfully deleted service (%s)", id)
|
||||||
|
}
|
32
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/rackspace/cdn/v1/serviceasset_test.go
generated
vendored
Normal file
32
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/rackspace/cdn/v1/serviceasset_test.go
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
// +build acceptance
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
osServiceAssets "github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets"
|
||||||
|
"github.com/rackspace/gophercloud/rackspace/cdn/v1/serviceassets"
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestServiceAsset(t *testing.T) {
|
||||||
|
client := newClient(t)
|
||||||
|
|
||||||
|
t.Log("Creating Service")
|
||||||
|
loc := testServiceCreate(t, client, "test-site-2")
|
||||||
|
t.Logf("Created service at location: %s", loc)
|
||||||
|
|
||||||
|
t.Log("Deleting Service Assets")
|
||||||
|
testServiceAssetDelete(t, client, loc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testServiceAssetDelete(t *testing.T, client *gophercloud.ServiceClient, url string) {
|
||||||
|
deleteOpts := osServiceAssets.DeleteOpts{
|
||||||
|
All: true,
|
||||||
|
}
|
||||||
|
err := serviceassets.Delete(client, url, deleteOpts).ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Log("Successfully deleted all Service Assets")
|
||||||
|
}
|
|
@ -41,6 +41,9 @@ func TestBootFromVolume(t *testing.T) {
|
||||||
}).Extract()
|
}).Extract()
|
||||||
th.AssertNoErr(t, err)
|
th.AssertNoErr(t, err)
|
||||||
t.Logf("Created server: %+v\n", server)
|
t.Logf("Created server: %+v\n", server)
|
||||||
//defer deleteServer(t, client, server)
|
defer deleteServer(t, client, server)
|
||||||
t.Logf("Deleting server [%s]...", name)
|
|
||||||
|
getServer(t, client, server)
|
||||||
|
|
||||||
|
listServers(t, client)
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,18 @@ func getServer(t *testing.T, client *gophercloud.ServiceClient, server *os.Serve
|
||||||
logServer(t, details, -1)
|
logServer(t, details, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateServer(t *testing.T, client *gophercloud.ServiceClient, server *os.Server) {
|
||||||
|
t.Logf("> servers.Get")
|
||||||
|
|
||||||
|
opts := os.UpdateOpts{
|
||||||
|
Name: "updated-server",
|
||||||
|
}
|
||||||
|
updatedServer, err := servers.Update(client, server.ID, opts).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
th.AssertEquals(t, "updated-server", updatedServer.Name)
|
||||||
|
logServer(t, updatedServer, -1)
|
||||||
|
}
|
||||||
|
|
||||||
func listServers(t *testing.T, client *gophercloud.ServiceClient) {
|
func listServers(t *testing.T, client *gophercloud.ServiceClient) {
|
||||||
t.Logf("> servers.List")
|
t.Logf("> servers.List")
|
||||||
|
|
||||||
|
@ -197,6 +209,7 @@ func TestServerOperations(t *testing.T) {
|
||||||
defer deleteServer(t, client, server)
|
defer deleteServer(t, client, server)
|
||||||
|
|
||||||
getServer(t, client, server)
|
getServer(t, client, server)
|
||||||
|
updateServer(t, client, server)
|
||||||
listServers(t, client)
|
listServers(t, client)
|
||||||
changeAdminPassword(t, client, server)
|
changeAdminPassword(t, client, server)
|
||||||
rebootServer(t, client, server)
|
rebootServer(t, client, server)
|
||||||
|
|
|
@ -13,11 +13,11 @@ func TestAccounts(t *testing.T) {
|
||||||
c, err := createClient(t, false)
|
c, err := createClient(t, false)
|
||||||
th.AssertNoErr(t, err)
|
th.AssertNoErr(t, err)
|
||||||
|
|
||||||
updateres := raxAccounts.Update(c, raxAccounts.UpdateOpts{Metadata: map[string]string{"white": "mountains"}})
|
updateHeaders, err := raxAccounts.Update(c, raxAccounts.UpdateOpts{Metadata: map[string]string{"white": "mountains"}}).Extract()
|
||||||
th.AssertNoErr(t, updateres.Err)
|
th.AssertNoErr(t, err)
|
||||||
t.Logf("Headers from Update Account request: %+v\n", updateres.Header)
|
t.Logf("Update Account Response Headers: %+v\n", updateHeaders)
|
||||||
defer func() {
|
defer func() {
|
||||||
updateres = raxAccounts.Update(c, raxAccounts.UpdateOpts{Metadata: map[string]string{"white": ""}})
|
updateres := raxAccounts.Update(c, raxAccounts.UpdateOpts{Metadata: map[string]string{"white": ""}})
|
||||||
th.AssertNoErr(t, updateres.Err)
|
th.AssertNoErr(t, updateres.Err)
|
||||||
metadata, err := raxAccounts.Get(c).ExtractMetadata()
|
metadata, err := raxAccounts.Get(c).ExtractMetadata()
|
||||||
th.AssertNoErr(t, err)
|
th.AssertNoErr(t, err)
|
||||||
|
@ -25,8 +25,13 @@ func TestAccounts(t *testing.T) {
|
||||||
th.CheckEquals(t, metadata["White"], "")
|
th.CheckEquals(t, metadata["White"], "")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
metadata, err := raxAccounts.Get(c).ExtractMetadata()
|
getResp := raxAccounts.Get(c)
|
||||||
th.AssertNoErr(t, err)
|
th.AssertNoErr(t, getResp.Err)
|
||||||
|
|
||||||
|
getHeaders, _ := getResp.Extract()
|
||||||
|
t.Logf("Get Account Response Headers: %+v\n", getHeaders)
|
||||||
|
|
||||||
|
metadata, _ := getResp.ExtractMetadata()
|
||||||
t.Logf("Metadata from Get Account request (after update): %+v\n", metadata)
|
t.Logf("Metadata from Get Account request (after update): %+v\n", metadata)
|
||||||
|
|
||||||
th.CheckEquals(t, metadata["White"], "mountains")
|
th.CheckEquals(t, metadata["White"], "mountains")
|
||||||
|
|
|
@ -26,10 +26,11 @@ func TestCDNContainers(t *testing.T) {
|
||||||
|
|
||||||
raxCDNClient, err := createClient(t, true)
|
raxCDNClient, err := createClient(t, true)
|
||||||
th.AssertNoErr(t, err)
|
th.AssertNoErr(t, err)
|
||||||
|
enableRes := raxCDNContainers.Enable(raxCDNClient, "gophercloud-test", raxCDNContainers.EnableOpts{CDNEnabled: true, TTL: 900})
|
||||||
r := raxCDNContainers.Enable(raxCDNClient, "gophercloud-test", raxCDNContainers.EnableOpts{CDNEnabled: true, TTL: 900})
|
t.Logf("Header map from Enable CDN Container request: %+v\n", enableRes.Header)
|
||||||
th.AssertNoErr(t, r.Err)
|
enableHeader, err := enableRes.Extract()
|
||||||
t.Logf("Headers from Enable CDN Container request: %+v\n", r.Header)
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Headers from Enable CDN Container request: %+v\n", enableHeader)
|
||||||
|
|
||||||
t.Logf("Container Names available to the currently issued token:")
|
t.Logf("Container Names available to the currently issued token:")
|
||||||
count := 0
|
count := 0
|
||||||
|
@ -51,11 +52,15 @@ func TestCDNContainers(t *testing.T) {
|
||||||
t.Errorf("No CDN containers listed for your current token.")
|
t.Errorf("No CDN containers listed for your current token.")
|
||||||
}
|
}
|
||||||
|
|
||||||
updateres := raxCDNContainers.Update(raxCDNClient, "gophercloud-test", raxCDNContainers.UpdateOpts{CDNEnabled: false})
|
updateOpts := raxCDNContainers.UpdateOpts{XCDNEnabled: raxCDNContainers.Disabled, XLogRetention: raxCDNContainers.Enabled}
|
||||||
th.AssertNoErr(t, updateres.Err)
|
updateHeader, err := raxCDNContainers.Update(raxCDNClient, "gophercloud-test", updateOpts).Extract()
|
||||||
t.Logf("Headers from Update CDN Container request: %+v\n", updateres.Header)
|
|
||||||
|
|
||||||
metadata, err := raxCDNContainers.Get(raxCDNClient, "gophercloud-test").ExtractMetadata()
|
|
||||||
th.AssertNoErr(t, err)
|
th.AssertNoErr(t, err)
|
||||||
t.Logf("Headers from Get CDN Container request (after update): %+v\n", metadata)
|
t.Logf("Headers from Update CDN Container request: %+v\n", updateHeader)
|
||||||
|
|
||||||
|
getRes := raxCDNContainers.Get(raxCDNClient, "gophercloud-test")
|
||||||
|
getHeader, err := getRes.Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Headers from Get CDN Container request (after update): %+v\n", getHeader)
|
||||||
|
metadata, err := getRes.ExtractMetadata()
|
||||||
|
t.Logf("Metadata from Get CDN Container request (after update): %+v\n", metadata)
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,11 +36,15 @@ func TestCDNObjects(t *testing.T) {
|
||||||
raxCDNClient, err := createClient(t, true)
|
raxCDNClient, err := createClient(t, true)
|
||||||
th.AssertNoErr(t, err)
|
th.AssertNoErr(t, err)
|
||||||
|
|
||||||
enableResult := raxCDNContainers.Enable(raxCDNClient, "gophercloud-test", raxCDNContainers.EnableOpts{CDNEnabled: true, TTL: 900})
|
enableHeader, err := raxCDNContainers.Enable(raxCDNClient, "gophercloud-test", raxCDNContainers.EnableOpts{CDNEnabled: true, TTL: 900}).Extract()
|
||||||
th.AssertNoErr(t, enableResult.Err)
|
th.AssertNoErr(t, err)
|
||||||
t.Logf("Headers from Enable CDN Container request: %+v\n", enableResult.Header)
|
t.Logf("Headers from Enable CDN Container request: %+v\n", enableHeader)
|
||||||
|
|
||||||
deleteResult := raxCDNObjects.Delete(raxCDNClient, "gophercloud-test", "test-object", nil)
|
objCDNURL, err := raxCDNObjects.CDNURL(raxCDNClient, "gophercloud-test", "test-object")
|
||||||
th.AssertNoErr(t, deleteResult.Err)
|
th.AssertNoErr(t, err)
|
||||||
t.Logf("Headers from Delete CDN Object request: %+v\n", deleteResult.Err)
|
t.Logf("%s CDN URL: %s\n", "test_object", objCDNURL)
|
||||||
|
|
||||||
|
deleteHeader, err := raxCDNObjects.Delete(raxCDNClient, "gophercloud-test", "test-object", nil).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Headers from Delete CDN Object request: %+v\n", deleteHeader)
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,29 +57,34 @@ func TestContainers(t *testing.T) {
|
||||||
t.Errorf("No containers listed for your current token.")
|
t.Errorf("No containers listed for your current token.")
|
||||||
}
|
}
|
||||||
|
|
||||||
createres := raxContainers.Create(c, "gophercloud-test", nil)
|
createHeader, err := raxContainers.Create(c, "gophercloud-test", nil).Extract()
|
||||||
th.AssertNoErr(t, createres.Err)
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Headers from Create Container request: %+v\n", createHeader)
|
||||||
defer func() {
|
defer func() {
|
||||||
res := raxContainers.Delete(c, "gophercloud-test")
|
deleteres := raxContainers.Delete(c, "gophercloud-test")
|
||||||
th.AssertNoErr(t, res.Err)
|
deleteHeader, err := deleteres.Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Headers from Delete Container request: %+v\n", deleteres.Header)
|
||||||
|
t.Logf("Headers from Delete Container request: %+v\n", deleteHeader)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
updateres := raxContainers.Update(c, "gophercloud-test", raxContainers.UpdateOpts{Metadata: map[string]string{"white": "mountains"}})
|
updateHeader, err := raxContainers.Update(c, "gophercloud-test", raxContainers.UpdateOpts{Metadata: map[string]string{"white": "mountains"}}).Extract()
|
||||||
th.AssertNoErr(t, updateres.Err)
|
th.AssertNoErr(t, err)
|
||||||
t.Logf("Headers from Update Account request: %+v\n", updateres.Header)
|
t.Logf("Headers from Update Container request: %+v\n", updateHeader)
|
||||||
defer func() {
|
defer func() {
|
||||||
res := raxContainers.Update(c, "gophercloud-test", raxContainers.UpdateOpts{Metadata: map[string]string{"white": ""}})
|
res := raxContainers.Update(c, "gophercloud-test", raxContainers.UpdateOpts{Metadata: map[string]string{"white": ""}})
|
||||||
th.AssertNoErr(t, res.Err)
|
th.AssertNoErr(t, res.Err)
|
||||||
metadata, err := raxContainers.Get(c, "gophercloud-test").ExtractMetadata()
|
metadata, err := raxContainers.Get(c, "gophercloud-test").ExtractMetadata()
|
||||||
th.AssertNoErr(t, err)
|
th.AssertNoErr(t, err)
|
||||||
t.Logf("Metadata from Get Account request (after update reverted): %+v\n", metadata)
|
t.Logf("Metadata from Get Container request (after update reverted): %+v\n", metadata)
|
||||||
th.CheckEquals(t, metadata["White"], "")
|
th.CheckEquals(t, metadata["White"], "")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
getres := raxContainers.Get(c, "gophercloud-test")
|
getres := raxContainers.Get(c, "gophercloud-test")
|
||||||
t.Logf("Headers from Get Account request (after update): %+v\n", getres.Header)
|
getHeader, err := getres.Extract()
|
||||||
metadata, err := getres.ExtractMetadata()
|
|
||||||
th.AssertNoErr(t, err)
|
th.AssertNoErr(t, err)
|
||||||
t.Logf("Metadata from Get Account request (after update): %+v\n", metadata)
|
t.Logf("Headers from Get Container request (after update): %+v\n", getHeader)
|
||||||
|
metadata, err := getres.ExtractMetadata()
|
||||||
|
t.Logf("Metadata from Get Container request (after update): %+v\n", metadata)
|
||||||
th.CheckEquals(t, metadata["White"], "mountains")
|
th.CheckEquals(t, metadata["White"], "mountains")
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ func TestObjects(t *testing.T) {
|
||||||
th.AssertNoErr(t, res.Err)
|
th.AssertNoErr(t, res.Err)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
t.Logf("Deleting container...")
|
||||||
res := raxContainers.Delete(c, "gophercloud-test")
|
res := raxContainers.Delete(c, "gophercloud-test")
|
||||||
th.AssertNoErr(t, res.Err)
|
th.AssertNoErr(t, res.Err)
|
||||||
}()
|
}()
|
||||||
|
@ -29,7 +30,9 @@ func TestObjects(t *testing.T) {
|
||||||
options := &osObjects.CreateOpts{ContentType: "text/plain"}
|
options := &osObjects.CreateOpts{ContentType: "text/plain"}
|
||||||
createres := raxObjects.Create(c, "gophercloud-test", "o1", content, options)
|
createres := raxObjects.Create(c, "gophercloud-test", "o1", content, options)
|
||||||
th.AssertNoErr(t, createres.Err)
|
th.AssertNoErr(t, createres.Err)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
t.Logf("Deleting object o1...")
|
||||||
res := raxObjects.Delete(c, "gophercloud-test", "o1", nil)
|
res := raxObjects.Delete(c, "gophercloud-test", "o1", nil)
|
||||||
th.AssertNoErr(t, res.Err)
|
th.AssertNoErr(t, res.Err)
|
||||||
}()
|
}()
|
||||||
|
@ -80,6 +83,7 @@ func TestObjects(t *testing.T) {
|
||||||
copyres := raxObjects.Copy(c, "gophercloud-test", "o1", &raxObjects.CopyOpts{Destination: "gophercloud-test/o2"})
|
copyres := raxObjects.Copy(c, "gophercloud-test", "o1", &raxObjects.CopyOpts{Destination: "gophercloud-test/o2"})
|
||||||
th.AssertNoErr(t, copyres.Err)
|
th.AssertNoErr(t, copyres.Err)
|
||||||
defer func() {
|
defer func() {
|
||||||
|
t.Logf("Deleting object o2...")
|
||||||
res := raxObjects.Delete(c, "gophercloud-test", "o2", nil)
|
res := raxObjects.Delete(c, "gophercloud-test", "o2", nil)
|
||||||
th.AssertNoErr(t, res.Err)
|
th.AssertNoErr(t, res.Err)
|
||||||
}()
|
}()
|
||||||
|
@ -99,7 +103,7 @@ func TestObjects(t *testing.T) {
|
||||||
metadata, err := raxObjects.Get(c, "gophercloud-test", "o2", nil).ExtractMetadata()
|
metadata, err := raxObjects.Get(c, "gophercloud-test", "o2", nil).ExtractMetadata()
|
||||||
th.AssertNoErr(t, err)
|
th.AssertNoErr(t, err)
|
||||||
t.Logf("Metadata from Get Account request (after update reverted): %+v\n", metadata)
|
t.Logf("Metadata from Get Account request (after update reverted): %+v\n", metadata)
|
||||||
th.CheckEquals(t, metadata["White"], "")
|
th.CheckEquals(t, "", metadata["White"])
|
||||||
}()
|
}()
|
||||||
|
|
||||||
getres := raxObjects.Get(c, "gophercloud-test", "o2", nil)
|
getres := raxObjects.Get(c, "gophercloud-test", "o2", nil)
|
||||||
|
@ -108,5 +112,13 @@ func TestObjects(t *testing.T) {
|
||||||
metadata, err := getres.ExtractMetadata()
|
metadata, err := getres.ExtractMetadata()
|
||||||
th.AssertNoErr(t, err)
|
th.AssertNoErr(t, err)
|
||||||
t.Logf("Metadata from Get Account request (after update): %+v\n", metadata)
|
t.Logf("Metadata from Get Account request (after update): %+v\n", metadata)
|
||||||
th.CheckEquals(t, metadata["White"], "mountains")
|
th.CheckEquals(t, "mountains", metadata["White"])
|
||||||
|
|
||||||
|
createTempURLOpts := osObjects.CreateTempURLOpts{
|
||||||
|
Method: osObjects.GET,
|
||||||
|
TTL: 600,
|
||||||
|
}
|
||||||
|
tempURL, err := raxObjects.CreateTempURL(c, "gophercloud-test", "o1", createTempURLOpts)
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("TempURL for object (%s): %s", "o1", tempURL)
|
||||||
}
|
}
|
||||||
|
|
20
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/rackspace/orchestration/v1/buildinfo_test.go
generated
vendored
Normal file
20
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/rackspace/orchestration/v1/buildinfo_test.go
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// +build acceptance
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud/rackspace/orchestration/v1/buildinfo"
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBuildInfo(t *testing.T) {
|
||||||
|
// Create a provider client for making the HTTP requests.
|
||||||
|
// See common.go in this directory for more information.
|
||||||
|
client := newClient(t)
|
||||||
|
|
||||||
|
bi, err := buildinfo.Get(client).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("retrieved build info: %+v\n", bi)
|
||||||
|
}
|
45
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/rackspace/orchestration/v1/common.go
generated
vendored
Normal file
45
Godeps/_workspace/src/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
|
||||||
|
}
|
70
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/rackspace/orchestration/v1/stackevents_test.go
generated
vendored
Normal file
70
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/rackspace/orchestration/v1/stackevents_test.go
generated
vendored
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
// +build acceptance
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
osStackEvents "github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents"
|
||||||
|
osStacks "github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
"github.com/rackspace/gophercloud/rackspace/orchestration/v1/stackevents"
|
||||||
|
"github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacks"
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStackEvents(t *testing.T) {
|
||||||
|
// Create a provider client for making the HTTP requests.
|
||||||
|
// See common.go in this directory for more information.
|
||||||
|
client := newClient(t)
|
||||||
|
|
||||||
|
stackName := "postman_stack_2"
|
||||||
|
resourceName := "hello_world"
|
||||||
|
var eventID string
|
||||||
|
|
||||||
|
createOpts := osStacks.CreateOpts{
|
||||||
|
Name: stackName,
|
||||||
|
Template: template,
|
||||||
|
Timeout: 5,
|
||||||
|
}
|
||||||
|
stack, err := stacks.Create(client, createOpts).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Created stack: %+v\n", stack)
|
||||||
|
defer func() {
|
||||||
|
err := stacks.Delete(client, stackName, stack.ID).ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Deleted stack (%s)", stackName)
|
||||||
|
}()
|
||||||
|
err = gophercloud.WaitFor(60, func() (bool, error) {
|
||||||
|
getStack, err := stacks.Get(client, stackName, stack.ID).Extract()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if getStack.Status == "CREATE_COMPLETE" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
err = stackevents.List(client, stackName, stack.ID, nil).EachPage(func(page pagination.Page) (bool, error) {
|
||||||
|
events, err := osStackEvents.ExtractEvents(page)
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("listed events: %+v\n", events)
|
||||||
|
eventID = events[0].ID
|
||||||
|
return false, nil
|
||||||
|
})
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
|
||||||
|
err = stackevents.ListResourceEvents(client, stackName, stack.ID, resourceName, nil).EachPage(func(page pagination.Page) (bool, error) {
|
||||||
|
resourceEvents, err := osStackEvents.ExtractResourceEvents(page)
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("listed resource events: %+v\n", resourceEvents)
|
||||||
|
return false, nil
|
||||||
|
})
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
|
||||||
|
event, err := stackevents.Get(client, stackName, stack.ID, resourceName, eventID).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("retrieved event: %+v\n", event)
|
||||||
|
}
|
64
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/rackspace/orchestration/v1/stackresources_test.go
generated
vendored
Normal file
64
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/rackspace/orchestration/v1/stackresources_test.go
generated
vendored
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
// +build acceptance
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
osStackResources "github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources"
|
||||||
|
osStacks "github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
"github.com/rackspace/gophercloud/rackspace/orchestration/v1/stackresources"
|
||||||
|
"github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacks"
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStackResources(t *testing.T) {
|
||||||
|
// Create a provider client for making the HTTP requests.
|
||||||
|
// See common.go in this directory for more information.
|
||||||
|
client := newClient(t)
|
||||||
|
|
||||||
|
stackName := "postman_stack_2"
|
||||||
|
|
||||||
|
createOpts := osStacks.CreateOpts{
|
||||||
|
Name: stackName,
|
||||||
|
Template: template,
|
||||||
|
Timeout: 5,
|
||||||
|
}
|
||||||
|
stack, err := stacks.Create(client, createOpts).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Created stack: %+v\n", stack)
|
||||||
|
defer func() {
|
||||||
|
err := stacks.Delete(client, stackName, stack.ID).ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Deleted stack (%s)", stackName)
|
||||||
|
}()
|
||||||
|
err = gophercloud.WaitFor(60, func() (bool, error) {
|
||||||
|
getStack, err := stacks.Get(client, stackName, stack.ID).Extract()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if getStack.Status == "CREATE_COMPLETE" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
resourceName := "hello_world"
|
||||||
|
resource, err := stackresources.Get(client, stackName, stack.ID, resourceName).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Got stack resource: %+v\n", resource)
|
||||||
|
|
||||||
|
metadata, err := stackresources.Metadata(client, stackName, stack.ID, resourceName).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Got stack resource metadata: %+v\n", metadata)
|
||||||
|
|
||||||
|
err = stackresources.List(client, stackName, stack.ID, nil).EachPage(func(page pagination.Page) (bool, error) {
|
||||||
|
resources, err := osStackResources.ExtractResources(page)
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("resources: %+v\n", resources)
|
||||||
|
return false, nil
|
||||||
|
})
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
}
|
82
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/rackspace/orchestration/v1/stacks_test.go
generated
vendored
Normal file
82
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/rackspace/orchestration/v1/stacks_test.go
generated
vendored
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
// +build acceptance
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
osStacks "github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
"github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacks"
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStacks(t *testing.T) {
|
||||||
|
// Create a provider client for making the HTTP requests.
|
||||||
|
// See common.go in this directory for more information.
|
||||||
|
client := newClient(t)
|
||||||
|
|
||||||
|
stackName1 := "gophercloud-test-stack-2"
|
||||||
|
createOpts := osStacks.CreateOpts{
|
||||||
|
Name: stackName1,
|
||||||
|
Template: template,
|
||||||
|
Timeout: 5,
|
||||||
|
}
|
||||||
|
stack, err := stacks.Create(client, createOpts).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Created stack: %+v\n", stack)
|
||||||
|
defer func() {
|
||||||
|
err := stacks.Delete(client, stackName1, stack.ID).ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Deleted stack (%s)", stackName1)
|
||||||
|
}()
|
||||||
|
err = gophercloud.WaitFor(60, func() (bool, error) {
|
||||||
|
getStack, err := stacks.Get(client, stackName1, stack.ID).Extract()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if getStack.Status == "CREATE_COMPLETE" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
updateOpts := osStacks.UpdateOpts{
|
||||||
|
Template: template,
|
||||||
|
Timeout: 20,
|
||||||
|
}
|
||||||
|
err = stacks.Update(client, stackName1, stack.ID, updateOpts).ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
err = gophercloud.WaitFor(60, func() (bool, error) {
|
||||||
|
getStack, err := stacks.Get(client, stackName1, stack.ID).Extract()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if getStack.Status == "UPDATE_COMPLETE" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Logf("Updated stack")
|
||||||
|
|
||||||
|
err = stacks.List(client, nil).EachPage(func(page pagination.Page) (bool, error) {
|
||||||
|
stackList, err := osStacks.ExtractStacks(page)
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
|
||||||
|
t.Logf("Got stack list: %+v\n", stackList)
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
})
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
|
||||||
|
getStack, err := stacks.Get(client, stackName1, stack.ID).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Got stack: %+v\n", getStack)
|
||||||
|
|
||||||
|
abandonedStack, err := stacks.Abandon(client, stackName1, stack.ID).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Abandonded stack %+v\n", abandonedStack)
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
}
|
79
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/rackspace/orchestration/v1/stacktemplates_test.go
generated
vendored
Normal file
79
Godeps/_workspace/src/github.com/rackspace/gophercloud/acceptance/rackspace/orchestration/v1/stacktemplates_test.go
generated
vendored
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
// +build acceptance
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
osStacks "github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks"
|
||||||
|
osStacktemplates "github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates"
|
||||||
|
"github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacks"
|
||||||
|
"github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacktemplates"
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStackTemplates(t *testing.T) {
|
||||||
|
// Create a provider client for making the HTTP requests.
|
||||||
|
// See common.go in this directory for more information.
|
||||||
|
client := newClient(t)
|
||||||
|
|
||||||
|
stackName := "postman_stack_2"
|
||||||
|
|
||||||
|
createOpts := osStacks.CreateOpts{
|
||||||
|
Name: stackName,
|
||||||
|
Template: template,
|
||||||
|
Timeout: 5,
|
||||||
|
}
|
||||||
|
stack, err := stacks.Create(client, createOpts).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Created stack: %+v\n", stack)
|
||||||
|
defer func() {
|
||||||
|
err := stacks.Delete(client, stackName, stack.ID).ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("Deleted stack (%s)", stackName)
|
||||||
|
}()
|
||||||
|
err = gophercloud.WaitFor(60, func() (bool, error) {
|
||||||
|
getStack, err := stacks.Get(client, stackName, stack.ID).Extract()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if getStack.Status == "CREATE_COMPLETE" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
tmpl, err := stacktemplates.Get(client, stackName, stack.ID).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("retrieved template: %+v\n", tmpl)
|
||||||
|
|
||||||
|
validateOpts := osStacktemplates.ValidateOpts{
|
||||||
|
Template: map[string]interface{}{
|
||||||
|
"heat_template_version": "2013-05-23",
|
||||||
|
"description": "Simple template to test heat commands",
|
||||||
|
"parameters": map[string]interface{}{
|
||||||
|
"flavor": map[string]interface{}{
|
||||||
|
"default": "m1.tiny",
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"resources": map[string]interface{}{
|
||||||
|
"hello_world": map[string]interface{}{
|
||||||
|
"type": "OS::Nova::Server",
|
||||||
|
"properties": map[string]interface{}{
|
||||||
|
"key_name": "heat_key",
|
||||||
|
"flavor": map[string]interface{}{
|
||||||
|
"get_param": "flavor",
|
||||||
|
},
|
||||||
|
"image": "ad091b52-742f-469e-8f3c-fd81cadf0743",
|
||||||
|
"user_data": "#!/bin/bash -xv\necho \"hello world\" > /root/hello-world.txt\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
validatedTemplate, err := stacktemplates.Validate(client, validateOpts).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
t.Logf("validated template: %+v\n", validatedTemplate)
|
||||||
|
}
|
|
@ -42,7 +42,5 @@ type AuthOptions struct {
|
||||||
// re-authenticate automatically if/when your token expires. If you set it 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
|
// false, it will not cache these settings, but re-authentication will not be
|
||||||
// possible. This setting defaults to false.
|
// possible. This setting defaults to false.
|
||||||
//
|
|
||||||
// This setting is speculative and is currently not respected!
|
|
||||||
AllowReauth bool
|
AllowReauth bool
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,6 @@ package apiversions
|
||||||
import (
|
import (
|
||||||
"github.com/rackspace/gophercloud"
|
"github.com/rackspace/gophercloud"
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
|
||||||
"github.com/racker/perigee"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// List lists all the Cinder API versions available to end-users.
|
// List lists all the Cinder API versions available to end-users.
|
||||||
|
@ -18,11 +16,9 @@ func List(c *gophercloud.ServiceClient) pagination.Pager {
|
||||||
// type from the result, call the Extract method on the GetResult.
|
// type from the result, call the Extract method on the GetResult.
|
||||||
func Get(client *gophercloud.ServiceClient, v string) GetResult {
|
func Get(client *gophercloud.ServiceClient, v string) GetResult {
|
||||||
var res GetResult
|
var res GetResult
|
||||||
_, err := perigee.Request("GET", getURL(client, v), perigee.Options{
|
_, res.Err = client.Request("GET", getURL(client, v), gophercloud.RequestOpts{
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
OkCodes: []int{200},
|
||||||
OkCodes: []int{200},
|
JSONResponse: &res.Body,
|
||||||
Results: &res.Body,
|
|
||||||
})
|
})
|
||||||
res.Err = err
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,6 @@ import (
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud"
|
"github.com/rackspace/gophercloud"
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
|
||||||
"github.com/racker/perigee"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateOptsBuilder allows extensions to add additional parameters to the
|
// CreateOptsBuilder allows extensions to add additional parameters to the
|
||||||
|
@ -69,11 +67,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
_, res.Err = perigee.Request("POST", createURL(client), perigee.Options{
|
_, res.Err = client.Request("POST", createURL(client), gophercloud.RequestOpts{
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
OkCodes: []int{200, 201},
|
||||||
OkCodes: []int{200, 201},
|
JSONBody: &reqBody,
|
||||||
ReqBody: &reqBody,
|
JSONResponse: &res.Body,
|
||||||
Results: &res.Body,
|
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
@ -81,9 +78,8 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
|
||||||
// Delete will delete the existing Snapshot with the provided ID.
|
// Delete will delete the existing Snapshot with the provided ID.
|
||||||
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
|
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
|
||||||
var res DeleteResult
|
var res DeleteResult
|
||||||
_, res.Err = perigee.Request("DELETE", deleteURL(client, id), perigee.Options{
|
_, res.Err = client.Request("DELETE", deleteURL(client, id), gophercloud.RequestOpts{
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
OkCodes: []int{202, 204},
|
||||||
OkCodes: []int{202, 204},
|
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
@ -92,10 +88,9 @@ func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
|
||||||
// object from the response, call the Extract method on the GetResult.
|
// object from the response, call the Extract method on the GetResult.
|
||||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||||
var res GetResult
|
var res GetResult
|
||||||
_, res.Err = perigee.Request("GET", getURL(client, id), perigee.Options{
|
_, res.Err = client.Request("GET", getURL(client, id), gophercloud.RequestOpts{
|
||||||
Results: &res.Body,
|
OkCodes: []int{200},
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
JSONResponse: &res.Body,
|
||||||
OkCodes: []int{200},
|
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
@ -178,11 +173,10 @@ func UpdateMetadata(client *gophercloud.ServiceClient, id string, opts UpdateMet
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
_, res.Err = perigee.Request("PUT", updateMetadataURL(client, id), perigee.Options{
|
_, res.Err = client.Request("PUT", updateMetadataURL(client, id), gophercloud.RequestOpts{
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
OkCodes: []int{200},
|
||||||
OkCodes: []int{200},
|
JSONBody: &reqBody,
|
||||||
ReqBody: &reqBody,
|
JSONResponse: &res.Body,
|
||||||
Results: &res.Body,
|
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,8 +45,16 @@ func MockGetResponse(t *testing.T) {
|
||||||
{
|
{
|
||||||
"volume": {
|
"volume": {
|
||||||
"display_name": "vol-001",
|
"display_name": "vol-001",
|
||||||
"id": "d32019d3-bc6e-4319-9c1d-6722fc136a22"
|
"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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
|
|
@ -5,8 +5,6 @@ import (
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud"
|
"github.com/rackspace/gophercloud"
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
|
||||||
"github.com/racker/perigee"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateOptsBuilder allows extensions to add additional parameters to the
|
// CreateOptsBuilder allows extensions to add additional parameters to the
|
||||||
|
@ -85,11 +83,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
_, res.Err = perigee.Request("POST", createURL(client), perigee.Options{
|
_, res.Err = client.Request("POST", createURL(client), gophercloud.RequestOpts{
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
OkCodes: []int{200, 201},
|
||||||
ReqBody: &reqBody,
|
JSONBody: &reqBody,
|
||||||
Results: &res.Body,
|
JSONResponse: &res.Body,
|
||||||
OkCodes: []int{200, 201},
|
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
@ -97,9 +94,8 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
|
||||||
// Delete will delete the existing Volume with the provided ID.
|
// Delete will delete the existing Volume with the provided ID.
|
||||||
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
|
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
|
||||||
var res DeleteResult
|
var res DeleteResult
|
||||||
_, res.Err = perigee.Request("DELETE", deleteURL(client, id), perigee.Options{
|
_, res.Err = client.Request("DELETE", deleteURL(client, id), gophercloud.RequestOpts{
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
OkCodes: []int{202, 204},
|
||||||
OkCodes: []int{202, 204},
|
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
@ -108,10 +104,9 @@ func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
|
||||||
// from the response, call the Extract method on the GetResult.
|
// from the response, call the Extract method on the GetResult.
|
||||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||||
var res GetResult
|
var res GetResult
|
||||||
_, res.Err = perigee.Request("GET", getURL(client, id), perigee.Options{
|
_, res.Err = client.Request("GET", getURL(client, id), gophercloud.RequestOpts{
|
||||||
Results: &res.Body,
|
JSONResponse: &res.Body,
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
OkCodes: []int{200},
|
||||||
OkCodes: []int{200},
|
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
@ -207,11 +202,10 @@ func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
_, res.Err = perigee.Request("PUT", updateURL(client, id), perigee.Options{
|
_, res.Err = client.Request("PUT", updateURL(client, id), gophercloud.RequestOpts{
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
OkCodes: []int{200},
|
||||||
OkCodes: []int{200},
|
JSONBody: &reqBody,
|
||||||
ReqBody: &reqBody,
|
JSONResponse: &res.Body,
|
||||||
Results: &res.Body,
|
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,7 @@ func TestGet(t *testing.T) {
|
||||||
|
|
||||||
th.AssertEquals(t, v.Name, "vol-001")
|
th.AssertEquals(t, v.Name, "vol-001")
|
||||||
th.AssertEquals(t, v.ID, "d32019d3-bc6e-4319-9c1d-6722fc136a22")
|
th.AssertEquals(t, v.ID, "d32019d3-bc6e-4319-9c1d-6722fc136a22")
|
||||||
|
th.AssertEquals(t, v.Attachments[0]["device"], "/dev/vde")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreate(t *testing.T) {
|
func TestCreate(t *testing.T) {
|
||||||
|
|
|
@ -16,7 +16,7 @@ type Volume struct {
|
||||||
Name string `mapstructure:"display_name"`
|
Name string `mapstructure:"display_name"`
|
||||||
|
|
||||||
// Instances onto which the volume is attached.
|
// Instances onto which the volume is attached.
|
||||||
Attachments []string `mapstructure:"attachments"`
|
Attachments []map[string]interface{} `mapstructure:"attachments"`
|
||||||
|
|
||||||
// This parameter is no longer used.
|
// This parameter is no longer used.
|
||||||
AvailabilityZone string `mapstructure:"availability_zone"`
|
AvailabilityZone string `mapstructure:"availability_zone"`
|
||||||
|
@ -28,7 +28,7 @@ type Volume struct {
|
||||||
CreatedAt string `mapstructure:"created_at"`
|
CreatedAt string `mapstructure:"created_at"`
|
||||||
|
|
||||||
// Human-readable description for the volume.
|
// Human-readable description for the volume.
|
||||||
Description string `mapstructure:"display_discription"`
|
Description string `mapstructure:"display_description"`
|
||||||
|
|
||||||
// The type of volume to create, either SATA or SSD.
|
// The type of volume to create, either SATA or SSD.
|
||||||
VolumeType string `mapstructure:"volume_type"`
|
VolumeType string `mapstructure:"volume_type"`
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package volumetypes
|
package volumetypes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/racker/perigee"
|
|
||||||
"github.com/rackspace/gophercloud"
|
"github.com/rackspace/gophercloud"
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
)
|
)
|
||||||
|
@ -45,11 +44,11 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
_, res.Err = perigee.Request("POST", createURL(client), perigee.Options{
|
_, res.Err = client.Request("POST", createURL(client), gophercloud.RequestOpts{
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
MoreHeaders: client.AuthenticatedHeaders(),
|
||||||
OkCodes: []int{200, 201},
|
OkCodes: []int{200, 201},
|
||||||
ReqBody: &reqBody,
|
JSONBody: &reqBody,
|
||||||
Results: &res.Body,
|
JSONResponse: &res.Body,
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
@ -57,7 +56,7 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
|
||||||
// Delete will delete the volume type with the provided ID.
|
// Delete will delete the volume type with the provided ID.
|
||||||
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
|
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
|
||||||
var res DeleteResult
|
var res DeleteResult
|
||||||
_, res.Err = perigee.Request("DELETE", deleteURL(client, id), perigee.Options{
|
_, res.Err = client.Request("DELETE", deleteURL(client, id), gophercloud.RequestOpts{
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
MoreHeaders: client.AuthenticatedHeaders(),
|
||||||
OkCodes: []int{202},
|
OkCodes: []int{202},
|
||||||
})
|
})
|
||||||
|
@ -68,10 +67,10 @@ func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
|
||||||
// type from the result, call the Extract method on the GetResult.
|
// type from the result, call the Extract method on the GetResult.
|
||||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||||
var res GetResult
|
var res GetResult
|
||||||
_, err := perigee.Request("GET", getURL(client, id), perigee.Options{
|
_, err := client.Request("GET", getURL(client, id), gophercloud.RequestOpts{
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
MoreHeaders: client.AuthenticatedHeaders(),
|
||||||
OkCodes: []int{200},
|
OkCodes: []int{200},
|
||||||
Results: &res.Body,
|
JSONResponse: &res.Body,
|
||||||
})
|
})
|
||||||
res.Err = err
|
res.Err = err
|
||||||
return res
|
return res
|
||||||
|
|
4
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/base/doc.go
generated
vendored
Normal file
4
Godeps/_workspace/src/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
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/base/fixtures.go
generated
vendored
Normal file
53
Godeps/_workspace/src/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)
|
||||||
|
})
|
||||||
|
}
|
24
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/base/requests.go
generated
vendored
Normal file
24
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/base/requests.go
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
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.Request("GET", getURL(c), gophercloud.RequestOpts{
|
||||||
|
JSONResponse: &res.Body,
|
||||||
|
OkCodes: []int{200},
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ping retrieves a ping to the server.
|
||||||
|
func Ping(c *gophercloud.ServiceClient) PingResult {
|
||||||
|
var res PingResult
|
||||||
|
_, res.Err = c.Request("GET", pingURL(c), gophercloud.RequestOpts{
|
||||||
|
OkCodes: []int{204},
|
||||||
|
MoreHeaders: map[string]string{"Accept": ""},
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
43
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/base/requests_test.go
generated
vendored
Normal file
43
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/base/requests_test.go
generated
vendored
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
package base
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
fake "github.com/rackspace/gophercloud/testhelper/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetHomeDocument(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
HandleGetSuccessfully(t)
|
||||||
|
|
||||||
|
actual, err := Get(fake.ServiceClient()).Extract()
|
||||||
|
th.CheckNoErr(t, err)
|
||||||
|
|
||||||
|
expected := HomeDocument{
|
||||||
|
"rel/cdn": map[string]interface{}{
|
||||||
|
"href-template": "services{?marker,limit}",
|
||||||
|
"href-vars": map[string]interface{}{
|
||||||
|
"marker": "param/marker",
|
||||||
|
"limit": "param/limit",
|
||||||
|
},
|
||||||
|
"hints": map[string]interface{}{
|
||||||
|
"allow": []string{"GET"},
|
||||||
|
"formats": map[string]interface{}{
|
||||||
|
"application/json": map[string]interface{}{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
th.CheckDeepEquals(t, expected, *actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPing(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
HandlePingSuccessfully(t)
|
||||||
|
|
||||||
|
err := Ping(fake.ServiceClient()).ExtractErr()
|
||||||
|
th.CheckNoErr(t, err)
|
||||||
|
}
|
35
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/base/results.go
generated
vendored
Normal file
35
Godeps/_workspace/src/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
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/base/urls.go
generated
vendored
Normal file
11
Godeps/_workspace/src/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
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/doc.go
generated
vendored
Normal file
6
Godeps/_workspace/src/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
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/fixtures.go
generated
vendored
Normal file
82
Godeps/_workspace/src/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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
})
|
||||||
|
}
|
25
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/requests.go
generated
vendored
Normal file
25
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/requests.go
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
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.Request("GET", getURL(c, id), gophercloud.RequestOpts{
|
||||||
|
JSONResponse: &res.Body,
|
||||||
|
OkCodes: []int{200},
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
90
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/requests_test.go
generated
vendored
Normal file
90
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/requests_test.go
generated
vendored
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
package flavors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
fake "github.com/rackspace/gophercloud/testhelper/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestList(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
|
||||||
|
HandleListCDNFlavorsSuccessfully(t)
|
||||||
|
|
||||||
|
count := 0
|
||||||
|
|
||||||
|
err := List(fake.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
|
||||||
|
count++
|
||||||
|
actual, err := ExtractFlavors(page)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to extract flavors: %v", err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := []Flavor{
|
||||||
|
Flavor{
|
||||||
|
ID: "europe",
|
||||||
|
Providers: []Provider{
|
||||||
|
Provider{
|
||||||
|
Provider: "Fastly",
|
||||||
|
Links: []gophercloud.Link{
|
||||||
|
gophercloud.Link{
|
||||||
|
Href: "http://www.fastly.com",
|
||||||
|
Rel: "provider_url",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Links: []gophercloud.Link{
|
||||||
|
gophercloud.Link{
|
||||||
|
Href: "https://www.poppycdn.io/v1.0/flavors/europe",
|
||||||
|
Rel: "self",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
th.CheckDeepEquals(t, expected, actual)
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
})
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
th.CheckEquals(t, 1, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGet(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
|
||||||
|
HandleGetCDNFlavorSuccessfully(t)
|
||||||
|
|
||||||
|
expected := &Flavor{
|
||||||
|
ID: "asia",
|
||||||
|
Providers: []Provider{
|
||||||
|
Provider{
|
||||||
|
Provider: "ChinaCache",
|
||||||
|
Links: []gophercloud.Link{
|
||||||
|
gophercloud.Link{
|
||||||
|
Href: "http://www.chinacache.com",
|
||||||
|
Rel: "provider_url",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Links: []gophercloud.Link{
|
||||||
|
gophercloud.Link{
|
||||||
|
Href: "https://www.poppycdn.io/v1.0/flavors/asia",
|
||||||
|
Rel: "self",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
actual, err := Get(fake.ServiceClient(), "asia").Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
th.AssertDeepEquals(t, expected, actual)
|
||||||
|
}
|
71
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/results.go
generated
vendored
Normal file
71
Godeps/_workspace/src/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
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/flavors/urls.go
generated
vendored
Normal file
11
Godeps/_workspace/src/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
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/doc.go
generated
vendored
Normal file
7
Godeps/_workspace/src/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
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/fixtures.go
generated
vendored
Normal file
19
Godeps/_workspace/src/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)
|
||||||
|
})
|
||||||
|
}
|
50
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/requests.go
generated
vendored
Normal file
50
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/requests.go
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
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.Request("DELETE", url, gophercloud.RequestOpts{
|
||||||
|
OkCodes: []int{202},
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
18
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/requests_test.go
generated
vendored
Normal file
18
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/requests_test.go
generated
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
package serviceassets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
fake "github.com/rackspace/gophercloud/testhelper/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDelete(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
|
||||||
|
HandleDeleteCDNAssetSuccessfully(t)
|
||||||
|
|
||||||
|
err := Delete(fake.ServiceClient(), "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0", nil).ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
}
|
8
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/results.go
generated
vendored
Normal file
8
Godeps/_workspace/src/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
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets/urls.go
generated
vendored
Normal file
7
Godeps/_workspace/src/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
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/services/doc.go
generated
vendored
Normal file
7
Godeps/_workspace/src/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
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/services/errors.go
generated
vendored
Normal file
7
Godeps/_workspace/src/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
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/services/fixtures.go
generated
vendored
Normal file
372
Godeps/_workspace/src/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)
|
||||||
|
})
|
||||||
|
}
|
386
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/services/requests.go
generated
vendored
Normal file
386
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/services/requests.go
generated
vendored
Normal file
|
@ -0,0 +1,386 @@
|
||||||
|
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.Request("POST", createURL(c), gophercloud.RequestOpts{
|
||||||
|
JSONBody: &reqBody,
|
||||||
|
OkCodes: []int{202},
|
||||||
|
})
|
||||||
|
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.Request("GET", url, gophercloud.RequestOpts{
|
||||||
|
JSONResponse: &res.Body,
|
||||||
|
OkCodes: []int{200},
|
||||||
|
})
|
||||||
|
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.Request("DELETE", url, gophercloud.RequestOpts{
|
||||||
|
OkCodes: []int{202},
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
358
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/services/requests_test.go
generated
vendored
Normal file
358
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/services/requests_test.go
generated
vendored
Normal file
|
@ -0,0 +1,358 @@
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
fake "github.com/rackspace/gophercloud/testhelper/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestList(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
|
||||||
|
HandleListCDNServiceSuccessfully(t)
|
||||||
|
|
||||||
|
count := 0
|
||||||
|
|
||||||
|
err := List(fake.ServiceClient(), &ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
|
||||||
|
count++
|
||||||
|
actual, err := ExtractServices(page)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to extract services: %v", err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := []Service{
|
||||||
|
Service{
|
||||||
|
ID: "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0",
|
||||||
|
Name: "mywebsite.com",
|
||||||
|
Domains: []Domain{
|
||||||
|
Domain{
|
||||||
|
Domain: "www.mywebsite.com",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Origins: []Origin{
|
||||||
|
Origin{
|
||||||
|
Origin: "mywebsite.com",
|
||||||
|
Port: 80,
|
||||||
|
SSL: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Caching: []CacheRule{
|
||||||
|
CacheRule{
|
||||||
|
Name: "default",
|
||||||
|
TTL: 3600,
|
||||||
|
},
|
||||||
|
CacheRule{
|
||||||
|
Name: "home",
|
||||||
|
TTL: 17200,
|
||||||
|
Rules: []TTLRule{
|
||||||
|
TTLRule{
|
||||||
|
Name: "index",
|
||||||
|
RequestURL: "/index.htm",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
CacheRule{
|
||||||
|
Name: "images",
|
||||||
|
TTL: 12800,
|
||||||
|
Rules: []TTLRule{
|
||||||
|
TTLRule{
|
||||||
|
Name: "images",
|
||||||
|
RequestURL: "*.png",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Restrictions: []Restriction{
|
||||||
|
Restriction{
|
||||||
|
Name: "website only",
|
||||||
|
Rules: []RestrictionRule{
|
||||||
|
RestrictionRule{
|
||||||
|
Name: "mywebsite.com",
|
||||||
|
Referrer: "www.mywebsite.com",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
FlavorID: "asia",
|
||||||
|
Status: "deployed",
|
||||||
|
Errors: []Error{},
|
||||||
|
Links: []gophercloud.Link{
|
||||||
|
gophercloud.Link{
|
||||||
|
Href: "https://www.poppycdn.io/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0",
|
||||||
|
Rel: "self",
|
||||||
|
},
|
||||||
|
gophercloud.Link{
|
||||||
|
Href: "mywebsite.com.cdn123.poppycdn.net",
|
||||||
|
Rel: "access_url",
|
||||||
|
},
|
||||||
|
gophercloud.Link{
|
||||||
|
Href: "https://www.poppycdn.io/v1.0/flavors/asia",
|
||||||
|
Rel: "flavor",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Service{
|
||||||
|
ID: "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f1",
|
||||||
|
Name: "myothersite.com",
|
||||||
|
Domains: []Domain{
|
||||||
|
Domain{
|
||||||
|
Domain: "www.myothersite.com",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Origins: []Origin{
|
||||||
|
Origin{
|
||||||
|
Origin: "44.33.22.11",
|
||||||
|
Port: 80,
|
||||||
|
SSL: false,
|
||||||
|
},
|
||||||
|
Origin{
|
||||||
|
Origin: "77.66.55.44",
|
||||||
|
Port: 80,
|
||||||
|
SSL: false,
|
||||||
|
Rules: []OriginRule{
|
||||||
|
OriginRule{
|
||||||
|
Name: "videos",
|
||||||
|
RequestURL: "^/videos/*.m3u",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Caching: []CacheRule{
|
||||||
|
CacheRule{
|
||||||
|
Name: "default",
|
||||||
|
TTL: 3600,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Restrictions: []Restriction{},
|
||||||
|
FlavorID: "europe",
|
||||||
|
Status: "deployed",
|
||||||
|
Links: []gophercloud.Link{
|
||||||
|
gophercloud.Link{
|
||||||
|
Href: "https://www.poppycdn.io/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f1",
|
||||||
|
Rel: "self",
|
||||||
|
},
|
||||||
|
gophercloud.Link{
|
||||||
|
Href: "myothersite.com.poppycdn.net",
|
||||||
|
Rel: "access_url",
|
||||||
|
},
|
||||||
|
gophercloud.Link{
|
||||||
|
Href: "https://www.poppycdn.io/v1.0/flavors/europe",
|
||||||
|
Rel: "flavor",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
th.CheckDeepEquals(t, expected, actual)
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
})
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
|
||||||
|
if count != 1 {
|
||||||
|
t.Errorf("Expected 1 page, got %d", count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreate(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
|
||||||
|
HandleCreateCDNServiceSuccessfully(t)
|
||||||
|
|
||||||
|
createOpts := CreateOpts{
|
||||||
|
Name: "mywebsite.com",
|
||||||
|
Domains: []Domain{
|
||||||
|
Domain{
|
||||||
|
Domain: "www.mywebsite.com",
|
||||||
|
},
|
||||||
|
Domain{
|
||||||
|
Domain: "blog.mywebsite.com",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Origins: []Origin{
|
||||||
|
Origin{
|
||||||
|
Origin: "mywebsite.com",
|
||||||
|
Port: 80,
|
||||||
|
SSL: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Restrictions: []Restriction{
|
||||||
|
Restriction{
|
||||||
|
Name: "website only",
|
||||||
|
Rules: []RestrictionRule{
|
||||||
|
RestrictionRule{
|
||||||
|
Name: "mywebsite.com",
|
||||||
|
Referrer: "www.mywebsite.com",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Caching: []CacheRule{
|
||||||
|
CacheRule{
|
||||||
|
Name: "default",
|
||||||
|
TTL: 3600,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
FlavorID: "cdn",
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0"
|
||||||
|
actual, err := Create(fake.ServiceClient(), createOpts).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
th.AssertEquals(t, expected, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGet(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
|
||||||
|
HandleGetCDNServiceSuccessfully(t)
|
||||||
|
|
||||||
|
expected := &Service{
|
||||||
|
ID: "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0",
|
||||||
|
Name: "mywebsite.com",
|
||||||
|
Domains: []Domain{
|
||||||
|
Domain{
|
||||||
|
Domain: "www.mywebsite.com",
|
||||||
|
Protocol: "http",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Origins: []Origin{
|
||||||
|
Origin{
|
||||||
|
Origin: "mywebsite.com",
|
||||||
|
Port: 80,
|
||||||
|
SSL: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Caching: []CacheRule{
|
||||||
|
CacheRule{
|
||||||
|
Name: "default",
|
||||||
|
TTL: 3600,
|
||||||
|
},
|
||||||
|
CacheRule{
|
||||||
|
Name: "home",
|
||||||
|
TTL: 17200,
|
||||||
|
Rules: []TTLRule{
|
||||||
|
TTLRule{
|
||||||
|
Name: "index",
|
||||||
|
RequestURL: "/index.htm",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
CacheRule{
|
||||||
|
Name: "images",
|
||||||
|
TTL: 12800,
|
||||||
|
Rules: []TTLRule{
|
||||||
|
TTLRule{
|
||||||
|
Name: "images",
|
||||||
|
RequestURL: "*.png",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Restrictions: []Restriction{
|
||||||
|
Restriction{
|
||||||
|
Name: "website only",
|
||||||
|
Rules: []RestrictionRule{
|
||||||
|
RestrictionRule{
|
||||||
|
Name: "mywebsite.com",
|
||||||
|
Referrer: "www.mywebsite.com",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
FlavorID: "cdn",
|
||||||
|
Status: "deployed",
|
||||||
|
Errors: []Error{},
|
||||||
|
Links: []gophercloud.Link{
|
||||||
|
gophercloud.Link{
|
||||||
|
Href: "https://global.cdn.api.rackspacecloud.com/v1.0/110011/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0",
|
||||||
|
Rel: "self",
|
||||||
|
},
|
||||||
|
gophercloud.Link{
|
||||||
|
Href: "blog.mywebsite.com.cdn1.raxcdn.com",
|
||||||
|
Rel: "access_url",
|
||||||
|
},
|
||||||
|
gophercloud.Link{
|
||||||
|
Href: "https://global.cdn.api.rackspacecloud.com/v1.0/110011/flavors/cdn",
|
||||||
|
Rel: "flavor",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
actual, err := Get(fake.ServiceClient(), "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0").Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
th.AssertDeepEquals(t, expected, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSuccessfulUpdate(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
|
||||||
|
HandleUpdateCDNServiceSuccessfully(t)
|
||||||
|
|
||||||
|
expected := "https://www.poppycdn.io/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0"
|
||||||
|
ops := UpdateOpts{
|
||||||
|
// Append a single Domain
|
||||||
|
Append{Value: Domain{Domain: "appended.mocksite4.com"}},
|
||||||
|
// Insert a single Domain
|
||||||
|
Insertion{
|
||||||
|
Index: 4,
|
||||||
|
Value: Domain{Domain: "inserted.mocksite4.com"},
|
||||||
|
},
|
||||||
|
// Bulk addition
|
||||||
|
Append{
|
||||||
|
Value: DomainList{
|
||||||
|
Domain{Domain: "bulkadded1.mocksite4.com"},
|
||||||
|
Domain{Domain: "bulkadded2.mocksite4.com"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Replace a single Origin
|
||||||
|
Replacement{
|
||||||
|
Index: 2,
|
||||||
|
Value: Origin{Origin: "44.33.22.11", Port: 80, SSL: false},
|
||||||
|
},
|
||||||
|
// Bulk replace Origins
|
||||||
|
Replacement{
|
||||||
|
Index: 0, // Ignored
|
||||||
|
Value: OriginList{
|
||||||
|
Origin{Origin: "44.33.22.11", Port: 80, SSL: false},
|
||||||
|
Origin{Origin: "55.44.33.22", Port: 443, SSL: true},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Remove a single CacheRule
|
||||||
|
Removal{
|
||||||
|
Index: 8,
|
||||||
|
Path: PathCaching,
|
||||||
|
},
|
||||||
|
// Bulk removal
|
||||||
|
Removal{
|
||||||
|
All: true,
|
||||||
|
Path: PathCaching,
|
||||||
|
},
|
||||||
|
// Service name replacement
|
||||||
|
NameReplacement{
|
||||||
|
NewName: "differentServiceName",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
actual, err := Update(fake.ServiceClient(), "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0", ops).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
th.AssertEquals(t, expected, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDelete(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
|
||||||
|
HandleDeleteCDNServiceSuccessfully(t)
|
||||||
|
|
||||||
|
err := Delete(fake.ServiceClient(), "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0").ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
}
|
316
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/services/results.go
generated
vendored
Normal file
316
Godeps/_workspace/src/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
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/cdn/v1/services/urls.go
generated
vendored
Normal file
23
Godeps/_workspace/src/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)
|
||||||
|
}
|
|
@ -68,7 +68,7 @@ func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOp
|
||||||
&utils.Version{ID: v30, Priority: 30, Suffix: "/v3/"},
|
&utils.Version{ID: v30, Priority: 30, Suffix: "/v3/"},
|
||||||
}
|
}
|
||||||
|
|
||||||
chosen, endpoint, err := utils.ChooseVersion(client.IdentityBase, client.IdentityEndpoint, versions)
|
chosen, endpoint, err := utils.ChooseVersion(client, versions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -107,6 +107,11 @@ func v2auth(client *gophercloud.ProviderClient, endpoint string, options gopherc
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if options.AllowReauth {
|
||||||
|
client.ReauthFunc = func() error {
|
||||||
|
return AuthenticateV2(client, options)
|
||||||
|
}
|
||||||
|
}
|
||||||
client.TokenID = token.ID
|
client.TokenID = token.ID
|
||||||
client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
|
client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
|
||||||
return V2EndpointURL(catalog, opts)
|
return V2EndpointURL(catalog, opts)
|
||||||
|
@ -133,6 +138,11 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, options gopherc
|
||||||
}
|
}
|
||||||
client.TokenID = token.ID
|
client.TokenID = token.ID
|
||||||
|
|
||||||
|
if options.AllowReauth {
|
||||||
|
client.ReauthFunc = func() error {
|
||||||
|
return AuthenticateV3(client, options)
|
||||||
|
}
|
||||||
|
}
|
||||||
client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
|
client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
|
||||||
return V3EndpointURL(v3Client, opts)
|
return V3EndpointURL(v3Client, opts)
|
||||||
}
|
}
|
||||||
|
@ -203,3 +213,24 @@ func NewBlockStorageV1(client *gophercloud.ProviderClient, eo gophercloud.Endpoi
|
||||||
}
|
}
|
||||||
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package extensions
|
package extensions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/racker/perigee"
|
|
||||||
"github.com/rackspace/gophercloud"
|
"github.com/rackspace/gophercloud"
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
)
|
)
|
||||||
|
@ -9,10 +8,9 @@ import (
|
||||||
// Get retrieves information for a specific extension using its alias.
|
// Get retrieves information for a specific extension using its alias.
|
||||||
func Get(c *gophercloud.ServiceClient, alias string) GetResult {
|
func Get(c *gophercloud.ServiceClient, alias string) GetResult {
|
||||||
var res GetResult
|
var res GetResult
|
||||||
_, res.Err = perigee.Request("GET", ExtensionURL(c, alias), perigee.Options{
|
_, res.Err = c.Request("GET", ExtensionURL(c, alias), gophercloud.RequestOpts{
|
||||||
MoreHeaders: c.AuthenticatedHeaders(),
|
JSONResponse: &res.Body,
|
||||||
Results: &res.Body,
|
OkCodes: []int{200},
|
||||||
OkCodes: []int{200},
|
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,6 @@ import (
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud"
|
"github.com/rackspace/gophercloud"
|
||||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||||
|
|
||||||
"github.com/racker/perigee"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// SourceType represents the type of medium being used to create the volume.
|
// SourceType represents the type of medium being used to create the volume.
|
||||||
|
@ -101,11 +99,10 @@ func Create(client *gophercloud.ServiceClient, opts servers.CreateOptsBuilder) s
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
_, res.Err = perigee.Request("POST", createURL(client), perigee.Options{
|
_, res.Err = client.Request("POST", createURL(client), gophercloud.RequestOpts{
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
JSONBody: reqBody,
|
||||||
ReqBody: reqBody,
|
JSONResponse: &res.Body,
|
||||||
Results: &res.Body,
|
OkCodes: []int{200, 202},
|
||||||
OkCodes: []int{200, 202},
|
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,6 @@ package defsecrules
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/racker/perigee"
|
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud"
|
"github.com/rackspace/gophercloud"
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
)
|
)
|
||||||
|
@ -75,11 +73,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
_, result.Err = perigee.Request("POST", rootURL(client), perigee.Options{
|
_, result.Err = client.Request("POST", rootURL(client), gophercloud.RequestOpts{
|
||||||
Results: &result.Body,
|
JSONResponse: &result.Body,
|
||||||
ReqBody: &reqBody,
|
JSONBody: &reqBody,
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
OkCodes: []int{200},
|
||||||
OkCodes: []int{200},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -89,10 +86,9 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
|
||||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||||
var result GetResult
|
var result GetResult
|
||||||
|
|
||||||
_, result.Err = perigee.Request("GET", resourceURL(client, id), perigee.Options{
|
_, result.Err = client.Request("GET", resourceURL(client, id), gophercloud.RequestOpts{
|
||||||
Results: &result.Body,
|
JSONResponse: &result.Body,
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
OkCodes: []int{200},
|
||||||
OkCodes: []int{200},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -102,9 +98,8 @@ func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||||
func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
|
func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
|
||||||
var result gophercloud.ErrResult
|
var result gophercloud.ErrResult
|
||||||
|
|
||||||
_, result.Err = perigee.Request("DELETE", resourceURL(client, id), perigee.Options{
|
_, result.Err = client.Request("DELETE", resourceURL(client, id), gophercloud.RequestOpts{
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
OkCodes: []int{204},
|
||||||
OkCodes: []int{204},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
3
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/doc.go
generated
vendored
Normal file
3
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
// Package floatingip provides the ability to manage floating ips through
|
||||||
|
// nova-network
|
||||||
|
package floatingip
|
174
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/fixtures.go
generated
vendored
Normal file
174
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/fixtures.go
generated
vendored
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
// +build fixtures
|
||||||
|
|
||||||
|
package floatingip
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
"github.com/rackspace/gophercloud/testhelper/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListOutput is a sample response to a List call.
|
||||||
|
const ListOutput = `
|
||||||
|
{
|
||||||
|
"floating_ips": [
|
||||||
|
{
|
||||||
|
"fixed_ip": null,
|
||||||
|
"id": 1,
|
||||||
|
"instance_id": null,
|
||||||
|
"ip": "10.10.10.1",
|
||||||
|
"pool": "nova"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fixed_ip": "166.78.185.201",
|
||||||
|
"id": 2,
|
||||||
|
"instance_id": "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
||||||
|
"ip": "10.10.10.2",
|
||||||
|
"pool": "nova"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
// GetOutput is a sample response to a Get call.
|
||||||
|
const GetOutput = `
|
||||||
|
{
|
||||||
|
"floating_ip": {
|
||||||
|
"fixed_ip": "166.78.185.201",
|
||||||
|
"id": 2,
|
||||||
|
"instance_id": "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
||||||
|
"ip": "10.10.10.2",
|
||||||
|
"pool": "nova"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
// CreateOutput is a sample response to a Post call
|
||||||
|
const CreateOutput = `
|
||||||
|
{
|
||||||
|
"floating_ip": {
|
||||||
|
"fixed_ip": null,
|
||||||
|
"id": 1,
|
||||||
|
"instance_id": null,
|
||||||
|
"ip": "10.10.10.1",
|
||||||
|
"pool": "nova"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
// FirstFloatingIP is the first result in ListOutput.
|
||||||
|
var FirstFloatingIP = FloatingIP{
|
||||||
|
ID: "1",
|
||||||
|
IP: "10.10.10.1",
|
||||||
|
Pool: "nova",
|
||||||
|
}
|
||||||
|
|
||||||
|
// SecondFloatingIP is the first result in ListOutput.
|
||||||
|
var SecondFloatingIP = FloatingIP{
|
||||||
|
FixedIP: "166.78.185.201",
|
||||||
|
ID: "2",
|
||||||
|
InstanceID: "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
||||||
|
IP: "10.10.10.2",
|
||||||
|
Pool: "nova",
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpectedFloatingIPsSlice is the slice of results that should be parsed
|
||||||
|
// from ListOutput, in the expected order.
|
||||||
|
var ExpectedFloatingIPsSlice = []FloatingIP{FirstFloatingIP, SecondFloatingIP}
|
||||||
|
|
||||||
|
// CreatedFloatingIP is the parsed result from CreateOutput.
|
||||||
|
var CreatedFloatingIP = FloatingIP{
|
||||||
|
ID: "1",
|
||||||
|
IP: "10.10.10.1",
|
||||||
|
Pool: "nova",
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleListSuccessfully configures the test server to respond to a List request.
|
||||||
|
func HandleListSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/os-floating-ips", 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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleGetSuccessfully configures the test server to respond to a Get request
|
||||||
|
// for an existing floating ip
|
||||||
|
func HandleGetSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/os-floating-ips/2", 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, GetOutput)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleCreateSuccessfully configures the test server to respond to a Create request
|
||||||
|
// for a new floating ip
|
||||||
|
func HandleCreateSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/os-floating-ips", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "POST")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
th.TestJSONRequest(t, r, `
|
||||||
|
{
|
||||||
|
"pool": "nova"
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
w.Header().Add("Content-Type", "application/json")
|
||||||
|
fmt.Fprintf(w, CreateOutput)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleDeleteSuccessfully configures the test server to respond to a Delete request for a
|
||||||
|
// an existing floating ip
|
||||||
|
func HandleDeleteSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/os-floating-ips/1", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "DELETE")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusAccepted)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleAssociateSuccessfully configures the test server to respond to a Post request
|
||||||
|
// to associate an allocated floating IP
|
||||||
|
func HandleAssociateSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/action", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "POST")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
th.TestJSONRequest(t, r, `
|
||||||
|
{
|
||||||
|
"addFloatingIp": {
|
||||||
|
"address": "10.10.10.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusAccepted)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleDisassociateSuccessfully configures the test server to respond to a Post request
|
||||||
|
// to disassociate an allocated floating IP
|
||||||
|
func HandleDisassociateSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/action", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "POST")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
th.TestJSONRequest(t, r, `
|
||||||
|
{
|
||||||
|
"removeFloatingIp": {
|
||||||
|
"address": "10.10.10.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusAccepted)
|
||||||
|
})
|
||||||
|
}
|
105
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/requests.go
generated
vendored
Normal file
105
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/requests.go
generated
vendored
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
package floatingip
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
)
|
||||||
|
|
||||||
|
// List returns a Pager that allows you to iterate over a collection of FloatingIPs.
|
||||||
|
func List(client *gophercloud.ServiceClient) pagination.Pager {
|
||||||
|
return pagination.NewPager(client, listURL(client), func(r pagination.PageResult) pagination.Page {
|
||||||
|
return FloatingIPsPage{pagination.SinglePageBase(r)}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOptsBuilder describes struct types that can be accepted by the Create call. Notable, the
|
||||||
|
// CreateOpts struct in this package does.
|
||||||
|
type CreateOptsBuilder interface {
|
||||||
|
ToFloatingIPCreateMap() (map[string]interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOpts specifies a Floating IP allocation request
|
||||||
|
type CreateOpts struct {
|
||||||
|
// Pool is the pool of floating IPs to allocate one from
|
||||||
|
Pool string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToFloatingIPCreateMap constructs a request body from CreateOpts.
|
||||||
|
func (opts CreateOpts) ToFloatingIPCreateMap() (map[string]interface{}, error) {
|
||||||
|
if opts.Pool == "" {
|
||||||
|
return nil, errors.New("Missing field required for floating IP creation: Pool")
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string]interface{}{"pool": opts.Pool}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create requests the creation of a new floating IP
|
||||||
|
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
|
||||||
|
var res CreateResult
|
||||||
|
|
||||||
|
reqBody, err := opts.ToFloatingIPCreateMap()
|
||||||
|
if err != nil {
|
||||||
|
res.Err = err
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
_, res.Err = client.Request("POST", createURL(client), gophercloud.RequestOpts{
|
||||||
|
JSONBody: reqBody,
|
||||||
|
JSONResponse: &res.Body,
|
||||||
|
OkCodes: []int{200},
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns data about a previously created FloatingIP.
|
||||||
|
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||||
|
var res GetResult
|
||||||
|
_, res.Err = client.Request("GET", getURL(client, id), gophercloud.RequestOpts{
|
||||||
|
JSONResponse: &res.Body,
|
||||||
|
OkCodes: []int{200},
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete requests the deletion of a previous allocated FloatingIP.
|
||||||
|
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
|
||||||
|
var res DeleteResult
|
||||||
|
_, res.Err = client.Request("DELETE", deleteURL(client, id), gophercloud.RequestOpts{
|
||||||
|
OkCodes: []int{202},
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// association / disassociation
|
||||||
|
|
||||||
|
// Associate pairs an allocated floating IP with an instance
|
||||||
|
func Associate(client *gophercloud.ServiceClient, serverId, fip string) AssociateResult {
|
||||||
|
var res AssociateResult
|
||||||
|
|
||||||
|
addFloatingIp := make(map[string]interface{})
|
||||||
|
addFloatingIp["address"] = fip
|
||||||
|
reqBody := map[string]interface{}{"addFloatingIp": addFloatingIp}
|
||||||
|
|
||||||
|
_, res.Err = client.Request("POST", associateURL(client, serverId), gophercloud.RequestOpts{
|
||||||
|
JSONBody: reqBody,
|
||||||
|
OkCodes: []int{202},
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disassociate decouples an allocated floating IP from an instance
|
||||||
|
func Disassociate(client *gophercloud.ServiceClient, serverId, fip string) DisassociateResult {
|
||||||
|
var res DisassociateResult
|
||||||
|
|
||||||
|
removeFloatingIp := make(map[string]interface{})
|
||||||
|
removeFloatingIp["address"] = fip
|
||||||
|
reqBody := map[string]interface{}{"removeFloatingIp": removeFloatingIp}
|
||||||
|
|
||||||
|
_, res.Err = client.Request("POST", disassociateURL(client, serverId), gophercloud.RequestOpts{
|
||||||
|
JSONBody: reqBody,
|
||||||
|
OkCodes: []int{202},
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
80
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/requests_test.go
generated
vendored
Normal file
80
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/requests_test.go
generated
vendored
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
package floatingip
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
"github.com/rackspace/gophercloud/testhelper/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestList(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
HandleListSuccessfully(t)
|
||||||
|
|
||||||
|
count := 0
|
||||||
|
err := List(client.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
|
||||||
|
count++
|
||||||
|
actual, err := ExtractFloatingIPs(page)
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
th.CheckDeepEquals(t, ExpectedFloatingIPsSlice, actual)
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
})
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
th.CheckEquals(t, 1, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreate(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
HandleCreateSuccessfully(t)
|
||||||
|
|
||||||
|
actual, err := Create(client.ServiceClient(), CreateOpts{
|
||||||
|
Pool: "nova",
|
||||||
|
}).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
th.CheckDeepEquals(t, &CreatedFloatingIP, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGet(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
HandleGetSuccessfully(t)
|
||||||
|
|
||||||
|
actual, err := Get(client.ServiceClient(), "2").Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
th.CheckDeepEquals(t, &SecondFloatingIP, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDelete(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
HandleDeleteSuccessfully(t)
|
||||||
|
|
||||||
|
err := Delete(client.ServiceClient(), "1").ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAssociate(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
HandleAssociateSuccessfully(t)
|
||||||
|
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||||
|
fip := "10.10.10.2"
|
||||||
|
|
||||||
|
err := Associate(client.ServiceClient(), serverId, fip).ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDisassociate(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
HandleDisassociateSuccessfully(t)
|
||||||
|
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||||
|
fip := "10.10.10.2"
|
||||||
|
|
||||||
|
err := Disassociate(client.ServiceClient(), serverId, fip).ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
}
|
99
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/results.go
generated
vendored
Normal file
99
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/results.go
generated
vendored
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
package floatingip
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/mitchellh/mapstructure"
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A FloatingIP is an IP that can be associated with an instance
|
||||||
|
type FloatingIP struct {
|
||||||
|
// ID is a unique ID of the Floating IP
|
||||||
|
ID string `mapstructure:"id"`
|
||||||
|
|
||||||
|
// FixedIP is the IP of the instance related to the Floating IP
|
||||||
|
FixedIP string `mapstructure:"fixed_ip,omitempty"`
|
||||||
|
|
||||||
|
// InstanceID is the ID of the instance that is using the Floating IP
|
||||||
|
InstanceID string `mapstructure:"instance_id"`
|
||||||
|
|
||||||
|
// IP is the actual Floating IP
|
||||||
|
IP string `mapstructure:"ip"`
|
||||||
|
|
||||||
|
// Pool is the pool of floating IPs that this floating IP belongs to
|
||||||
|
Pool string `mapstructure:"pool"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// FloatingIPsPage stores a single, only page of FloatingIPs
|
||||||
|
// results from a List call.
|
||||||
|
type FloatingIPsPage struct {
|
||||||
|
pagination.SinglePageBase
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty determines whether or not a FloatingIPsPage is empty.
|
||||||
|
func (page FloatingIPsPage) IsEmpty() (bool, error) {
|
||||||
|
va, err := ExtractFloatingIPs(page)
|
||||||
|
return len(va) == 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtractFloatingIPs interprets a page of results as a slice of
|
||||||
|
// FloatingIPs.
|
||||||
|
func ExtractFloatingIPs(page pagination.Page) ([]FloatingIP, error) {
|
||||||
|
casted := page.(FloatingIPsPage).Body
|
||||||
|
var response struct {
|
||||||
|
FloatingIPs []FloatingIP `mapstructure:"floating_ips"`
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mapstructure.WeakDecode(casted, &response)
|
||||||
|
|
||||||
|
return response.FloatingIPs, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type FloatingIPResult struct {
|
||||||
|
gophercloud.Result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract is a method that attempts to interpret any FloatingIP resource
|
||||||
|
// response as a FloatingIP struct.
|
||||||
|
func (r FloatingIPResult) Extract() (*FloatingIP, error) {
|
||||||
|
if r.Err != nil {
|
||||||
|
return nil, r.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
var res struct {
|
||||||
|
FloatingIP *FloatingIP `json:"floating_ip" mapstructure:"floating_ip"`
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mapstructure.WeakDecode(r.Body, &res)
|
||||||
|
return res.FloatingIP, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateResult is the response from a Create operation. Call its Extract method to interpret it
|
||||||
|
// as a FloatingIP.
|
||||||
|
type CreateResult struct {
|
||||||
|
FloatingIPResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetResult is the response from a Get operation. Call its Extract method to interpret it
|
||||||
|
// as a FloatingIP.
|
||||||
|
type GetResult struct {
|
||||||
|
FloatingIPResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteResult is the response from a Delete operation. Call its Extract method to determine if
|
||||||
|
// the call succeeded or failed.
|
||||||
|
type DeleteResult struct {
|
||||||
|
gophercloud.ErrResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssociateResult is the response from a Delete operation. Call its Extract method to determine if
|
||||||
|
// the call succeeded or failed.
|
||||||
|
type AssociateResult struct {
|
||||||
|
gophercloud.ErrResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisassociateResult is the response from a Delete operation. Call its Extract method to determine if
|
||||||
|
// the call succeeded or failed.
|
||||||
|
type DisassociateResult struct {
|
||||||
|
gophercloud.ErrResult
|
||||||
|
}
|
37
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/urls.go
generated
vendored
Normal file
37
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/urls.go
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
package floatingip
|
||||||
|
|
||||||
|
import "github.com/rackspace/gophercloud"
|
||||||
|
|
||||||
|
const resourcePath = "os-floating-ips"
|
||||||
|
|
||||||
|
func resourceURL(c *gophercloud.ServiceClient) string {
|
||||||
|
return c.ServiceURL(resourcePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func listURL(c *gophercloud.ServiceClient) string {
|
||||||
|
return resourceURL(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createURL(c *gophercloud.ServiceClient) string {
|
||||||
|
return resourceURL(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getURL(c *gophercloud.ServiceClient, id string) string {
|
||||||
|
return c.ServiceURL(resourcePath, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteURL(c *gophercloud.ServiceClient, id string) string {
|
||||||
|
return getURL(c, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func serverURL(c *gophercloud.ServiceClient, serverId string) string {
|
||||||
|
return c.ServiceURL("servers/" + serverId + "/action")
|
||||||
|
}
|
||||||
|
|
||||||
|
func associateURL(c *gophercloud.ServiceClient, serverId string) string {
|
||||||
|
return serverURL(c, serverId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func disassociateURL(c *gophercloud.ServiceClient, serverId string) string {
|
||||||
|
return serverURL(c, serverId)
|
||||||
|
}
|
60
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/urls_test.go
generated
vendored
Normal file
60
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/urls_test.go
generated
vendored
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
package floatingip
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
"github.com/rackspace/gophercloud/testhelper/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestListURL(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
c := client.ServiceClient()
|
||||||
|
|
||||||
|
th.CheckEquals(t, c.Endpoint+"os-floating-ips", listURL(c))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateURL(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
c := client.ServiceClient()
|
||||||
|
|
||||||
|
th.CheckEquals(t, c.Endpoint+"os-floating-ips", createURL(c))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetURL(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
c := client.ServiceClient()
|
||||||
|
id := "1"
|
||||||
|
|
||||||
|
th.CheckEquals(t, c.Endpoint+"os-floating-ips/"+id, getURL(c, id))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDeleteURL(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
c := client.ServiceClient()
|
||||||
|
id := "1"
|
||||||
|
|
||||||
|
th.CheckEquals(t, c.Endpoint+"os-floating-ips/"+id, deleteURL(c, id))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAssociateURL(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
c := client.ServiceClient()
|
||||||
|
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||||
|
|
||||||
|
th.CheckEquals(t, c.Endpoint+"servers/"+serverId+"/action", associateURL(c, serverId))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDisassociateURL(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
c := client.ServiceClient()
|
||||||
|
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||||
|
|
||||||
|
th.CheckEquals(t, c.Endpoint+"servers/"+serverId+"/action", disassociateURL(c, serverId))
|
||||||
|
}
|
|
@ -3,7 +3,6 @@ package keypairs
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/racker/perigee"
|
|
||||||
"github.com/rackspace/gophercloud"
|
"github.com/rackspace/gophercloud"
|
||||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
@ -82,11 +81,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
_, res.Err = perigee.Request("POST", createURL(client), perigee.Options{
|
_, res.Err = client.Request("POST", createURL(client), gophercloud.RequestOpts{
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
JSONBody: reqBody,
|
||||||
ReqBody: reqBody,
|
JSONResponse: &res.Body,
|
||||||
Results: &res.Body,
|
OkCodes: []int{200},
|
||||||
OkCodes: []int{200},
|
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
@ -94,10 +92,9 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
|
||||||
// Get returns public data about a previously uploaded KeyPair.
|
// Get returns public data about a previously uploaded KeyPair.
|
||||||
func Get(client *gophercloud.ServiceClient, name string) GetResult {
|
func Get(client *gophercloud.ServiceClient, name string) GetResult {
|
||||||
var res GetResult
|
var res GetResult
|
||||||
_, res.Err = perigee.Request("GET", getURL(client, name), perigee.Options{
|
_, res.Err = client.Request("GET", getURL(client, name), gophercloud.RequestOpts{
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
JSONResponse: &res.Body,
|
||||||
Results: &res.Body,
|
OkCodes: []int{200},
|
||||||
OkCodes: []int{200},
|
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
@ -105,9 +102,8 @@ func Get(client *gophercloud.ServiceClient, name string) GetResult {
|
||||||
// Delete requests the deletion of a previous stored KeyPair from the server.
|
// Delete requests the deletion of a previous stored KeyPair from the server.
|
||||||
func Delete(client *gophercloud.ServiceClient, name string) DeleteResult {
|
func Delete(client *gophercloud.ServiceClient, name string) DeleteResult {
|
||||||
var res DeleteResult
|
var res DeleteResult
|
||||||
_, res.Err = perigee.Request("DELETE", deleteURL(client, name), perigee.Options{
|
_, res.Err = client.Request("DELETE", deleteURL(client, name), gophercloud.RequestOpts{
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
OkCodes: []int{202},
|
||||||
OkCodes: []int{202},
|
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ func mockListGroupsResponse(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func mockListGroupsByServerResponse(t *testing.T, serverID string) {
|
func mockListGroupsByServerResponse(t *testing.T, serverID string) {
|
||||||
url := fmt.Sprintf("%s/servers/%s%s", rootPath, serverID, rootPath)
|
url := fmt.Sprintf("/servers/%s%s", serverID, rootPath)
|
||||||
th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
|
th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
|
||||||
th.TestMethod(t, r, "GET")
|
th.TestMethod(t, r, "GET")
|
||||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||||
|
|
|
@ -3,8 +3,6 @@ package secgroups
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/racker/perigee"
|
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud"
|
"github.com/rackspace/gophercloud"
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
)
|
)
|
||||||
|
@ -80,11 +78,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
_, result.Err = perigee.Request("POST", rootURL(client), perigee.Options{
|
_, result.Err = client.Request("POST", rootURL(client), gophercloud.RequestOpts{
|
||||||
Results: &result.Body,
|
JSONResponse: &result.Body,
|
||||||
ReqBody: &reqBody,
|
JSONBody: &reqBody,
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
OkCodes: []int{200},
|
||||||
OkCodes: []int{200},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -126,11 +123,10 @@ func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
_, result.Err = perigee.Request("PUT", resourceURL(client, id), perigee.Options{
|
_, result.Err = client.Request("PUT", resourceURL(client, id), gophercloud.RequestOpts{
|
||||||
Results: &result.Body,
|
JSONResponse: &result.Body,
|
||||||
ReqBody: &reqBody,
|
JSONBody: &reqBody,
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
OkCodes: []int{200},
|
||||||
OkCodes: []int{200},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -140,10 +136,9 @@ func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder
|
||||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||||
var result GetResult
|
var result GetResult
|
||||||
|
|
||||||
_, result.Err = perigee.Request("GET", resourceURL(client, id), perigee.Options{
|
_, result.Err = client.Request("GET", resourceURL(client, id), gophercloud.RequestOpts{
|
||||||
Results: &result.Body,
|
JSONResponse: &result.Body,
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
OkCodes: []int{200},
|
||||||
OkCodes: []int{200},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -153,9 +148,8 @@ func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||||
func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
|
func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
|
||||||
var result gophercloud.ErrResult
|
var result gophercloud.ErrResult
|
||||||
|
|
||||||
_, result.Err = perigee.Request("DELETE", resourceURL(client, id), perigee.Options{
|
_, result.Err = client.Request("DELETE", resourceURL(client, id), gophercloud.RequestOpts{
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
OkCodes: []int{202},
|
||||||
OkCodes: []int{202},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -222,7 +216,7 @@ func (opts CreateRuleOpts) ToRuleCreateMap() (map[string]interface{}, error) {
|
||||||
rule["cidr"] = opts.CIDR
|
rule["cidr"] = opts.CIDR
|
||||||
}
|
}
|
||||||
if opts.FromGroupID != "" {
|
if opts.FromGroupID != "" {
|
||||||
rule["from_group_id"] = opts.FromGroupID
|
rule["group_id"] = opts.FromGroupID
|
||||||
}
|
}
|
||||||
|
|
||||||
return map[string]interface{}{"security_group_rule": rule}, nil
|
return map[string]interface{}{"security_group_rule": rule}, nil
|
||||||
|
@ -240,11 +234,10 @@ func CreateRule(client *gophercloud.ServiceClient, opts CreateRuleOptsBuilder) C
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
_, result.Err = perigee.Request("POST", rootRuleURL(client), perigee.Options{
|
_, result.Err = client.Request("POST", rootRuleURL(client), gophercloud.RequestOpts{
|
||||||
Results: &result.Body,
|
JSONResponse: &result.Body,
|
||||||
ReqBody: &reqBody,
|
JSONBody: &reqBody,
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
OkCodes: []int{200},
|
||||||
OkCodes: []int{200},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -254,9 +247,8 @@ func CreateRule(client *gophercloud.ServiceClient, opts CreateRuleOptsBuilder) C
|
||||||
func DeleteRule(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
|
func DeleteRule(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
|
||||||
var result gophercloud.ErrResult
|
var result gophercloud.ErrResult
|
||||||
|
|
||||||
_, result.Err = perigee.Request("DELETE", resourceRuleURL(client, id), perigee.Options{
|
_, result.Err = client.Request("DELETE", resourceRuleURL(client, id), gophercloud.RequestOpts{
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
OkCodes: []int{202},
|
||||||
OkCodes: []int{202},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -273,11 +265,10 @@ func actionMap(prefix, groupName string) map[string]map[string]string {
|
||||||
func AddServerToGroup(client *gophercloud.ServiceClient, serverID, groupName string) gophercloud.ErrResult {
|
func AddServerToGroup(client *gophercloud.ServiceClient, serverID, groupName string) gophercloud.ErrResult {
|
||||||
var result gophercloud.ErrResult
|
var result gophercloud.ErrResult
|
||||||
|
|
||||||
_, result.Err = perigee.Request("POST", serverActionURL(client, serverID), perigee.Options{
|
_, result.Err = client.Request("POST", serverActionURL(client, serverID), gophercloud.RequestOpts{
|
||||||
Results: &result.Body,
|
JSONResponse: &result.Body,
|
||||||
ReqBody: actionMap("add", groupName),
|
JSONBody: actionMap("add", groupName),
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
OkCodes: []int{202},
|
||||||
OkCodes: []int{202},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -287,11 +278,10 @@ func AddServerToGroup(client *gophercloud.ServiceClient, serverID, groupName str
|
||||||
func RemoveServerFromGroup(client *gophercloud.ServiceClient, serverID, groupName string) gophercloud.ErrResult {
|
func RemoveServerFromGroup(client *gophercloud.ServiceClient, serverID, groupName string) gophercloud.ErrResult {
|
||||||
var result gophercloud.ErrResult
|
var result gophercloud.ErrResult
|
||||||
|
|
||||||
_, result.Err = perigee.Request("POST", serverActionURL(client, serverID), perigee.Options{
|
_, result.Err = client.Request("POST", serverActionURL(client, serverID), gophercloud.RequestOpts{
|
||||||
Results: &result.Body,
|
JSONResponse: &result.Body,
|
||||||
ReqBody: actionMap("remove", groupName),
|
JSONBody: actionMap("remove", groupName),
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
OkCodes: []int{202},
|
||||||
OkCodes: []int{202},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -16,7 +16,7 @@ func rootURL(c *gophercloud.ServiceClient) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func listByServerURL(c *gophercloud.ServiceClient, serverID string) string {
|
func listByServerURL(c *gophercloud.ServiceClient, serverID string) string {
|
||||||
return c.ServiceURL(secgrouppath, "servers", serverID, secgrouppath)
|
return c.ServiceURL("servers", serverID, secgrouppath)
|
||||||
}
|
}
|
||||||
|
|
||||||
func rootRuleURL(c *gophercloud.ServiceClient) string {
|
func rootRuleURL(c *gophercloud.ServiceClient) string {
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
package startstop
|
package startstop
|
||||||
|
|
||||||
import (
|
import "github.com/rackspace/gophercloud"
|
||||||
"github.com/racker/perigee"
|
|
||||||
"github.com/rackspace/gophercloud"
|
|
||||||
)
|
|
||||||
|
|
||||||
func actionURL(client *gophercloud.ServiceClient, id string) string {
|
func actionURL(client *gophercloud.ServiceClient, id string) string {
|
||||||
return client.ServiceURL("servers", id, "action")
|
return client.ServiceURL("servers", id, "action")
|
||||||
|
@ -15,10 +12,9 @@ func Start(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
|
||||||
|
|
||||||
reqBody := map[string]interface{}{"os-start": nil}
|
reqBody := map[string]interface{}{"os-start": nil}
|
||||||
|
|
||||||
_, res.Err = perigee.Request("POST", actionURL(client, id), perigee.Options{
|
_, res.Err = client.Request("POST", actionURL(client, id), gophercloud.RequestOpts{
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
JSONBody: reqBody,
|
||||||
ReqBody: reqBody,
|
OkCodes: []int{202},
|
||||||
OkCodes: []int{202},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
@ -30,10 +26,9 @@ func Stop(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
|
||||||
|
|
||||||
reqBody := map[string]interface{}{"os-stop": nil}
|
reqBody := map[string]interface{}{"os-stop": nil}
|
||||||
|
|
||||||
_, res.Err = perigee.Request("POST", actionURL(client, id), perigee.Options{
|
_, res.Err = client.Request("POST", actionURL(client, id), gophercloud.RequestOpts{
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
JSONBody: reqBody,
|
||||||
ReqBody: reqBody,
|
OkCodes: []int{202},
|
||||||
OkCodes: []int{202},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
3
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/doc.go
generated
vendored
Normal file
3
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
// Package volumeattach provides the ability to attach and detach volumes
|
||||||
|
// to instances
|
||||||
|
package volumeattach
|
138
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/fixtures.go
generated
vendored
Normal file
138
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/fixtures.go
generated
vendored
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
// +build fixtures
|
||||||
|
|
||||||
|
package volumeattach
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
"github.com/rackspace/gophercloud/testhelper/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListOutput is a sample response to a List call.
|
||||||
|
const ListOutput = `
|
||||||
|
{
|
||||||
|
"volumeAttachments": [
|
||||||
|
{
|
||||||
|
"device": "/dev/vdd",
|
||||||
|
"id": "a26887c6-c47b-4654-abb5-dfadf7d3f803",
|
||||||
|
"serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
||||||
|
"volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f803"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"device": "/dev/vdc",
|
||||||
|
"id": "a26887c6-c47b-4654-abb5-dfadf7d3f804",
|
||||||
|
"serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
||||||
|
"volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f804"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
// GetOutput is a sample response to a Get call.
|
||||||
|
const GetOutput = `
|
||||||
|
{
|
||||||
|
"volumeAttachment": {
|
||||||
|
"device": "/dev/vdc",
|
||||||
|
"id": "a26887c6-c47b-4654-abb5-dfadf7d3f804",
|
||||||
|
"serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
||||||
|
"volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f804"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
// CreateOutput is a sample response to a Create call.
|
||||||
|
const CreateOutput = `
|
||||||
|
{
|
||||||
|
"volumeAttachment": {
|
||||||
|
"device": "/dev/vdc",
|
||||||
|
"id": "a26887c6-c47b-4654-abb5-dfadf7d3f804",
|
||||||
|
"serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
||||||
|
"volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f804"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
// FirstVolumeAttachment is the first result in ListOutput.
|
||||||
|
var FirstVolumeAttachment = VolumeAttachment{
|
||||||
|
Device: "/dev/vdd",
|
||||||
|
ID: "a26887c6-c47b-4654-abb5-dfadf7d3f803",
|
||||||
|
ServerID: "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
||||||
|
VolumeID: "a26887c6-c47b-4654-abb5-dfadf7d3f803",
|
||||||
|
}
|
||||||
|
|
||||||
|
// SecondVolumeAttachment is the first result in ListOutput.
|
||||||
|
var SecondVolumeAttachment = VolumeAttachment{
|
||||||
|
Device: "/dev/vdc",
|
||||||
|
ID: "a26887c6-c47b-4654-abb5-dfadf7d3f804",
|
||||||
|
ServerID: "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
||||||
|
VolumeID: "a26887c6-c47b-4654-abb5-dfadf7d3f804",
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpectedVolumeAttachmentSlide is the slice of results that should be parsed
|
||||||
|
// from ListOutput, in the expected order.
|
||||||
|
var ExpectedVolumeAttachmentSlice = []VolumeAttachment{FirstVolumeAttachment, SecondVolumeAttachment}
|
||||||
|
|
||||||
|
// CreatedVolumeAttachment is the parsed result from CreatedOutput.
|
||||||
|
var CreatedVolumeAttachment = VolumeAttachment{
|
||||||
|
Device: "/dev/vdc",
|
||||||
|
ID: "a26887c6-c47b-4654-abb5-dfadf7d3f804",
|
||||||
|
ServerID: "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
||||||
|
VolumeID: "a26887c6-c47b-4654-abb5-dfadf7d3f804",
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleListSuccessfully configures the test server to respond to a List request.
|
||||||
|
func HandleListSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/os-volume_attachments", 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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleGetSuccessfully configures the test server to respond to a Get request
|
||||||
|
// for an existing attachment
|
||||||
|
func HandleGetSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/os-volume_attachments/a26887c6-c47b-4654-abb5-dfadf7d3f804", 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, GetOutput)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleCreateSuccessfully configures the test server to respond to a Create request
|
||||||
|
// for a new attachment
|
||||||
|
func HandleCreateSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/os-volume_attachments", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "POST")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
th.TestJSONRequest(t, r, `
|
||||||
|
{
|
||||||
|
"volumeAttachment": {
|
||||||
|
"volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f804",
|
||||||
|
"device": "/dev/vdc"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
w.Header().Add("Content-Type", "application/json")
|
||||||
|
fmt.Fprintf(w, CreateOutput)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleDeleteSuccessfully configures the test server to respond to a Delete request for a
|
||||||
|
// an existing attachment
|
||||||
|
func HandleDeleteSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/os-volume_attachments/a26887c6-c47b-4654-abb5-dfadf7d3f804", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "DELETE")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusAccepted)
|
||||||
|
})
|
||||||
|
}
|
82
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/requests.go
generated
vendored
Normal file
82
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/requests.go
generated
vendored
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
package volumeattach
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
)
|
||||||
|
|
||||||
|
// List returns a Pager that allows you to iterate over a collection of VolumeAttachments.
|
||||||
|
func List(client *gophercloud.ServiceClient, serverId string) pagination.Pager {
|
||||||
|
return pagination.NewPager(client, listURL(client, serverId), func(r pagination.PageResult) pagination.Page {
|
||||||
|
return VolumeAttachmentsPage{pagination.SinglePageBase(r)}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOptsBuilder describes struct types that can be accepted by the Create call. Notable, the
|
||||||
|
// CreateOpts struct in this package does.
|
||||||
|
type CreateOptsBuilder interface {
|
||||||
|
ToVolumeAttachmentCreateMap() (map[string]interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOpts specifies volume attachment creation or import parameters.
|
||||||
|
type CreateOpts struct {
|
||||||
|
// Device is the device that the volume will attach to the instance as. Omit for "auto"
|
||||||
|
Device string
|
||||||
|
|
||||||
|
// VolumeID is the ID of the volume to attach to the instance
|
||||||
|
VolumeID string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToVolumeAttachmentCreateMap constructs a request body from CreateOpts.
|
||||||
|
func (opts CreateOpts) ToVolumeAttachmentCreateMap() (map[string]interface{}, error) {
|
||||||
|
if opts.VolumeID == "" {
|
||||||
|
return nil, errors.New("Missing field required for volume attachment creation: VolumeID")
|
||||||
|
}
|
||||||
|
|
||||||
|
volumeAttachment := make(map[string]interface{})
|
||||||
|
volumeAttachment["volumeId"] = opts.VolumeID
|
||||||
|
if opts.Device != "" {
|
||||||
|
volumeAttachment["device"] = opts.Device
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string]interface{}{"volumeAttachment": volumeAttachment}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create requests the creation of a new volume attachment on the server
|
||||||
|
func Create(client *gophercloud.ServiceClient, serverId string, opts CreateOptsBuilder) CreateResult {
|
||||||
|
var res CreateResult
|
||||||
|
|
||||||
|
reqBody, err := opts.ToVolumeAttachmentCreateMap()
|
||||||
|
if err != nil {
|
||||||
|
res.Err = err
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
_, res.Err = client.Request("POST", createURL(client, serverId), gophercloud.RequestOpts{
|
||||||
|
JSONBody: reqBody,
|
||||||
|
JSONResponse: &res.Body,
|
||||||
|
OkCodes: []int{200},
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns public data about a previously created VolumeAttachment.
|
||||||
|
func Get(client *gophercloud.ServiceClient, serverId, aId string) GetResult {
|
||||||
|
var res GetResult
|
||||||
|
_, res.Err = client.Request("GET", getURL(client, serverId, aId), gophercloud.RequestOpts{
|
||||||
|
JSONResponse: &res.Body,
|
||||||
|
OkCodes: []int{200},
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete requests the deletion of a previous stored VolumeAttachment from the server.
|
||||||
|
func Delete(client *gophercloud.ServiceClient, serverId, aId string) DeleteResult {
|
||||||
|
var res DeleteResult
|
||||||
|
_, res.Err = client.Request("DELETE", deleteURL(client, serverId, aId), gophercloud.RequestOpts{
|
||||||
|
OkCodes: []int{202},
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
65
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/requests_test.go
generated
vendored
Normal file
65
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/requests_test.go
generated
vendored
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
package volumeattach
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
"github.com/rackspace/gophercloud/testhelper/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestList(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
HandleListSuccessfully(t)
|
||||||
|
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||||
|
|
||||||
|
count := 0
|
||||||
|
err := List(client.ServiceClient(), serverId).EachPage(func(page pagination.Page) (bool, error) {
|
||||||
|
count++
|
||||||
|
actual, err := ExtractVolumeAttachments(page)
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
th.CheckDeepEquals(t, ExpectedVolumeAttachmentSlice, actual)
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
})
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
th.CheckEquals(t, 1, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreate(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
HandleCreateSuccessfully(t)
|
||||||
|
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||||
|
|
||||||
|
actual, err := Create(client.ServiceClient(), serverId, CreateOpts{
|
||||||
|
Device: "/dev/vdc",
|
||||||
|
VolumeID: "a26887c6-c47b-4654-abb5-dfadf7d3f804",
|
||||||
|
}).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
th.CheckDeepEquals(t, &CreatedVolumeAttachment, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGet(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
HandleGetSuccessfully(t)
|
||||||
|
aId := "a26887c6-c47b-4654-abb5-dfadf7d3f804"
|
||||||
|
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||||
|
|
||||||
|
actual, err := Get(client.ServiceClient(), serverId, aId).Extract()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
th.CheckDeepEquals(t, &SecondVolumeAttachment, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDelete(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
HandleDeleteSuccessfully(t)
|
||||||
|
aId := "a26887c6-c47b-4654-abb5-dfadf7d3f804"
|
||||||
|
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||||
|
|
||||||
|
err := Delete(client.ServiceClient(), serverId, aId).ExtractErr()
|
||||||
|
th.AssertNoErr(t, err)
|
||||||
|
}
|
84
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/results.go
generated
vendored
Normal file
84
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/results.go
generated
vendored
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
package volumeattach
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/mitchellh/mapstructure"
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
)
|
||||||
|
|
||||||
|
// VolumeAttach controls the attachment of a volume to an instance.
|
||||||
|
type VolumeAttachment struct {
|
||||||
|
// ID is a unique id of the attachment
|
||||||
|
ID string `mapstructure:"id"`
|
||||||
|
|
||||||
|
// Device is what device the volume is attached as
|
||||||
|
Device string `mapstructure:"device"`
|
||||||
|
|
||||||
|
// VolumeID is the ID of the attached volume
|
||||||
|
VolumeID string `mapstructure:"volumeId"`
|
||||||
|
|
||||||
|
// ServerID is the ID of the instance that has the volume attached
|
||||||
|
ServerID string `mapstructure:"serverId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// VolumeAttachmentsPage stores a single, only page of VolumeAttachments
|
||||||
|
// results from a List call.
|
||||||
|
type VolumeAttachmentsPage struct {
|
||||||
|
pagination.SinglePageBase
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty determines whether or not a VolumeAttachmentsPage is empty.
|
||||||
|
func (page VolumeAttachmentsPage) IsEmpty() (bool, error) {
|
||||||
|
va, err := ExtractVolumeAttachments(page)
|
||||||
|
return len(va) == 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtractVolumeAttachments interprets a page of results as a slice of
|
||||||
|
// VolumeAttachments.
|
||||||
|
func ExtractVolumeAttachments(page pagination.Page) ([]VolumeAttachment, error) {
|
||||||
|
casted := page.(VolumeAttachmentsPage).Body
|
||||||
|
var response struct {
|
||||||
|
VolumeAttachments []VolumeAttachment `mapstructure:"volumeAttachments"`
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mapstructure.WeakDecode(casted, &response)
|
||||||
|
|
||||||
|
return response.VolumeAttachments, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type VolumeAttachmentResult struct {
|
||||||
|
gophercloud.Result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract is a method that attempts to interpret any VolumeAttachment resource
|
||||||
|
// response as a VolumeAttachment struct.
|
||||||
|
func (r VolumeAttachmentResult) Extract() (*VolumeAttachment, error) {
|
||||||
|
if r.Err != nil {
|
||||||
|
return nil, r.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
var res struct {
|
||||||
|
VolumeAttachment *VolumeAttachment `json:"volumeAttachment" mapstructure:"volumeAttachment"`
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mapstructure.Decode(r.Body, &res)
|
||||||
|
return res.VolumeAttachment, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateResult is the response from a Create operation. Call its Extract method to interpret it
|
||||||
|
// as a VolumeAttachment.
|
||||||
|
type CreateResult struct {
|
||||||
|
VolumeAttachmentResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetResult is the response from a Get operation. Call its Extract method to interpret it
|
||||||
|
// as a VolumeAttachment.
|
||||||
|
type GetResult struct {
|
||||||
|
VolumeAttachmentResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteResult is the response from a Delete operation. Call its Extract method to determine if
|
||||||
|
// the call succeeded or failed.
|
||||||
|
type DeleteResult struct {
|
||||||
|
gophercloud.ErrResult
|
||||||
|
}
|
25
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/urls.go
generated
vendored
Normal file
25
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/urls.go
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
package volumeattach
|
||||||
|
|
||||||
|
import "github.com/rackspace/gophercloud"
|
||||||
|
|
||||||
|
const resourcePath = "os-volume_attachments"
|
||||||
|
|
||||||
|
func resourceURL(c *gophercloud.ServiceClient, serverId string) string {
|
||||||
|
return c.ServiceURL("servers", serverId, resourcePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func listURL(c *gophercloud.ServiceClient, serverId string) string {
|
||||||
|
return resourceURL(c, serverId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createURL(c *gophercloud.ServiceClient, serverId string) string {
|
||||||
|
return resourceURL(c, serverId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getURL(c *gophercloud.ServiceClient, serverId, aId string) string {
|
||||||
|
return c.ServiceURL("servers", serverId, resourcePath, aId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteURL(c *gophercloud.ServiceClient, serverId, aId string) string {
|
||||||
|
return getURL(c, serverId, aId)
|
||||||
|
}
|
46
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/urls_test.go
generated
vendored
Normal file
46
Godeps/_workspace/src/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/urls_test.go
generated
vendored
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
package volumeattach
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
"github.com/rackspace/gophercloud/testhelper/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestListURL(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
c := client.ServiceClient()
|
||||||
|
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||||
|
|
||||||
|
th.CheckEquals(t, c.Endpoint+"servers/"+serverId+"/os-volume_attachments", listURL(c, serverId))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateURL(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
c := client.ServiceClient()
|
||||||
|
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||||
|
|
||||||
|
th.CheckEquals(t, c.Endpoint+"servers/"+serverId+"/os-volume_attachments", createURL(c, serverId))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetURL(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
c := client.ServiceClient()
|
||||||
|
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||||
|
aId := "a26887c6-c47b-4654-abb5-dfadf7d3f804"
|
||||||
|
|
||||||
|
th.CheckEquals(t, c.Endpoint+"servers/"+serverId+"/os-volume_attachments/"+aId, getURL(c, serverId, aId))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDeleteURL(t *testing.T) {
|
||||||
|
th.SetupHTTP()
|
||||||
|
defer th.TeardownHTTP()
|
||||||
|
c := client.ServiceClient()
|
||||||
|
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||||
|
aId := "a26887c6-c47b-4654-abb5-dfadf7d3f804"
|
||||||
|
|
||||||
|
th.CheckEquals(t, c.Endpoint+"servers/"+serverId+"/os-volume_attachments/"+aId, deleteURL(c, serverId, aId))
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
package flavors
|
package flavors
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/racker/perigee"
|
|
||||||
"github.com/rackspace/gophercloud"
|
"github.com/rackspace/gophercloud"
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
)
|
)
|
||||||
|
@ -64,9 +63,8 @@ func ListDetail(client *gophercloud.ServiceClient, opts ListOptsBuilder) paginat
|
||||||
// Use ExtractFlavor to convert its result into a Flavor.
|
// Use ExtractFlavor to convert its result into a Flavor.
|
||||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||||
var gr GetResult
|
var gr GetResult
|
||||||
gr.Err = perigee.Get(getURL(client, id), perigee.Options{
|
_, gr.Err = client.Request("GET", getURL(client, id), gophercloud.RequestOpts{
|
||||||
Results: &gr.Body,
|
JSONResponse: &gr.Body,
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
|
||||||
})
|
})
|
||||||
return gr
|
return gr
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,6 @@ package images
|
||||||
import (
|
import (
|
||||||
"github.com/rackspace/gophercloud"
|
"github.com/rackspace/gophercloud"
|
||||||
"github.com/rackspace/gophercloud/pagination"
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
|
||||||
"github.com/racker/perigee"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ListOptsBuilder allows extensions to add additional parameters to the
|
// ListOptsBuilder allows extensions to add additional parameters to the
|
||||||
|
@ -22,7 +20,7 @@ type ListOpts struct {
|
||||||
// UUID of the Image at which to set a marker.
|
// UUID of the Image at which to set a marker.
|
||||||
Marker string `q:"marker"`
|
Marker string `q:"marker"`
|
||||||
// The name of the Image.
|
// The name of the Image.
|
||||||
Name string `q:"name:"`
|
Name string `q:"name"`
|
||||||
// The name of the Server (in URL format).
|
// The name of the Server (in URL format).
|
||||||
Server string `q:"server"`
|
Server string `q:"server"`
|
||||||
// The current status of the Image.
|
// The current status of the Image.
|
||||||
|
@ -62,10 +60,9 @@ func ListDetail(client *gophercloud.ServiceClient, opts ListOptsBuilder) paginat
|
||||||
// Use ExtractImage() to interpret the result as an openstack Image.
|
// Use ExtractImage() to interpret the result as an openstack Image.
|
||||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||||
var result GetResult
|
var result GetResult
|
||||||
_, result.Err = perigee.Request("GET", getURL(client, id), perigee.Options{
|
_, result.Err = client.Request("GET", getURL(client, id), gophercloud.RequestOpts{
|
||||||
MoreHeaders: client.AuthenticatedHeaders(),
|
JSONResponse: &result.Body,
|
||||||
Results: &result.Body,
|
OkCodes: []int{200},
|
||||||
OkCodes: []int{200},
|
|
||||||
})
|
})
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue