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",
|
||||
"Rev": "740c764bc6149d3f1806231418adb9f52c11bcbf"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/racker/perigee",
|
||||
"Comment": "v0.0.0-18-g0c00cb0",
|
||||
"Rev": "0c00cb0a026b71034ebc8205263c77dad3577db5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/rackspace/gophercloud",
|
||||
"Comment": "v1.0.0-232-g2e7ab37",
|
||||
"Rev": "2e7ab378257b8723e02cbceac7410be4db286436"
|
||||
"Comment": "v1.0.0-473-g7ca169d",
|
||||
"Rev": "7ca169d371b29e3dbab9e631c3a6151896b06330"
|
||||
},
|
||||
{
|
||||
"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:
|
||||
- 1.1
|
||||
- 1.2
|
||||
- 1.3
|
||||
- 1.4
|
||||
- tip
|
||||
script: script/cibuild
|
||||
after_success:
|
||||
|
@ -12,3 +14,4 @@ after_success:
|
|||
- go get github.com/mattn/goveralls
|
||||
- export PATH=$PATH:$HOME/gopath/bin/
|
||||
- goveralls 2k7PTU3xa474Hymwgdj6XjqenNfGTNkO8
|
||||
sudo: false
|
||||
|
|
|
@ -10,3 +10,4 @@ Contributors
|
|||
| Ash Wilson | <ash.wilson@rackspace.com>
|
||||
| Jamie Hannaford | <jamie.hannaford@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.
|
||||
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 func() {
|
||||
|
@ -29,11 +32,14 @@ func TestAccounts(t *testing.T) {
|
|||
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.
|
||||
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)
|
||||
for k := range metadata {
|
||||
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()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Created server: %+v\n", server)
|
||||
//defer deleteServer(t, client, server)
|
||||
t.Logf("Deleting server [%s]...", name)
|
||||
defer deleteServer(t, client, server)
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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) {
|
||||
t.Logf("> servers.List")
|
||||
|
||||
|
@ -197,6 +209,7 @@ func TestServerOperations(t *testing.T) {
|
|||
defer deleteServer(t, client, server)
|
||||
|
||||
getServer(t, client, server)
|
||||
updateServer(t, client, server)
|
||||
listServers(t, client)
|
||||
changeAdminPassword(t, client, server)
|
||||
rebootServer(t, client, server)
|
||||
|
|
|
@ -13,11 +13,11 @@ func TestAccounts(t *testing.T) {
|
|||
c, err := createClient(t, false)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
updateres := raxAccounts.Update(c, raxAccounts.UpdateOpts{Metadata: map[string]string{"white": "mountains"}})
|
||||
th.AssertNoErr(t, updateres.Err)
|
||||
t.Logf("Headers from Update Account request: %+v\n", updateres.Header)
|
||||
updateHeaders, err := raxAccounts.Update(c, raxAccounts.UpdateOpts{Metadata: map[string]string{"white": "mountains"}}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Update Account Response Headers: %+v\n", updateHeaders)
|
||||
defer func() {
|
||||
updateres = raxAccounts.Update(c, raxAccounts.UpdateOpts{Metadata: map[string]string{"white": ""}})
|
||||
updateres := raxAccounts.Update(c, raxAccounts.UpdateOpts{Metadata: map[string]string{"white": ""}})
|
||||
th.AssertNoErr(t, updateres.Err)
|
||||
metadata, err := raxAccounts.Get(c).ExtractMetadata()
|
||||
th.AssertNoErr(t, err)
|
||||
|
@ -25,8 +25,13 @@ func TestAccounts(t *testing.T) {
|
|||
th.CheckEquals(t, metadata["White"], "")
|
||||
}()
|
||||
|
||||
metadata, err := raxAccounts.Get(c).ExtractMetadata()
|
||||
th.AssertNoErr(t, err)
|
||||
getResp := raxAccounts.Get(c)
|
||||
th.AssertNoErr(t, getResp.Err)
|
||||
|
||||
getHeaders, _ := getResp.Extract()
|
||||
t.Logf("Get Account Response Headers: %+v\n", getHeaders)
|
||||
|
||||
metadata, _ := getResp.ExtractMetadata()
|
||||
t.Logf("Metadata from Get Account request (after update): %+v\n", metadata)
|
||||
|
||||
th.CheckEquals(t, metadata["White"], "mountains")
|
||||
|
|
|
@ -26,10 +26,11 @@ func TestCDNContainers(t *testing.T) {
|
|||
|
||||
raxCDNClient, err := createClient(t, true)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
r := raxCDNContainers.Enable(raxCDNClient, "gophercloud-test", raxCDNContainers.EnableOpts{CDNEnabled: true, TTL: 900})
|
||||
th.AssertNoErr(t, r.Err)
|
||||
t.Logf("Headers from Enable CDN Container request: %+v\n", r.Header)
|
||||
enableRes := raxCDNContainers.Enable(raxCDNClient, "gophercloud-test", raxCDNContainers.EnableOpts{CDNEnabled: true, TTL: 900})
|
||||
t.Logf("Header map from Enable CDN Container request: %+v\n", enableRes.Header)
|
||||
enableHeader, err := enableRes.Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Headers from Enable CDN Container request: %+v\n", enableHeader)
|
||||
|
||||
t.Logf("Container Names available to the currently issued token:")
|
||||
count := 0
|
||||
|
@ -51,11 +52,15 @@ func TestCDNContainers(t *testing.T) {
|
|||
t.Errorf("No CDN containers listed for your current token.")
|
||||
}
|
||||
|
||||
updateres := raxCDNContainers.Update(raxCDNClient, "gophercloud-test", raxCDNContainers.UpdateOpts{CDNEnabled: false})
|
||||
th.AssertNoErr(t, updateres.Err)
|
||||
t.Logf("Headers from Update CDN Container request: %+v\n", updateres.Header)
|
||||
|
||||
metadata, err := raxCDNContainers.Get(raxCDNClient, "gophercloud-test").ExtractMetadata()
|
||||
updateOpts := raxCDNContainers.UpdateOpts{XCDNEnabled: raxCDNContainers.Disabled, XLogRetention: raxCDNContainers.Enabled}
|
||||
updateHeader, err := raxCDNContainers.Update(raxCDNClient, "gophercloud-test", updateOpts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Headers from Get CDN Container request (after update): %+v\n", metadata)
|
||||
t.Logf("Headers from Update CDN Container request: %+v\n", updateHeader)
|
||||
|
||||
getRes := raxCDNContainers.Get(raxCDNClient, "gophercloud-test")
|
||||
getHeader, err := getRes.Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Headers from Get CDN Container request (after update): %+v\n", getHeader)
|
||||
metadata, err := getRes.ExtractMetadata()
|
||||
t.Logf("Metadata from Get CDN Container request (after update): %+v\n", metadata)
|
||||
}
|
||||
|
|
|
@ -36,11 +36,15 @@ func TestCDNObjects(t *testing.T) {
|
|||
raxCDNClient, err := createClient(t, true)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
enableResult := raxCDNContainers.Enable(raxCDNClient, "gophercloud-test", raxCDNContainers.EnableOpts{CDNEnabled: true, TTL: 900})
|
||||
th.AssertNoErr(t, enableResult.Err)
|
||||
t.Logf("Headers from Enable CDN Container request: %+v\n", enableResult.Header)
|
||||
enableHeader, err := raxCDNContainers.Enable(raxCDNClient, "gophercloud-test", raxCDNContainers.EnableOpts{CDNEnabled: true, TTL: 900}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Headers from Enable CDN Container request: %+v\n", enableHeader)
|
||||
|
||||
deleteResult := raxCDNObjects.Delete(raxCDNClient, "gophercloud-test", "test-object", nil)
|
||||
th.AssertNoErr(t, deleteResult.Err)
|
||||
t.Logf("Headers from Delete CDN Object request: %+v\n", deleteResult.Err)
|
||||
objCDNURL, err := raxCDNObjects.CDNURL(raxCDNClient, "gophercloud-test", "test-object")
|
||||
th.AssertNoErr(t, 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.")
|
||||
}
|
||||
|
||||
createres := raxContainers.Create(c, "gophercloud-test", nil)
|
||||
th.AssertNoErr(t, createres.Err)
|
||||
createHeader, err := raxContainers.Create(c, "gophercloud-test", nil).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Headers from Create Container request: %+v\n", createHeader)
|
||||
defer func() {
|
||||
res := raxContainers.Delete(c, "gophercloud-test")
|
||||
th.AssertNoErr(t, res.Err)
|
||||
deleteres := raxContainers.Delete(c, "gophercloud-test")
|
||||
deleteHeader, err := deleteres.Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Headers from Delete Container request: %+v\n", deleteres.Header)
|
||||
t.Logf("Headers from Delete Container request: %+v\n", deleteHeader)
|
||||
}()
|
||||
|
||||
updateres := raxContainers.Update(c, "gophercloud-test", raxContainers.UpdateOpts{Metadata: map[string]string{"white": "mountains"}})
|
||||
th.AssertNoErr(t, updateres.Err)
|
||||
t.Logf("Headers from Update Account request: %+v\n", updateres.Header)
|
||||
updateHeader, err := raxContainers.Update(c, "gophercloud-test", raxContainers.UpdateOpts{Metadata: map[string]string{"white": "mountains"}}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Headers from Update Container request: %+v\n", updateHeader)
|
||||
defer func() {
|
||||
res := raxContainers.Update(c, "gophercloud-test", raxContainers.UpdateOpts{Metadata: map[string]string{"white": ""}})
|
||||
th.AssertNoErr(t, res.Err)
|
||||
metadata, err := raxContainers.Get(c, "gophercloud-test").ExtractMetadata()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Metadata from Get Account request (after update reverted): %+v\n", metadata)
|
||||
t.Logf("Metadata from Get Container request (after update reverted): %+v\n", metadata)
|
||||
th.CheckEquals(t, metadata["White"], "")
|
||||
}()
|
||||
|
||||
getres := raxContainers.Get(c, "gophercloud-test")
|
||||
t.Logf("Headers from Get Account request (after update): %+v\n", getres.Header)
|
||||
metadata, err := getres.ExtractMetadata()
|
||||
getHeader, err := getres.Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Metadata from Get Account request (after update): %+v\n", metadata)
|
||||
t.Logf("Headers from Get Container request (after update): %+v\n", getHeader)
|
||||
metadata, err := getres.ExtractMetadata()
|
||||
t.Logf("Metadata from Get Container request (after update): %+v\n", metadata)
|
||||
th.CheckEquals(t, metadata["White"], "mountains")
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ func TestObjects(t *testing.T) {
|
|||
th.AssertNoErr(t, res.Err)
|
||||
|
||||
defer func() {
|
||||
t.Logf("Deleting container...")
|
||||
res := raxContainers.Delete(c, "gophercloud-test")
|
||||
th.AssertNoErr(t, res.Err)
|
||||
}()
|
||||
|
@ -29,7 +30,9 @@ func TestObjects(t *testing.T) {
|
|||
options := &osObjects.CreateOpts{ContentType: "text/plain"}
|
||||
createres := raxObjects.Create(c, "gophercloud-test", "o1", content, options)
|
||||
th.AssertNoErr(t, createres.Err)
|
||||
|
||||
defer func() {
|
||||
t.Logf("Deleting object o1...")
|
||||
res := raxObjects.Delete(c, "gophercloud-test", "o1", nil)
|
||||
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"})
|
||||
th.AssertNoErr(t, copyres.Err)
|
||||
defer func() {
|
||||
t.Logf("Deleting object o2...")
|
||||
res := raxObjects.Delete(c, "gophercloud-test", "o2", nil)
|
||||
th.AssertNoErr(t, res.Err)
|
||||
}()
|
||||
|
@ -99,7 +103,7 @@ func TestObjects(t *testing.T) {
|
|||
metadata, err := raxObjects.Get(c, "gophercloud-test", "o2", nil).ExtractMetadata()
|
||||
th.AssertNoErr(t, err)
|
||||
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)
|
||||
|
@ -108,5 +112,13 @@ func TestObjects(t *testing.T) {
|
|||
metadata, err := getres.ExtractMetadata()
|
||||
th.AssertNoErr(t, err)
|
||||
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
|
||||
// false, it will not cache these settings, but re-authentication will not be
|
||||
// possible. This setting defaults to false.
|
||||
//
|
||||
// This setting is speculative and is currently not respected!
|
||||
AllowReauth bool
|
||||
}
|
||||
|
|
|
@ -3,8 +3,6 @@ package apiversions
|
|||
import (
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
|
||||
"github.com/racker/perigee"
|
||||
)
|
||||
|
||||
// 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.
|
||||
func Get(client *gophercloud.ServiceClient, v string) GetResult {
|
||||
var res GetResult
|
||||
_, err := perigee.Request("GET", getURL(client, v), perigee.Options{
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{200},
|
||||
Results: &res.Body,
|
||||
_, res.Err = client.Request("GET", getURL(client, v), gophercloud.RequestOpts{
|
||||
OkCodes: []int{200},
|
||||
JSONResponse: &res.Body,
|
||||
})
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
|
|
@ -5,8 +5,6 @@ import (
|
|||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
|
||||
"github.com/racker/perigee"
|
||||
)
|
||||
|
||||
// CreateOptsBuilder allows extensions to add additional parameters to the
|
||||
|
@ -69,11 +67,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
|
|||
return res
|
||||
}
|
||||
|
||||
_, res.Err = perigee.Request("POST", createURL(client), perigee.Options{
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{200, 201},
|
||||
ReqBody: &reqBody,
|
||||
Results: &res.Body,
|
||||
_, res.Err = client.Request("POST", createURL(client), gophercloud.RequestOpts{
|
||||
OkCodes: []int{200, 201},
|
||||
JSONBody: &reqBody,
|
||||
JSONResponse: &res.Body,
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
@ -81,9 +78,8 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
|
|||
// Delete will delete the existing Snapshot with the provided ID.
|
||||
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
|
||||
var res DeleteResult
|
||||
_, res.Err = perigee.Request("DELETE", deleteURL(client, id), perigee.Options{
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{202, 204},
|
||||
_, res.Err = client.Request("DELETE", deleteURL(client, id), gophercloud.RequestOpts{
|
||||
OkCodes: []int{202, 204},
|
||||
})
|
||||
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.
|
||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||
var res GetResult
|
||||
_, res.Err = perigee.Request("GET", getURL(client, id), perigee.Options{
|
||||
Results: &res.Body,
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{200},
|
||||
_, res.Err = client.Request("GET", getURL(client, id), gophercloud.RequestOpts{
|
||||
OkCodes: []int{200},
|
||||
JSONResponse: &res.Body,
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
@ -178,11 +173,10 @@ func UpdateMetadata(client *gophercloud.ServiceClient, id string, opts UpdateMet
|
|||
return res
|
||||
}
|
||||
|
||||
_, res.Err = perigee.Request("PUT", updateMetadataURL(client, id), perigee.Options{
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{200},
|
||||
ReqBody: &reqBody,
|
||||
Results: &res.Body,
|
||||
_, res.Err = client.Request("PUT", updateMetadataURL(client, id), gophercloud.RequestOpts{
|
||||
OkCodes: []int{200},
|
||||
JSONBody: &reqBody,
|
||||
JSONResponse: &res.Body,
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
|
|
@ -45,8 +45,16 @@ func MockGetResponse(t *testing.T) {
|
|||
{
|
||||
"volume": {
|
||||
"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/pagination"
|
||||
|
||||
"github.com/racker/perigee"
|
||||
)
|
||||
|
||||
// CreateOptsBuilder allows extensions to add additional parameters to the
|
||||
|
@ -85,11 +83,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
|
|||
return res
|
||||
}
|
||||
|
||||
_, res.Err = perigee.Request("POST", createURL(client), perigee.Options{
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
ReqBody: &reqBody,
|
||||
Results: &res.Body,
|
||||
OkCodes: []int{200, 201},
|
||||
_, res.Err = client.Request("POST", createURL(client), gophercloud.RequestOpts{
|
||||
OkCodes: []int{200, 201},
|
||||
JSONBody: &reqBody,
|
||||
JSONResponse: &res.Body,
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
@ -97,9 +94,8 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
|
|||
// Delete will delete the existing Volume with the provided ID.
|
||||
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
|
||||
var res DeleteResult
|
||||
_, res.Err = perigee.Request("DELETE", deleteURL(client, id), perigee.Options{
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{202, 204},
|
||||
_, res.Err = client.Request("DELETE", deleteURL(client, id), gophercloud.RequestOpts{
|
||||
OkCodes: []int{202, 204},
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
@ -108,10 +104,9 @@ func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
|
|||
// from the response, call the Extract method on the GetResult.
|
||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||
var res GetResult
|
||||
_, res.Err = perigee.Request("GET", getURL(client, id), perigee.Options{
|
||||
Results: &res.Body,
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{200},
|
||||
_, res.Err = client.Request("GET", getURL(client, id), gophercloud.RequestOpts{
|
||||
JSONResponse: &res.Body,
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
@ -207,11 +202,10 @@ func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder
|
|||
return res
|
||||
}
|
||||
|
||||
_, res.Err = perigee.Request("PUT", updateURL(client, id), perigee.Options{
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{200},
|
||||
ReqBody: &reqBody,
|
||||
Results: &res.Body,
|
||||
_, res.Err = client.Request("PUT", updateURL(client, id), gophercloud.RequestOpts{
|
||||
OkCodes: []int{200},
|
||||
JSONBody: &reqBody,
|
||||
JSONResponse: &res.Body,
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ func TestGet(t *testing.T) {
|
|||
|
||||
th.AssertEquals(t, v.Name, "vol-001")
|
||||
th.AssertEquals(t, v.ID, "d32019d3-bc6e-4319-9c1d-6722fc136a22")
|
||||
th.AssertEquals(t, v.Attachments[0]["device"], "/dev/vde")
|
||||
}
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
|
|
|
@ -16,7 +16,7 @@ type Volume struct {
|
|||
Name string `mapstructure:"display_name"`
|
||||
|
||||
// Instances onto which the volume is attached.
|
||||
Attachments []string `mapstructure:"attachments"`
|
||||
Attachments []map[string]interface{} `mapstructure:"attachments"`
|
||||
|
||||
// This parameter is no longer used.
|
||||
AvailabilityZone string `mapstructure:"availability_zone"`
|
||||
|
@ -28,7 +28,7 @@ type Volume struct {
|
|||
CreatedAt string `mapstructure:"created_at"`
|
||||
|
||||
// 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.
|
||||
VolumeType string `mapstructure:"volume_type"`
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package volumetypes
|
||||
|
||||
import (
|
||||
"github.com/racker/perigee"
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
@ -45,11 +44,11 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
|
|||
return res
|
||||
}
|
||||
|
||||
_, res.Err = perigee.Request("POST", createURL(client), perigee.Options{
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{200, 201},
|
||||
ReqBody: &reqBody,
|
||||
Results: &res.Body,
|
||||
_, res.Err = client.Request("POST", createURL(client), gophercloud.RequestOpts{
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{200, 201},
|
||||
JSONBody: &reqBody,
|
||||
JSONResponse: &res.Body,
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
@ -57,7 +56,7 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
|
|||
// Delete will delete the volume type with the provided ID.
|
||||
func Delete(client *gophercloud.ServiceClient, id string) 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},
|
||||
})
|
||||
|
@ -68,10 +67,10 @@ func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
|
|||
// type from the result, call the Extract method on the GetResult.
|
||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||
var res GetResult
|
||||
_, err := perigee.Request("GET", getURL(client, id), perigee.Options{
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{200},
|
||||
Results: &res.Body,
|
||||
_, err := client.Request("GET", getURL(client, id), gophercloud.RequestOpts{
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{200},
|
||||
JSONResponse: &res.Body,
|
||||
})
|
||||
res.Err = err
|
||||
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/"},
|
||||
}
|
||||
|
||||
chosen, endpoint, err := utils.ChooseVersion(client.IdentityBase, client.IdentityEndpoint, versions)
|
||||
chosen, endpoint, err := utils.ChooseVersion(client, versions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -107,6 +107,11 @@ func v2auth(client *gophercloud.ProviderClient, endpoint string, options gopherc
|
|||
return err
|
||||
}
|
||||
|
||||
if options.AllowReauth {
|
||||
client.ReauthFunc = func() error {
|
||||
return AuthenticateV2(client, options)
|
||||
}
|
||||
}
|
||||
client.TokenID = token.ID
|
||||
client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
|
||||
return V2EndpointURL(catalog, opts)
|
||||
|
@ -133,6 +138,11 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, options gopherc
|
|||
}
|
||||
client.TokenID = token.ID
|
||||
|
||||
if options.AllowReauth {
|
||||
client.ReauthFunc = func() error {
|
||||
return AuthenticateV3(client, options)
|
||||
}
|
||||
}
|
||||
client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
|
||||
return V3EndpointURL(v3Client, opts)
|
||||
}
|
||||
|
@ -203,3 +213,24 @@ func NewBlockStorageV1(client *gophercloud.ProviderClient, eo gophercloud.Endpoi
|
|||
}
|
||||
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
|
||||
|
||||
import (
|
||||
"github.com/racker/perigee"
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
@ -9,10 +8,9 @@ import (
|
|||
// Get retrieves information for a specific extension using its alias.
|
||||
func Get(c *gophercloud.ServiceClient, alias string) GetResult {
|
||||
var res GetResult
|
||||
_, res.Err = perigee.Request("GET", ExtensionURL(c, alias), perigee.Options{
|
||||
MoreHeaders: c.AuthenticatedHeaders(),
|
||||
Results: &res.Body,
|
||||
OkCodes: []int{200},
|
||||
_, res.Err = c.Request("GET", ExtensionURL(c, alias), gophercloud.RequestOpts{
|
||||
JSONResponse: &res.Body,
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
|
|
@ -6,8 +6,6 @@ import (
|
|||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
|
||||
"github.com/racker/perigee"
|
||||
)
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
_, res.Err = perigee.Request("POST", createURL(client), perigee.Options{
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
ReqBody: reqBody,
|
||||
Results: &res.Body,
|
||||
OkCodes: []int{200, 202},
|
||||
_, res.Err = client.Request("POST", createURL(client), gophercloud.RequestOpts{
|
||||
JSONBody: reqBody,
|
||||
JSONResponse: &res.Body,
|
||||
OkCodes: []int{200, 202},
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
|
|
@ -3,8 +3,6 @@ package defsecrules
|
|||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/racker/perigee"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
@ -75,11 +73,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
|
|||
return result
|
||||
}
|
||||
|
||||
_, result.Err = perigee.Request("POST", rootURL(client), perigee.Options{
|
||||
Results: &result.Body,
|
||||
ReqBody: &reqBody,
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{200},
|
||||
_, result.Err = client.Request("POST", rootURL(client), gophercloud.RequestOpts{
|
||||
JSONResponse: &result.Body,
|
||||
JSONBody: &reqBody,
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
|
||||
return result
|
||||
|
@ -89,10 +86,9 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
|
|||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||
var result GetResult
|
||||
|
||||
_, result.Err = perigee.Request("GET", resourceURL(client, id), perigee.Options{
|
||||
Results: &result.Body,
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{200},
|
||||
_, result.Err = client.Request("GET", resourceURL(client, id), gophercloud.RequestOpts{
|
||||
JSONResponse: &result.Body,
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
|
||||
return result
|
||||
|
@ -102,9 +98,8 @@ func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
|||
func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
|
||||
var result gophercloud.ErrResult
|
||||
|
||||
_, result.Err = perigee.Request("DELETE", resourceURL(client, id), perigee.Options{
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{204},
|
||||
_, result.Err = client.Request("DELETE", resourceURL(client, id), gophercloud.RequestOpts{
|
||||
OkCodes: []int{204},
|
||||
})
|
||||
|
||||
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 (
|
||||
"errors"
|
||||
|
||||
"github.com/racker/perigee"
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
|
@ -82,11 +81,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
|
|||
return res
|
||||
}
|
||||
|
||||
_, res.Err = perigee.Request("POST", createURL(client), perigee.Options{
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
ReqBody: reqBody,
|
||||
Results: &res.Body,
|
||||
OkCodes: []int{200},
|
||||
_, res.Err = client.Request("POST", createURL(client), gophercloud.RequestOpts{
|
||||
JSONBody: reqBody,
|
||||
JSONResponse: &res.Body,
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
@ -94,10 +92,9 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
|
|||
// Get returns public data about a previously uploaded KeyPair.
|
||||
func Get(client *gophercloud.ServiceClient, name string) GetResult {
|
||||
var res GetResult
|
||||
_, res.Err = perigee.Request("GET", getURL(client, name), perigee.Options{
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
Results: &res.Body,
|
||||
OkCodes: []int{200},
|
||||
_, res.Err = client.Request("GET", getURL(client, name), gophercloud.RequestOpts{
|
||||
JSONResponse: &res.Body,
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
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.
|
||||
func Delete(client *gophercloud.ServiceClient, name string) DeleteResult {
|
||||
var res DeleteResult
|
||||
_, res.Err = perigee.Request("DELETE", deleteURL(client, name), perigee.Options{
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{202},
|
||||
_, res.Err = client.Request("DELETE", deleteURL(client, name), gophercloud.RequestOpts{
|
||||
OkCodes: []int{202},
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ func mockListGroupsResponse(t *testing.T) {
|
|||
}
|
||||
|
||||
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.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
|
|
@ -3,8 +3,6 @@ package secgroups
|
|||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/racker/perigee"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
@ -80,11 +78,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
|
|||
return result
|
||||
}
|
||||
|
||||
_, result.Err = perigee.Request("POST", rootURL(client), perigee.Options{
|
||||
Results: &result.Body,
|
||||
ReqBody: &reqBody,
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{200},
|
||||
_, result.Err = client.Request("POST", rootURL(client), gophercloud.RequestOpts{
|
||||
JSONResponse: &result.Body,
|
||||
JSONBody: &reqBody,
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
|
||||
return result
|
||||
|
@ -126,11 +123,10 @@ func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder
|
|||
return result
|
||||
}
|
||||
|
||||
_, result.Err = perigee.Request("PUT", resourceURL(client, id), perigee.Options{
|
||||
Results: &result.Body,
|
||||
ReqBody: &reqBody,
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{200},
|
||||
_, result.Err = client.Request("PUT", resourceURL(client, id), gophercloud.RequestOpts{
|
||||
JSONResponse: &result.Body,
|
||||
JSONBody: &reqBody,
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
|
||||
return result
|
||||
|
@ -140,10 +136,9 @@ func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder
|
|||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||
var result GetResult
|
||||
|
||||
_, result.Err = perigee.Request("GET", resourceURL(client, id), perigee.Options{
|
||||
Results: &result.Body,
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{200},
|
||||
_, result.Err = client.Request("GET", resourceURL(client, id), gophercloud.RequestOpts{
|
||||
JSONResponse: &result.Body,
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
|
||||
return result
|
||||
|
@ -153,9 +148,8 @@ func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
|||
func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
|
||||
var result gophercloud.ErrResult
|
||||
|
||||
_, result.Err = perigee.Request("DELETE", resourceURL(client, id), perigee.Options{
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{202},
|
||||
_, result.Err = client.Request("DELETE", resourceURL(client, id), gophercloud.RequestOpts{
|
||||
OkCodes: []int{202},
|
||||
})
|
||||
|
||||
return result
|
||||
|
@ -222,7 +216,7 @@ func (opts CreateRuleOpts) ToRuleCreateMap() (map[string]interface{}, error) {
|
|||
rule["cidr"] = opts.CIDR
|
||||
}
|
||||
if opts.FromGroupID != "" {
|
||||
rule["from_group_id"] = opts.FromGroupID
|
||||
rule["group_id"] = opts.FromGroupID
|
||||
}
|
||||
|
||||
return map[string]interface{}{"security_group_rule": rule}, nil
|
||||
|
@ -240,11 +234,10 @@ func CreateRule(client *gophercloud.ServiceClient, opts CreateRuleOptsBuilder) C
|
|||
return result
|
||||
}
|
||||
|
||||
_, result.Err = perigee.Request("POST", rootRuleURL(client), perigee.Options{
|
||||
Results: &result.Body,
|
||||
ReqBody: &reqBody,
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{200},
|
||||
_, result.Err = client.Request("POST", rootRuleURL(client), gophercloud.RequestOpts{
|
||||
JSONResponse: &result.Body,
|
||||
JSONBody: &reqBody,
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
|
||||
return result
|
||||
|
@ -254,9 +247,8 @@ func CreateRule(client *gophercloud.ServiceClient, opts CreateRuleOptsBuilder) C
|
|||
func DeleteRule(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
|
||||
var result gophercloud.ErrResult
|
||||
|
||||
_, result.Err = perigee.Request("DELETE", resourceRuleURL(client, id), perigee.Options{
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{202},
|
||||
_, result.Err = client.Request("DELETE", resourceRuleURL(client, id), gophercloud.RequestOpts{
|
||||
OkCodes: []int{202},
|
||||
})
|
||||
|
||||
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 {
|
||||
var result gophercloud.ErrResult
|
||||
|
||||
_, result.Err = perigee.Request("POST", serverActionURL(client, serverID), perigee.Options{
|
||||
Results: &result.Body,
|
||||
ReqBody: actionMap("add", groupName),
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{202},
|
||||
_, result.Err = client.Request("POST", serverActionURL(client, serverID), gophercloud.RequestOpts{
|
||||
JSONResponse: &result.Body,
|
||||
JSONBody: actionMap("add", groupName),
|
||||
OkCodes: []int{202},
|
||||
})
|
||||
|
||||
return result
|
||||
|
@ -287,11 +278,10 @@ func AddServerToGroup(client *gophercloud.ServiceClient, serverID, groupName str
|
|||
func RemoveServerFromGroup(client *gophercloud.ServiceClient, serverID, groupName string) gophercloud.ErrResult {
|
||||
var result gophercloud.ErrResult
|
||||
|
||||
_, result.Err = perigee.Request("POST", serverActionURL(client, serverID), perigee.Options{
|
||||
Results: &result.Body,
|
||||
ReqBody: actionMap("remove", groupName),
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
OkCodes: []int{202},
|
||||
_, result.Err = client.Request("POST", serverActionURL(client, serverID), gophercloud.RequestOpts{
|
||||
JSONResponse: &result.Body,
|
||||
JSONBody: actionMap("remove", groupName),
|
||||
OkCodes: []int{202},
|
||||
})
|
||||
|
||||
return result
|
||||
|
|
|
@ -16,7 +16,7 @@ func rootURL(c *gophercloud.ServiceClient) 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 {
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
package startstop
|
||||
|
||||
import (
|
||||
"github.com/racker/perigee"
|
||||
"github.com/rackspace/gophercloud"
|
||||
)
|
||||
import "github.com/rackspace/gophercloud"
|
||||
|
||||
func actionURL(client *gophercloud.ServiceClient, id string) string {
|
||||
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}
|
||||
|
||||
_, res.Err = perigee.Request("POST", actionURL(client, id), perigee.Options{
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
ReqBody: reqBody,
|
||||
OkCodes: []int{202},
|
||||
_, res.Err = client.Request("POST", actionURL(client, id), gophercloud.RequestOpts{
|
||||
JSONBody: reqBody,
|
||||
OkCodes: []int{202},
|
||||
})
|
||||
|
||||
return res
|
||||
|
@ -30,10 +26,9 @@ func Stop(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
|
|||
|
||||
reqBody := map[string]interface{}{"os-stop": nil}
|
||||
|
||||
_, res.Err = perigee.Request("POST", actionURL(client, id), perigee.Options{
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
ReqBody: reqBody,
|
||||
OkCodes: []int{202},
|
||||
_, res.Err = client.Request("POST", actionURL(client, id), gophercloud.RequestOpts{
|
||||
JSONBody: reqBody,
|
||||
OkCodes: []int{202},
|
||||
})
|
||||
|
||||
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
|
||||
|
||||
import (
|
||||
"github.com/racker/perigee"
|
||||
"github.com/rackspace/gophercloud"
|
||||
"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.
|
||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||
var gr GetResult
|
||||
gr.Err = perigee.Get(getURL(client, id), perigee.Options{
|
||||
Results: &gr.Body,
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
_, gr.Err = client.Request("GET", getURL(client, id), gophercloud.RequestOpts{
|
||||
JSONResponse: &gr.Body,
|
||||
})
|
||||
return gr
|
||||
}
|
||||
|
|
|
@ -3,8 +3,6 @@ package images
|
|||
import (
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
|
||||
"github.com/racker/perigee"
|
||||
)
|
||||
|
||||
// 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.
|
||||
Marker string `q:"marker"`
|
||||
// The name of the Image.
|
||||
Name string `q:"name:"`
|
||||
Name string `q:"name"`
|
||||
// The name of the Server (in URL format).
|
||||
Server string `q:"server"`
|
||||
// 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.
|
||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||
var result GetResult
|
||||
_, result.Err = perigee.Request("GET", getURL(client, id), perigee.Options{
|
||||
MoreHeaders: client.AuthenticatedHeaders(),
|
||||
Results: &result.Body,
|
||||
OkCodes: []int{200},
|
||||
_, result.Err = client.Request("GET", getURL(client, id), gophercloud.RequestOpts{
|
||||
JSONResponse: &result.Body,
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue