1
0
mirror of https://github.com/kubernetes-sigs/descheduler.git synced 2026-01-27 05:46:13 +01:00

Remove old vendor, glide.lock/yaml

This commit is contained in:
Mike Dame
2020-01-24 18:56:21 -05:00
parent 86d0f3b038
commit 2b68e65238
11438 changed files with 0 additions and 3675402 deletions

View File

@@ -1,256 +0,0 @@
# Contributing to Gophercloud
- [New Contributor Tutorial](#new-contributor-tutorial)
- [3 ways to get involved](#3-ways-to-get-involved)
- [Getting started](#getting-started)
- [Tests](#tests)
- [Style guide](#basic-style-guide)
## New Contributor Tutorial
For new contributors, we've put together a detailed tutorial
[here](https://github.com/gophercloud/gophercloud/tree/master/docs/contributor-tutorial)!
## 3 ways to get involved
There are three main ways you can get involved in our open-source project, and
each is described briefly below.
### 1. Fixing bugs
If you want to start fixing open bugs, we'd really appreciate that! Bug fixing
is central to any project. The best way to get started is by heading to our
[bug tracker](https://github.com/gophercloud/gophercloud/issues) and finding open
bugs that you think nobody is working on. It might be useful to comment on the
thread to see the current state of the issue and if anybody has made any
breakthroughs on it so far.
### 2. Improving documentation
Gophercloud's documentation is automatically generated from the source code
and can be read online at [godoc.org](https://godoc.org/github.com/gophercloud/gophercloud).
If you feel that a certain section could be improved - whether it's to clarify
ambiguity, correct a technical mistake, or to fix a grammatical error - please
feel entitled to do so! We welcome doc pull requests with the same childlike
enthusiasm as any other contribution!
### 3. Working on a new feature
If you've found something we've left out, we'd love for you to add it! Please
first open an issue to indicate your interest to a core contributor - this
enables quick/early feedback and can help steer you in the right direction by
avoiding known issues. It might also help you avoid losing time implementing
something that might not ever work or is outside the scope of the project.
While you're implementing the feature, one tip is to prefix your Pull Request
title with `[wip]` - then people know it's a work in progress. Once the PR is
ready for review, you can remove the `[wip]` tag and request a review.
We ask that you do not submit a feature that you have not spent time researching
and testing first-hand in an actual OpenStack environment. While we appreciate
the contribution, submitting code which you are unfamiliar with is a risk to the
users who will ultimately use it. See our [acceptance tests readme](/acceptance)
for information about how you can create a local development environment to
better understand the feature you're working on.
Please do not hesitate to ask questions or request clarification. Your
contribution is very much appreciated and we are happy to work with you to get
it merged.
## Getting Started
As a contributor you will need to setup your workspace in a slightly different
way than just downloading it. Here are the basic instructions:
1. Configure your `$GOPATH` and run `go get` as described in the main
[README](/README.md#how-to-install) but add `-tags "fixtures acceptance"` to
get dependencies for unit and acceptance tests.
```bash
go get -tags "fixtures acceptance" github.com/gophercloud/gophercloud
```
2. Move into the directory that houses your local repository:
```bash
cd ${GOPATH}/src/github.com/gophercloud/gophercloud
```
3. Fork the `gophercloud/gophercloud` repository and update your remote refs. You
will need to rename the `origin` remote branch to `upstream`, and add your
fork as `origin` instead:
```bash
git remote rename origin upstream
git remote add origin git@github.com:<my_username>/gophercloud.git
```
4. Checkout the latest development branch:
```bash
git checkout master
```
5. If you're working on something (discussed more in detail below), you will
need to checkout a new feature branch:
```bash
git checkout -b my-new-feature
```
6. Use a standard text editor or IDE of your choice to make your changes to the code or documentation. Once finished, commit them.
```bash
git status
git add path/to/changed/file.go
git commit
```
7. Submit your branch as a [Pull Request](https://help.github.com/articles/creating-a-pull-request/). When submitting a Pull Request, please follow our [Style Guide](https://github.com/gophercloud/gophercloud/blob/master/docs/STYLEGUIDE.md).
> Further information about using Git can be found [here](https://git-scm.com/book/en/v2).
Happy Hacking!
## Tests
When working on a new or existing feature, testing will be the backbone of your
work since it helps uncover and prevent regressions in the codebase. There are
two types of test we use in Gophercloud: unit tests and acceptance tests, which
are both described below.
### Unit tests
Unit tests are the fine-grained tests that establish and ensure the behavior
of individual units of functionality. We usually test on an
operation-by-operation basis (an operation typically being an API action) with
the use of mocking to set up explicit expectations. Each operation will set up
its HTTP response expectation, and then test how the system responds when fed
this controlled, pre-determined input.
To make life easier, we've introduced a bunch of test helpers to simplify the
process of testing expectations with assertions:
```go
import (
"testing"
"github.com/gophercloud/gophercloud/testhelper"
)
func TestSomething(t *testing.T) {
result, err := Operation()
testhelper.AssertEquals(t, "foo", result.Bar)
testhelper.AssertNoErr(t, err)
}
func TestSomethingElse(t *testing.T) {
testhelper.CheckEquals(t, "expected", "actual")
}
```
`AssertEquals` and `AssertNoErr` will throw a fatal error if a value does not
match an expected value or if an error has been declared, respectively. You can
also use `CheckEquals` and `CheckNoErr` for the same purpose; the only difference
being that `t.Errorf` is raised rather than `t.Fatalf`.
Here is a truncated example of mocked HTTP responses:
```go
import (
"testing"
th "github.com/gophercloud/gophercloud/testhelper"
fake "github.com/gophercloud/gophercloud/testhelper/client"
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
)
func TestGet(t *testing.T) {
// Setup the HTTP request multiplexer and server
th.SetupHTTP()
defer th.TeardownHTTP()
th.Mux.HandleFunc("/networks/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) {
// Test we're using the correct HTTP method
th.TestMethod(t, r, "GET")
// Test we're setting the auth token
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
// Set the appropriate headers for our mocked response
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
// Set the HTTP body
fmt.Fprintf(w, `
{
"network": {
"status": "ACTIVE",
"name": "private-network",
"admin_state_up": true,
"tenant_id": "4fd44f30292945e481c7b8a0c8908869",
"shared": true,
"id": "d32019d3-bc6e-4319-9c1d-6722fc136a22"
}
}
`)
})
// Call our API operation
network, err := networks.Get(fake.ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22").Extract()
// Assert no errors and equality
th.AssertNoErr(t, err)
th.AssertEquals(t, n.Status, "ACTIVE")
}
```
### Acceptance tests
As we've already mentioned, unit tests have a very narrow and confined focus -
they test small units of behavior. Acceptance tests on the other hand have a
far larger scope: they are fully functional tests that test the entire API of a
service in one fell swoop. They don't care about unit isolation or mocking
expectations, they instead do a full run-through and consequently test how the
entire system _integrates_ together. When an API satisfies expectations, it
proves by default that the requirements for a contract have been met.
Please be aware that acceptance tests will hit a live API - and may incur
service charges from your provider. Although most tests handle their own
teardown procedures, it is always worth manually checking that resources are
deleted after the test suite finishes.
We provide detailed information about how to set up local acceptance test
environments in our [acceptance tests readme](/acceptance).
### Running tests
To run all tests:
```bash
go test -tags fixtures ./...
```
To run all tests with verbose output:
```bash
go test -v -tags fixtures ./...
```
To run tests that match certain [build tags]():
```bash
go test -tags "fixtures foo bar" ./...
```
To run tests for a particular sub-package:
```bash
cd ./path/to/package && go test -tags fixtures ./...
```
## Style guide
See [here](/docs/STYLEGUIDE.md)

View File

@@ -1 +0,0 @@
Before starting a PR, please read our [contributor tutorial](https://github.com/gophercloud/gophercloud/tree/master/docs/contributor-tutorial).

View File

@@ -1,12 +0,0 @@
Prior to starting a PR, please make sure you have read our
[contributor tutorial](https://github.com/gophercloud/gophercloud/tree/master/docs/contributor-tutorial).
Prior to a PR being reviewed, there needs to be a Github issue that the PR
addresses. Replace the brackets and text below with that issue number.
For #[PUT ISSUE NUMBER HERE]
Links to the line numbers/files in the OpenStack source code that support the
code in this PR:
[PUT URLS HERE]

View File

@@ -1,3 +0,0 @@
**/*.swp
.idea
.vscode

View File

@@ -1,25 +0,0 @@
language: go
sudo: false
install:
- GO111MODULE=off go get golang.org/x/crypto/ssh
- GO111MODULE=off go get -v -tags 'fixtures acceptance' ./...
- GO111MODULE=off go get github.com/wadey/gocovmerge
- GO111MODULE=off go get github.com/mattn/goveralls
- GO111MODULE=off go get golang.org/x/tools/cmd/goimports
go:
- "1.10"
- "1.11"
- "1.12"
- "tip"
env:
global:
- secure: "xSQsAG5wlL9emjbCdxzz/hYQsSpJ/bABO1kkbwMSISVcJ3Nk0u4ywF+LS4bgeOnwPfmFvNTOqVDu3RwEvMeWXSI76t1piCPcObutb2faKLVD/hLoAS76gYX+Z8yGWGHrSB7Do5vTPj1ERe2UljdrnsSeOXzoDwFxYRaZLX4bBOB4AyoGvRniil5QXPATiA1tsWX1VMicj8a4F8X+xeESzjt1Q5Iy31e7vkptu71bhvXCaoo5QhYwT+pLR9dN0S1b7Ro0KVvkRefmr1lUOSYd2e74h6Lc34tC1h3uYZCS4h47t7v5cOXvMNxinEj2C51RvbjvZI1RLVdkuAEJD1Iz4+Ote46nXbZ//6XRZMZz/YxQ13l7ux1PFjgEB6HAapmF5Xd8PRsgeTU9LRJxpiTJ3P5QJ3leS1va8qnziM5kYipj/Rn+V8g2ad/rgkRox9LSiR9VYZD2Pe45YCb1mTKSl2aIJnV7nkOqsShY5LNB4JZSg7xIffA+9YVDktw8dJlATjZqt7WvJJ49g6A61mIUV4C15q2JPGKTkZzDiG81NtmS7hFa7k0yaE2ELgYocbcuyUcAahhxntYTC0i23nJmEHVNiZmBO3u7EgpWe4KGVfumU+lt12tIn5b3dZRBBUk3QakKKozSK1QPHGpk/AZGrhu7H6l8to6IICKWtDcyMPQ="
- GO111MODULE=on
before_script:
- go vet ./...
script:
- ./script/coverage
- ./script/unittest
- ./script/format
after_success:
- $HOME/gopath/bin/goveralls -service=travis-ci -coverprofile=cover.out

View File

@@ -1,114 +0,0 @@
- job:
name: gophercloud-unittest
parent: golang-test
description: |
Run gophercloud unit test
run: .zuul/playbooks/gophercloud-unittest/run.yaml
nodeset: ubuntu-xenial-ut
- job:
name: gophercloud-acceptance-test
parent: golang-test
description: |
Run gophercloud acceptance test on master branch
run: .zuul/playbooks/gophercloud-acceptance-test/run.yaml
- job:
name: gophercloud-acceptance-test-ironic
parent: golang-test
description: |
Run gophercloud ironic acceptance test on master branch
run: .zuul/playbooks/gophercloud-acceptance-test-ironic/run.yaml
- job:
name: gophercloud-acceptance-test-stein
parent: gophercloud-acceptance-test
description: |
Run gophercloud acceptance test on stein branch
vars:
global_env:
OS_BRANCH: stable/stein
- job:
name: gophercloud-acceptance-test-rocky
parent: gophercloud-acceptance-test
description: |
Run gophercloud acceptance test on rocky branch
vars:
global_env:
OS_BRANCH: stable/rocky
- job:
name: gophercloud-acceptance-test-queens
parent: gophercloud-acceptance-test
description: |
Run gophercloud acceptance test on queens branch
vars:
global_env:
OS_BRANCH: stable/queens
- job:
name: gophercloud-acceptance-test-pike
parent: gophercloud-acceptance-test
description: |
Run gophercloud acceptance test on pike branch
vars:
global_env:
OS_BRANCH: stable/pike
- job:
name: gophercloud-acceptance-test-ocata
parent: gophercloud-acceptance-test
description: |
Run gophercloud acceptance test on ocata branch
vars:
global_env:
OS_BRANCH: stable/ocata
- job:
name: gophercloud-acceptance-test-newton
parent: gophercloud-acceptance-test
description: |
Run gophercloud acceptance test on newton branch
vars:
global_env:
OS_BRANCH: stable/newton
- job:
name: gophercloud-acceptance-test-mitaka
parent: gophercloud-acceptance-test
description: |
Run gophercloud acceptance test on mitaka branch
vars:
global_env:
OS_BRANCH: stable/mitaka
nodeset: ubuntu-trusty
- project:
name: gophercloud/gophercloud
check:
jobs:
- gophercloud-unittest
- gophercloud-acceptance-test
- gophercloud-acceptance-test-ironic
recheck-mitaka:
jobs:
- gophercloud-acceptance-test-mitaka
recheck-newton:
jobs:
- gophercloud-acceptance-test-newton
recheck-ocata:
jobs:
- gophercloud-acceptance-test-ocata
recheck-pike:
jobs:
- gophercloud-acceptance-test-pike
recheck-queens:
jobs:
- gophercloud-acceptance-test-queens
recheck-rocky:
jobs:
- gophercloud-acceptance-test-rocky
recheck-stein:
jobs:
- gophercloud-acceptance-test-stein

View File

@@ -1,26 +0,0 @@
- hosts: all
become: yes
roles:
- config-golang
- clone-devstack-gate-to-workspace
- role: create-devstack-local-conf
enable_services:
- 'ironic'
- role: install-devstack
environment:
OVERRIDE_ENABLED_SERVICES: 'g-api,g-reg,q-agt,q-dhcp,q-l3,q-svc,key,mysql,rabbit,ir-api,ir-cond,s-account,s-container,s-object,s-proxy,tempest'
PROJECTS: 'openstack/ironic'
tasks:
- name: Run ironic acceptance tests with gophercloud
shell:
cmd: |
set -e
set -o pipefail
set -x
echo $(export |grep OS_BRANCH)
go get ./... || true
./script/acceptancetest-ironic -v 2>&1 | tee $TEST_RESULTS_TXT
executable: /bin/bash
chdir: '{{ zuul.project.src_dir }}'
environment: '{{ global_env }}'

View File

@@ -1,27 +0,0 @@
- hosts: all
become: yes
roles:
- config-golang
- clone-devstack-gate-to-workspace
- role: create-devstack-local-conf
enable_services:
- 'manila'
- 'designate'
- 'zun'
- 'octavia'
- 'neutron-ext'
- install-devstack
tasks:
- name: Run acceptance tests with gophercloud
shell:
cmd: |
set -e
set -o pipefail
set -x
echo $(export |grep OS_BRANCH)
go get ./... || true
./script/acceptancetest -v 2>&1 | tee $TEST_RESULTS_TXT
executable: /bin/bash
chdir: '{{ zuul.project.src_dir }}'
environment: '{{ global_env }}'

View File

@@ -1,16 +0,0 @@
- hosts: all
become: yes
roles:
- config-golang
tasks:
- name: Run unit tests with gophercloud
shell:
cmd: |
set -e
set -o pipefail
set -x
go get ./... || true
./script/unittest -v 2>&1 | tee $TEST_RESULTS_TXT
executable: /bin/bash
chdir: '{{ zuul.project.src_dir }}'
environment: '{{ global_env }}'

View File

@@ -1,191 +0,0 @@
Copyright 2012-2013 Rackspace, Inc.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
------
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View File

@@ -1,159 +0,0 @@
# Gophercloud: an OpenStack SDK for Go
[![Build Status](https://travis-ci.org/gophercloud/gophercloud.svg?branch=master)](https://travis-ci.org/gophercloud/gophercloud)
[![Coverage Status](https://coveralls.io/repos/github/gophercloud/gophercloud/badge.svg?branch=master)](https://coveralls.io/github/gophercloud/gophercloud?branch=master)
Gophercloud is an OpenStack Go SDK.
## Useful links
* [Reference documentation](http://godoc.org/github.com/gophercloud/gophercloud)
* [Effective Go](https://golang.org/doc/effective_go.html)
## How to install
Before installing, you need to ensure that your [GOPATH environment variable](https://golang.org/doc/code.html#GOPATH)
is pointing to an appropriate directory where you want to install Gophercloud:
```bash
mkdir $HOME/go
export GOPATH=$HOME/go
```
To protect yourself against changes in your dependencies, we highly recommend choosing a
[dependency management solution](https://github.com/golang/go/wiki/PackageManagementTools) for
your projects, such as [godep](https://github.com/tools/godep). Once this is set up, you can install
Gophercloud as a dependency like so:
```bash
go get github.com/gophercloud/gophercloud
# Edit your code to import relevant packages from "github.com/gophercloud/gophercloud"
godep save ./...
```
This will install all the source files you need into a `Godeps/_workspace` directory, which is
referenceable from your own source files when you use the `godep go` command.
## Getting started
### Credentials
Because you'll be hitting an API, you will need to retrieve your OpenStack
credentials and either store them as environment variables or in your local Go
files. The first method is recommended because it decouples credential
information from source code, allowing you to push the latter to your version
control system without any security risk.
You will need to retrieve the following:
* username
* password
* a valid Keystone identity URL
For users that have the OpenStack dashboard installed, there's a shortcut. If
you visit the `project/access_and_security` path in Horizon and click on the
"Download OpenStack RC File" button at the top right hand corner, you will
download a bash file that exports all of your access details to environment
variables. To execute the file, run `source admin-openrc.sh` and you will be
prompted for your password.
### Authentication
Once you have access to your credentials, you can begin plugging them into
Gophercloud. The next step is authentication, and this is handled by a base
"Provider" struct. To get one, you can either pass in your credentials
explicitly, or tell Gophercloud to use environment variables:
```go
import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack"
"github.com/gophercloud/gophercloud/openstack/utils"
)
// Option 1: Pass in the values yourself
opts := gophercloud.AuthOptions{
IdentityEndpoint: "https://openstack.example.com:5000/v2.0",
Username: "{username}",
Password: "{password}",
}
// Option 2: Use a utility function to retrieve all your environment variables
opts, err := openstack.AuthOptionsFromEnv()
```
Once you have the `opts` variable, you can pass it in and get back a
`ProviderClient` struct:
```go
provider, err := openstack.AuthenticatedClient(opts)
```
The `ProviderClient` is the top-level client that all of your OpenStack services
derive from. The provider contains all of the authentication details that allow
your Go code to access the API - such as the base URL and token ID.
### Provision a server
Once we have a base Provider, we inject it as a dependency into each OpenStack
service. In order to work with the Compute API, we need a Compute service
client; which can be created like so:
```go
client, err := openstack.NewComputeV2(provider, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
```
We then use this `client` for any Compute API operation we want. In our case,
we want to provision a new server - so we invoke the `Create` method and pass
in the flavor ID (hardware specification) and image ID (operating system) we're
interested in:
```go
import "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
server, err := servers.Create(client, servers.CreateOpts{
Name: "My new server!",
FlavorRef: "flavor_id",
ImageRef: "image_id",
}).Extract()
```
The above code sample creates a new server with the parameters, and embodies the
new resource in the `server` variable (a
[`servers.Server`](http://godoc.org/github.com/gophercloud/gophercloud) struct).
## Advanced Usage
Have a look at the [FAQ](./docs/FAQ.md) for some tips on customizing the way Gophercloud works.
## Backwards-Compatibility Guarantees
None. Vendor it and write tests covering the parts you use.
## Contributing
See the [contributing guide](./.github/CONTRIBUTING.md).
## Help and feedback
If you're struggling with something or have spotted a potential bug, feel free
to submit an issue to our [bug tracker](https://github.com/gophercloud/gophercloud/issues).
## Thank You
We'd like to extend special thanks and appreciation to the following:
### OpenLab
<a href="http://openlabtesting.org/"><img src="./docs/assets/openlab.png" width="600px"></a>
OpenLab is providing a full CI environment to test each PR and merge for a variety of OpenStack releases.
### VEXXHOST
<a href="https://vexxhost.com/"><img src="./docs/assets/vexxhost.png" width="600px"></a>
VEXXHOST is providing their services to assist with the development and testing of Gophercloud.

View File

@@ -1,114 +0,0 @@
# Gophercloud Acceptance tests
The purpose of these acceptance tests is to validate that SDK features meet
the requirements of a contract - to consumers, other parts of the library, and
to a remote API.
> **Note:** Because every test will be run against a real API endpoint, you
> may incur bandwidth and service charges for all the resource usage. These
> tests *should* remove their remote products automatically. However, there may
> be certain cases where this does not happen; always double-check to make sure
> you have no stragglers left behind.
### Step 1. Creating a Testing Environment
Running tests on an existing OpenStack cloud can be risky. Malformed tests,
especially ones which require Admin privileges, can cause damage to the
environment. Additionally, you may incur bandwidth and service charges for
the resources used, as mentioned in the note above.
Therefore, it is usually best to first practice running acceptance tests in
an isolated test environment. Two options to easily create a testing
environment are [DevStack](https://docs.openstack.org/devstack/latest/)
and [PackStack](https://www.rdoproject.org/install/packstack/).
The following blog posts detail how to create reusable PackStack environments.
These posts were written with Gophercloud in mind:
* http://terrarum.net/blog/building-openstack-environments.html
* http://terrarum.net/blog/building-openstack-environments-2.html
* http://terrarum.net/blog/building-openstack-environments-3.html
### Step 2. Set environment variables
A lot of tests rely on environment variables for configuration - so you will need
to set them before running the suite. If you're testing against pure OpenStack APIs,
you can download a file that contains all of these variables for you: just visit
the `project/access_and_security` page in your control panel and click the "Download
OpenStack RC File" button at the top right. For all other providers, you will need
to set them manually.
#### Authentication
|Name|Description|
|---|---|
|`OS_USERNAME`|Your API username|
|`OS_PASSWORD`|Your API password|
|`OS_AUTH_URL`|The identity URL you need to authenticate|
|`OS_TENANT_NAME`|Your API tenant name|
|`OS_TENANT_ID`|Your API tenant ID|
#### General
|Name|Description|
|---|---|
|`OS_REGION_NAME`|The region you want your resources to reside in|
#### Compute
|Name|Description|
|---|---|
|`OS_IMAGE_ID`|The ID of the image your want your server to be based on|
|`OS_FLAVOR_ID`|The ID of the flavor you want your server to be based on|
|`OS_FLAVOR_ID_RESIZE`|The ID of the flavor you want your server to be resized to|
|`OS_POOL_NAME`|The Pool from where to obtain Floating IPs|
|`OS_NETWORK_NAME`|The internal/private network to launch instances on|
|`OS_EXTGW_ID`|The external/public network|
#### Database
|Name|Description|
|---|---|
|`OS_DB_DATASTORE_TYPE`|The Datastore type to use. Example: `mariadb`|
|`OS_DB_DATASTORE_VERSION`|The Datastore version to use. Example: `mariadb-10`|
#### Shared file systems
|Name|Description|
|---|---|
|`OS_NETWORK_ID`| The network ID to use when creating shared network|
|`OS_SUBNET_ID`| The subnet ID to use when creating shared network|
### 3. Run the test suite
From the root directory, run:
```
./script/acceptancetest
```
Alternatively, add the following to your `.bashrc`:
```bash
gophercloudtest() {
if [[ -n $1 ]] && [[ -n $2 ]]; then
pushd $GOPATH/src/github.com/gophercloud/gophercloud
go test -v -tags "fixtures acceptance" -run "$1" github.com/gophercloud/gophercloud/acceptance/openstack/$2 | tee ~/gophercloud.log
popd
fi
}
```
Then run either groups or individual tests by doing:
```shell
$ gophercloudtest TestFlavorsList compute/v2
$ gophercloudtest TestFlavors compute/v2
$ gophercloudtest Test compute/v2
```
### 4. Notes
#### Compute Tests
* In order to run the `TestBootFromVolumeMultiEphemeral` test, a flavor with ephemeral disk space must be used.
* The `TestDefSecRules` tests require a compatible network driver and admin privileges.

View File

@@ -1,717 +0,0 @@
// Package clients contains functions for creating OpenStack service clients
// for use in acceptance tests. It also manages the required environment
// variables to run the tests.
package clients
import (
"fmt"
"net/http"
"os"
"strings"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack"
baremetalNoAuth "github.com/gophercloud/gophercloud/openstack/baremetal/noauth"
blockstorageNoAuth "github.com/gophercloud/gophercloud/openstack/blockstorage/noauth"
)
// AcceptanceTestChoices contains image and flavor selections for use by the acceptance tests.
type AcceptanceTestChoices struct {
// ImageID contains the ID of a valid image.
ImageID string
// FlavorID contains the ID of a valid flavor.
FlavorID string
// FlavorIDResize contains the ID of a different flavor available on the same OpenStack installation, that is distinct
// from FlavorID.
FlavorIDResize string
// FloatingIPPool contains the name of the pool from where to obtain floating IPs.
FloatingIPPoolName string
// MagnumKeypair contains the ID of a valid key pair.
MagnumKeypair string
// MagnumImageID contains the ID of a valid magnum image.
MagnumImageID string
// NetworkName is the name of a network to launch the instance on.
NetworkName string
// NetworkID is the ID of a network to launch the instance on.
NetworkID string
// SubnetID is the ID of a subnet to launch the instance on.
SubnetID string
// ExternalNetworkID is the network ID of the external network.
ExternalNetworkID string
// DBDatastoreType is the datastore type for DB tests.
DBDatastoreType string
// DBDatastoreTypeID is the datastore type version for DB tests.
DBDatastoreVersion string
}
// AcceptanceTestChoicesFromEnv populates a ComputeChoices struct from environment variables.
// If any required state is missing, an `error` will be returned that enumerates the missing properties.
func AcceptanceTestChoicesFromEnv() (*AcceptanceTestChoices, error) {
imageID := os.Getenv("OS_IMAGE_ID")
flavorID := os.Getenv("OS_FLAVOR_ID")
flavorIDResize := os.Getenv("OS_FLAVOR_ID_RESIZE")
magnumImageID := os.Getenv("OS_MAGNUM_IMAGE_ID")
magnumKeypair := os.Getenv("OS_MAGNUM_KEYPAIR")
networkName := os.Getenv("OS_NETWORK_NAME")
networkID := os.Getenv("OS_NETWORK_ID")
subnetID := os.Getenv("OS_SUBNET_ID")
floatingIPPoolName := os.Getenv("OS_POOL_NAME")
externalNetworkID := os.Getenv("OS_EXTGW_ID")
dbDatastoreType := os.Getenv("OS_DB_DATASTORE_TYPE")
dbDatastoreVersion := os.Getenv("OS_DB_DATASTORE_VERSION")
missing := make([]string, 0, 3)
if imageID == "" {
missing = append(missing, "OS_IMAGE_ID")
}
if flavorID == "" {
missing = append(missing, "OS_FLAVOR_ID")
}
if flavorIDResize == "" {
missing = append(missing, "OS_FLAVOR_ID_RESIZE")
}
if floatingIPPoolName == "" {
missing = append(missing, "OS_POOL_NAME")
}
if externalNetworkID == "" {
missing = append(missing, "OS_EXTGW_ID")
}
/* // Temporarily disabled, see https://github.com/gophercloud/gophercloud/issues/1345
if networkID == "" {
missing = append(missing, "OS_NETWORK_ID")
}
if subnetID == "" {
missing = append(missing, "OS_SUBNET_ID")
}
*/
if networkName == "" {
networkName = "private"
}
notDistinct := ""
if flavorID == flavorIDResize {
notDistinct = "OS_FLAVOR_ID and OS_FLAVOR_ID_RESIZE must be distinct."
}
if len(missing) > 0 || notDistinct != "" {
text := "You're missing some important setup:\n"
if len(missing) > 0 {
text += " * These environment variables must be provided: " + strings.Join(missing, ", ") + "\n"
}
if notDistinct != "" {
text += " * " + notDistinct + "\n"
}
return nil, fmt.Errorf(text)
}
return &AcceptanceTestChoices{
ImageID: imageID,
FlavorID: flavorID,
FlavorIDResize: flavorIDResize,
FloatingIPPoolName: floatingIPPoolName,
MagnumImageID: magnumImageID,
MagnumKeypair: magnumKeypair,
NetworkName: networkName,
NetworkID: networkID,
SubnetID: subnetID,
ExternalNetworkID: externalNetworkID,
DBDatastoreType: dbDatastoreType,
DBDatastoreVersion: dbDatastoreVersion,
}, nil
}
// NewBlockStorageV1Client returns a *ServiceClient for making calls
// to the OpenStack Block Storage v1 API. An error will be returned
// if authentication or client creation was not possible.
func NewBlockStorageV1Client() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewBlockStorageV1(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
}
// NewBlockStorageV2Client returns a *ServiceClient for making calls
// to the OpenStack Block Storage v2 API. An error will be returned
// if authentication or client creation was not possible.
func NewBlockStorageV2Client() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewBlockStorageV2(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
}
// NewBlockStorageV3Client returns a *ServiceClient for making calls
// to the OpenStack Block Storage v3 API. An error will be returned
// if authentication or client creation was not possible.
func NewBlockStorageV3Client() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewBlockStorageV3(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
}
// NewBlockStorageV2NoAuthClient returns a noauth *ServiceClient for
// making calls to the OpenStack Block Storage v2 API. An error will be
// returned if client creation was not possible.
func NewBlockStorageV2NoAuthClient() (*gophercloud.ServiceClient, error) {
client, err := blockstorageNoAuth.NewClient(gophercloud.AuthOptions{
Username: os.Getenv("OS_USERNAME"),
TenantName: os.Getenv("OS_TENANT_NAME"),
})
if err != nil {
return nil, err
}
client = configureDebug(client)
return blockstorageNoAuth.NewBlockStorageNoAuth(client, blockstorageNoAuth.EndpointOpts{
CinderEndpoint: os.Getenv("CINDER_ENDPOINT"),
})
}
// NewBlockStorageV3NoAuthClient returns a noauth *ServiceClient for
// making calls to the OpenStack Block Storage v2 API. An error will be
// returned if client creation was not possible.
func NewBlockStorageV3NoAuthClient() (*gophercloud.ServiceClient, error) {
client, err := blockstorageNoAuth.NewClient(gophercloud.AuthOptions{
Username: os.Getenv("OS_USERNAME"),
TenantName: os.Getenv("OS_TENANT_NAME"),
})
if err != nil {
return nil, err
}
client = configureDebug(client)
return blockstorageNoAuth.NewBlockStorageNoAuth(client, blockstorageNoAuth.EndpointOpts{
CinderEndpoint: os.Getenv("CINDER_ENDPOINT"),
})
}
// NewComputeV2Client returns a *ServiceClient for making calls
// to the OpenStack Compute v2 API. An error will be returned
// if authentication or client creation was not possible.
func NewComputeV2Client() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewComputeV2(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
}
// NewBareMetalV1Client returns a *ServiceClient for making calls
// to the OpenStack Bare Metal v1 API. An error will be returned
// if authentication or client creation was not possible.
func NewBareMetalV1Client() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewBareMetalV1(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
}
// NewBareMetalV1NoAuthClient returns a *ServiceClient for making calls
// to the OpenStack Bare Metal v1 API. An error will be returned
// if authentication or client creation was not possible.
func NewBareMetalV1NoAuthClient() (*gophercloud.ServiceClient, error) {
return baremetalNoAuth.NewBareMetalNoAuth(baremetalNoAuth.EndpointOpts{
IronicEndpoint: os.Getenv("IRONIC_ENDPOINT"),
})
}
// NewBareMetalIntrospectionV1Client returns a *ServiceClient for making calls
// to the OpenStack Bare Metal Introspection v1 API. An error will be returned
// if authentication or client creation was not possible.
func NewBareMetalIntrospectionV1Client() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewBareMetalIntrospectionV1(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
}
// NewDBV1Client returns a *ServiceClient for making calls
// to the OpenStack Database v1 API. An error will be returned
// if authentication or client creation was not possible.
func NewDBV1Client() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewDBV1(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
}
// NewDNSV2Client returns a *ServiceClient for making calls
// to the OpenStack Compute v2 API. An error will be returned
// if authentication or client creation was not possible.
func NewDNSV2Client() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewDNSV2(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
}
// NewIdentityV2Client returns a *ServiceClient for making calls
// to the OpenStack Identity v2 API. An error will be returned
// if authentication or client creation was not possible.
func NewIdentityV2Client() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewIdentityV2(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
}
// NewIdentityV2AdminClient returns a *ServiceClient for making calls
// to the Admin Endpoint of the OpenStack Identity v2 API. An error
// will be returned if authentication or client creation was not possible.
func NewIdentityV2AdminClient() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewIdentityV2(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
Availability: gophercloud.AvailabilityAdmin,
})
}
// NewIdentityV2UnauthenticatedClient returns an unauthenticated *ServiceClient
// for the OpenStack Identity v2 API. An error will be returned if
// authentication or client creation was not possible.
func NewIdentityV2UnauthenticatedClient() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.NewClient(ao.IdentityEndpoint)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewIdentityV2(client, gophercloud.EndpointOpts{})
}
// NewIdentityV3Client returns a *ServiceClient for making calls
// to the OpenStack Identity v3 API. An error will be returned
// if authentication or client creation was not possible.
func NewIdentityV3Client() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewIdentityV3(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
}
// NewIdentityV3UnauthenticatedClient returns an unauthenticated *ServiceClient
// for the OpenStack Identity v3 API. An error will be returned if
// authentication or client creation was not possible.
func NewIdentityV3UnauthenticatedClient() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.NewClient(ao.IdentityEndpoint)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewIdentityV3(client, gophercloud.EndpointOpts{})
}
// NewImageServiceV2Client returns a *ServiceClient for making calls to the
// OpenStack Image v2 API. An error will be returned if authentication or
// client creation was not possible.
func NewImageServiceV2Client() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewImageServiceV2(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
}
// NewNetworkV2Client returns a *ServiceClient for making calls to the
// OpenStack Networking v2 API. An error will be returned if authentication
// or client creation was not possible.
func NewNetworkV2Client() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewNetworkV2(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
}
// NewObjectStorageV1Client returns a *ServiceClient for making calls to the
// OpenStack Object Storage v1 API. An error will be returned if authentication
// or client creation was not possible.
func NewObjectStorageV1Client() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewObjectStorageV1(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
}
// NewSharedFileSystemV2Client returns a *ServiceClient for making calls
// to the OpenStack Shared File System v2 API. An error will be returned
// if authentication or client creation was not possible.
func NewSharedFileSystemV2Client() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewSharedFileSystemV2(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
}
// NewLoadBalancerV2Client returns a *ServiceClient for making calls to the
// OpenStack Octavia v2 API. An error will be returned if authentication
// or client creation was not possible.
func NewLoadBalancerV2Client() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewLoadBalancerV2(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
}
// NewClusteringV1Client returns a *ServiceClient for making calls
// to the OpenStack Clustering v1 API. An error will be returned
// if authentication or client creation was not possible.
func NewClusteringV1Client() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewClusteringV1(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
}
// NewMessagingV2Client returns a *ServiceClient for making calls
// to the OpenStack Messaging (Zaqar) v2 API. An error will be returned
// if authentication or client creation was not possible.
func NewMessagingV2Client(clientID string) (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewMessagingV2(client, clientID, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
}
// NewContainerV1Client returns a *ServiceClient for making calls
// to the OpenStack Container V1 API. An error will be returned
// if authentication or client creation was not possible.
func NewContainerV1Client() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewContainerV1(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
}
// NewKeyManagerV1Client returns a *ServiceClient for making calls
// to the OpenStack Key Manager (Barbican) v1 API. An error will be
// returned if authentication or client creation was not possible.
func NewKeyManagerV1Client() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewKeyManagerV1(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
}
// configureDebug will configure the provider client to print the API
// requests and responses if OS_DEBUG is enabled.
func configureDebug(client *gophercloud.ProviderClient) *gophercloud.ProviderClient {
if os.Getenv("OS_DEBUG") != "" {
client.HTTPClient = http.Client{
Transport: &LogRoundTripper{
Rt: &http.Transport{},
},
}
}
return client
}
// NewContainerInfraV1Client returns a *ServiceClient for making calls
// to the OpenStack Container Infra Management v1 API. An error will be returned
// if authentication or client creation was not possible.
func NewContainerInfraV1Client() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewContainerInfraV1(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
}
// NewWorkflowV2Client returns a *ServiceClient for making calls
// to the OpenStack Workflow v2 API (Mistral). An error will be returned if
// authentication or client creation failed.
func NewWorkflowV2Client() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewWorkflowV2(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
}
// NewOrchestrationV1Client returns a *ServiceClient for making calls
// to the OpenStack Orchestration v1 API. An error will be returned
// if authentication or client creation was not possible.
func NewOrchestrationV1Client() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
return nil, err
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, err
}
client = configureDebug(client)
return openstack.NewOrchestrationV1(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
}

View File

@@ -1,75 +0,0 @@
package clients
import (
"os"
"testing"
)
// RequireAdmin will restrict a test to only be run by admin users.
func RequireAdmin(t *testing.T) {
if os.Getenv("OS_USERNAME") != "admin" {
t.Skip("must be admin to run this test")
}
}
// RequireNonAdmin will restrict a test to only be run by non-admin users.
func RequireNonAdmin(t *testing.T) {
if os.Getenv("OS_USERNAME") == "admin" {
t.Skip("must be a non-admin to run this test")
}
}
// RequireDNS will restrict a test to only be run in environments
// that support DNSaaS.
func RequireDNS(t *testing.T) {
if os.Getenv("OS_DNS_ENVIRONMENT") == "" {
t.Skip("this test requires DNSaaS")
}
}
// RequireGuestAgent will restrict a test to only be run in
// environments that support the QEMU guest agent.
func RequireGuestAgent(t *testing.T) {
if os.Getenv("OS_GUEST_AGENT") == "" {
t.Skip("this test requires support for qemu guest agent and to set OS_GUEST_AGENT to 1")
}
}
// RequireIdentityV2 will restrict a test to only be run in
// environments that support the Identity V2 API.
func RequireIdentityV2(t *testing.T) {
if os.Getenv("OS_IDENTITY_API_VERSION") != "2.0" {
t.Skip("this test requires support for the identity v2 API")
}
}
// RequireLiveMigration will restrict a test to only be run in
// environments that support live migration.
func RequireLiveMigration(t *testing.T) {
if os.Getenv("OS_LIVE_MIGRATE") == "" {
t.Skip("this test requires support for live migration and to set OS_LIVE_MIGRATE to 1")
}
}
// RequireLong will ensure long-running tests can run.
func RequireLong(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode")
}
}
// RequireNovaNetwork will restrict a test to only be run in
// environments that support nova-network.
func RequireNovaNetwork(t *testing.T) {
if os.Getenv("OS_NOVANET") == "" {
t.Skip("this test requires nova-network and to set OS_NOVANET to 1")
}
}
// SkipRelease will have the test be skipped on a certain
// release. Releases are named such as 'stable/mitaka', master, etc.
func SkipRelease(t *testing.T, release string) {
if os.Getenv("OS_BRANCH") == release {
t.Skipf("this is not supported in %s", release)
}
}

View File

@@ -1,185 +0,0 @@
package clients
import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"sort"
"strings"
)
// List of headers that need to be redacted
var REDACT_HEADERS = []string{"x-auth-token", "x-auth-key", "x-service-token",
"x-storage-token", "x-account-meta-temp-url-key", "x-account-meta-temp-url-key-2",
"x-container-meta-temp-url-key", "x-container-meta-temp-url-key-2", "set-cookie",
"x-subject-token"}
// LogRoundTripper satisfies the http.RoundTripper interface and is used to
// customize the default http client RoundTripper to allow logging.
type LogRoundTripper struct {
Rt http.RoundTripper
}
// RoundTrip performs a round-trip HTTP request and logs relevant information
// about it.
func (lrt *LogRoundTripper) RoundTrip(request *http.Request) (*http.Response, error) {
defer func() {
if request.Body != nil {
request.Body.Close()
}
}()
var err error
log.Printf("[DEBUG] OpenStack Request URL: %s %s", request.Method, request.URL)
log.Printf("[DEBUG] OpenStack request Headers:\n%s", formatHeaders(request.Header))
if request.Body != nil {
request.Body, err = lrt.logRequest(request.Body, request.Header.Get("Content-Type"))
if err != nil {
return nil, err
}
}
response, err := lrt.Rt.RoundTrip(request)
if response == nil {
return nil, err
}
log.Printf("[DEBUG] OpenStack Response Code: %d", response.StatusCode)
log.Printf("[DEBUG] OpenStack Response Headers:\n%s", formatHeaders(response.Header))
response.Body, err = lrt.logResponse(response.Body, response.Header.Get("Content-Type"))
return response, err
}
// logRequest will log the HTTP Request details.
// If the body is JSON, it will attempt to be pretty-formatted.
func (lrt *LogRoundTripper) logRequest(original io.ReadCloser, contentType string) (io.ReadCloser, error) {
defer original.Close()
var bs bytes.Buffer
_, err := io.Copy(&bs, original)
if err != nil {
return nil, err
}
// Handle request contentType
if strings.HasPrefix(contentType, "application/json") {
debugInfo := lrt.formatJSON(bs.Bytes())
log.Printf("[DEBUG] OpenStack Request Body: %s", debugInfo)
}
return ioutil.NopCloser(strings.NewReader(bs.String())), nil
}
// logResponse will log the HTTP Response details.
// If the body is JSON, it will attempt to be pretty-formatted.
func (lrt *LogRoundTripper) logResponse(original io.ReadCloser, contentType string) (io.ReadCloser, error) {
if strings.HasPrefix(contentType, "application/json") {
var bs bytes.Buffer
defer original.Close()
_, err := io.Copy(&bs, original)
if err != nil {
return nil, err
}
debugInfo := lrt.formatJSON(bs.Bytes())
if debugInfo != "" {
log.Printf("[DEBUG] OpenStack Response Body: %s", debugInfo)
}
return ioutil.NopCloser(strings.NewReader(bs.String())), nil
}
log.Printf("[DEBUG] Not logging because OpenStack response body isn't JSON")
return original, nil
}
// formatJSON will try to pretty-format a JSON body.
// It will also mask known fields which contain sensitive information.
func (lrt *LogRoundTripper) formatJSON(raw []byte) string {
var rawData interface{}
err := json.Unmarshal(raw, &rawData)
if err != nil {
log.Printf("[DEBUG] Unable to parse OpenStack JSON: %s", err)
return string(raw)
}
data, ok := rawData.(map[string]interface{})
if !ok {
pretty, err := json.MarshalIndent(rawData, "", " ")
if err != nil {
log.Printf("[DEBUG] Unable to re-marshal OpenStack JSON: %s", err)
return string(raw)
}
return string(pretty)
}
// Mask known password fields
if v, ok := data["auth"].(map[string]interface{}); ok {
if v, ok := v["identity"].(map[string]interface{}); ok {
if v, ok := v["password"].(map[string]interface{}); ok {
if v, ok := v["user"].(map[string]interface{}); ok {
v["password"] = "***"
}
}
if v, ok := v["application_credential"].(map[string]interface{}); ok {
v["secret"] = "***"
}
if v, ok := v["token"].(map[string]interface{}); ok {
v["id"] = "***"
}
}
}
// Ignore the catalog
if v, ok := data["token"].(map[string]interface{}); ok {
if _, ok := v["catalog"]; ok {
return ""
}
}
pretty, err := json.MarshalIndent(data, "", " ")
if err != nil {
log.Printf("[DEBUG] Unable to re-marshal OpenStack JSON: %s", err)
return string(raw)
}
return string(pretty)
}
// redactHeaders processes a headers object, returning a redacted list
func redactHeaders(headers http.Header) (processedHeaders []string) {
for name, header := range headers {
var sensitive bool
for _, redact_header := range REDACT_HEADERS {
if strings.ToLower(name) == strings.ToLower(redact_header) {
sensitive = true
}
}
for _, v := range header {
if sensitive {
processedHeaders = append(processedHeaders, fmt.Sprintf("%v: %v", name, "***"))
} else {
processedHeaders = append(processedHeaders, fmt.Sprintf("%v: %v", name, v))
}
}
}
return
}
// formatHeaders processes a headers object plus a deliminator, returning a string
func formatHeaders(headers http.Header) string {
redactedHeaders := redactHeaders(headers)
sort.Strings(redactedHeaders)
return strings.Join(redactedHeaders, "\n")
}

View File

@@ -1,45 +0,0 @@
// +build acceptance baremetal allocations
package noauth
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
v1 "github.com/gophercloud/gophercloud/acceptance/openstack/baremetal/v1"
"github.com/gophercloud/gophercloud/openstack/baremetal/v1/allocations"
"github.com/gophercloud/gophercloud/pagination"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestAllocationsCreateDestroy(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewBareMetalV1NoAuthClient()
th.AssertNoErr(t, err)
client.Microversion = "1.52"
allocation, err := v1.CreateAllocation(t, client)
th.AssertNoErr(t, err)
defer v1.DeleteAllocation(t, client, allocation)
found := false
err = allocations.List(client, allocations.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
allocationList, err := allocations.ExtractAllocations(page)
if err != nil {
return false, err
}
for _, a := range allocationList {
if a.UUID == allocation.UUID {
found = true
return true, nil
}
}
return false, nil
})
th.AssertNoErr(t, err)
th.AssertEquals(t, found, true)
}

View File

@@ -1,8 +0,0 @@
package noauth
/*
Acceptance tests for Ironic endpoints with auth_strategy=noauth. Specify
IRONIC_ENDPOINT environment variable. For example:
IRONIC_ENDPOINT="http://127.0.0.1:6385/v1" go test ./acceptance/openstack/baremetal/noauth/...
*/

View File

@@ -1,95 +0,0 @@
package noauth
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
v1 "github.com/gophercloud/gophercloud/acceptance/openstack/baremetal/v1"
"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
"github.com/gophercloud/gophercloud/pagination"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestNodesCreateDestroy(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewBareMetalV1NoAuthClient()
th.AssertNoErr(t, err)
client.Microversion = "1.50"
node, err := v1.CreateNode(t, client)
th.AssertNoErr(t, err)
defer v1.DeleteNode(t, client, node)
found := false
err = nodes.List(client, nodes.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
nodeList, err := nodes.ExtractNodes(page)
if err != nil {
return false, err
}
for _, n := range nodeList {
if n.UUID == node.UUID {
found = true
return true, nil
}
}
return false, nil
})
th.AssertNoErr(t, err)
th.AssertEquals(t, found, true)
}
func TestNodesUpdate(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewBareMetalV1NoAuthClient()
th.AssertNoErr(t, err)
client.Microversion = "1.50"
node, err := v1.CreateNode(t, client)
th.AssertNoErr(t, err)
defer v1.DeleteNode(t, client, node)
updated, err := nodes.Update(client, node.UUID, nodes.UpdateOpts{
nodes.UpdateOperation{
Op: nodes.ReplaceOp,
Path: "/maintenance",
Value: "true",
},
}).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, updated.Maintenance, true)
}
func TestNodesRAIDConfig(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewBareMetalV1NoAuthClient()
th.AssertNoErr(t, err)
client.Microversion = "1.50"
node, err := v1.CreateNode(t, client)
th.AssertNoErr(t, err)
defer v1.DeleteNode(t, client, node)
sizeGB := 100
isTrue := true
err = nodes.SetRAIDConfig(client, node.UUID, nodes.RAIDConfigOpts{
LogicalDisks: []nodes.LogicalDisk{
{
SizeGB: &sizeGB,
IsRootVolume: &isTrue,
RAIDLevel: nodes.RAID5,
DiskType: nodes.HDD,
NumberOfPhysicalDisks: 5,
},
},
}).ExtractErr()
th.AssertNoErr(t, err)
}

View File

@@ -1,73 +0,0 @@
// +build acceptance baremetal ports
package noauth
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
v1 "github.com/gophercloud/gophercloud/acceptance/openstack/baremetal/v1"
"github.com/gophercloud/gophercloud/openstack/baremetal/v1/ports"
"github.com/gophercloud/gophercloud/pagination"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestPortsCreateDestroy(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewBareMetalV1NoAuthClient()
th.AssertNoErr(t, err)
client.Microversion = "1.53"
node, err := v1.CreateFakeNode(t, client)
port, err := v1.CreatePort(t, client, node)
th.AssertNoErr(t, err)
defer v1.DeleteNode(t, client, node)
defer v1.DeletePort(t, client, port)
found := false
err = ports.List(client, ports.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
portList, err := ports.ExtractPorts(page)
if err != nil {
return false, err
}
for _, p := range portList {
if p.UUID == port.UUID {
found = true
return true, nil
}
}
return false, nil
})
th.AssertNoErr(t, err)
th.AssertEquals(t, found, true)
}
func TestPortsUpdate(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewBareMetalV1NoAuthClient()
th.AssertNoErr(t, err)
client.Microversion = "1.53"
node, err := v1.CreateFakeNode(t, client)
port, err := v1.CreatePort(t, client, node)
th.AssertNoErr(t, err)
defer v1.DeleteNode(t, client, node)
defer v1.DeletePort(t, client, port)
updated, err := ports.Update(client, port.UUID, ports.UpdateOpts{
ports.UpdateOperation{
Op: ports.ReplaceOp,
Path: "/address",
Value: "aa:bb:cc:dd:ee:ff",
},
}).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, updated.Address, "aa:bb:cc:dd:ee:ff")
}

View File

@@ -1,44 +0,0 @@
// +build acceptance baremetal allocations
package v1
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/openstack/baremetal/v1/allocations"
"github.com/gophercloud/gophercloud/pagination"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestAllocationsCreateDestroy(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewBareMetalV1Client()
th.AssertNoErr(t, err)
client.Microversion = "1.52"
allocation, err := CreateAllocation(t, client)
th.AssertNoErr(t, err)
defer DeleteAllocation(t, client, allocation)
found := false
err = allocations.List(client, allocations.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
allocationList, err := allocations.ExtractAllocations(page)
if err != nil {
return false, err
}
for _, a := range allocationList {
if a.UUID == allocation.UUID {
found = true
return true, nil
}
}
return false, nil
})
th.AssertNoErr(t, err)
th.AssertEquals(t, found, true)
}

View File

@@ -1,115 +0,0 @@
package v1
import (
"testing"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/baremetal/v1/allocations"
"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
"github.com/gophercloud/gophercloud/openstack/baremetal/v1/ports"
)
// CreateNode creates a basic node with a randomly generated name.
func CreateNode(t *testing.T, client *gophercloud.ServiceClient) (*nodes.Node, error) {
name := tools.RandomString("ACPTTEST", 16)
t.Logf("Attempting to create bare metal node: %s", name)
node, err := nodes.Create(client, nodes.CreateOpts{
Name: name,
Driver: "ipmi",
BootInterface: "pxe",
RAIDInterface: "agent",
DriverInfo: map[string]interface{}{
"ipmi_port": "6230",
"ipmi_username": "admin",
"deploy_kernel": "http://172.22.0.1/images/tinyipa-stable-rocky.vmlinuz",
"ipmi_address": "192.168.122.1",
"deploy_ramdisk": "http://172.22.0.1/images/tinyipa-stable-rocky.gz",
"ipmi_password": "admin",
},
}).Extract()
return node, err
}
// DeleteNode deletes a bare metal node via its UUID.
func DeleteNode(t *testing.T, client *gophercloud.ServiceClient, node *nodes.Node) {
err := nodes.Delete(client, node.UUID).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete node %s: %s", node.UUID, err)
}
t.Logf("Deleted server: %s", node.UUID)
}
// CreateAllocation creates an allocation
func CreateAllocation(t *testing.T, client *gophercloud.ServiceClient) (*allocations.Allocation, error) {
name := tools.RandomString("ACPTTEST", 16)
t.Logf("Attempting to create bare metal allocation: %s", name)
allocation, err := allocations.Create(client, allocations.CreateOpts{
Name: name,
ResourceClass: "baremetal",
}).Extract()
return allocation, err
}
// DeleteAllocation deletes a bare metal allocation via its UUID.
func DeleteAllocation(t *testing.T, client *gophercloud.ServiceClient, allocation *allocations.Allocation) {
err := allocations.Delete(client, allocation.UUID).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete allocation %s: %s", allocation.UUID, err)
}
t.Logf("Deleted allocation: %s", allocation.UUID)
}
// CreateFakeNode creates a node with fake-hardware to use for port tests.
func CreateFakeNode(t *testing.T, client *gophercloud.ServiceClient) (*nodes.Node, error) {
name := tools.RandomString("ACPTTEST", 16)
t.Logf("Attempting to create bare metal node: %s", name)
node, err := nodes.Create(client, nodes.CreateOpts{
Name: name,
Driver: "fake-hardware",
BootInterface: "pxe",
DriverInfo: map[string]interface{}{
"ipmi_port": "6230",
"ipmi_username": "admin",
"deploy_kernel": "http://172.22.0.1/images/tinyipa-stable-rocky.vmlinuz",
"ipmi_address": "192.168.122.1",
"deploy_ramdisk": "http://172.22.0.1/images/tinyipa-stable-rocky.gz",
"ipmi_password": "admin",
},
}).Extract()
return node, err
}
// CreatePort - creates a port for a node with a fixed Address
func CreatePort(t *testing.T, client *gophercloud.ServiceClient, node *nodes.Node) (*ports.Port, error) {
mac := "e6:72:1f:52:00:f4"
t.Logf("Attempting to create Port for Node: %s with Address: %s", node.UUID, mac)
iTrue := true
port, err := ports.Create(client, ports.CreateOpts{
NodeUUID: node.UUID,
Address: mac,
PXEEnabled: &iTrue,
}).Extract()
return port, err
}
// DeletePort - deletes a port via its UUID
func DeletePort(t *testing.T, client *gophercloud.ServiceClient, port *ports.Port) {
err := ports.Delete(client, port.UUID).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete port %s: %s", port.UUID, err)
}
t.Logf("Deleted port: %s", port.UUID)
}

View File

@@ -1,96 +0,0 @@
// +build acceptance baremetal nodes
package v1
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
"github.com/gophercloud/gophercloud/pagination"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestNodesCreateDestroy(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewBareMetalV1Client()
th.AssertNoErr(t, err)
client.Microversion = "1.38"
node, err := CreateNode(t, client)
th.AssertNoErr(t, err)
defer DeleteNode(t, client, node)
found := false
err = nodes.List(client, nodes.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
nodeList, err := nodes.ExtractNodes(page)
if err != nil {
return false, err
}
for _, n := range nodeList {
if n.UUID == node.UUID {
found = true
return true, nil
}
}
return false, nil
})
th.AssertNoErr(t, err)
th.AssertEquals(t, found, true)
}
func TestNodesUpdate(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewBareMetalV1Client()
th.AssertNoErr(t, err)
client.Microversion = "1.38"
node, err := CreateNode(t, client)
th.AssertNoErr(t, err)
defer DeleteNode(t, client, node)
updated, err := nodes.Update(client, node.UUID, nodes.UpdateOpts{
nodes.UpdateOperation{
Op: nodes.ReplaceOp,
Path: "/maintenance",
Value: "true",
},
}).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, updated.Maintenance, true)
}
func TestNodesRAIDConfig(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewBareMetalV1Client()
th.AssertNoErr(t, err)
client.Microversion = "1.50"
node, err := CreateNode(t, client)
th.AssertNoErr(t, err)
defer DeleteNode(t, client, node)
sizeGB := 100
isTrue := true
err = nodes.SetRAIDConfig(client, node.UUID, nodes.RAIDConfigOpts{
LogicalDisks: []nodes.LogicalDisk{
{
SizeGB: &sizeGB,
IsRootVolume: &isTrue,
RAIDLevel: nodes.RAID5,
DiskType: nodes.HDD,
NumberOfPhysicalDisks: 5,
},
},
}).ExtractErr()
th.AssertNoErr(t, err)
}

View File

@@ -1,72 +0,0 @@
// +build acceptance baremetal ports
package v1
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/openstack/baremetal/v1/ports"
"github.com/gophercloud/gophercloud/pagination"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestPortsCreateDestroy(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewBareMetalV1Client()
th.AssertNoErr(t, err)
client.Microversion = "1.53"
node, err := CreateFakeNode(t, client)
port, err := CreatePort(t, client, node)
th.AssertNoErr(t, err)
defer DeleteNode(t, client, node)
defer DeletePort(t, client, port)
found := false
err = ports.List(client, ports.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
portList, err := ports.ExtractPorts(page)
if err != nil {
return false, err
}
for _, p := range portList {
if p.UUID == port.UUID {
found = true
return true, nil
}
}
return false, nil
})
th.AssertNoErr(t, err)
th.AssertEquals(t, found, true)
}
func TestPortsUpdate(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewBareMetalV1Client()
th.AssertNoErr(t, err)
client.Microversion = "1.53"
node, err := CreateFakeNode(t, client)
port, err := CreatePort(t, client, node)
th.AssertNoErr(t, err)
defer DeleteNode(t, client, node)
defer DeletePort(t, client, port)
updated, err := ports.Update(client, port.UUID, ports.UpdateOpts{
ports.UpdateOperation{
Op: ports.ReplaceOp,
Path: "/address",
Value: "aa:bb:cc:dd:ee:ff",
},
}).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, updated.Address, "aa:bb:cc:dd:ee:ff")
}

View File

@@ -1,41 +0,0 @@
// +build acceptance blockstorage
package extensions
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/backups"
blockstorage "github.com/gophercloud/gophercloud/acceptance/openstack/blockstorage/v3"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestBackupsCRUD(t *testing.T) {
blockClient, err := clients.NewBlockStorageV3Client()
th.AssertNoErr(t, err)
volume, err := blockstorage.CreateVolume(t, blockClient)
th.AssertNoErr(t, err)
defer blockstorage.DeleteVolume(t, blockClient, volume)
backup, err := CreateBackup(t, blockClient, volume.ID)
th.AssertNoErr(t, err)
defer DeleteBackup(t, blockClient, backup.ID)
allPages, err := backups.List(blockClient, nil).AllPages()
th.AssertNoErr(t, err)
allBackups, err := backups.ExtractBackups(allPages)
th.AssertNoErr(t, err)
var found bool
for _, v := range allBackups {
if backup.Name == v.Name {
found = true
}
}
th.AssertEquals(t, found, true)
}

View File

@@ -1,236 +0,0 @@
// Package extensions contains common functions for creating block storage
// resources that are extensions of the block storage API. See the `*_test.go`
// files for example usages.
package extensions
import (
"testing"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/backups"
"github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes"
"github.com/gophercloud/gophercloud/openstack/compute/v2/images"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
th "github.com/gophercloud/gophercloud/testhelper"
)
// CreateUploadImage will upload volume it as volume-baked image. An name of new image or err will be
// returned
func CreateUploadImage(t *testing.T, client *gophercloud.ServiceClient, volume *volumes.Volume) (volumeactions.VolumeImage, error) {
if testing.Short() {
t.Skip("Skipping test that requires volume-backed image uploading in short mode.")
}
imageName := tools.RandomString("ACPTTEST", 16)
uploadImageOpts := volumeactions.UploadImageOpts{
ImageName: imageName,
Force: true,
}
volumeImage, err := volumeactions.UploadImage(client, volume.ID, uploadImageOpts).Extract()
if err != nil {
return volumeImage, err
}
t.Logf("Uploading volume %s as volume-backed image %s", volume.ID, imageName)
if err := volumes.WaitForStatus(client, volume.ID, "available", 60); err != nil {
return volumeImage, err
}
t.Logf("Uploaded volume %s as volume-backed image %s", volume.ID, imageName)
return volumeImage, nil
}
// DeleteUploadedImage deletes uploaded image. An error will be returned
// if the deletion request failed.
func DeleteUploadedImage(t *testing.T, client *gophercloud.ServiceClient, imageName string) error {
if testing.Short() {
t.Skip("Skipping test that requires volume-backed image removing in short mode.")
}
t.Logf("Getting image id for image name %s", imageName)
imageID, err := images.IDFromName(client, imageName)
if err != nil {
return err
}
t.Logf("Removing image %s", imageID)
err = images.Delete(client, imageID).ExtractErr()
if err != nil {
return err
}
return nil
}
// CreateVolumeAttach will attach a volume to an instance. An error will be
// returned if the attachment failed.
func CreateVolumeAttach(t *testing.T, client *gophercloud.ServiceClient, volume *volumes.Volume, server *servers.Server) error {
if testing.Short() {
t.Skip("Skipping test that requires volume attachment in short mode.")
}
attachOpts := volumeactions.AttachOpts{
MountPoint: "/mnt",
Mode: "rw",
InstanceUUID: server.ID,
}
t.Logf("Attempting to attach volume %s to server %s", volume.ID, server.ID)
if err := volumeactions.Attach(client, volume.ID, attachOpts).ExtractErr(); err != nil {
return err
}
if err := volumes.WaitForStatus(client, volume.ID, "in-use", 60); err != nil {
return err
}
t.Logf("Attached volume %s to server %s", volume.ID, server.ID)
return nil
}
// CreateVolumeReserve creates a volume reservation. An error will be returned
// if the reservation failed.
func CreateVolumeReserve(t *testing.T, client *gophercloud.ServiceClient, volume *volumes.Volume) error {
if testing.Short() {
t.Skip("Skipping test that requires volume reservation in short mode.")
}
t.Logf("Attempting to reserve volume %s", volume.ID)
if err := volumeactions.Reserve(client, volume.ID).ExtractErr(); err != nil {
return err
}
t.Logf("Reserved volume %s", volume.ID)
return nil
}
// DeleteVolumeAttach will detach a volume from an instance. A fatal error will
// occur if the snapshot failed to be deleted. This works best when used as a
// deferred function.
func DeleteVolumeAttach(t *testing.T, client *gophercloud.ServiceClient, volume *volumes.Volume) {
t.Logf("Attepting to detach volume volume: %s", volume.ID)
detachOpts := volumeactions.DetachOpts{
AttachmentID: volume.Attachments[0].AttachmentID,
}
if err := volumeactions.Detach(client, volume.ID, detachOpts).ExtractErr(); err != nil {
t.Fatalf("Unable to detach volume %s: %v", volume.ID, err)
}
if err := volumes.WaitForStatus(client, volume.ID, "available", 60); err != nil {
t.Fatalf("Volume %s failed to become unavailable in 60 seconds: %v", volume.ID, err)
}
t.Logf("Detached volume: %s", volume.ID)
}
// DeleteVolumeReserve deletes a volume reservation. A fatal error will occur
// if the deletion request failed. This works best when used as a deferred
// function.
func DeleteVolumeReserve(t *testing.T, client *gophercloud.ServiceClient, volume *volumes.Volume) {
if testing.Short() {
t.Skip("Skipping test that requires volume reservation in short mode.")
}
t.Logf("Attempting to unreserve volume %s", volume.ID)
if err := volumeactions.Unreserve(client, volume.ID).ExtractErr(); err != nil {
t.Fatalf("Unable to unreserve volume %s: %v", volume.ID, err)
}
t.Logf("Unreserved volume %s", volume.ID)
}
// ExtendVolumeSize will extend the size of a volume.
func ExtendVolumeSize(t *testing.T, client *gophercloud.ServiceClient, volume *volumes.Volume) error {
t.Logf("Attempting to extend the size of volume %s", volume.ID)
extendOpts := volumeactions.ExtendSizeOpts{
NewSize: 2,
}
err := volumeactions.ExtendSize(client, volume.ID, extendOpts).ExtractErr()
if err != nil {
return err
}
if err := volumes.WaitForStatus(client, volume.ID, "available", 60); err != nil {
return err
}
return nil
}
// CreateBackup will create a backup based on a volume. An error will be
// will be returned if the backup could not be created.
func CreateBackup(t *testing.T, client *gophercloud.ServiceClient, volumeID string) (*backups.Backup, error) {
t.Logf("Attempting to create a backup of volume %s", volumeID)
backupName := tools.RandomString("ACPTTEST", 16)
createOpts := backups.CreateOpts{
VolumeID: volumeID,
Name: backupName,
}
backup, err := backups.Create(client, createOpts).Extract()
if err != nil {
return nil, err
}
err = WaitForBackupStatus(client, backup.ID, "available", 120)
if err != nil {
return nil, err
}
backup, err = backups.Get(client, backup.ID).Extract()
if err != nil {
return nil, err
}
t.Logf("Successfully created backup %s", backup.ID)
tools.PrintResource(t, backup)
th.AssertEquals(t, backup.Name, backupName)
return backup, nil
}
// DeleteBackup will delete a backup. A fatal error will occur if the backup
// could not be deleted. This works best when used as a deferred function.
func DeleteBackup(t *testing.T, client *gophercloud.ServiceClient, backupID string) {
if err := backups.Delete(client, backupID).ExtractErr(); err != nil {
t.Fatalf("Unable to delete backup %s: %s", backupID, err)
}
t.Logf("Deleted backup %s", backupID)
}
// WaitForBackupStatus will continually poll a backup, checking for a particular
// status. It will do this for the amount of seconds defined.
func WaitForBackupStatus(client *gophercloud.ServiceClient, id, status string, secs int) error {
return gophercloud.WaitFor(secs, func() (bool, error) {
current, err := backups.Get(client, id).Extract()
if err != nil {
return false, err
}
if current.Status == status {
return true, nil
}
return false, nil
})
}

View File

@@ -1,3 +0,0 @@
// The extensions package contains acceptance tests for the Openstack Cinder extensions service.
package extensions

View File

@@ -1,59 +0,0 @@
// +build acceptance blockstorage
package extensions
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/schedulerhints"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestSchedulerHints(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewBlockStorageV3Client()
th.AssertNoErr(t, err)
volumeName := tools.RandomString("ACPTTEST", 16)
createOpts := volumes.CreateOpts{
Size: 1,
Name: volumeName,
}
volume1, err := volumes.Create(client, createOpts).Extract()
th.AssertNoErr(t, err)
err = volumes.WaitForStatus(client, volume1.ID, "available", 60)
th.AssertNoErr(t, err)
defer volumes.Delete(client, volume1.ID, volumes.DeleteOpts{})
volumeName = tools.RandomString("ACPTTEST", 16)
base := volumes.CreateOpts{
Size: 1,
Name: volumeName,
}
schedulerHints := schedulerhints.SchedulerHints{
SameHost: []string{
volume1.ID,
},
}
createOptsWithHints := schedulerhints.CreateOptsExt{
VolumeCreateOptsBuilder: base,
SchedulerHints: schedulerHints,
}
volume2, err := volumes.Create(client, createOptsWithHints).Extract()
th.AssertNoErr(t, err)
err = volumes.WaitForStatus(client, volume2.ID, "available", 60)
th.AssertNoErr(t, err)
err = volumes.Delete(client, volume2.ID, volumes.DeleteOpts{}).ExtractErr()
th.AssertNoErr(t, err)
}

View File

@@ -1,33 +0,0 @@
// +build acceptance blockstorage
package extensions
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/schedulerstats"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestSchedulerStatsList(t *testing.T) {
clients.RequireAdmin(t)
blockClient, err := clients.NewBlockStorageV2Client()
th.AssertNoErr(t, err)
listOpts := schedulerstats.ListOpts{
Detail: true,
}
allPages, err := schedulerstats.List(blockClient, listOpts).AllPages()
th.AssertNoErr(t, err)
allStats, err := schedulerstats.ExtractStoragePools(allPages)
th.AssertNoErr(t, err)
for _, stat := range allStats {
tools.PrintResource(t, stat)
}
}

View File

@@ -1,29 +0,0 @@
// +build acceptance blockstorage
package extensions
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/services"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestServicesList(t *testing.T) {
clients.RequireAdmin(t)
blockClient, err := clients.NewBlockStorageV3Client()
th.AssertNoErr(t, err)
allPages, err := services.List(blockClient, services.ListOpts{}).AllPages()
th.AssertNoErr(t, err)
allServices, err := services.ExtractServices(allPages)
th.AssertNoErr(t, err)
for _, service := range allServices {
tools.PrintResource(t, service)
}
}

View File

@@ -1,137 +0,0 @@
// +build acceptance blockstorage
package extensions
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
blockstorage "github.com/gophercloud/gophercloud/acceptance/openstack/blockstorage/v2"
compute "github.com/gophercloud/gophercloud/acceptance/openstack/compute/v2"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestVolumeActionsUploadImageDestroy(t *testing.T) {
t.Skip("This test is diabled because it sometimes fails in OpenLab")
blockClient, err := clients.NewBlockStorageV2Client()
th.AssertNoErr(t, err)
computeClient, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
volume, err := blockstorage.CreateVolume(t, blockClient)
th.AssertNoErr(t, err)
defer blockstorage.DeleteVolume(t, blockClient, volume)
volumeImage, err := CreateUploadImage(t, blockClient, volume)
th.AssertNoErr(t, err)
tools.PrintResource(t, volumeImage)
err = DeleteUploadedImage(t, computeClient, volumeImage.ImageName)
th.AssertNoErr(t, err)
}
func TestVolumeActionsAttachCreateDestroy(t *testing.T) {
blockClient, err := clients.NewBlockStorageV2Client()
th.AssertNoErr(t, err)
computeClient, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
server, err := compute.CreateServer(t, computeClient)
th.AssertNoErr(t, err)
defer compute.DeleteServer(t, computeClient, server)
volume, err := blockstorage.CreateVolume(t, blockClient)
th.AssertNoErr(t, err)
defer blockstorage.DeleteVolume(t, blockClient, volume)
err = CreateVolumeAttach(t, blockClient, volume, server)
th.AssertNoErr(t, err)
newVolume, err := volumes.Get(blockClient, volume.ID).Extract()
th.AssertNoErr(t, err)
DeleteVolumeAttach(t, blockClient, newVolume)
}
func TestVolumeActionsReserveUnreserve(t *testing.T) {
client, err := clients.NewBlockStorageV2Client()
th.AssertNoErr(t, err)
volume, err := blockstorage.CreateVolume(t, client)
th.AssertNoErr(t, err)
defer blockstorage.DeleteVolume(t, client, volume)
err = CreateVolumeReserve(t, client, volume)
th.AssertNoErr(t, err)
defer DeleteVolumeReserve(t, client, volume)
}
func TestVolumeActionsExtendSize(t *testing.T) {
blockClient, err := clients.NewBlockStorageV2Client()
th.AssertNoErr(t, err)
volume, err := blockstorage.CreateVolume(t, blockClient)
th.AssertNoErr(t, err)
defer blockstorage.DeleteVolume(t, blockClient, volume)
tools.PrintResource(t, volume)
err = ExtendVolumeSize(t, blockClient, volume)
th.AssertNoErr(t, err)
newVolume, err := volumes.Get(blockClient, volume.ID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, newVolume)
}
// Note(jtopjian): I plan to work on this at some point, but it requires
// setting up a server with iscsi utils.
/*
func TestVolumeConns(t *testing.T) {
client, err := newClient()
th.AssertNoErr(t, err)
t.Logf("Creating volume")
cv, err := volumes.Create(client, &volumes.CreateOpts{
Size: 1,
Name: "blockv2-volume",
}).Extract()
th.AssertNoErr(t, err)
defer func() {
err = volumes.WaitForStatus(client, cv.ID, "available", 60)
th.AssertNoErr(t, err)
t.Logf("Deleting volume")
err = volumes.Delete(client, cv.ID, volumes.DeleteOpts{}).ExtractErr()
th.AssertNoErr(t, err)
}()
err = volumes.WaitForStatus(client, cv.ID, "available", 60)
th.AssertNoErr(t, err)
connOpts := &volumeactions.ConnectorOpts{
IP: "127.0.0.1",
Host: "stack",
Initiator: "iqn.1994-05.com.redhat:17cf566367d2",
Multipath: false,
Platform: "x86_64",
OSType: "linux2",
}
t.Logf("Initializing connection")
_, err = volumeactions.InitializeConnection(client, cv.ID, connOpts).Extract()
th.AssertNoErr(t, err)
t.Logf("Terminating connection")
err = volumeactions.TerminateConnection(client, cv.ID, connOpts).ExtractErr()
th.AssertNoErr(t, err)
}
*/

View File

@@ -1,46 +0,0 @@
// +build acceptance blockstorage
package extensions
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
blockstorage "github.com/gophercloud/gophercloud/acceptance/openstack/blockstorage/v3"
"github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumetenants"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestVolumeTenants(t *testing.T) {
type volumeWithTenant struct {
volumes.Volume
volumetenants.VolumeTenantExt
}
var allVolumes []volumeWithTenant
client, err := clients.NewBlockStorageV3Client()
th.AssertNoErr(t, err)
listOpts := volumes.ListOpts{
Name: "I SHOULD NOT EXIST",
}
allPages, err := volumes.List(client, listOpts).AllPages()
th.AssertNoErr(t, err)
err = volumes.ExtractVolumesInto(allPages, &allVolumes)
th.AssertNoErr(t, err)
th.AssertEquals(t, 0, len(allVolumes))
volume1, err := blockstorage.CreateVolume(t, client)
th.AssertNoErr(t, err)
defer blockstorage.DeleteVolume(t, client, volume1)
allPages, err = volumes.List(client, nil).AllPages()
th.AssertNoErr(t, err)
err = volumes.ExtractVolumesInto(allPages, &allVolumes)
th.AssertNoErr(t, err)
th.AssertEquals(t, true, len(allVolumes) > 0)
}

View File

@@ -1,142 +0,0 @@
// Package noauth contains common functions for creating block storage based
// resources for use in acceptance tests. See the `*_test.go` files for
// example usages.
package noauth
import (
"testing"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v2/snapshots"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes"
)
// CreateVolume will create a volume with a random name and size of 1GB. An
// error will be returned if the volume was unable to be created.
func CreateVolume(t *testing.T, client *gophercloud.ServiceClient) (*volumes.Volume, error) {
if testing.Short() {
t.Skip("Skipping test that requires volume creation in short mode.")
}
volumeName := tools.RandomString("ACPTTEST", 16)
t.Logf("Attempting to create volume: %s", volumeName)
createOpts := volumes.CreateOpts{
Size: 1,
Name: volumeName,
}
volume, err := volumes.Create(client, createOpts).Extract()
if err != nil {
return volume, err
}
err = volumes.WaitForStatus(client, volume.ID, "available", 60)
if err != nil {
return volume, err
}
return volume, nil
}
// CreateVolumeFromImage will create a volume from with a random name and size of
// 1GB. An error will be returned if the volume was unable to be created.
func CreateVolumeFromImage(t *testing.T, client *gophercloud.ServiceClient) (*volumes.Volume, error) {
if testing.Short() {
t.Skip("Skipping test that requires volume creation in short mode.")
}
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
t.Fatal(err)
}
volumeName := tools.RandomString("ACPTTEST", 16)
t.Logf("Attempting to create volume: %s", volumeName)
createOpts := volumes.CreateOpts{
Size: 1,
Name: volumeName,
ImageID: choices.ImageID,
}
volume, err := volumes.Create(client, createOpts).Extract()
if err != nil {
return volume, err
}
err = volumes.WaitForStatus(client, volume.ID, "available", 60)
if err != nil {
return volume, err
}
return volume, nil
}
// DeleteVolume will delete a volume. A fatal error will occur if the volume
// failed to be deleted. This works best when used as a deferred function.
func DeleteVolume(t *testing.T, client *gophercloud.ServiceClient, volume *volumes.Volume) {
err := volumes.Delete(client, volume.ID, volumes.DeleteOpts{}).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete volume %s: %v", volume.ID, err)
}
t.Logf("Deleted volume: %s", volume.ID)
}
// CreateSnapshot will create a snapshot of the specified volume.
// Snapshot will be assigned a random name and description.
func CreateSnapshot(t *testing.T, client *gophercloud.ServiceClient, volume *volumes.Volume) (*snapshots.Snapshot, error) {
if testing.Short() {
t.Skip("Skipping test that requires snapshot creation in short mode.")
}
snapshotName := tools.RandomString("ACPTTEST", 16)
snapshotDescription := tools.RandomString("ACPTTEST", 16)
t.Logf("Attempting to create snapshot: %s", snapshotName)
createOpts := snapshots.CreateOpts{
VolumeID: volume.ID,
Name: snapshotName,
Description: snapshotDescription,
}
snapshot, err := snapshots.Create(client, createOpts).Extract()
if err != nil {
return snapshot, err
}
err = snapshots.WaitForStatus(client, snapshot.ID, "available", 60)
if err != nil {
return snapshot, err
}
return snapshot, nil
}
// DeleteSnapshot will delete a snapshot. A fatal error will occur if the
// snapshot failed to be deleted.
func DeleteSnapshot(t *testing.T, client *gophercloud.ServiceClient, snapshot *snapshots.Snapshot) {
err := snapshots.Delete(client, snapshot.ID).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete snapshot %s: %+v", snapshot.ID, err)
}
// Volumes can't be deleted until their snapshots have been,
// so block up to 120 seconds for the snapshot to delete.
err = gophercloud.WaitFor(120, func() (bool, error) {
_, err := snapshots.Get(client, snapshot.ID).Extract()
if err != nil {
return true, nil
}
return false, nil
})
if err != nil {
t.Fatalf("Error waiting for snapshot to delete: %v", err)
}
t.Logf("Deleted snapshot: %s", snapshot.ID)
}

View File

@@ -1,3 +0,0 @@
// The noauth package contains acceptance tests for the Openstack Cinder standalone service.
package noauth

View File

@@ -1,58 +0,0 @@
// +build acceptance blockstorage
package noauth
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v2/snapshots"
)
func TestSnapshotsList(t *testing.T) {
client, err := clients.NewBlockStorageV2NoAuthClient()
if err != nil {
t.Fatalf("Unable to create a blockstorage client: %v", err)
}
allPages, err := snapshots.List(client, snapshots.ListOpts{}).AllPages()
if err != nil {
t.Fatalf("Unable to retrieve snapshots: %v", err)
}
allSnapshots, err := snapshots.ExtractSnapshots(allPages)
if err != nil {
t.Fatalf("Unable to extract snapshots: %v", err)
}
for _, snapshot := range allSnapshots {
tools.PrintResource(t, snapshot)
}
}
func TestSnapshotsCreateDelete(t *testing.T) {
client, err := clients.NewBlockStorageV2NoAuthClient()
if err != nil {
t.Fatalf("Unable to create a blockstorage client: %v", err)
}
volume, err := CreateVolume(t, client)
if err != nil {
t.Fatalf("Unable to create volume: %v", err)
}
defer DeleteVolume(t, client, volume)
snapshot, err := CreateSnapshot(t, client, volume)
if err != nil {
t.Fatalf("Unable to create snapshot: %v", err)
}
defer DeleteSnapshot(t, client, snapshot)
newSnapshot, err := snapshots.Get(client, snapshot.ID).Extract()
if err != nil {
t.Errorf("Unable to retrieve snapshot: %v", err)
}
tools.PrintResource(t, newSnapshot)
}

View File

@@ -1,52 +0,0 @@
// +build acceptance blockstorage
package noauth
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes"
)
func TestVolumesList(t *testing.T) {
client, err := clients.NewBlockStorageV2NoAuthClient()
if err != nil {
t.Fatalf("Unable to create a blockstorage client: %v", err)
}
allPages, err := volumes.List(client, volumes.ListOpts{}).AllPages()
if err != nil {
t.Fatalf("Unable to retrieve volumes: %v", err)
}
allVolumes, err := volumes.ExtractVolumes(allPages)
if err != nil {
t.Fatalf("Unable to extract volumes: %v", err)
}
for _, volume := range allVolumes {
tools.PrintResource(t, volume)
}
}
func TestVolumesCreateDestroy(t *testing.T) {
client, err := clients.NewBlockStorageV2NoAuthClient()
if err != nil {
t.Fatalf("Unable to create blockstorage client: %v", err)
}
volume, err := CreateVolume(t, client)
if err != nil {
t.Fatalf("Unable to create volume: %v", err)
}
defer DeleteVolume(t, client, volume)
newVolume, err := volumes.Get(client, volume.ID).Extract()
if err != nil {
t.Errorf("Unable to retrieve volume: %v", err)
}
tools.PrintResource(t, newVolume)
}

View File

@@ -1,144 +0,0 @@
// Package v1 contains common functions for creating block storage based
// resources for use in acceptance tests. See the `*_test.go` files for
// example usages.
package v1
import (
"testing"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v1/snapshots"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumetypes"
)
// CreateSnapshot will create a volume snapshot based off of a given volume and
// with a random name. An error will be returned if the snapshot failed to be
// created.
func CreateSnapshot(t *testing.T, client *gophercloud.ServiceClient, volume *volumes.Volume) (*snapshots.Snapshot, error) {
if testing.Short() {
t.Skip("Skipping test that requires snapshot creation in short mode.")
}
snapshotName := tools.RandomString("ACPTTEST", 16)
t.Logf("Attempting to create snapshot %s based on volume %s", snapshotName, volume.ID)
createOpts := snapshots.CreateOpts{
Name: snapshotName,
VolumeID: volume.ID,
}
snapshot, err := snapshots.Create(client, createOpts).Extract()
if err != nil {
return snapshot, err
}
err = snapshots.WaitForStatus(client, snapshot.ID, "available", 60)
if err != nil {
return snapshot, err
}
return snapshot, nil
}
// CreateVolume will create a volume with a random name and size of 1GB. An
// error will be returned if the volume was unable to be created.
func CreateVolume(t *testing.T, client *gophercloud.ServiceClient) (*volumes.Volume, error) {
if testing.Short() {
t.Skip("Skipping test that requires volume creation in short mode.")
}
volumeName := tools.RandomString("ACPTTEST", 16)
volumeDescription := tools.RandomString("ACPTTEST-DESC", 16)
t.Logf("Attempting to create volume: %s", volumeName)
createOpts := volumes.CreateOpts{
Size: 1,
Name: volumeName,
Description: volumeDescription,
}
volume, err := volumes.Create(client, createOpts).Extract()
if err != nil {
return volume, err
}
err = volumes.WaitForStatus(client, volume.ID, "available", 60)
if err != nil {
return volume, err
}
return volume, nil
}
// CreateVolumeType will create a volume type with a random name. An error will
// be returned if the volume type was unable to be created.
func CreateVolumeType(t *testing.T, client *gophercloud.ServiceClient) (*volumetypes.VolumeType, error) {
volumeTypeName := tools.RandomString("ACPTTEST", 16)
t.Logf("Attempting to create volume type: %s", volumeTypeName)
createOpts := volumetypes.CreateOpts{
Name: volumeTypeName,
ExtraSpecs: map[string]interface{}{
"capabilities": "ssd",
"priority": 3,
},
}
volumeType, err := volumetypes.Create(client, createOpts).Extract()
if err != nil {
return volumeType, err
}
return volumeType, nil
}
// DeleteSnapshot will delete a snapshot. A fatal error will occur if the
// snapshot failed to be deleted. This works best when used as a deferred
// function.
func DeleteSnapshotshot(t *testing.T, client *gophercloud.ServiceClient, snapshot *snapshots.Snapshot) {
err := snapshots.Delete(client, snapshot.ID).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete snapshot %s: %v", snapshot.ID, err)
}
// Volumes can't be deleted until their snapshots have been,
// so block up to 120 seconds for the snapshot to delete.
err = gophercloud.WaitFor(120, func() (bool, error) {
_, err := snapshots.Get(client, snapshot.ID).Extract()
if err != nil {
return true, nil
}
return false, nil
})
if err != nil {
t.Fatalf("Unable to wait for snapshot to delete: %v", err)
}
t.Logf("Deleted snapshot: %s", snapshot.ID)
}
// DeleteVolume will delete a volume. A fatal error will occur if the volume
// failed to be deleted. This works best when used as a deferred function.
func DeleteVolume(t *testing.T, client *gophercloud.ServiceClient, volume *volumes.Volume) {
err := volumes.Delete(client, volume.ID).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete volume %s: %v", volume.ID, err)
}
t.Logf("Deleted volume: %s", volume.ID)
}
// DeleteVolumeType will delete a volume type. A fatal error will occur if the
// volume type failed to be deleted. This works best when used as a deferred
// function.
func DeleteVolumeType(t *testing.T, client *gophercloud.ServiceClient, volumeType *volumetypes.VolumeType) {
err := volumetypes.Delete(client, volumeType.ID).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete volume type %s: %v", volumeType.ID, err)
}
t.Logf("Deleted volume type: %s", volumeType.ID)
}

View File

@@ -1,2 +0,0 @@
// Package v1 contains openstack cinder acceptance tests
package v1

View File

@@ -1,58 +0,0 @@
// +build acceptance blockstorage
package v1
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v1/snapshots"
)
func TestSnapshotsList(t *testing.T) {
client, err := clients.NewBlockStorageV1Client()
if err != nil {
t.Fatalf("Unable to create a blockstorage client: %v", err)
}
allPages, err := snapshots.List(client, snapshots.ListOpts{}).AllPages()
if err != nil {
t.Fatalf("Unable to retrieve snapshots: %v", err)
}
allSnapshots, err := snapshots.ExtractSnapshots(allPages)
if err != nil {
t.Fatalf("Unable to extract snapshots: %v", err)
}
for _, snapshot := range allSnapshots {
tools.PrintResource(t, snapshot)
}
}
func TestSnapshotsCreateDelete(t *testing.T) {
client, err := clients.NewBlockStorageV1Client()
if err != nil {
t.Fatalf("Unable to create a blockstorage client: %v", err)
}
volume, err := CreateVolume(t, client)
if err != nil {
t.Fatalf("Unable to create volume: %v", err)
}
defer DeleteVolume(t, client, volume)
snapshot, err := CreateSnapshot(t, client, volume)
if err != nil {
t.Fatalf("Unable to create snapshot: %v", err)
}
defer DeleteSnapshotshot(t, client, snapshot)
newSnapshot, err := snapshots.Get(client, snapshot.ID).Extract()
if err != nil {
t.Errorf("Unable to retrieve snapshot: %v", err)
}
tools.PrintResource(t, newSnapshot)
}

View File

@@ -1,69 +0,0 @@
// +build acceptance blockstorage
package v1
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestVolumesList(t *testing.T) {
client, err := clients.NewBlockStorageV1Client()
if err != nil {
t.Fatalf("Unable to create a blockstorage client: %v", err)
}
allPages, err := volumes.List(client, volumes.ListOpts{}).AllPages()
if err != nil {
t.Fatalf("Unable to retrieve volumes: %v", err)
}
allVolumes, err := volumes.ExtractVolumes(allPages)
if err != nil {
t.Fatalf("Unable to extract volumes: %v", err)
}
for _, volume := range allVolumes {
tools.PrintResource(t, volume)
}
}
func TestVolumesCreateDestroy(t *testing.T) {
client, err := clients.NewBlockStorageV1Client()
if err != nil {
t.Fatalf("Unable to create blockstorage client: %v", err)
}
volume, err := CreateVolume(t, client)
if err != nil {
t.Fatalf("Unable to create volume: %v", err)
}
defer DeleteVolume(t, client, volume)
newVolume, err := volumes.Get(client, volume.ID).Extract()
if err != nil {
t.Errorf("Unable to retrieve volume: %v", err)
}
tools.PrintResource(t, newVolume)
th.AssertEquals(t, volume.Name, newVolume.Name)
th.AssertEquals(t, volume.Description, newVolume.Description)
// Update volume
updatedVolumeName := ""
updatedVolumeDescription := ""
updateOpts := volumes.UpdateOpts{
Name: &updatedVolumeName,
Description: &updatedVolumeDescription,
}
updatedVolume, err := volumes.Update(client, volume.ID, updateOpts).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, updatedVolume)
th.AssertEquals(t, updatedVolume.Name, updatedVolumeName)
th.AssertEquals(t, updatedVolume.Description, updatedVolumeDescription)
}

View File

@@ -1,47 +0,0 @@
// +build acceptance blockstorage
package v1
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumetypes"
)
func TestVolumeTypesList(t *testing.T) {
client, err := clients.NewBlockStorageV1Client()
if err != nil {
t.Fatalf("Unable to create a blockstorage client: %v", err)
}
allPages, err := volumetypes.List(client).AllPages()
if err != nil {
t.Fatalf("Unable to retrieve volume types: %v", err)
}
allVolumeTypes, err := volumetypes.ExtractVolumeTypes(allPages)
if err != nil {
t.Fatalf("Unable to extract volume types: %v", err)
}
for _, volumeType := range allVolumeTypes {
tools.PrintResource(t, volumeType)
}
}
func TestVolumeTypesCreateDestroy(t *testing.T) {
client, err := clients.NewBlockStorageV1Client()
if err != nil {
t.Fatalf("Unable to create a blockstorage client: %v", err)
}
volumeType, err := CreateVolumeType(t, client)
if err != nil {
t.Fatalf("Unable to create volume type: %v", err)
}
defer DeleteVolumeType(t, client, volumeType)
tools.PrintResource(t, volumeType)
}

View File

@@ -1,156 +0,0 @@
// Package v2 contains common functions for creating block storage based
// resources for use in acceptance tests. See the `*_test.go` files for
// example usages.
package v2
import (
"testing"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v2/snapshots"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes"
th "github.com/gophercloud/gophercloud/testhelper"
)
// CreateSnapshot will create a snapshot of the specified volume.
// Snapshot will be assigned a random name and description.
func CreateSnapshot(t *testing.T, client *gophercloud.ServiceClient, volume *volumes.Volume) (*snapshots.Snapshot, error) {
snapshotName := tools.RandomString("ACPTTEST", 16)
snapshotDescription := tools.RandomString("ACPTTEST", 16)
t.Logf("Attempting to create snapshot: %s", snapshotName)
createOpts := snapshots.CreateOpts{
VolumeID: volume.ID,
Name: snapshotName,
Description: snapshotDescription,
}
snapshot, err := snapshots.Create(client, createOpts).Extract()
if err != nil {
return snapshot, err
}
err = snapshots.WaitForStatus(client, snapshot.ID, "available", 60)
if err != nil {
return snapshot, err
}
t.Logf("Successfully created snapshot: %s", snapshot.ID)
return snapshot, nil
}
// CreateVolume will create a volume with a random name and size of 1GB. An
// error will be returned if the volume was unable to be created.
func CreateVolume(t *testing.T, client *gophercloud.ServiceClient) (*volumes.Volume, error) {
volumeName := tools.RandomString("ACPTTEST", 16)
volumeDescription := tools.RandomString("ACPTTEST-DESC", 16)
t.Logf("Attempting to create volume: %s", volumeName)
createOpts := volumes.CreateOpts{
Size: 1,
Name: volumeName,
Description: volumeDescription,
}
volume, err := volumes.Create(client, createOpts).Extract()
if err != nil {
return volume, err
}
err = volumes.WaitForStatus(client, volume.ID, "available", 60)
if err != nil {
return volume, err
}
tools.PrintResource(t, volume)
th.AssertEquals(t, volume.Name, volumeName)
th.AssertEquals(t, volume.Description, volumeDescription)
th.AssertEquals(t, volume.Size, 1)
t.Logf("Successfully created volume: %s", volume.ID)
return volume, nil
}
// CreateVolumeFromImage will create a volume from with a random name and size of
// 1GB. An error will be returned if the volume was unable to be created.
func CreateVolumeFromImage(t *testing.T, client *gophercloud.ServiceClient) (*volumes.Volume, error) {
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
t.Fatal(err)
}
volumeName := tools.RandomString("ACPTTEST", 16)
t.Logf("Attempting to create volume: %s", volumeName)
createOpts := volumes.CreateOpts{
Size: 1,
Name: volumeName,
ImageID: choices.ImageID,
}
volume, err := volumes.Create(client, createOpts).Extract()
if err != nil {
return volume, err
}
err = volumes.WaitForStatus(client, volume.ID, "available", 60)
if err != nil {
return volume, err
}
newVolume, err := volumes.Get(client, volume.ID).Extract()
if err != nil {
return nil, err
}
th.AssertEquals(t, newVolume.Name, volumeName)
th.AssertEquals(t, newVolume.Size, 1)
t.Logf("Successfully created volume from image: %s", newVolume.ID)
return newVolume, nil
}
// DeleteVolume will delete a volume. A fatal error will occur if the volume
// failed to be deleted. This works best when used as a deferred function.
func DeleteVolume(t *testing.T, client *gophercloud.ServiceClient, volume *volumes.Volume) {
t.Logf("Attempting to delete volume: %s", volume.ID)
err := volumes.Delete(client, volume.ID, volumes.DeleteOpts{}).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete volume %s: %v", volume.ID, err)
}
t.Logf("Successfully deleted volume: %s", volume.ID)
}
// DeleteSnapshot will delete a snapshot. A fatal error will occur if the
// snapshot failed to be deleted.
func DeleteSnapshot(t *testing.T, client *gophercloud.ServiceClient, snapshot *snapshots.Snapshot) {
t.Logf("Attempting to delete snapshot: %s", snapshot.ID)
err := snapshots.Delete(client, snapshot.ID).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete snapshot %s: %+v", snapshot.ID, err)
}
// Volumes can't be deleted until their snapshots have been,
// so block up to 120 seconds for the snapshot to delete.
err = gophercloud.WaitFor(120, func() (bool, error) {
_, err := snapshots.Get(client, snapshot.ID).Extract()
if err != nil {
return true, nil
}
return false, nil
})
if err != nil {
t.Fatalf("Error waiting for snapshot to delete: %v", err)
}
t.Logf("Successfully deleted snapshot: %s", snapshot.ID)
}

View File

@@ -1,3 +0,0 @@
// The v2 package contains acceptance tests for the Openstack Cinder V2 service.
package v2

View File

@@ -1,46 +0,0 @@
// +build acceptance blockstorage
package v2
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v2/snapshots"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestSnapshots(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewBlockStorageV2Client()
th.AssertNoErr(t, err)
volume, err := CreateVolume(t, client)
th.AssertNoErr(t, err)
defer DeleteVolume(t, client, volume)
snapshot, err := CreateSnapshot(t, client, volume)
th.AssertNoErr(t, err)
defer DeleteSnapshot(t, client, snapshot)
newSnapshot, err := snapshots.Get(client, snapshot.ID).Extract()
th.AssertNoErr(t, err)
allPages, err := snapshots.List(client, snapshots.ListOpts{}).AllPages()
th.AssertNoErr(t, err)
allSnapshots, err := snapshots.ExtractSnapshots(allPages)
th.AssertNoErr(t, err)
var found bool
for _, v := range allSnapshots {
tools.PrintResource(t, snapshot)
if v.ID == newSnapshot.ID {
found = true
}
}
th.AssertEquals(t, found, true)
}

View File

@@ -1,128 +0,0 @@
// +build acceptance blockstorage
package v2
import (
"testing"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v2/snapshots"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestVolumesCreateDestroy(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewBlockStorageV2Client()
th.AssertNoErr(t, err)
volume, err := CreateVolume(t, client)
th.AssertNoErr(t, err)
defer DeleteVolume(t, client, volume)
newVolume, err := volumes.Get(client, volume.ID).Extract()
th.AssertNoErr(t, err)
// Update volume
updatedVolumeName := ""
updatedVolumeDescription := ""
updateOpts := volumes.UpdateOpts{
Name: &updatedVolumeName,
Description: &updatedVolumeDescription,
}
updatedVolume, err := volumes.Update(client, volume.ID, updateOpts).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, updatedVolume)
th.AssertEquals(t, updatedVolume.Name, updatedVolumeName)
th.AssertEquals(t, updatedVolume.Description, updatedVolumeDescription)
allPages, err := volumes.List(client, volumes.ListOpts{}).AllPages()
th.AssertNoErr(t, err)
allVolumes, err := volumes.ExtractVolumes(allPages)
th.AssertNoErr(t, err)
var found bool
for _, v := range allVolumes {
tools.PrintResource(t, volume)
if v.ID == newVolume.ID {
found = true
}
}
th.AssertEquals(t, found, true)
}
func TestVolumesCreateForceDestroy(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewBlockStorageV2Client()
th.AssertNoErr(t, err)
volume, err := CreateVolume(t, client)
th.AssertNoErr(t, err)
newVolume, err := volumes.Get(client, volume.ID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, newVolume)
err = volumeactions.ForceDelete(client, newVolume.ID).ExtractErr()
th.AssertNoErr(t, err)
}
func TestVolumesCascadeDelete(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewBlockStorageV3Client()
th.AssertNoErr(t, err)
vol, err := CreateVolume(t, client)
th.AssertNoErr(t, err)
err = volumes.WaitForStatus(client, vol.ID, "available", 60)
th.AssertNoErr(t, err)
snapshot1, err := CreateSnapshot(t, client, vol)
th.AssertNoErr(t, err)
snapshot2, err := CreateSnapshot(t, client, vol)
th.AssertNoErr(t, err)
t.Logf("Attempting to delete volume: %s", vol.ID)
deleteOpts := volumes.DeleteOpts{Cascade: true}
err = volumes.Delete(client, vol.ID, deleteOpts).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete volume %s: %v", vol.ID, err)
}
for _, sid := range []string{snapshot1.ID, snapshot2.ID} {
err := gophercloud.WaitFor(120, func() (bool, error) {
_, err := snapshots.Get(client, sid).Extract()
if err != nil {
return true, nil
}
return false, nil
})
th.AssertNoErr(t, err)
t.Logf("Successfully deleted snapshot: %s", sid)
}
err = gophercloud.WaitFor(120, func() (bool, error) {
_, err := volumes.Get(client, vol.ID).Extract()
if err != nil {
return true, nil
}
return false, nil
})
th.AssertNoErr(t, err)
t.Logf("Successfully deleted volume: %s", vol.ID)
}

View File

@@ -1,163 +0,0 @@
// Package v3 contains common functions for creating block storage based
// resources for use in acceptance tests. See the `*_test.go` files for
// example usages.
package v3
import (
"testing"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/snapshots"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumetypes"
th "github.com/gophercloud/gophercloud/testhelper"
)
// CreateSnapshot will create a snapshot of the specified volume.
// Snapshot will be assigned a random name and description.
func CreateSnapshot(t *testing.T, client *gophercloud.ServiceClient, volume *volumes.Volume) (*snapshots.Snapshot, error) {
snapshotName := tools.RandomString("ACPTTEST", 16)
snapshotDescription := tools.RandomString("ACPTTEST", 16)
t.Logf("Attempting to create snapshot: %s", snapshotName)
createOpts := snapshots.CreateOpts{
VolumeID: volume.ID,
Name: snapshotName,
Description: snapshotDescription,
}
snapshot, err := snapshots.Create(client, createOpts).Extract()
if err != nil {
return snapshot, err
}
err = snapshots.WaitForStatus(client, snapshot.ID, "available", 60)
if err != nil {
return snapshot, err
}
tools.PrintResource(t, snapshot)
th.AssertEquals(t, snapshot.Name, snapshotName)
th.AssertEquals(t, snapshot.VolumeID, volume.ID)
t.Logf("Successfully created snapshot: %s", snapshot.ID)
return snapshot, nil
}
// CreateVolume will create a volume with a random name and size of 1GB. An
// error will be returned if the volume was unable to be created.
func CreateVolume(t *testing.T, client *gophercloud.ServiceClient) (*volumes.Volume, error) {
volumeName := tools.RandomString("ACPTTEST", 16)
volumeDescription := tools.RandomString("ACPTTEST-DESC", 16)
t.Logf("Attempting to create volume: %s", volumeName)
createOpts := volumes.CreateOpts{
Size: 1,
Name: volumeName,
Description: volumeDescription,
}
volume, err := volumes.Create(client, createOpts).Extract()
if err != nil {
return volume, err
}
err = volumes.WaitForStatus(client, volume.ID, "available", 60)
if err != nil {
return volume, err
}
tools.PrintResource(t, volume)
th.AssertEquals(t, volume.Name, volumeName)
th.AssertEquals(t, volume.Description, volumeDescription)
th.AssertEquals(t, volume.Size, 1)
t.Logf("Successfully created volume: %s", volume.ID)
return volume, nil
}
// CreateVolumeType will create a volume type with a random name. An
// error will be returned if the volume was unable to be created.
func CreateVolumeType(t *testing.T, client *gophercloud.ServiceClient) (*volumetypes.VolumeType, error) {
name := tools.RandomString("ACPTTEST", 16)
description := "create_from_gophercloud"
t.Logf("Attempting to create volume type: %s", name)
createOpts := volumetypes.CreateOpts{
Name: name,
ExtraSpecs: map[string]string{"volume_backend_name": "fake_backend_name"},
Description: description,
}
vt, err := volumetypes.Create(client, createOpts).Extract()
if err != nil {
return nil, err
}
tools.PrintResource(t, vt)
th.AssertEquals(t, vt.IsPublic, true)
th.AssertEquals(t, vt.Name, name)
th.AssertEquals(t, vt.Description, description)
// TODO: For some reason returned extra_specs are empty even in API reference: https://developer.openstack.org/api-ref/block-storage/v3/?expanded=create-a-volume-type-detail#volume-types-types
// "extra_specs": {}
// th.AssertEquals(t, vt.ExtraSpecs, createOpts.ExtraSpecs)
t.Logf("Successfully created volume type: %s", vt.ID)
return vt, nil
}
// DeleteSnapshot will delete a snapshot. A fatal error will occur if the
// snapshot failed to be deleted.
func DeleteSnapshot(t *testing.T, client *gophercloud.ServiceClient, snapshot *snapshots.Snapshot) {
err := snapshots.Delete(client, snapshot.ID).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete snapshot %s: %+v", snapshot.ID, err)
}
// Volumes can't be deleted until their snapshots have been,
// so block up to 120 seconds for the snapshot to delete.
err = gophercloud.WaitFor(120, func() (bool, error) {
_, err := snapshots.Get(client, snapshot.ID).Extract()
if err != nil {
return true, nil
}
return false, nil
})
if err != nil {
t.Fatalf("Error waiting for snapshot to delete: %v", err)
}
t.Logf("Deleted snapshot: %s", snapshot.ID)
}
// DeleteVolume will delete a volume. A fatal error will occur if the volume
// failed to be deleted. This works best when used as a deferred function.
func DeleteVolume(t *testing.T, client *gophercloud.ServiceClient, volume *volumes.Volume) {
t.Logf("Attempting to delete volume: %s", volume.ID)
err := volumes.Delete(client, volume.ID, volumes.DeleteOpts{}).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete volume %s: %v", volume.ID, err)
}
t.Logf("Successfully deleted volume: %s", volume.ID)
}
// DeleteVolumeType will delete a volume type. A fatal error will occur if the
// volume type failed to be deleted. This works best when used as a deferred
// function.
func DeleteVolumeType(t *testing.T, client *gophercloud.ServiceClient, vt *volumetypes.VolumeType) {
t.Logf("Attempting to delete volume type: %s", vt.ID)
err := volumetypes.Delete(client, vt.ID).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete volume %s: %v", vt.ID, err)
}
t.Logf("Successfully deleted volume type: %s", vt.ID)
}

View File

@@ -1,3 +0,0 @@
// The v3 package contains acceptance tests for the OpenStack Cinder V3 service.
package v3

View File

@@ -1,145 +0,0 @@
// +build acceptance quotasets
package v3
import (
"os"
"testing"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/quotasets"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestQuotasetGet(t *testing.T) {
clients.RequireAdmin(t)
client, projectID := getClientAndProject(t)
quotaSet, err := quotasets.Get(client, projectID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, quotaSet)
}
func TestQuotasetGetDefaults(t *testing.T) {
clients.RequireAdmin(t)
client, projectID := getClientAndProject(t)
quotaSet, err := quotasets.GetDefaults(client, projectID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, quotaSet)
}
func TestQuotasetGetUsage(t *testing.T) {
clients.RequireAdmin(t)
client, projectID := getClientAndProject(t)
quotaSetUsage, err := quotasets.GetUsage(client, projectID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, quotaSetUsage)
}
var UpdateQuotaOpts = quotasets.UpdateOpts{
Volumes: gophercloud.IntToPointer(100),
Snapshots: gophercloud.IntToPointer(200),
Gigabytes: gophercloud.IntToPointer(300),
PerVolumeGigabytes: gophercloud.IntToPointer(50),
Backups: gophercloud.IntToPointer(2),
BackupGigabytes: gophercloud.IntToPointer(300),
}
var UpdatedQuotas = quotasets.QuotaSet{
Volumes: 100,
Snapshots: 200,
Gigabytes: 300,
PerVolumeGigabytes: 50,
Backups: 2,
BackupGigabytes: 300,
}
func TestQuotasetUpdate(t *testing.T) {
clients.RequireAdmin(t)
client, projectID := getClientAndProject(t)
// save original quotas
orig, err := quotasets.Get(client, projectID).Extract()
th.AssertNoErr(t, err)
defer func() {
restore := quotasets.UpdateOpts{}
FillUpdateOptsFromQuotaSet(*orig, &restore)
_, err = quotasets.Update(client, projectID, restore).Extract()
th.AssertNoErr(t, err)
}()
// test Update
resultQuotas, err := quotasets.Update(client, projectID, UpdateQuotaOpts).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, UpdatedQuotas, *resultQuotas)
// We dont know the default quotas, so just check if the quotas are not the
// same as before
newQuotas, err := quotasets.Get(client, projectID).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, resultQuotas.Volumes, newQuotas.Volumes)
}
func TestQuotasetDelete(t *testing.T) {
clients.RequireAdmin(t)
client, projectID := getClientAndProject(t)
// save original quotas
orig, err := quotasets.Get(client, projectID).Extract()
th.AssertNoErr(t, err)
defer func() {
restore := quotasets.UpdateOpts{}
FillUpdateOptsFromQuotaSet(*orig, &restore)
_, err = quotasets.Update(client, projectID, restore).Extract()
th.AssertNoErr(t, err)
}()
// Obtain environment default quotaset values to validate deletion.
defaultQuotaSet, err := quotasets.GetDefaults(client, projectID).Extract()
th.AssertNoErr(t, err)
// Test Delete
err = quotasets.Delete(client, projectID).ExtractErr()
th.AssertNoErr(t, err)
newQuotas, err := quotasets.Get(client, projectID).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, newQuotas.Volumes, defaultQuotaSet.Volumes)
}
// getClientAndProject reduces boilerplate by returning a new blockstorage v3
// ServiceClient and a project ID obtained from the OS_PROJECT_NAME envvar.
func getClientAndProject(t *testing.T) (*gophercloud.ServiceClient, string) {
client, err := clients.NewBlockStorageV3Client()
th.AssertNoErr(t, err)
projectID := os.Getenv("OS_PROJECT_NAME")
th.AssertNoErr(t, err)
return client, projectID
}
func FillUpdateOptsFromQuotaSet(src quotasets.QuotaSet, dest *quotasets.UpdateOpts) {
dest.Volumes = &src.Volumes
dest.Snapshots = &src.Snapshots
dest.Gigabytes = &src.Gigabytes
dest.PerVolumeGigabytes = &src.PerVolumeGigabytes
dest.Backups = &src.Backups
dest.BackupGigabytes = &src.BackupGigabytes
}

View File

@@ -1,58 +0,0 @@
// +build acceptance blockstorage
package v3
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/snapshots"
"github.com/gophercloud/gophercloud/pagination"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestSnapshots(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewBlockStorageV3Client()
th.AssertNoErr(t, err)
volume1, err := CreateVolume(t, client)
th.AssertNoErr(t, err)
defer DeleteVolume(t, client, volume1)
snapshot1, err := CreateSnapshot(t, client, volume1)
th.AssertNoErr(t, err)
defer DeleteSnapshot(t, client, snapshot1)
volume2, err := CreateVolume(t, client)
th.AssertNoErr(t, err)
defer DeleteVolume(t, client, volume2)
snapshot2, err := CreateSnapshot(t, client, volume2)
th.AssertNoErr(t, err)
defer DeleteSnapshot(t, client, snapshot2)
listOpts := snapshots.ListOpts{
Limit: 1,
}
err = snapshots.List(client, listOpts).EachPage(func(page pagination.Page) (bool, error) {
actual, err := snapshots.ExtractSnapshots(page)
th.AssertNoErr(t, err)
th.AssertEquals(t, 1, len(actual))
var found bool
for _, v := range actual {
if v.ID == snapshot1.ID || v.ID == snapshot2.ID {
found = true
}
}
th.AssertEquals(t, found, true)
return true, nil
})
th.AssertNoErr(t, err)
}

View File

@@ -1,145 +0,0 @@
// +build acceptance blockstorage
package v3
import (
"testing"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/snapshots"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes"
"github.com/gophercloud/gophercloud/pagination"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestVolumes(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewBlockStorageV3Client()
th.AssertNoErr(t, err)
volume1, err := CreateVolume(t, client)
th.AssertNoErr(t, err)
defer DeleteVolume(t, client, volume1)
volume2, err := CreateVolume(t, client)
th.AssertNoErr(t, err)
defer DeleteVolume(t, client, volume2)
// Update volume
updatedVolumeName := ""
updatedVolumeDescription := ""
updateOpts := volumes.UpdateOpts{
Name: &updatedVolumeName,
Description: &updatedVolumeDescription,
}
updatedVolume, err := volumes.Update(client, volume1.ID, updateOpts).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, updatedVolume)
th.AssertEquals(t, updatedVolume.Name, updatedVolumeName)
th.AssertEquals(t, updatedVolume.Description, updatedVolumeDescription)
listOpts := volumes.ListOpts{
Limit: 1,
}
err = volumes.List(client, listOpts).EachPage(func(page pagination.Page) (bool, error) {
actual, err := volumes.ExtractVolumes(page)
th.AssertNoErr(t, err)
th.AssertEquals(t, 1, len(actual))
var found bool
for _, v := range actual {
if v.ID == volume1.ID || v.ID == volume2.ID {
found = true
}
}
th.AssertEquals(t, found, true)
return true, nil
})
th.AssertNoErr(t, err)
}
func TestVolumesMultiAttach(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewBlockStorageV3Client()
th.AssertNoErr(t, err)
volumeName := tools.RandomString("ACPTTEST", 16)
volOpts := volumes.CreateOpts{
Size: 1,
Name: volumeName,
Description: "Testing creation of multiattach enabled volume",
Multiattach: true,
}
vol, err := volumes.Create(client, volOpts).Extract()
th.AssertNoErr(t, err)
err = volumes.WaitForStatus(client, vol.ID, "available", 60)
th.AssertNoErr(t, err)
th.AssertEquals(t, vol.Multiattach, true)
err = volumes.Delete(client, vol.ID, volumes.DeleteOpts{}).ExtractErr()
th.AssertNoErr(t, err)
}
func TestVolumesCascadeDelete(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewBlockStorageV3Client()
th.AssertNoErr(t, err)
vol, err := CreateVolume(t, client)
th.AssertNoErr(t, err)
err = volumes.WaitForStatus(client, vol.ID, "available", 60)
th.AssertNoErr(t, err)
snapshot1, err := CreateSnapshot(t, client, vol)
th.AssertNoErr(t, err)
snapshot2, err := CreateSnapshot(t, client, vol)
th.AssertNoErr(t, err)
t.Logf("Attempting to delete volume: %s", vol.ID)
deleteOpts := volumes.DeleteOpts{Cascade: true}
err = volumes.Delete(client, vol.ID, deleteOpts).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete volume %s: %v", vol.ID, err)
}
for _, sid := range []string{snapshot1.ID, snapshot2.ID} {
err := gophercloud.WaitFor(120, func() (bool, error) {
_, err := snapshots.Get(client, sid).Extract()
if err != nil {
return true, nil
}
return false, nil
})
th.AssertNoErr(t, err)
t.Logf("Successfully deleted snapshot: %s", sid)
}
err = gophercloud.WaitFor(120, func() (bool, error) {
_, err := volumes.Get(client, vol.ID).Extract()
if err != nil {
return true, nil
}
return false, nil
})
th.AssertNoErr(t, err)
t.Logf("Successfully deleted volume: %s", vol.ID)
}

View File

@@ -1,56 +0,0 @@
// +build acceptance blockstorage
package v3
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumetypes"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestVolumeTypes(t *testing.T) {
clients.RequireAdmin(t)
client, err := clients.NewBlockStorageV3Client()
th.AssertNoErr(t, err)
vt, err := CreateVolumeType(t, client)
th.AssertNoErr(t, err)
defer DeleteVolumeType(t, client, vt)
allPages, err := volumetypes.List(client, nil).AllPages()
th.AssertNoErr(t, err)
allVolumeTypes, err := volumetypes.ExtractVolumeTypes(allPages)
th.AssertNoErr(t, err)
var found bool
for _, v := range allVolumeTypes {
tools.PrintResource(t, v)
if v.ID == vt.ID {
found = true
}
}
th.AssertEquals(t, found, true)
isPublic := false
name := vt.Name + "-UPDATED"
description := ""
updateOpts := volumetypes.UpdateOpts{
Name: &name,
Description: &description,
IsPublic: &isPublic,
}
newVT, err := volumetypes.Update(client, vt.ID, updateOpts).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, newVT)
th.AssertEquals(t, name, newVT.Name)
th.AssertEquals(t, description, newVT.Description)
th.AssertEquals(t, isPublic, newVT.IsPublic)
}

View File

@@ -1,86 +0,0 @@
// +build acceptance
package openstack
import (
"os"
"testing"
"time"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack"
)
func TestAuthenticatedClient(t *testing.T) {
// Obtain credentials from the environment.
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
t.Fatalf("Unable to acquire credentials: %v", err)
}
client, err := openstack.AuthenticatedClient(ao)
if err != nil {
t.Fatalf("Unable to authenticate: %v", err)
}
if client.TokenID == "" {
t.Errorf("No token ID assigned to the client")
}
t.Logf("Client successfully acquired a token: %v", client.TokenID)
// Find the storage service in the service catalog.
storage, err := openstack.NewObjectStorageV1(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
if err != nil {
t.Errorf("Unable to locate a storage service: %v", err)
} else {
t.Logf("Located a storage service at endpoint: [%s]", storage.Endpoint)
}
}
func TestReauth(t *testing.T) {
ao, err := openstack.AuthOptionsFromEnv()
if err != nil {
t.Fatalf("Unable to obtain environment auth options: %v", err)
}
// Allow reauth
ao.AllowReauth = true
provider, err := openstack.NewClient(ao.IdentityEndpoint)
if err != nil {
t.Fatalf("Unable to create provider: %v", err)
}
err = openstack.Authenticate(provider, ao)
if err != nil {
t.Fatalf("Unable to authenticate: %v", err)
}
t.Logf("Creating a compute client")
_, err = openstack.NewComputeV2(provider, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
if err != nil {
t.Fatalf("Unable to create compute client: %v", err)
}
t.Logf("Sleeping for 1 second")
time.Sleep(1 * time.Second)
t.Logf("Attempting to reauthenticate")
err = provider.ReauthFunc()
if err != nil {
t.Fatalf("Unable to reauthenticate: %v", err)
}
t.Logf("Creating a compute client")
_, err = openstack.NewComputeV2(provider, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
if err != nil {
t.Fatalf("Unable to create compute client: %v", err)
}
}

View File

@@ -1,31 +0,0 @@
// +build acceptance clustering actions
package v1
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/clustering/v1/actions"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestActionsList(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
opts := actions.ListOpts{
Limit: 200,
}
allPages, err := actions.List(client, opts).AllPages()
th.AssertNoErr(t, err)
allActions, err := actions.ExtractActions(allPages)
th.AssertNoErr(t, err)
for _, action := range allActions {
tools.PrintResource(t, action)
}
}

View File

@@ -1,472 +0,0 @@
package v1
import (
"fmt"
"net/http"
"strings"
"testing"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/clustering/v1/actions"
"github.com/gophercloud/gophercloud/openstack/clustering/v1/clusters"
"github.com/gophercloud/gophercloud/openstack/clustering/v1/nodes"
"github.com/gophercloud/gophercloud/openstack/clustering/v1/policies"
"github.com/gophercloud/gophercloud/openstack/clustering/v1/profiles"
"github.com/gophercloud/gophercloud/openstack/clustering/v1/receivers"
th "github.com/gophercloud/gophercloud/testhelper"
)
var TestPolicySpec = policies.Spec{
Description: "new policy description",
Properties: map[string]interface{}{
"destroy_after_deletion": true,
"grace_period": 60,
"reduce_desired_capacity": false,
"criteria": "OLDEST_FIRST",
},
Type: "senlin.policy.deletion",
Version: "1.1",
}
// CreateCluster creates a random cluster. An error will be returned if
// the cluster could not be created.
func CreateCluster(t *testing.T, client *gophercloud.ServiceClient, profileID string) (*clusters.Cluster, error) {
name := tools.RandomString("TESTACC-", 8)
t.Logf("Attempting to create cluster: %s", name)
createOpts := clusters.CreateOpts{
Name: name,
DesiredCapacity: 1,
ProfileID: profileID,
MinSize: new(int),
MaxSize: 20,
Timeout: 3600,
Metadata: map[string]interface{}{
"foo": "bar",
"test": map[string]interface{}{
"nil_interface": interface{}(nil),
"float_value": float64(123.3),
"string_value": "test_string",
"bool_value": false,
},
},
Config: map[string]interface{}{},
}
res := clusters.Create(client, createOpts)
if res.Err != nil {
return nil, res.Err
}
requestID := res.Header.Get("X-OpenStack-Request-Id")
th.AssertEquals(t, true, requestID != "")
t.Logf("Cluster %s request ID: %s", name, requestID)
actionID, err := GetActionID(res.Header)
th.AssertNoErr(t, err)
th.AssertEquals(t, true, actionID != "")
t.Logf("Cluster %s action ID: %s", name, actionID)
err = WaitForAction(client, actionID)
if err != nil {
return nil, err
}
cluster, err := res.Extract()
if err != nil {
return nil, err
}
t.Logf("Successfully created cluster: %s", cluster.ID)
tools.PrintResource(t, cluster)
tools.PrintResource(t, cluster.CreatedAt)
th.AssertEquals(t, name, cluster.Name)
th.AssertEquals(t, profileID, cluster.ProfileID)
return cluster, nil
}
// CreateNode creates a random node. An error will be returned if
// the node could not be created.
func CreateNode(t *testing.T, client *gophercloud.ServiceClient, clusterID, profileID string) (*nodes.Node, error) {
name := tools.RandomString("TESTACC-", 8)
t.Logf("Attempting to create node: %s", name)
createOpts := nodes.CreateOpts{
ClusterID: clusterID,
Metadata: map[string]interface{}{
"foo": "bar",
"test": map[string]interface{}{
"nil_interface": interface{}(nil),
"float_value": float64(123.3),
"string_value": "test_string",
"bool_value": false,
},
},
Name: name,
ProfileID: profileID,
Role: "",
}
res := nodes.Create(client, createOpts)
if res.Err != nil {
return nil, res.Err
}
requestID := res.Header.Get("X-OpenStack-Request-Id")
th.AssertEquals(t, true, requestID != "")
t.Logf("Node %s request ID: %s", name, requestID)
actionID, err := GetActionID(res.Header)
th.AssertNoErr(t, err)
th.AssertEquals(t, true, actionID != "")
t.Logf("Node %s action ID: %s", name, actionID)
err = WaitForAction(client, actionID)
if err != nil {
return nil, err
}
node, err := res.Extract()
if err != nil {
return nil, err
}
err = WaitForNodeStatus(client, node.ID, "ACTIVE")
if err != nil {
return nil, err
}
t.Logf("Successfully created node: %s", node.ID)
node, err = nodes.Get(client, node.ID).Extract()
if err != nil {
return nil, err
}
tools.PrintResource(t, node)
tools.PrintResource(t, node.CreatedAt)
th.AssertEquals(t, profileID, node.ProfileID)
th.AssertEquals(t, clusterID, node.ClusterID)
th.AssertDeepEquals(t, createOpts.Metadata, node.Metadata)
return node, nil
}
// CreatePolicy creates a random policy. An error will be returned if the
// policy could not be created.
func CreatePolicy(t *testing.T, client *gophercloud.ServiceClient) (*policies.Policy, error) {
name := tools.RandomString("TESTACC-", 8)
t.Logf("Attempting to create policy: %s", name)
createOpts := policies.CreateOpts{
Name: name,
Spec: TestPolicySpec,
}
res := policies.Create(client, createOpts)
if res.Err != nil {
return nil, res.Err
}
requestID := res.Header.Get("X-OpenStack-Request-Id")
th.AssertEquals(t, true, requestID != "")
t.Logf("Policy %s request ID: %s", name, requestID)
policy, err := res.Extract()
if err != nil {
return nil, err
}
t.Logf("Successfully created policy: %s", policy.ID)
tools.PrintResource(t, policy)
tools.PrintResource(t, policy.CreatedAt)
th.AssertEquals(t, name, policy.Name)
return policy, nil
}
// CreateProfile will create a random profile. An error will be returned if the
// profile could not be created.
func CreateProfile(t *testing.T, client *gophercloud.ServiceClient) (*profiles.Profile, error) {
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
return nil, err
}
name := tools.RandomString("TESTACC-", 8)
t.Logf("Attempting to create profile: %s", name)
networks := []map[string]interface{}{
{"network": choices.NetworkName},
}
props := map[string]interface{}{
"name": name,
"flavor": choices.FlavorID,
"image": choices.ImageID,
"networks": networks,
"security_groups": "",
}
createOpts := profiles.CreateOpts{
Name: name,
Spec: profiles.Spec{
Type: "os.nova.server",
Version: "1.0",
Properties: props,
},
}
res := profiles.Create(client, createOpts)
if res.Err != nil {
return nil, res.Err
}
requestID := res.Header.Get("X-OpenStack-Request-Id")
th.AssertEquals(t, true, requestID != "")
t.Logf("Profile %s request ID: %s", name, requestID)
profile, err := res.Extract()
if err != nil {
return nil, err
}
t.Logf("Successfully created profile: %s", profile.ID)
tools.PrintResource(t, profile)
tools.PrintResource(t, profile.CreatedAt)
th.AssertEquals(t, name, profile.Name)
th.AssertEquals(t, profile.Spec.Type, "os.nova.server")
th.AssertEquals(t, profile.Spec.Version, "1.0")
return profile, nil
}
// CreateWebhookReceiver will create a random webhook receiver. An error will be returned if the
// receiver could not be created.
func CreateWebhookReceiver(t *testing.T, client *gophercloud.ServiceClient, clusterID string) (*receivers.Receiver, error) {
name := tools.RandomString("TESTACC-", 8)
t.Logf("Attempting to create receiver: %s", name)
createOpts := receivers.CreateOpts{
Name: name,
ClusterID: clusterID,
Type: receivers.WebhookReceiver,
Action: "CLUSTER_SCALE_OUT",
}
res := receivers.Create(client, createOpts)
if res.Err != nil {
return nil, res.Err
}
receiver, err := res.Extract()
if err != nil {
return nil, err
}
t.Logf("Successfully created webhook receiver: %s", receiver.ID)
tools.PrintResource(t, receiver)
tools.PrintResource(t, receiver.CreatedAt)
th.AssertEquals(t, name, receiver.Name)
th.AssertEquals(t, createOpts.Action, receiver.Action)
return receiver, nil
}
// CreateMessageReceiver will create a message receiver with a random name. An error will be returned if the
// receiver could not be created.
func CreateMessageReceiver(t *testing.T, client *gophercloud.ServiceClient, clusterID string) (*receivers.Receiver, error) {
name := tools.RandomString("TESTACC-", 8)
t.Logf("Attempting to create receiver: %s", name)
createOpts := receivers.CreateOpts{
Name: name,
ClusterID: clusterID,
Type: receivers.MessageReceiver,
}
res := receivers.Create(client, createOpts)
if res.Err != nil {
return nil, res.Err
}
receiver, err := res.Extract()
if err != nil {
return nil, err
}
t.Logf("Successfully created message receiver: %s", receiver.ID)
tools.PrintResource(t, receiver)
tools.PrintResource(t, receiver.CreatedAt)
th.AssertEquals(t, name, receiver.Name)
th.AssertEquals(t, createOpts.Action, receiver.Action)
return receiver, nil
}
// DeleteCluster will delete a given policy. A fatal error will occur if the
// cluster could not be deleted. This works best as a deferred function.
func DeleteCluster(t *testing.T, client *gophercloud.ServiceClient, id string) {
t.Logf("Attempting to delete cluster: %s", id)
res := clusters.Delete(client, id)
if res.Err != nil {
t.Fatalf("Error deleting cluster %s: %s:", id, res.Err)
}
actionID, err := GetActionID(res.Header)
if err != nil {
t.Fatalf("Error deleting cluster %s: %s:", id, res.Err)
}
err = WaitForAction(client, actionID)
if err != nil {
t.Fatalf("Error deleting cluster %s: %s:", id, res.Err)
}
t.Logf("Successfully deleted cluster: %s", id)
return
}
// DeleteNode will delete a given node. A fatal error will occur if the
// node could not be deleted. This works best as a deferred function.
func DeleteNode(t *testing.T, client *gophercloud.ServiceClient, id string) {
t.Logf("Attempting to delete node: %s", id)
res := nodes.Delete(client, id)
if res.Err != nil {
t.Fatalf("Error deleting node %s: %s:", id, res.Err)
}
actionID, err := GetActionID(res.Header)
if err != nil {
t.Fatalf("Error getting actionID %s: %s:", id, err)
}
err = WaitForAction(client, actionID)
if err != nil {
t.Fatalf("Error deleting node %s: %s", id, err)
}
t.Logf("Successfully deleted node: %s", id)
return
}
// DeletePolicy will delete a given policy. A fatal error will occur if the
// policy could not be deleted. This works best as a deferred function.
func DeletePolicy(t *testing.T, client *gophercloud.ServiceClient, id string) {
t.Logf("Attempting to delete policy: %s", id)
err := policies.Delete(client, id).ExtractErr()
if err != nil {
t.Fatalf("Error deleting policy %s: %s:", id, err)
}
t.Logf("Successfully deleted policy: %s", id)
return
}
// DeleteProfile will delete a given profile. A fatal error will occur if the
// profile could not be deleted. This works best as a deferred function.
func DeleteProfile(t *testing.T, client *gophercloud.ServiceClient, id string) {
t.Logf("Attempting to delete profile: %s", id)
err := profiles.Delete(client, id).ExtractErr()
if err != nil {
t.Fatalf("Error deleting profile %s: %s:", id, err)
}
t.Logf("Successfully deleted profile: %s", id)
return
}
// DeleteReceiver will delete a given receiver. A fatal error will occur if the
// receiver could not be deleted. This works best as a deferred function.
func DeleteReceiver(t *testing.T, client *gophercloud.ServiceClient, id string) {
t.Logf("Attempting to delete Receiver: %s", id)
res := receivers.Delete(client, id)
if res.Err != nil {
t.Fatalf("Error deleting receiver %s: %s:", id, res.Err)
}
t.Logf("Successfully deleted receiver: %s", id)
return
}
// GetActionID parses an HTTP header and returns the action ID.
func GetActionID(headers http.Header) (string, error) {
location := headers.Get("Location")
v := strings.Split(location, "actions/")
if len(v) < 2 {
return "", fmt.Errorf("unable to determine action ID")
}
actionID := v[1]
return actionID, nil
}
func WaitForAction(client *gophercloud.ServiceClient, actionID string) error {
return tools.WaitFor(func() (bool, error) {
action, err := actions.Get(client, actionID).Extract()
if err != nil {
return false, err
}
if action.Status == "SUCCEEDED" {
return true, nil
}
if action.Status == "FAILED" {
return false, fmt.Errorf("Action %s in FAILED state", actionID)
}
return false, nil
})
}
func WaitForNodeStatus(client *gophercloud.ServiceClient, id string, status string) error {
return tools.WaitFor(func() (bool, error) {
latest, err := nodes.Get(client, id).Extract()
if err != nil {
if _, ok := err.(gophercloud.ErrDefault404); ok && status == "DELETED" {
return true, nil
}
return false, err
}
if latest.Status == status {
return true, nil
}
if latest.Status == "ERROR" {
return false, fmt.Errorf("Node %s in ERROR state", id)
}
return false, nil
})
}

View File

@@ -1,510 +0,0 @@
// +build acceptance clustering policies
package v1
import (
"sort"
"strings"
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/clustering/v1/actions"
"github.com/gophercloud/gophercloud/openstack/clustering/v1/clusters"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestClustersCRUD(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
profile, err := CreateProfile(t, client)
th.AssertNoErr(t, err)
defer DeleteProfile(t, client, profile.ID)
cluster, err := CreateCluster(t, client, profile.ID)
th.AssertNoErr(t, err)
defer DeleteCluster(t, client, cluster.ID)
// Test clusters list
allPages, err := clusters.List(client, nil).AllPages()
th.AssertNoErr(t, err)
allClusters, err := clusters.ExtractClusters(allPages)
th.AssertNoErr(t, err)
var found bool
for _, v := range allClusters {
if v.ID == cluster.ID {
found = true
}
}
th.AssertEquals(t, found, true)
// Test cluster update
updateOpts := clusters.UpdateOpts{
Name: cluster.Name + "-UPDATED",
}
res := clusters.Update(client, cluster.ID, updateOpts)
th.AssertNoErr(t, res.Err)
actionID, err := GetActionID(res.Header)
th.AssertNoErr(t, err)
err = WaitForAction(client, actionID)
th.AssertNoErr(t, err)
newCluster, err := clusters.Get(client, cluster.ID).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, newCluster.Name, cluster.Name+"-UPDATED")
tools.PrintResource(t, newCluster)
// Test cluster health
actionID, err = clusters.Check(client, cluster.ID).Extract()
th.AssertNoErr(t, err)
err = WaitForAction(client, actionID)
th.AssertNoErr(t, err)
}
func TestClustersResize(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
profile, err := CreateProfile(t, client)
th.AssertNoErr(t, err)
defer DeleteProfile(t, client, profile.ID)
cluster, err := CreateCluster(t, client, profile.ID)
th.AssertNoErr(t, err)
defer DeleteCluster(t, client, cluster.ID)
iTrue := true
resizeOpts := clusters.ResizeOpts{
AdjustmentType: clusters.ChangeInCapacityAdjustment,
Number: 1,
Strict: &iTrue,
}
actionID, err := clusters.Resize(client, cluster.ID, resizeOpts).Extract()
th.AssertNoErr(t, err)
err = WaitForAction(client, actionID)
th.AssertNoErr(t, err)
newCluster, err := clusters.Get(client, cluster.ID).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, newCluster.DesiredCapacity, 2)
tools.PrintResource(t, newCluster)
}
func TestClustersScale(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
profile, err := CreateProfile(t, client)
th.AssertNoErr(t, err)
defer DeleteProfile(t, client, profile.ID)
cluster, err := CreateCluster(t, client, profile.ID)
th.AssertNoErr(t, err)
defer DeleteCluster(t, client, cluster.ID)
// increase cluster size to 2
scaleOutOpts := clusters.ScaleOutOpts{
Count: 1,
}
actionID, err := clusters.ScaleOut(client, cluster.ID, scaleOutOpts).Extract()
th.AssertNoErr(t, err)
err = WaitForAction(client, actionID)
th.AssertNoErr(t, err)
newCluster, err := clusters.Get(client, cluster.ID).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, newCluster.DesiredCapacity, 2)
// reduce cluster size to 0
count := 2
scaleInOpts := clusters.ScaleInOpts{
Count: &count,
}
actionID, err = clusters.ScaleIn(client, cluster.ID, scaleInOpts).Extract()
th.AssertNoErr(t, err)
err = WaitForAction(client, actionID)
th.AssertNoErr(t, err)
newCluster, err = clusters.Get(client, cluster.ID).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, newCluster.DesiredCapacity, 0)
tools.PrintResource(t, newCluster)
}
func TestClustersPolicies(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
client.Microversion = "1.5"
profile, err := CreateProfile(t, client)
th.AssertNoErr(t, err)
defer DeleteProfile(t, client, profile.ID)
cluster, err := CreateCluster(t, client, profile.ID)
th.AssertNoErr(t, err)
defer DeleteCluster(t, client, cluster.ID)
policy, err := CreatePolicy(t, client)
th.AssertNoErr(t, err)
defer DeletePolicy(t, client, policy.ID)
iTrue := true
attachPolicyOpts := clusters.AttachPolicyOpts{
PolicyID: policy.ID,
Enabled: &iTrue,
}
actionID, err := clusters.AttachPolicy(client, cluster.ID, attachPolicyOpts).Extract()
th.AssertNoErr(t, err)
err = WaitForAction(client, actionID)
th.AssertNoErr(t, err)
// List all policies in the cluster to see if the policy was
// successfully attached.
allPages, err := clusters.ListPolicies(client, cluster.ID, nil).AllPages()
th.AssertNoErr(t, err)
allPolicies, err := clusters.ExtractClusterPolicies(allPages)
th.AssertNoErr(t, err)
var found bool
for _, v := range allPolicies {
tools.PrintResource(t, v)
if v.PolicyID == policy.ID {
found = true
}
}
th.AssertEquals(t, found, true)
// Set the policy to disabled
iFalse := false
updatePolicyOpts := clusters.UpdatePolicyOpts{
PolicyID: policy.ID,
Enabled: &iFalse,
}
actionID, err = clusters.UpdatePolicy(client, cluster.ID, updatePolicyOpts).Extract()
th.AssertNoErr(t, err)
err = WaitForAction(client, actionID)
th.AssertNoErr(t, err)
clusterPolicy, err := clusters.GetPolicy(client, cluster.ID, policy.ID).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, clusterPolicy.Enabled, false)
// Detach the policy
detachPolicyOpts := clusters.DetachPolicyOpts{
PolicyID: policy.ID,
}
actionID, err = clusters.DetachPolicy(client, cluster.ID, detachPolicyOpts).Extract()
th.AssertNoErr(t, err)
err = WaitForAction(client, actionID)
th.AssertNoErr(t, err)
// List all policies in the cluster to see if the policy was
// successfully detached.
allPages, err = clusters.ListPolicies(client, cluster.ID, nil).AllPages()
th.AssertNoErr(t, err)
allPolicies, err = clusters.ExtractClusterPolicies(allPages)
th.AssertNoErr(t, err)
found = false
for _, v := range allPolicies {
tools.PrintResource(t, v)
if v.PolicyID == policy.ID {
found = true
}
}
th.AssertEquals(t, found, false)
}
func TestClustersRecovery(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
profile, err := CreateProfile(t, client)
th.AssertNoErr(t, err)
defer DeleteProfile(t, client, profile.ID)
cluster, err := CreateCluster(t, client, profile.ID)
th.AssertNoErr(t, err)
defer DeleteCluster(t, client, cluster.ID)
recoverOpts := clusters.RecoverOpts{
Operation: clusters.RebuildRecovery,
}
actionID, err := clusters.Recover(client, cluster.ID, recoverOpts).Extract()
th.AssertNoErr(t, err)
err = WaitForAction(client, actionID)
th.AssertNoErr(t, err)
newCluster, err := clusters.Get(client, cluster.ID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, newCluster)
}
func TestClustersAddNode(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
profile, err := CreateProfile(t, client)
th.AssertNoErr(t, err)
defer DeleteProfile(t, client, profile.ID)
cluster, err := CreateCluster(t, client, profile.ID)
th.AssertNoErr(t, err)
defer DeleteCluster(t, client, cluster.ID)
node1, err := CreateNode(t, client, "", profile.ID)
th.AssertNoErr(t, err)
// Even tho deleting the cluster will delete the nodes but only if added into cluster successfully.
defer DeleteNode(t, client, node1.ID)
node2, err := CreateNode(t, client, "", profile.ID)
th.AssertNoErr(t, err)
// Even tho deleting the cluster will delete the nodes but only if added into cluster successfully.
defer DeleteNode(t, client, node2.ID)
cluster, err = clusters.Get(client, cluster.ID).Extract()
th.AssertNoErr(t, err)
nodeIDs := []string{node1.ID, node2.ID}
nodeIDs = append(nodeIDs, cluster.Nodes...)
nodeNames := []string{node1.Name, node2.Name}
addNodesOpts := clusters.AddNodesOpts{
Nodes: nodeNames,
}
actionID, err := clusters.AddNodes(client, cluster.ID, addNodesOpts).Extract()
if err != nil {
t.Fatalf("Unable to add nodes to cluster: %v", err)
}
err = WaitForAction(client, actionID)
th.AssertNoErr(t, err)
cluster, err = clusters.Get(client, cluster.ID).Extract()
th.AssertNoErr(t, err)
sort.Strings(nodeIDs)
sort.Strings(cluster.Nodes)
tools.PrintResource(t, nodeIDs)
tools.PrintResource(t, cluster.Nodes)
th.AssertDeepEquals(t, nodeIDs, cluster.Nodes)
tools.PrintResource(t, cluster)
}
func TestClustersRemoveNodeFromCluster(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
profile, err := CreateProfile(t, client)
th.AssertNoErr(t, err)
defer DeleteProfile(t, client, profile.ID)
cluster, err := CreateCluster(t, client, profile.ID)
th.AssertNoErr(t, err)
defer DeleteCluster(t, client, cluster.ID)
cluster, err = clusters.Get(client, cluster.ID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, cluster)
opt := clusters.RemoveNodesOpts{Nodes: cluster.Nodes}
res := clusters.RemoveNodes(client, cluster.ID, opt)
err = res.ExtractErr()
th.AssertNoErr(t, err)
for _, n := range cluster.Nodes {
defer DeleteNode(t, client, n)
}
actionID, err := GetActionID(res.Header)
th.AssertNoErr(t, err)
err = WaitForAction(client, actionID)
th.AssertNoErr(t, err)
cluster, err = clusters.Get(client, cluster.ID).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, 0, len(cluster.Nodes))
tools.PrintResource(t, cluster)
}
func TestClustersReplaceNode(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
client.Microversion = "1.3"
profile, err := CreateProfile(t, client)
th.AssertNoErr(t, err)
defer DeleteProfile(t, client, profile.ID)
cluster, err := CreateCluster(t, client, profile.ID)
th.AssertNoErr(t, err)
defer DeleteCluster(t, client, cluster.ID)
node1, err := CreateNode(t, client, "", profile.ID)
th.AssertNoErr(t, err)
defer DeleteNode(t, client, node1.ID)
cluster, err = clusters.Get(client, cluster.ID).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, true, len(cluster.Nodes) > 0)
for _, n := range cluster.Nodes {
defer DeleteNode(t, client, n)
}
nodeIDToBeReplaced := cluster.Nodes[0]
opts := clusters.ReplaceNodesOpts{Nodes: map[string]string{nodeIDToBeReplaced: node1.ID}}
actionID, err := clusters.ReplaceNodes(client, cluster.ID, opts).Extract()
th.AssertNoErr(t, err)
err = WaitForAction(client, actionID)
th.AssertNoErr(t, err)
cluster, err = clusters.Get(client, cluster.ID).Extract()
th.AssertNoErr(t, err)
clusterNodes := strings.Join(cluster.Nodes, ",")
th.AssertEquals(t, true, strings.Contains(clusterNodes, node1.ID))
th.AssertEquals(t, false, strings.Contains(clusterNodes, nodeIDToBeReplaced))
tools.PrintResource(t, cluster)
}
func TestClustersCollectAttributes(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
client.Microversion = "1.2"
profile, err := CreateProfile(t, client)
th.AssertNoErr(t, err)
defer DeleteProfile(t, client, profile.ID)
cluster, err := CreateCluster(t, client, profile.ID)
th.AssertNoErr(t, err)
defer DeleteCluster(t, client, cluster.ID)
cluster, err = clusters.Get(client, cluster.ID).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, true, len(cluster.Nodes) > 0)
_, err = CreateNode(t, client, cluster.ID, profile.ID)
th.AssertNoErr(t, err)
cluster, err = clusters.Get(client, cluster.ID).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, true, len(cluster.Nodes) > 0)
for _, n := range cluster.Nodes {
defer DeleteNode(t, client, n)
}
opts := clusters.CollectOpts{
Path: "status",
}
attrs, err := clusters.Collect(client, cluster.ID, opts).Extract()
th.AssertNoErr(t, err)
for _, attr := range attrs {
th.AssertEquals(t, attr.Value, "ACTIVE")
}
opts = clusters.CollectOpts{
Path: "data.placement.zone",
}
attrs, err = clusters.Collect(client, cluster.ID, opts).Extract()
th.AssertNoErr(t, err)
for _, attr := range attrs {
th.AssertEquals(t, attr.Value, "nova")
}
}
// Performs an operation on a cluster
func TestClustersOps(t *testing.T) {
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
client.Microversion = "1.4"
profile, err := CreateProfile(t, client)
th.AssertNoErr(t, err)
defer DeleteProfile(t, client, profile.ID)
cluster, err := CreateCluster(t, client, profile.ID)
th.AssertNoErr(t, err)
defer DeleteCluster(t, client, cluster.ID)
node, err := CreateNode(t, client, cluster.ID, profile.ID)
th.AssertNoErr(t, err)
defer DeleteNode(t, client, node.ID)
ops := []clusters.OperationOpts{
// TODO: Commented out due to backend returns error, as of 2019-01-09
//{Operation: clusters.RebuildOperation}, // Error in set_admin_password in nova log
//{Operation: clusters.EvacuateOperation, Params: clusters.OperationParams{"host": cluster.ID, "force": "True"}},
{Operation: clusters.RebootOperation, Params: clusters.OperationParams{"type": "SOFT"}},
{Operation: clusters.ChangePasswordOperation, Params: clusters.OperationParams{"admin_pass": "test"}},
{Operation: clusters.LockOperation},
{Operation: clusters.UnlockOperation},
{Operation: clusters.SuspendOperation},
{Operation: clusters.ResumeOperation},
{Operation: clusters.RescueOperation, Params: clusters.OperationParams{"image_ref": choices.ImageID}},
{Operation: clusters.PauseOperation},
{Operation: clusters.UnpauseOperation},
{Operation: clusters.StopOperation},
{Operation: clusters.StartOperation},
}
for _, op := range ops {
opName := string(op.Operation)
t.Logf("Attempting to perform '%s' on cluster: %s", opName, cluster.ID)
actionID, res := clusters.Ops(client, cluster.ID, op).Extract()
th.AssertNoErr(t, res)
err = WaitForAction(client, actionID)
th.AssertNoErr(t, err)
action, err := actions.Get(client, actionID).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, "SUCCEEDED", action.Status)
t.Logf("Successfully performed '%s' on cluster: %s", opName, cluster.ID)
}
cluster, err = clusters.Get(client, cluster.ID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, cluster)
}

View File

@@ -1,31 +0,0 @@
// +build acceptance clustering events
package v1
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/clustering/v1/events"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestEventsList(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
opts := events.ListOpts{
Limit: 200,
}
allPages, err := events.List(client, opts).AllPages()
th.AssertNoErr(t, err)
allEvents, err := events.ExtractEvents(allPages)
th.AssertNoErr(t, err)
for _, event := range allEvents {
tools.PrintResource(t, event)
}
}

View File

@@ -1,215 +0,0 @@
// +build acceptance clustering policies
package v1
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/clustering/v1/nodes"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestNodesCRUD(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
profile, err := CreateProfile(t, client)
th.AssertNoErr(t, err)
defer DeleteProfile(t, client, profile.ID)
cluster, err := CreateCluster(t, client, profile.ID)
th.AssertNoErr(t, err)
defer DeleteCluster(t, client, cluster.ID)
node, err := CreateNode(t, client, cluster.ID, profile.ID)
th.AssertNoErr(t, err)
defer DeleteNode(t, client, node.ID)
// Test nodes list
allPages, err := nodes.List(client, nil).AllPages()
th.AssertNoErr(t, err)
allNodes, err := nodes.ExtractNodes(allPages)
th.AssertNoErr(t, err)
var found bool
for _, v := range allNodes {
if v.ID == node.ID {
found = true
}
}
th.AssertEquals(t, found, true)
// Test nodes update
t.Logf("Attempting to update node %s", node.ID)
updateOpts := nodes.UpdateOpts{
Metadata: map[string]interface{}{
"bar": "baz",
},
}
res := nodes.Update(client, node.ID, updateOpts)
th.AssertNoErr(t, res.Err)
actionID, err := GetActionID(res.Header)
th.AssertNoErr(t, err)
err = WaitForAction(client, actionID)
th.AssertNoErr(t, err)
node, err = nodes.Get(client, node.ID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, node)
tools.PrintResource(t, node.Metadata)
}
// Performs an operation on a node
func TestNodesOps(t *testing.T) {
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
client.Microversion = "1.4"
profile, err := CreateProfile(t, client)
th.AssertNoErr(t, err)
defer DeleteProfile(t, client, profile.ID)
cluster, err := CreateCluster(t, client, profile.ID)
th.AssertNoErr(t, err)
defer DeleteCluster(t, client, cluster.ID)
node, err := CreateNode(t, client, cluster.ID, profile.ID)
th.AssertNoErr(t, err)
defer DeleteNode(t, client, node.ID)
ops := []nodes.OperationOpts{
// TODO: Commented out due to backend returns error, as of 2018-12-14
//{Operation: nodes.RebuildOperation},
//{Operation: nodes.EvacuateOperation, Params: nodes.OperationParams{"EvacuateHost": node.ID, "EvacuateForce", "True"}},
{Operation: nodes.RebootOperation, Params: nodes.OperationParams{"type": "SOFT"}},
{Operation: nodes.ChangePasswordOperation, Params: nodes.OperationParams{"admin_pass": "test"}},
{Operation: nodes.LockOperation},
{Operation: nodes.UnlockOperation},
{Operation: nodes.SuspendOperation},
{Operation: nodes.ResumeOperation},
{Operation: nodes.RescueOperation, Params: nodes.OperationParams{"image_ref": choices.ImageID}},
{Operation: nodes.PauseOperation},
{Operation: nodes.UnpauseOperation},
{Operation: nodes.StopOperation},
{Operation: nodes.StartOperation},
}
for _, op := range ops {
opName := string(op.Operation)
t.Logf("Attempting to perform '%s' on node: %s", opName, node.ID)
actionID, res := nodes.Ops(client, node.ID, op).Extract()
th.AssertNoErr(t, res)
err = WaitForAction(client, actionID)
th.AssertNoErr(t, err)
node, err = nodes.Get(client, node.ID).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, "Operation '"+opName+"' succeeded", node.StatusReason)
t.Logf("Successfully performed '%s' on node: %s", opName, node.ID)
}
}
func TestNodesRecover(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
client.Microversion = "1.6"
profile, err := CreateProfile(t, client)
th.AssertNoErr(t, err)
defer DeleteProfile(t, client, profile.ID)
cluster, err := CreateCluster(t, client, profile.ID)
th.AssertNoErr(t, err)
defer DeleteCluster(t, client, cluster.ID)
node, err := CreateNode(t, client, cluster.ID, profile.ID)
th.AssertNoErr(t, err)
defer DeleteNode(t, client, node.ID)
checkTrue := true
checkFalse := false
// TODO: nodes.RebuildRecovery is commented out as of 12/14/2018 the API backend can't perform the action without returning error
ops := []nodes.RecoverOpts{
// Microversion < 1.6 legacy support where argument DOES NOT support Check
nodes.RecoverOpts{},
nodes.RecoverOpts{Operation: nodes.RebootRecovery},
// nodes.RecoverOpts{Operation: nodes.RebuildRecovery},
// MicroVersion >= 1.6 that supports Check where Check is true
nodes.RecoverOpts{Check: &checkTrue},
nodes.RecoverOpts{Operation: nodes.RebootRecovery, Check: &checkTrue},
//nodes.RecoverOpts{Operation: nodes.RebuildRecovery, Check: &checkTrue},
// MicroVersion >= 1.6 that supports Check where Check is false
nodes.RecoverOpts{Check: &checkFalse},
nodes.RecoverOpts{Operation: nodes.RebootRecovery, Check: &checkFalse},
//nodes.RecoverOpts{Operation: nodes.RebuildRecovery, Check: &checkFalse},
}
for _, recoverOpt := range ops {
if recoverOpt.Check != nil {
t.Logf("Attempting to recover by using '%s' check=%t on node: %s", recoverOpt.Operation, *recoverOpt.Check, node.ID)
} else {
t.Logf("Attempting to recover by using '%s' on node: %s", recoverOpt.Operation, node.ID)
}
actionID, err := nodes.Recover(client, node.ID, recoverOpt).Extract()
th.AssertNoErr(t, err)
err = WaitForAction(client, actionID)
th.AssertNoErr(t, err)
if recoverOpt.Check != nil {
t.Logf("Successfully recovered by using '%s' check=%t on node: %s", recoverOpt.Operation, *recoverOpt.Check, node.ID)
} else {
t.Logf("Successfully recovered by using '%s' on node: %s", recoverOpt.Operation, node.ID)
}
node, err := nodes.Get(client, node.ID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, node)
}
}
func TestNodeCheck(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
profile, err := CreateProfile(t, client)
th.AssertNoErr(t, err)
defer DeleteProfile(t, client, profile.ID)
cluster, err := CreateCluster(t, client, profile.ID)
th.AssertNoErr(t, err)
defer DeleteCluster(t, client, cluster.ID)
node, err := CreateNode(t, client, cluster.ID, profile.ID)
th.AssertNoErr(t, err)
defer DeleteNode(t, client, node.ID)
t.Logf("Attempting to check on node: %s", node.ID)
actionID, err := nodes.Check(client, node.ID).Extract()
th.AssertNoErr(t, err)
err = WaitForAction(client, actionID)
th.AssertNoErr(t, err)
node, err = nodes.Get(client, node.ID).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, "Check: Node is ACTIVE.", node.StatusReason)
tools.PrintResource(t, node)
}

View File

@@ -1,2 +0,0 @@
// Package v1 package contains acceptance tests for the Openstack Clustering V1 service.
package v1

View File

@@ -1,69 +0,0 @@
// +build acceptance clustering policies
package v1
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/clustering/v1/policies"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestPoliciesCRUD(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
client.Microversion = "1.5"
policy, err := CreatePolicy(t, client)
th.AssertNoErr(t, err)
defer DeletePolicy(t, client, policy.ID)
// Test listing policies
allPages, err := policies.List(client, nil).AllPages()
th.AssertNoErr(t, err)
allPolicies, err := policies.ExtractPolicies(allPages)
th.AssertNoErr(t, err)
var found bool
for _, v := range allPolicies {
if v.ID == policy.ID {
found = true
}
}
th.AssertEquals(t, found, true)
// Test Get policy
getPolicy, err := policies.Get(client, policy.ID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, getPolicy)
// Test updating policy
updateOpts := policies.UpdateOpts{
Name: policy.Name + "-UPDATE",
}
t.Logf("Attempting to update policy: %s", policy.ID)
updatePolicy, err := policies.Update(client, policy.ID, updateOpts).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, updatePolicy)
tools.PrintResource(t, updatePolicy.UpdatedAt)
// Test validating policy
t.Logf("Attempting to validate policy: %s", policy.ID)
validateOpts := policies.ValidateOpts{
Spec: TestPolicySpec,
}
validatePolicy, err := policies.Validate(client, validateOpts).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, validatePolicy)
th.AssertEquals(t, validatePolicy.Name, "validated_policy")
th.AssertEquals(t, validatePolicy.Spec.Version, TestPolicySpec.Version)
}

View File

@@ -1,64 +0,0 @@
// +build acceptance clustering policytypes
package v1
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/clustering/v1/policytypes"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestPolicyTypeList(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
allPages, err := policytypes.List(client).AllPages()
th.AssertNoErr(t, err)
allPolicyTypes, err := policytypes.ExtractPolicyTypes(allPages)
th.AssertNoErr(t, err)
for _, v := range allPolicyTypes {
tools.PrintResource(t, v)
}
}
func TestPolicyTypeList_v_1_5(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
client.Microversion = "1.5"
allPages, err := policytypes.List(client).AllPages()
th.AssertNoErr(t, err)
allPolicyTypes, err := policytypes.ExtractPolicyTypes(allPages)
th.AssertNoErr(t, err)
for _, v := range allPolicyTypes {
tools.PrintResource(t, v)
}
}
func TestPolicyTypeGet(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
policyType, err := policytypes.Get(client, "senlin.policy.batch-1.0").Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, policyType)
}
func TestPolicyTypeGet_v_1_5(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
client.Microversion = "1.5"
policyType, err := policytypes.Get(client, "senlin.policy.batch-1.0").Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, policyType)
}

View File

@@ -1,76 +0,0 @@
// +build acceptance clustering policies
package v1
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/clustering/v1/profiles"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestProfilesCRUD(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
profile, err := CreateProfile(t, client)
th.AssertNoErr(t, err)
defer DeleteProfile(t, client, profile.ID)
// Test listing profiles
allPages, err := profiles.List(client, nil).AllPages()
th.AssertNoErr(t, err)
allProfiles, err := profiles.ExtractProfiles(allPages)
th.AssertNoErr(t, err)
var found bool
for _, v := range allProfiles {
if v.ID == profile.ID {
found = true
}
}
th.AssertEquals(t, found, true)
// Test updating profile
updateOpts := profiles.UpdateOpts{
Name: profile.Name + "-UPDATED",
}
newProfile, err := profiles.Update(client, profile.ID, updateOpts).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, newProfile.Name, profile.Name+"-UPDATED")
tools.PrintResource(t, newProfile)
tools.PrintResource(t, newProfile.UpdatedAt)
}
func TestProfileValidate(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
client.Microversion = "1.2"
profile, err := CreateProfile(t, client)
th.AssertNoErr(t, err)
defer DeleteProfile(t, client, profile.ID)
opts := profiles.ValidateOpts{
Spec: profile.Spec,
}
validatedProfile, err := profiles.Validate(client, opts).Extract()
th.AssertNoErr(t, err)
// Do not validate the following fields for AssertDeepEquals() because the actual fields are either missing or hardcoded.
profile.CreatedAt = validatedProfile.CreatedAt
profile.Domain = validatedProfile.Domain
profile.ID = validatedProfile.ID
profile.Metadata = validatedProfile.Metadata
profile.Name = "validated_profile"
profile.UpdatedAt = validatedProfile.UpdatedAt
th.AssertDeepEquals(t, validatedProfile, profile)
tools.PrintResource(t, validatedProfile)
}

View File

@@ -1,47 +0,0 @@
// +build acceptance clustering profiletypes
package v1
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/clustering/v1/profiletypes"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestProfileTypesList(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
client.Microversion = "1.5"
allPages, err := profiletypes.List(client).AllPages()
th.AssertNoErr(t, err)
allProfileTypes, err := profiletypes.ExtractProfileTypes(allPages)
th.AssertNoErr(t, err)
for _, profileType := range allProfileTypes {
tools.PrintResource(t, profileType)
}
}
func TestProfileTypesOpsList(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
client.Microversion = "1.5"
profileTypeName := "os.nova.server-1.0"
allPages, err := profiletypes.ListOps(client, profileTypeName).AllPages()
th.AssertNoErr(t, err)
ops, err := profiletypes.ExtractOps(allPages)
th.AssertNoErr(t, err)
for k, v := range ops {
tools.PrintResource(t, k)
tools.PrintResource(t, v)
}
}

View File

@@ -1,82 +0,0 @@
// +build acceptance clustering policies
package v1
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/clustering/v1/receivers"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestReceiversCRUD(t *testing.T) {
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
profile, err := CreateProfile(t, client)
th.AssertNoErr(t, err)
defer DeleteProfile(t, client, profile.ID)
cluster, err := CreateCluster(t, client, profile.ID)
th.AssertNoErr(t, err)
defer DeleteCluster(t, client, cluster.ID)
receiver, err := CreateWebhookReceiver(t, client, cluster.ID)
th.AssertNoErr(t, err)
defer DeleteReceiver(t, client, receiver.ID)
// Test listing receivers
allPages, err := receivers.List(client, nil).AllPages()
th.AssertNoErr(t, err)
allReceivers, err := receivers.ExtractReceivers(allPages)
th.AssertNoErr(t, err)
var found bool
for _, v := range allReceivers {
if v.ID == receiver.ID {
found = true
}
}
th.AssertEquals(t, found, true)
// Test updating receivers
newName := receiver.Name + "-UPDATED"
updateOpts := receivers.UpdateOpts{
Name: newName,
}
receiver, err = receivers.Update(client, receiver.ID, updateOpts).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, receiver)
tools.PrintResource(t, receiver.UpdatedAt)
th.AssertEquals(t, receiver.Name, newName)
}
func TestReceiversNotify(t *testing.T) {
t.Parallel()
client, err := clients.NewClusteringV1Client()
th.AssertNoErr(t, err)
profile, err := CreateProfile(t, client)
th.AssertNoErr(t, err)
defer DeleteProfile(t, client, profile.ID)
cluster, err := CreateCluster(t, client, profile.ID)
th.AssertNoErr(t, err)
defer DeleteCluster(t, client, cluster.ID)
receiver, err := CreateMessageReceiver(t, client, cluster.ID)
th.AssertNoErr(t, err)
defer DeleteReceiver(t, client, receiver.ID)
t.Logf("Created Mesage Receiver Name:[%s] Message Receiver ID:[%s]", receiver.Name, receiver.ID)
requestID, err := receivers.Notify(client, receiver.ID).Extract()
th.AssertNoErr(t, err)
t.Logf("Receiver Notify Service Request ID: %s", requestID)
}

View File

@@ -1,64 +0,0 @@
// +build acceptance clustering webhooks
package v1
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/openstack/clustering/v1/nodes"
"github.com/gophercloud/gophercloud/openstack/clustering/v1/webhooks"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestClusteringWebhookTrigger(t *testing.T) {
client, err := clients.NewClusteringV1Client()
if err != nil {
t.Fatalf("Unable to create clustering client: %v", err)
}
opts := webhooks.TriggerOpts{
V: "1",
}
// create profile, cluster and receiver first
profile, err := CreateProfile(t, client)
th.AssertNoErr(t, err)
defer DeleteProfile(t, client, profile.ID)
cluster, err := CreateCluster(t, client, profile.ID)
th.AssertNoErr(t, err)
defer DeleteCluster(t, client, cluster.ID)
receiver, err := CreateWebhookReceiver(t, client, cluster.ID)
th.AssertNoErr(t, err)
defer DeleteReceiver(t, client, receiver.ID)
// trigger webhook
actionID, err := webhooks.Trigger(client, receiver.ID, opts).Extract()
if err != nil {
t.Fatalf("Unable to extract webhooks trigger: %v", err)
} else {
t.Logf("Webhook trigger action id %s", actionID)
}
err = WaitForAction(client, actionID)
if err != nil {
t.Fatalf("Error scaling out cluster %s as a result from webhook trigger: %s:", cluster.ID, err)
}
// check that new node was created
nodelistopts := nodes.ListOpts{
ClusterID: cluster.ID,
}
allPages, err := nodes.List(client, nodelistopts).AllPages()
th.AssertNoErr(t, err)
allNodes, err := nodes.ExtractNodes(allPages)
th.AssertNoErr(t, err)
// there should be 2 nodes in the cluster after triggering webhook
th.AssertEquals(t, len(allNodes), 2)
}

View File

@@ -1,19 +0,0 @@
// Package openstack contains common functions that can be used
// across all OpenStack components for acceptance testing.
package openstack
import (
"testing"
"github.com/gophercloud/gophercloud/openstack/common/extensions"
)
// PrintExtension prints an extension and all of its attributes.
func PrintExtension(t *testing.T, extension *extensions.Extension) {
t.Logf("Name: %s", extension.Name)
t.Logf("Namespace: %s", extension.Namespace)
t.Logf("Alias: %s", extension.Alias)
t.Logf("Description: %s", extension.Description)
t.Logf("Updated: %s", extension.Updated)
t.Logf("Links: %v", extension.Links)
}

View File

@@ -1,146 +0,0 @@
// +build acceptance compute aggregates
package v2
import (
"fmt"
"testing"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/aggregates"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/hypervisors"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestAggregatesList(t *testing.T) {
clients.RequireAdmin(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
allPages, err := aggregates.List(client).AllPages()
th.AssertNoErr(t, err)
allAggregates, err := aggregates.ExtractAggregates(allPages)
th.AssertNoErr(t, err)
for _, v := range allAggregates {
tools.PrintResource(t, v)
}
}
func TestAggregatesCRUD(t *testing.T) {
clients.RequireAdmin(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
aggregate, err := CreateAggregate(t, client)
th.AssertNoErr(t, err)
defer DeleteAggregate(t, client, aggregate)
tools.PrintResource(t, aggregate)
updateOpts := aggregates.UpdateOpts{
Name: "new_aggregate_name",
AvailabilityZone: "new_azone",
}
updatedAggregate, err := aggregates.Update(client, aggregate.ID, updateOpts).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, aggregate)
th.AssertEquals(t, updatedAggregate.Name, "new_aggregate_name")
th.AssertEquals(t, updatedAggregate.AvailabilityZone, "new_azone")
}
func TestAggregatesAddRemoveHost(t *testing.T) {
clients.RequireAdmin(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
hostToAdd, err := getHypervisor(t, client)
th.AssertNoErr(t, err)
aggregate, err := CreateAggregate(t, client)
th.AssertNoErr(t, err)
defer DeleteAggregate(t, client, aggregate)
addHostOpts := aggregates.AddHostOpts{
Host: hostToAdd.HypervisorHostname,
}
aggregateWithNewHost, err := aggregates.AddHost(client, aggregate.ID, addHostOpts).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, aggregateWithNewHost)
th.AssertEquals(t, aggregateWithNewHost.Hosts[0], hostToAdd.HypervisorHostname)
removeHostOpts := aggregates.RemoveHostOpts{
Host: hostToAdd.HypervisorHostname,
}
aggregateWithRemovedHost, err := aggregates.RemoveHost(client, aggregate.ID, removeHostOpts).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, aggregateWithRemovedHost)
th.AssertEquals(t, len(aggregateWithRemovedHost.Hosts), 0)
}
func TestAggregatesSetRemoveMetadata(t *testing.T) {
clients.RequireAdmin(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
aggregate, err := CreateAggregate(t, client)
th.AssertNoErr(t, err)
defer DeleteAggregate(t, client, aggregate)
opts := aggregates.SetMetadataOpts{
Metadata: map[string]interface{}{"key": "value"},
}
aggregateWithMetadata, err := aggregates.SetMetadata(client, aggregate.ID, opts).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, aggregateWithMetadata)
if _, ok := aggregateWithMetadata.Metadata["key"]; !ok {
t.Fatalf("aggregate %s did not contain metadata", aggregateWithMetadata.Name)
}
optsToRemove := aggregates.SetMetadataOpts{
Metadata: map[string]interface{}{"key": nil},
}
aggregateWithRemovedKey, err := aggregates.SetMetadata(client, aggregate.ID, optsToRemove).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, aggregateWithRemovedKey)
if _, ok := aggregateWithRemovedKey.Metadata["key"]; ok {
t.Fatalf("aggregate %s still contains metadata", aggregateWithRemovedKey.Name)
}
}
func getHypervisor(t *testing.T, client *gophercloud.ServiceClient) (*hypervisors.Hypervisor, error) {
allPages, err := hypervisors.List(client).AllPages()
th.AssertNoErr(t, err)
allHypervisors, err := hypervisors.ExtractHypervisors(allPages)
th.AssertNoErr(t, err)
for _, h := range allHypervisors {
return &h, nil
}
return nil, fmt.Errorf("Unable to get hypervisor")
}

View File

@@ -1,51 +0,0 @@
// +build acceptance compute servers
package v2
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestAttachDetachInterface(t *testing.T) {
clients.RequireLong(t)
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
iface, err := AttachInterface(t, client, server.ID)
th.AssertNoErr(t, err)
defer DetachInterface(t, client, server.ID, iface.PortID)
tools.PrintResource(t, iface)
server, err = servers.Get(client, server.ID).Extract()
th.AssertNoErr(t, err)
var found bool
for _, networkAddresses := range server.Addresses[choices.NetworkName].([]interface{}) {
address := networkAddresses.(map[string]interface{})
if address["OS-EXT-IPS:type"] == "fixed" {
fixedIP := address["addr"].(string)
for _, v := range iface.FixedIPs {
if fixedIP == v.IPAddress {
found = true
}
}
}
}
th.AssertEquals(t, found, true)
}

View File

@@ -1,58 +0,0 @@
// +build acceptance compute availabilityzones
package v2
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/availabilityzones"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestAvailabilityZonesList(t *testing.T) {
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
allPages, err := availabilityzones.List(client).AllPages()
th.AssertNoErr(t, err)
availabilityZoneInfo, err := availabilityzones.ExtractAvailabilityZones(allPages)
th.AssertNoErr(t, err)
var found bool
for _, zoneInfo := range availabilityZoneInfo {
tools.PrintResource(t, zoneInfo)
if zoneInfo.ZoneName == "nova" {
found = true
}
}
th.AssertEquals(t, found, true)
}
func TestAvailabilityZonesListDetail(t *testing.T) {
clients.RequireAdmin(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
allPages, err := availabilityzones.ListDetail(client).AllPages()
th.AssertNoErr(t, err)
availabilityZoneInfo, err := availabilityzones.ExtractAvailabilityZones(allPages)
th.AssertNoErr(t, err)
var found bool
for _, zoneInfo := range availabilityZoneInfo {
tools.PrintResource(t, zoneInfo)
if zoneInfo.ZoneName == "nova" {
found = true
}
}
th.AssertEquals(t, found, true)
}

View File

@@ -1,304 +0,0 @@
// +build acceptance compute bootfromvolume
package v2
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
blockstorage "github.com/gophercloud/gophercloud/acceptance/openstack/blockstorage/v2"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/bootfromvolume"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestBootFromImage(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
blockDevices := []bootfromvolume.BlockDevice{
bootfromvolume.BlockDevice{
BootIndex: 0,
DeleteOnTermination: true,
DestinationType: bootfromvolume.DestinationLocal,
SourceType: bootfromvolume.SourceImage,
UUID: choices.ImageID,
},
}
server, err := CreateBootableVolumeServer(t, client, blockDevices)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
tools.PrintResource(t, server)
th.AssertEquals(t, server.Image["id"], choices.ImageID)
}
func TestBootFromNewVolume(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
blockDevices := []bootfromvolume.BlockDevice{
bootfromvolume.BlockDevice{
DeleteOnTermination: true,
DestinationType: bootfromvolume.DestinationVolume,
SourceType: bootfromvolume.SourceImage,
UUID: choices.ImageID,
VolumeSize: 2,
},
}
server, err := CreateBootableVolumeServer(t, client, blockDevices)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
attachPages, err := volumeattach.List(client, server.ID).AllPages()
th.AssertNoErr(t, err)
attachments, err := volumeattach.ExtractVolumeAttachments(attachPages)
th.AssertNoErr(t, err)
tools.PrintResource(t, server)
tools.PrintResource(t, attachments)
if server.Image != nil {
t.Fatalf("server image should be nil")
}
th.AssertEquals(t, len(attachments), 1)
// TODO: volumes_attached extension
}
func TestBootFromExistingVolume(t *testing.T) {
clients.RequireLong(t)
computeClient, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
blockStorageClient, err := clients.NewBlockStorageV2Client()
th.AssertNoErr(t, err)
volume, err := blockstorage.CreateVolumeFromImage(t, blockStorageClient)
th.AssertNoErr(t, err)
tools.PrintResource(t, volume)
blockDevices := []bootfromvolume.BlockDevice{
bootfromvolume.BlockDevice{
DeleteOnTermination: true,
DestinationType: bootfromvolume.DestinationVolume,
SourceType: bootfromvolume.SourceVolume,
UUID: volume.ID,
},
}
server, err := CreateBootableVolumeServer(t, computeClient, blockDevices)
th.AssertNoErr(t, err)
defer DeleteServer(t, computeClient, server)
attachPages, err := volumeattach.List(computeClient, server.ID).AllPages()
th.AssertNoErr(t, err)
attachments, err := volumeattach.ExtractVolumeAttachments(attachPages)
th.AssertNoErr(t, err)
tools.PrintResource(t, server)
tools.PrintResource(t, attachments)
if server.Image != nil {
t.Fatalf("server image should be nil")
}
th.AssertEquals(t, len(attachments), 1)
th.AssertEquals(t, attachments[0].VolumeID, volume.ID)
// TODO: volumes_attached extension
}
func TestBootFromMultiEphemeralServer(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
blockDevices := []bootfromvolume.BlockDevice{
bootfromvolume.BlockDevice{
BootIndex: 0,
DestinationType: bootfromvolume.DestinationLocal,
DeleteOnTermination: true,
SourceType: bootfromvolume.SourceImage,
UUID: choices.ImageID,
VolumeSize: 5,
},
bootfromvolume.BlockDevice{
BootIndex: -1,
DestinationType: bootfromvolume.DestinationLocal,
DeleteOnTermination: true,
GuestFormat: "ext4",
SourceType: bootfromvolume.SourceBlank,
VolumeSize: 1,
},
bootfromvolume.BlockDevice{
BootIndex: -1,
DestinationType: bootfromvolume.DestinationLocal,
DeleteOnTermination: true,
GuestFormat: "ext4",
SourceType: bootfromvolume.SourceBlank,
VolumeSize: 1,
},
}
server, err := CreateMultiEphemeralServer(t, client, blockDevices)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
tools.PrintResource(t, server)
}
func TestAttachNewVolume(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
blockDevices := []bootfromvolume.BlockDevice{
bootfromvolume.BlockDevice{
BootIndex: 0,
DeleteOnTermination: true,
DestinationType: bootfromvolume.DestinationLocal,
SourceType: bootfromvolume.SourceImage,
UUID: choices.ImageID,
},
bootfromvolume.BlockDevice{
BootIndex: 1,
DeleteOnTermination: true,
DestinationType: bootfromvolume.DestinationVolume,
SourceType: bootfromvolume.SourceBlank,
VolumeSize: 2,
},
}
server, err := CreateBootableVolumeServer(t, client, blockDevices)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
attachPages, err := volumeattach.List(client, server.ID).AllPages()
th.AssertNoErr(t, err)
attachments, err := volumeattach.ExtractVolumeAttachments(attachPages)
th.AssertNoErr(t, err)
tools.PrintResource(t, server)
tools.PrintResource(t, attachments)
th.AssertEquals(t, server.Image["id"], choices.ImageID)
th.AssertEquals(t, len(attachments), 1)
// TODO: volumes_attached extension
}
func TestAttachExistingVolume(t *testing.T) {
clients.RequireLong(t)
computeClient, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
blockStorageClient, err := clients.NewBlockStorageV2Client()
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
volume, err := blockstorage.CreateVolume(t, blockStorageClient)
th.AssertNoErr(t, err)
blockDevices := []bootfromvolume.BlockDevice{
bootfromvolume.BlockDevice{
BootIndex: 0,
DeleteOnTermination: true,
DestinationType: bootfromvolume.DestinationLocal,
SourceType: bootfromvolume.SourceImage,
UUID: choices.ImageID,
},
bootfromvolume.BlockDevice{
BootIndex: 1,
DeleteOnTermination: true,
DestinationType: bootfromvolume.DestinationVolume,
SourceType: bootfromvolume.SourceVolume,
UUID: volume.ID,
},
}
server, err := CreateBootableVolumeServer(t, computeClient, blockDevices)
th.AssertNoErr(t, err)
defer DeleteServer(t, computeClient, server)
attachPages, err := volumeattach.List(computeClient, server.ID).AllPages()
th.AssertNoErr(t, err)
attachments, err := volumeattach.ExtractVolumeAttachments(attachPages)
th.AssertNoErr(t, err)
tools.PrintResource(t, server)
tools.PrintResource(t, attachments)
th.AssertEquals(t, server.Image["id"], choices.ImageID)
th.AssertEquals(t, len(attachments), 1)
th.AssertEquals(t, attachments[0].VolumeID, volume.ID)
// TODO: volumes_attached extension
}
func TestBootFromNewCustomizedVolume(t *testing.T) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
t.Fatal(err)
}
blockDevices := []bootfromvolume.BlockDevice{
bootfromvolume.BlockDevice{
DeleteOnTermination: true,
DestinationType: bootfromvolume.DestinationVolume,
SourceType: bootfromvolume.SourceImage,
UUID: choices.ImageID,
VolumeSize: 2,
DeviceType: "disk",
DiskBus: "virtio",
},
}
server, err := CreateBootableVolumeServer(t, client, blockDevices)
if err != nil {
t.Fatalf("Unable to create server: %v", err)
}
defer DeleteServer(t, client, server)
tools.PrintResource(t, server)
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,61 +0,0 @@
// +build acceptance compute defsecrules
package v2
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
dsr "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/defsecrules"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestDefSecRulesList(t *testing.T) {
clients.RequireAdmin(t)
clients.RequireNovaNetwork(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
allPages, err := dsr.List(client).AllPages()
th.AssertNoErr(t, err)
allDefaultRules, err := dsr.ExtractDefaultRules(allPages)
th.AssertNoErr(t, err)
for _, defaultRule := range allDefaultRules {
tools.PrintResource(t, defaultRule)
}
}
func TestDefSecRulesCreate(t *testing.T) {
clients.RequireAdmin(t)
clients.RequireNovaNetwork(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
defaultRule, err := CreateDefaultRule(t, client)
th.AssertNoErr(t, err)
defer DeleteDefaultRule(t, client, defaultRule)
tools.PrintResource(t, defaultRule)
}
func TestDefSecRulesGet(t *testing.T) {
clients.RequireAdmin(t)
clients.RequireNovaNetwork(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
defaultRule, err := CreateDefaultRule(t, client)
th.AssertNoErr(t, err)
defer DeleteDefaultRule(t, client, defaultRule)
newDefaultRule, err := dsr.Get(client, defaultRule.ID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, newDefaultRule)
}

View File

@@ -1,46 +0,0 @@
// +build acceptance compute extensions
package v2
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/common/extensions"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestExtensionsList(t *testing.T) {
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
allPages, err := extensions.List(client).AllPages()
th.AssertNoErr(t, err)
allExtensions, err := extensions.ExtractExtensions(allPages)
th.AssertNoErr(t, err)
var found bool
for _, extension := range allExtensions {
tools.PrintResource(t, extension)
if extension.Name == "SchedulerHints" {
found = true
}
}
th.AssertEquals(t, found, true)
}
func TestExtensionsGet(t *testing.T) {
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
extension, err := extensions.Get(client, "os-admin-actions").Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, extension)
th.AssertEquals(t, extension.Name, "AdminActions")
}

View File

@@ -1,201 +0,0 @@
// +build acceptance compute flavors
package v2
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
identity "github.com/gophercloud/gophercloud/acceptance/openstack/identity/v3"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/compute/v2/flavors"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestFlavorsList(t *testing.T) {
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
allPages, err := flavors.ListDetail(client, nil).AllPages()
th.AssertNoErr(t, err)
allFlavors, err := flavors.ExtractFlavors(allPages)
th.AssertNoErr(t, err)
var found bool
for _, flavor := range allFlavors {
tools.PrintResource(t, flavor)
if flavor.ID == choices.FlavorID {
found = true
}
}
th.AssertEquals(t, found, true)
}
func TestFlavorsAccessTypeList(t *testing.T) {
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
flavorAccessTypes := map[string]flavors.AccessType{
"public": flavors.PublicAccess,
"private": flavors.PrivateAccess,
"all": flavors.AllAccess,
}
for flavorTypeName, flavorAccessType := range flavorAccessTypes {
t.Logf("** %s flavors: **", flavorTypeName)
allPages, err := flavors.ListDetail(client, flavors.ListOpts{AccessType: flavorAccessType}).AllPages()
th.AssertNoErr(t, err)
allFlavors, err := flavors.ExtractFlavors(allPages)
th.AssertNoErr(t, err)
for _, flavor := range allFlavors {
tools.PrintResource(t, flavor)
}
}
}
func TestFlavorsGet(t *testing.T) {
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
flavor, err := flavors.Get(client, choices.FlavorID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, flavor)
th.AssertEquals(t, flavor.ID, choices.FlavorID)
}
func TestFlavorsCreateDelete(t *testing.T) {
clients.RequireAdmin(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
flavor, err := CreateFlavor(t, client)
th.AssertNoErr(t, err)
defer DeleteFlavor(t, client, flavor)
tools.PrintResource(t, flavor)
}
func TestFlavorsAccessesList(t *testing.T) {
clients.RequireAdmin(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
flavor, err := CreatePrivateFlavor(t, client)
th.AssertNoErr(t, err)
defer DeleteFlavor(t, client, flavor)
allPages, err := flavors.ListAccesses(client, flavor.ID).AllPages()
th.AssertNoErr(t, err)
allAccesses, err := flavors.ExtractAccesses(allPages)
th.AssertNoErr(t, err)
th.AssertEquals(t, len(allAccesses), 0)
}
func TestFlavorsAccessCRUD(t *testing.T) {
clients.RequireAdmin(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
identityClient, err := clients.NewIdentityV3Client()
th.AssertNoErr(t, err)
project, err := identity.CreateProject(t, identityClient, nil)
th.AssertNoErr(t, err)
defer identity.DeleteProject(t, identityClient, project.ID)
flavor, err := CreatePrivateFlavor(t, client)
th.AssertNoErr(t, err)
defer DeleteFlavor(t, client, flavor)
addAccessOpts := flavors.AddAccessOpts{
Tenant: project.ID,
}
accessList, err := flavors.AddAccess(client, flavor.ID, addAccessOpts).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, len(accessList), 1)
th.AssertEquals(t, accessList[0].TenantID, project.ID)
th.AssertEquals(t, accessList[0].FlavorID, flavor.ID)
for _, access := range accessList {
tools.PrintResource(t, access)
}
removeAccessOpts := flavors.RemoveAccessOpts{
Tenant: project.ID,
}
accessList, err = flavors.RemoveAccess(client, flavor.ID, removeAccessOpts).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, len(accessList), 0)
}
func TestFlavorsExtraSpecsCRUD(t *testing.T) {
clients.RequireAdmin(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
flavor, err := CreatePrivateFlavor(t, client)
th.AssertNoErr(t, err)
defer DeleteFlavor(t, client, flavor)
createOpts := flavors.ExtraSpecsOpts{
"hw:cpu_policy": "CPU-POLICY",
"hw:cpu_thread_policy": "CPU-THREAD-POLICY",
}
createdExtraSpecs, err := flavors.CreateExtraSpecs(client, flavor.ID, createOpts).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, createdExtraSpecs)
th.AssertEquals(t, len(createdExtraSpecs), 2)
th.AssertEquals(t, createdExtraSpecs["hw:cpu_policy"], "CPU-POLICY")
th.AssertEquals(t, createdExtraSpecs["hw:cpu_thread_policy"], "CPU-THREAD-POLICY")
err = flavors.DeleteExtraSpec(client, flavor.ID, "hw:cpu_policy").ExtractErr()
th.AssertNoErr(t, err)
updateOpts := flavors.ExtraSpecsOpts{
"hw:cpu_thread_policy": "CPU-THREAD-POLICY-BETTER",
}
updatedExtraSpec, err := flavors.UpdateExtraSpec(client, flavor.ID, updateOpts).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, updatedExtraSpec)
allExtraSpecs, err := flavors.ListExtraSpecs(client, flavor.ID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, allExtraSpecs)
th.AssertEquals(t, len(allExtraSpecs), 1)
th.AssertEquals(t, allExtraSpecs["hw:cpu_thread_policy"], "CPU-THREAD-POLICY-BETTER")
spec, err := flavors.GetExtraSpec(client, flavor.ID, "hw:cpu_thread_policy").Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, spec)
th.AssertEquals(t, spec["hw:cpu_thread_policy"], "CPU-THREAD-POLICY-BETTER")
}

View File

@@ -1,123 +0,0 @@
// +build acceptance compute servers
package v2
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/floatingips"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestFloatingIPsCreateDelete(t *testing.T) {
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
floatingIP, err := CreateFloatingIP(t, client)
th.AssertNoErr(t, err)
defer DeleteFloatingIP(t, client, floatingIP)
tools.PrintResource(t, floatingIP)
allPages, err := floatingips.List(client).AllPages()
th.AssertNoErr(t, err)
allFloatingIPs, err := floatingips.ExtractFloatingIPs(allPages)
th.AssertNoErr(t, err)
var found bool
for _, fip := range allFloatingIPs {
tools.PrintResource(t, floatingIP)
if fip.ID == floatingIP.ID {
found = true
}
}
th.AssertEquals(t, found, true)
fip, err := floatingips.Get(client, floatingIP.ID).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, floatingIP.ID, fip.ID)
}
func TestFloatingIPsAssociate(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
floatingIP, err := CreateFloatingIP(t, client)
th.AssertNoErr(t, err)
defer DeleteFloatingIP(t, client, floatingIP)
tools.PrintResource(t, floatingIP)
err = AssociateFloatingIP(t, client, floatingIP, server)
th.AssertNoErr(t, err)
defer DisassociateFloatingIP(t, client, floatingIP, server)
newFloatingIP, err := floatingips.Get(client, floatingIP.ID).Extract()
th.AssertNoErr(t, err)
t.Logf("Floating IP %s is associated with Fixed IP %s", floatingIP.IP, newFloatingIP.FixedIP)
tools.PrintResource(t, newFloatingIP)
th.AssertEquals(t, newFloatingIP.InstanceID, server.ID)
}
func TestFloatingIPsFixedIPAssociate(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
newServer, err := servers.Get(client, server.ID).Extract()
th.AssertNoErr(t, err)
floatingIP, err := CreateFloatingIP(t, client)
th.AssertNoErr(t, err)
defer DeleteFloatingIP(t, client, floatingIP)
tools.PrintResource(t, floatingIP)
var fixedIP string
for _, networkAddresses := range newServer.Addresses[choices.NetworkName].([]interface{}) {
address := networkAddresses.(map[string]interface{})
if address["OS-EXT-IPS:type"] == "fixed" {
if address["version"].(float64) == 4 {
fixedIP = address["addr"].(string)
}
}
}
err = AssociateFloatingIPWithFixedIP(t, client, floatingIP, newServer, fixedIP)
th.AssertNoErr(t, err)
defer DisassociateFloatingIP(t, client, floatingIP, newServer)
newFloatingIP, err := floatingips.Get(client, floatingIP.ID).Extract()
th.AssertNoErr(t, err)
t.Logf("Floating IP %s is associated with Fixed IP %s", floatingIP.IP, newFloatingIP.FixedIP)
tools.PrintResource(t, newFloatingIP)
th.AssertEquals(t, newFloatingIP.InstanceID, server.ID)
th.AssertEquals(t, newFloatingIP.FixedIP, fixedIP)
}

View File

@@ -1,95 +0,0 @@
// +build acceptance compute hypervisors
package v2
import (
"fmt"
"testing"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/hypervisors"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestHypervisorsList(t *testing.T) {
clients.RequireAdmin(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
allPages, err := hypervisors.List(client).AllPages()
th.AssertNoErr(t, err)
allHypervisors, err := hypervisors.ExtractHypervisors(allPages)
th.AssertNoErr(t, err)
for _, h := range allHypervisors {
tools.PrintResource(t, h)
}
}
func TestHypervisorsGet(t *testing.T) {
clients.RequireAdmin(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
hypervisorID, err := getHypervisorID(t, client)
th.AssertNoErr(t, err)
hypervisor, err := hypervisors.Get(client, hypervisorID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, hypervisor)
th.AssertEquals(t, hypervisorID, hypervisor.ID)
}
func TestHypervisorsGetStatistics(t *testing.T) {
clients.RequireAdmin(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
hypervisorsStats, err := hypervisors.GetStatistics(client).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, hypervisorsStats)
if hypervisorsStats.Count == 0 {
t.Fatalf("Unable to get hypervisor stats")
}
}
func TestHypervisorsGetUptime(t *testing.T) {
clients.RequireAdmin(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
hypervisorID, err := getHypervisorID(t, client)
th.AssertNoErr(t, err)
hypervisor, err := hypervisors.GetUptime(client, hypervisorID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, hypervisor)
th.AssertEquals(t, hypervisorID, hypervisor.ID)
}
func getHypervisorID(t *testing.T, client *gophercloud.ServiceClient) (string, error) {
allPages, err := hypervisors.List(client).AllPages()
th.AssertNoErr(t, err)
allHypervisors, err := hypervisors.ExtractHypervisors(allPages)
th.AssertNoErr(t, err)
if len(allHypervisors) > 0 {
return allHypervisors[0].ID, nil
}
return "", fmt.Errorf("Unable to get hypervisor ID")
}

View File

@@ -1,52 +0,0 @@
// +build acceptance compute images
package v2
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/compute/v2/images"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestImagesList(t *testing.T) {
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
allPages, err := images.ListDetail(client, nil).AllPages()
th.AssertNoErr(t, err)
allImages, err := images.ExtractImages(allPages)
th.AssertNoErr(t, err)
var found bool
for _, image := range allImages {
tools.PrintResource(t, image)
if image.ID == choices.ImageID {
found = true
}
}
th.AssertEquals(t, found, true)
}
func TestImagesGet(t *testing.T) {
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
image, err := images.Get(client, choices.ImageID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, image)
th.AssertEquals(t, choices.ImageID, image.ID)
}

View File

@@ -1,101 +0,0 @@
// +build acceptance compute keypairs
package v2
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
th "github.com/gophercloud/gophercloud/testhelper"
"golang.org/x/crypto/ssh"
)
const keyName = "gophercloud_test_key_pair"
func TestKeypairsParse(t *testing.T) {
clients.SkipRelease(t, "stable/mitaka")
clients.SkipRelease(t, "stable/newton")
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
keyPair, err := CreateKeyPair(t, client)
th.AssertNoErr(t, err)
defer DeleteKeyPair(t, client, keyPair)
// There was a series of OpenStack releases, between Liberty and Ocata,
// where the returned SSH key was not parsable by Go.
// This checks if the issue is happening again.
_, err = ssh.ParsePrivateKey([]byte(keyPair.PrivateKey))
th.AssertNoErr(t, err)
tools.PrintResource(t, keyPair)
}
func TestKeypairsCreateDelete(t *testing.T) {
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
keyPair, err := CreateKeyPair(t, client)
th.AssertNoErr(t, err)
defer DeleteKeyPair(t, client, keyPair)
tools.PrintResource(t, keyPair)
allPages, err := keypairs.List(client).AllPages()
th.AssertNoErr(t, err)
allKeys, err := keypairs.ExtractKeyPairs(allPages)
th.AssertNoErr(t, err)
var found bool
for _, kp := range allKeys {
tools.PrintResource(t, kp)
if kp.Name == keyPair.Name {
found = true
}
}
th.AssertEquals(t, found, true)
}
func TestKeypairsImportPublicKey(t *testing.T) {
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
publicKey, err := createKey()
th.AssertNoErr(t, err)
keyPair, err := ImportPublicKey(t, client, publicKey)
th.AssertNoErr(t, err)
defer DeleteKeyPair(t, client, keyPair)
tools.PrintResource(t, keyPair)
}
func TestKeypairsServerCreateWithKey(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
publicKey, err := createKey()
th.AssertNoErr(t, err)
keyPair, err := ImportPublicKey(t, client, publicKey)
th.AssertNoErr(t, err)
defer DeleteKeyPair(t, client, keyPair)
server, err := CreateServerWithPublicKey(t, client, keyPair.Name)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
server, err = servers.Get(client, server.ID).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, server.KeyName, keyPair.Name)
}

View File

@@ -1,50 +0,0 @@
// +build acceptance compute limits
package v2
import (
"strings"
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/limits"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestLimits(t *testing.T) {
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
limits, err := limits.Get(client, nil).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, limits)
th.AssertEquals(t, limits.Absolute.MaxPersonalitySize, 10240)
}
func TestLimitsForTenant(t *testing.T) {
clients.RequireAdmin(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
// I think this is the easiest way to get the tenant ID while being
// agnostic to Identity v2 and v3.
// Technically we're just returning the limits for ourselves, but it's
// the fact that we're specifying a tenant ID that is important here.
endpointParts := strings.Split(client.Endpoint, "/")
tenantID := endpointParts[4]
getOpts := limits.GetOpts{
TenantID: tenantID,
}
limits, err := limits.Get(client, getOpts).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, limits)
th.AssertEquals(t, limits.Absolute.MaxPersonalitySize, 10240)
}

View File

@@ -1,56 +0,0 @@
// +build acceptance compute servers
package v2
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/migrate"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestMigrate(t *testing.T) {
t.Skip("This is not passing in OpenLab. Works locally")
clients.RequireLong(t)
clients.RequireAdmin(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
t.Logf("Attempting to migrate server %s", server.ID)
err = migrate.Migrate(client, server.ID).ExtractErr()
th.AssertNoErr(t, err)
}
func TestLiveMigrate(t *testing.T) {
clients.RequireLong(t)
clients.RequireAdmin(t)
clients.RequireLiveMigration(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
t.Logf("Attempting to migrate server %s", server.ID)
blockMigration := false
diskOverCommit := false
liveMigrateOpts := migrate.LiveMigrateOpts{
BlockMigration: &blockMigration,
DiskOverCommit: &diskOverCommit,
}
err = migrate.LiveMigrate(client, server.ID, liveMigrateOpts).ExtractErr()
th.AssertNoErr(t, err)
}

View File

@@ -1,55 +0,0 @@
// +build acceptance compute servers
package v2
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/networks"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestNetworksList(t *testing.T) {
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
allPages, err := networks.List(client).AllPages()
th.AssertNoErr(t, err)
allNetworks, err := networks.ExtractNetworks(allPages)
th.AssertNoErr(t, err)
var found bool
for _, network := range allNetworks {
tools.PrintResource(t, network)
if network.Label == choices.NetworkName {
found = true
}
}
th.AssertEquals(t, found, true)
}
func TestNetworksGet(t *testing.T) {
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
networkID, err := GetNetworkIDFromNetworks(t, client, choices.NetworkName)
th.AssertNoErr(t, err)
network, err := networks.Get(client, networkID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, network)
th.AssertEquals(t, network.Label, choices.NetworkName)
}

View File

@@ -1,2 +0,0 @@
// Package v2 package contains acceptance tests for the Openstack Compute V2 service.
package v2

View File

@@ -1,153 +0,0 @@
// +build acceptance compute quotasets
package v2
import (
"fmt"
"os"
"testing"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/quotasets"
"github.com/gophercloud/gophercloud/openstack/identity/v2/tenants"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestQuotasetGet(t *testing.T) {
clients.SkipRelease(t, "master")
clients.SkipRelease(t, "stable/queens")
clients.SkipRelease(t, "stable/rocky")
clients.SkipRelease(t, "stable/stein")
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
identityClient, err := clients.NewIdentityV2Client()
th.AssertNoErr(t, err)
tenantID, err := getTenantID(t, identityClient)
th.AssertNoErr(t, err)
quotaSet, err := quotasets.Get(client, tenantID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, quotaSet)
th.AssertEquals(t, quotaSet.FixedIPs, -1)
}
func getTenantID(t *testing.T, client *gophercloud.ServiceClient) (string, error) {
allPages, err := tenants.List(client, nil).AllPages()
th.AssertNoErr(t, err)
allTenants, err := tenants.ExtractTenants(allPages)
th.AssertNoErr(t, err)
for _, tenant := range allTenants {
return tenant.ID, nil
}
return "", fmt.Errorf("Unable to get tenant ID")
}
func getTenantIDByName(t *testing.T, client *gophercloud.ServiceClient, name string) (string, error) {
allPages, err := tenants.List(client, nil).AllPages()
th.AssertNoErr(t, err)
allTenants, err := tenants.ExtractTenants(allPages)
th.AssertNoErr(t, err)
for _, tenant := range allTenants {
if tenant.Name == name {
return tenant.ID, nil
}
}
return "", fmt.Errorf("Unable to get tenant ID")
}
// What will be sent as desired Quotas to the Server
var UpdateQuotaOpts = quotasets.UpdateOpts{
FixedIPs: gophercloud.IntToPointer(10),
FloatingIPs: gophercloud.IntToPointer(10),
InjectedFileContentBytes: gophercloud.IntToPointer(10240),
InjectedFilePathBytes: gophercloud.IntToPointer(255),
InjectedFiles: gophercloud.IntToPointer(5),
KeyPairs: gophercloud.IntToPointer(10),
MetadataItems: gophercloud.IntToPointer(128),
RAM: gophercloud.IntToPointer(20000),
SecurityGroupRules: gophercloud.IntToPointer(20),
SecurityGroups: gophercloud.IntToPointer(10),
Cores: gophercloud.IntToPointer(10),
Instances: gophercloud.IntToPointer(4),
ServerGroups: gophercloud.IntToPointer(2),
ServerGroupMembers: gophercloud.IntToPointer(3),
}
// What the Server hopefully returns as the new Quotas
var UpdatedQuotas = quotasets.QuotaSet{
FixedIPs: 10,
FloatingIPs: 10,
InjectedFileContentBytes: 10240,
InjectedFilePathBytes: 255,
InjectedFiles: 5,
KeyPairs: 10,
MetadataItems: 128,
RAM: 20000,
SecurityGroupRules: 20,
SecurityGroups: 10,
Cores: 10,
Instances: 4,
ServerGroups: 2,
ServerGroupMembers: 3,
}
func TestQuotasetUpdateDelete(t *testing.T) {
clients.SkipRelease(t, "master")
clients.SkipRelease(t, "stable/queens")
clients.SkipRelease(t, "stable/rocky")
clients.SkipRelease(t, "stable/stein")
clients.RequireAdmin(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
idclient, err := clients.NewIdentityV2Client()
th.AssertNoErr(t, err)
tenantid, err := getTenantIDByName(t, idclient, os.Getenv("OS_TENANT_NAME"))
th.AssertNoErr(t, err)
// save original quotas
orig, err := quotasets.Get(client, tenantid).Extract()
th.AssertNoErr(t, err)
// Test Update
res, err := quotasets.Update(client, tenantid, UpdateQuotaOpts).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, UpdatedQuotas, *res)
// Test Delete
_, err = quotasets.Delete(client, tenantid).Extract()
th.AssertNoErr(t, err)
// We dont know the default quotas, so just check if the quotas are not the same as before
newres, err := quotasets.Get(client, tenantid).Extract()
th.AssertNoErr(t, err)
if newres.RAM == res.RAM {
t.Fatalf("Failed to update quotas")
}
restore := quotasets.UpdateOpts{}
FillUpdateOptsFromQuotaSet(*orig, &restore)
// restore original quotas
res, err = quotasets.Update(client, tenantid, restore).Extract()
th.AssertNoErr(t, err)
orig.ID = ""
th.AssertDeepEquals(t, orig, res)
}

View File

@@ -1,29 +0,0 @@
// +build acceptance compute remoteconsoles
package v2
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestRemoteConsoleCreate(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
client.Microversion = "2.6"
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
remoteConsole, err := CreateRemoteConsole(t, client, server.ID)
th.AssertNoErr(t, err)
tools.PrintResource(t, remoteConsole)
}

View File

@@ -1,25 +0,0 @@
// +build acceptance compute rescueunrescue
package v2
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestServerRescueUnrescue(t *testing.T) {
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
err = RescueServer(t, client, server)
th.AssertNoErr(t, err)
err = UnrescueServer(t, client, server)
th.AssertNoErr(t, err)
}

View File

@@ -1,142 +0,0 @@
// +build acceptance compute secgroups
package v2
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/secgroups"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestSecGroupsList(t *testing.T) {
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
allPages, err := secgroups.List(client).AllPages()
th.AssertNoErr(t, err)
allSecGroups, err := secgroups.ExtractSecurityGroups(allPages)
th.AssertNoErr(t, err)
var found bool
for _, secgroup := range allSecGroups {
tools.PrintResource(t, secgroup)
if secgroup.Name == "default" {
found = true
}
}
th.AssertEquals(t, found, true)
}
func TestSecGroupsCRUD(t *testing.T) {
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
securityGroup, err := CreateSecurityGroup(t, client)
th.AssertNoErr(t, err)
defer DeleteSecurityGroup(t, client, securityGroup.ID)
tools.PrintResource(t, securityGroup)
newName := tools.RandomString("secgroup_", 4)
description := ""
updateOpts := secgroups.UpdateOpts{
Name: newName,
Description: &description,
}
updatedSecurityGroup, err := secgroups.Update(client, securityGroup.ID, updateOpts).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, updatedSecurityGroup)
t.Logf("Updated %s's name to %s", updatedSecurityGroup.ID, updatedSecurityGroup.Name)
th.AssertEquals(t, updatedSecurityGroup.Name, newName)
th.AssertEquals(t, updatedSecurityGroup.Description, description)
}
func TestSecGroupsRuleCreate(t *testing.T) {
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
securityGroup, err := CreateSecurityGroup(t, client)
th.AssertNoErr(t, err)
defer DeleteSecurityGroup(t, client, securityGroup.ID)
tools.PrintResource(t, securityGroup)
rule, err := CreateSecurityGroupRule(t, client, securityGroup.ID)
th.AssertNoErr(t, err)
defer DeleteSecurityGroupRule(t, client, rule.ID)
tools.PrintResource(t, rule)
newSecurityGroup, err := secgroups.Get(client, securityGroup.ID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, newSecurityGroup)
th.AssertEquals(t, len(newSecurityGroup.Rules), 1)
}
func TestSecGroupsAddGroupToServer(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
securityGroup, err := CreateSecurityGroup(t, client)
th.AssertNoErr(t, err)
defer DeleteSecurityGroup(t, client, securityGroup.ID)
rule, err := CreateSecurityGroupRule(t, client, securityGroup.ID)
th.AssertNoErr(t, err)
defer DeleteSecurityGroupRule(t, client, rule.ID)
t.Logf("Adding group %s to server %s", securityGroup.ID, server.ID)
err = secgroups.AddServer(client, server.ID, securityGroup.Name).ExtractErr()
th.AssertNoErr(t, err)
server, err = servers.Get(client, server.ID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, server)
var found bool
for _, sg := range server.SecurityGroups {
if sg["name"] == securityGroup.Name {
found = true
}
}
th.AssertEquals(t, found, true)
t.Logf("Removing group %s from server %s", securityGroup.ID, server.ID)
err = secgroups.RemoveServer(client, server.ID, securityGroup.Name).ExtractErr()
th.AssertNoErr(t, err)
server, err = servers.Get(client, server.ID).Extract()
th.AssertNoErr(t, err)
found = false
tools.PrintResource(t, server)
for _, sg := range server.SecurityGroups {
if sg["name"] == securityGroup.Name {
found = true
}
}
th.AssertEquals(t, found, false)
}

View File

@@ -1,71 +0,0 @@
// +build acceptance compute servergroups
package v2
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestServergroupsCreateDelete(t *testing.T) {
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
serverGroup, err := CreateServerGroup(t, client, "anti-affinity")
th.AssertNoErr(t, err)
defer DeleteServerGroup(t, client, serverGroup)
serverGroup, err = servergroups.Get(client, serverGroup.ID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, serverGroup)
allPages, err := servergroups.List(client).AllPages()
th.AssertNoErr(t, err)
allServerGroups, err := servergroups.ExtractServerGroups(allPages)
th.AssertNoErr(t, err)
var found bool
for _, sg := range allServerGroups {
tools.PrintResource(t, serverGroup)
if sg.ID == serverGroup.ID {
found = true
}
}
th.AssertEquals(t, found, true)
}
func TestServergroupsAffinityPolicy(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
serverGroup, err := CreateServerGroup(t, client, "affinity")
th.AssertNoErr(t, err)
defer DeleteServerGroup(t, client, serverGroup)
firstServer, err := CreateServerInServerGroup(t, client, serverGroup)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, firstServer)
firstServer, err = servers.Get(client, firstServer.ID).Extract()
th.AssertNoErr(t, err)
secondServer, err := CreateServerInServerGroup(t, client, serverGroup)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, secondServer)
secondServer, err = servers.Get(client, secondServer.ID).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, firstServer.HostID, secondServer.HostID)
}

View File

@@ -1,562 +0,0 @@
// +build acceptance compute servers
package v2
import (
"strings"
"testing"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/availabilityzones"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/extendedserverattributes"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/extendedstatus"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/lockunlock"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/pauseunpause"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/serverusage"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/suspendresume"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestServersCreateDestroy(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
allPages, err := servers.List(client, servers.ListOpts{}).AllPages()
th.AssertNoErr(t, err)
allServers, err := servers.ExtractServers(allPages)
th.AssertNoErr(t, err)
var found bool
for _, s := range allServers {
tools.PrintResource(t, server)
if s.ID == server.ID {
found = true
}
}
th.AssertEquals(t, found, true)
allAddressPages, err := servers.ListAddresses(client, server.ID).AllPages()
th.AssertNoErr(t, err)
allAddresses, err := servers.ExtractAddresses(allAddressPages)
th.AssertNoErr(t, err)
for network, address := range allAddresses {
t.Logf("Addresses on %s: %+v", network, address)
}
allInterfacePages, err := attachinterfaces.List(client, server.ID).AllPages()
th.AssertNoErr(t, err)
allInterfaces, err := attachinterfaces.ExtractInterfaces(allInterfacePages)
th.AssertNoErr(t, err)
for _, iface := range allInterfaces {
t.Logf("Interfaces: %+v", iface)
}
allNetworkAddressPages, err := servers.ListAddressesByNetwork(client, server.ID, choices.NetworkName).AllPages()
th.AssertNoErr(t, err)
allNetworkAddresses, err := servers.ExtractNetworkAddresses(allNetworkAddressPages)
th.AssertNoErr(t, err)
t.Logf("Addresses on %s:", choices.NetworkName)
for _, address := range allNetworkAddresses {
t.Logf("%+v", address)
}
}
func TestServersWithExtensionsCreateDestroy(t *testing.T) {
clients.RequireLong(t)
var extendedServer struct {
servers.Server
availabilityzones.ServerAvailabilityZoneExt
extendedstatus.ServerExtendedStatusExt
serverusage.UsageExt
}
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
err = servers.Get(client, server.ID).ExtractInto(&extendedServer)
th.AssertNoErr(t, err)
tools.PrintResource(t, extendedServer)
th.AssertEquals(t, extendedServer.AvailabilityZone, "nova")
th.AssertEquals(t, int(extendedServer.PowerState), extendedstatus.RUNNING)
th.AssertEquals(t, extendedServer.TaskState, "")
th.AssertEquals(t, extendedServer.VmState, "active")
th.AssertEquals(t, extendedServer.LaunchedAt.IsZero(), false)
th.AssertEquals(t, extendedServer.TerminatedAt.IsZero(), true)
}
func TestServersWithoutImageRef(t *testing.T) {
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
server, err := CreateServerWithoutImageRef(t, client)
if err != nil {
if err400, ok := err.(*gophercloud.ErrUnexpectedResponseCode); ok {
if !strings.Contains(string(err400.Body), "Missing imageRef attribute") {
defer DeleteServer(t, client, server)
}
}
}
}
func TestServersUpdate(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
alternateName := tools.RandomString("ACPTTEST", 16)
for alternateName == server.Name {
alternateName = tools.RandomString("ACPTTEST", 16)
}
t.Logf("Attempting to rename the server to %s.", alternateName)
updateOpts := servers.UpdateOpts{
Name: alternateName,
}
updated, err := servers.Update(client, server.ID, updateOpts).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, updated.ID, server.ID)
err = tools.WaitFor(func() (bool, error) {
latest, err := servers.Get(client, updated.ID).Extract()
if err != nil {
return false, err
}
return latest.Name == alternateName, nil
})
}
func TestServersMetadata(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
tools.PrintResource(t, server)
metadata, err := servers.UpdateMetadata(client, server.ID, servers.MetadataOpts{
"foo": "bar",
"this": "that",
}).Extract()
th.AssertNoErr(t, err)
t.Logf("UpdateMetadata result: %+v\n", metadata)
server, err = servers.Get(client, server.ID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, server)
expectedMetadata := map[string]string{
"abc": "def",
"foo": "bar",
"this": "that",
}
th.AssertDeepEquals(t, expectedMetadata, server.Metadata)
err = servers.DeleteMetadatum(client, server.ID, "foo").ExtractErr()
th.AssertNoErr(t, err)
server, err = servers.Get(client, server.ID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, server)
expectedMetadata = map[string]string{
"abc": "def",
"this": "that",
}
th.AssertDeepEquals(t, expectedMetadata, server.Metadata)
metadata, err = servers.CreateMetadatum(client, server.ID, servers.MetadatumOpts{
"foo": "baz",
}).Extract()
th.AssertNoErr(t, err)
t.Logf("CreateMetadatum result: %+v\n", metadata)
server, err = servers.Get(client, server.ID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, server)
expectedMetadata = map[string]string{
"abc": "def",
"this": "that",
"foo": "baz",
}
th.AssertDeepEquals(t, expectedMetadata, server.Metadata)
metadata, err = servers.Metadatum(client, server.ID, "foo").Extract()
th.AssertNoErr(t, err)
t.Logf("Metadatum result: %+v\n", metadata)
th.AssertEquals(t, "baz", metadata["foo"])
metadata, err = servers.Metadata(client, server.ID).Extract()
th.AssertNoErr(t, err)
t.Logf("Metadata result: %+v\n", metadata)
th.AssertDeepEquals(t, expectedMetadata, metadata)
metadata, err = servers.ResetMetadata(client, server.ID, servers.MetadataOpts{}).Extract()
th.AssertNoErr(t, err)
t.Logf("ResetMetadata result: %+v\n", metadata)
th.AssertDeepEquals(t, map[string]string{}, metadata)
}
func TestServersActionChangeAdminPassword(t *testing.T) {
clients.RequireLong(t)
clients.RequireGuestAgent(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
randomPassword := tools.MakeNewPassword(server.AdminPass)
res := servers.ChangeAdminPassword(client, server.ID, randomPassword)
th.AssertNoErr(t, res.Err)
if err = WaitForComputeStatus(client, server, "PASSWORD"); err != nil {
t.Fatal(err)
}
if err = WaitForComputeStatus(client, server, "ACTIVE"); err != nil {
t.Fatal(err)
}
}
func TestServersActionReboot(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
rebootOpts := servers.RebootOpts{
Type: servers.SoftReboot,
}
t.Logf("Attempting reboot of server %s", server.ID)
res := servers.Reboot(client, server.ID, rebootOpts)
th.AssertNoErr(t, res.Err)
if err = WaitForComputeStatus(client, server, "REBOOT"); err != nil {
t.Fatal(err)
}
if err = WaitForComputeStatus(client, server, "ACTIVE"); err != nil {
t.Fatal(err)
}
}
func TestServersActionRebuild(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
t.Logf("Attempting to rebuild server %s", server.ID)
rebuildOpts := servers.RebuildOpts{
Name: tools.RandomString("ACPTTEST", 16),
AdminPass: tools.MakeNewPassword(server.AdminPass),
ImageID: choices.ImageID,
}
rebuilt, err := servers.Rebuild(client, server.ID, rebuildOpts).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, rebuilt.ID, server.ID)
if err = WaitForComputeStatus(client, rebuilt, "REBUILD"); err != nil {
t.Fatal(err)
}
if err = WaitForComputeStatus(client, rebuilt, "ACTIVE"); err != nil {
t.Fatal(err)
}
}
func TestServersActionResizeConfirm(t *testing.T) {
clients.RequireLong(t)
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
t.Logf("Attempting to resize server %s", server.ID)
ResizeServer(t, client, server)
t.Logf("Attempting to confirm resize for server %s", server.ID)
if res := servers.ConfirmResize(client, server.ID); res.Err != nil {
t.Fatal(res.Err)
}
if err = WaitForComputeStatus(client, server, "ACTIVE"); err != nil {
t.Fatal(err)
}
server, err = servers.Get(client, server.ID).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, server.Flavor["id"], choices.FlavorIDResize)
}
func TestServersActionResizeRevert(t *testing.T) {
clients.RequireLong(t)
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
t.Logf("Attempting to resize server %s", server.ID)
ResizeServer(t, client, server)
t.Logf("Attempting to revert resize for server %s", server.ID)
if res := servers.RevertResize(client, server.ID); res.Err != nil {
t.Fatal(res.Err)
}
if err = WaitForComputeStatus(client, server, "ACTIVE"); err != nil {
t.Fatal(err)
}
server, err = servers.Get(client, server.ID).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, server.Flavor["id"], choices.FlavorID)
}
func TestServersActionPause(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
t.Logf("Attempting to pause server %s", server.ID)
err = pauseunpause.Pause(client, server.ID).ExtractErr()
th.AssertNoErr(t, err)
err = WaitForComputeStatus(client, server, "PAUSED")
th.AssertNoErr(t, err)
err = pauseunpause.Unpause(client, server.ID).ExtractErr()
th.AssertNoErr(t, err)
err = WaitForComputeStatus(client, server, "ACTIVE")
th.AssertNoErr(t, err)
}
func TestServersActionSuspend(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
t.Logf("Attempting to suspend server %s", server.ID)
err = suspendresume.Suspend(client, server.ID).ExtractErr()
th.AssertNoErr(t, err)
err = WaitForComputeStatus(client, server, "SUSPENDED")
th.AssertNoErr(t, err)
err = suspendresume.Resume(client, server.ID).ExtractErr()
th.AssertNoErr(t, err)
err = WaitForComputeStatus(client, server, "ACTIVE")
th.AssertNoErr(t, err)
}
func TestServersActionLock(t *testing.T) {
clients.RequireLong(t)
clients.RequireNonAdmin(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
t.Logf("Attempting to Lock server %s", server.ID)
err = lockunlock.Lock(client, server.ID).ExtractErr()
th.AssertNoErr(t, err)
t.Logf("Attempting to delete locked server %s", server.ID)
err = servers.Delete(client, server.ID).ExtractErr()
th.AssertEquals(t, err != nil, true)
t.Logf("Attempting to unlock server %s", server.ID)
err = lockunlock.Unlock(client, server.ID).ExtractErr()
th.AssertNoErr(t, err)
err = WaitForComputeStatus(client, server, "ACTIVE")
th.AssertNoErr(t, err)
}
func TestServersConsoleOutput(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
outputOpts := &servers.ShowConsoleOutputOpts{
Length: 4,
}
output, err := servers.ShowConsoleOutput(client, server.ID, outputOpts).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, output)
}
func TestServersTags(t *testing.T) {
clients.RequireLong(t)
clients.SkipRelease(t, "mitaka")
clients.SkipRelease(t, "newton")
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
client.Microversion = "2.52"
networkClient, err := clients.NewNetworkV2Client()
th.AssertNoErr(t, err)
networkID, err := networks.IDFromName(networkClient, choices.NetworkName)
th.AssertNoErr(t, err)
server, err := CreateServerWithTags(t, client, networkID)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
}
func TestServersWithExtendedAttributesCreateDestroy(t *testing.T) {
clients.RequireLong(t)
clients.RequireAdmin(t)
clients.SkipRelease(t, "stable/mitaka")
clients.SkipRelease(t, "stable/newton")
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
client.Microversion = "2.3"
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
result := servers.Get(client, server.ID)
th.AssertNoErr(t, result.Err)
reservationID, err := extendedserverattributes.ExtractReservationID(result.Result)
th.AssertNoErr(t, err)
th.AssertEquals(t, reservationID != "", true)
t.Logf("reservationID: %s", reservationID)
launchIndex, err := extendedserverattributes.ExtractLaunchIndex(result.Result)
th.AssertNoErr(t, err)
th.AssertEquals(t, launchIndex, 0)
t.Logf("launchIndex: %d", launchIndex)
ramdiskID, err := extendedserverattributes.ExtractRamdiskID(result.Result)
th.AssertNoErr(t, err)
th.AssertEquals(t, ramdiskID == "", true)
t.Logf("ramdiskID: %s", ramdiskID)
kernelID, err := extendedserverattributes.ExtractKernelID(result.Result)
th.AssertNoErr(t, err)
th.AssertEquals(t, kernelID == "", true)
t.Logf("kernelID: %s", kernelID)
hostname, err := extendedserverattributes.ExtractHostname(result.Result)
th.AssertNoErr(t, err)
th.AssertEquals(t, hostname != "", true)
t.Logf("hostname: %s", hostname)
rootDeviceName, err := extendedserverattributes.ExtractRootDeviceName(result.Result)
th.AssertNoErr(t, err)
th.AssertEquals(t, rootDeviceName != "", true)
t.Logf("rootDeviceName: %s", rootDeviceName)
userData, err := extendedserverattributes.ExtractUserData(result.Result)
th.AssertNoErr(t, err)
th.AssertEquals(t, userData == "", true)
t.Logf("userData: %s", userData)
}

View File

@@ -1,36 +0,0 @@
// +build acceptance compute services
package v2
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/services"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestServicesList(t *testing.T) {
clients.RequireAdmin(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
allPages, err := services.List(client).AllPages()
th.AssertNoErr(t, err)
allServices, err := services.ExtractServices(allPages)
th.AssertNoErr(t, err)
var found bool
for _, service := range allServices {
tools.PrintResource(t, service)
if service.Binary == "nova-scheduler" {
found = true
}
}
th.AssertEquals(t, found, true)
}

View File

@@ -1,53 +0,0 @@
// +build acceptance compute servers
package v2
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/tenantnetworks"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestTenantNetworksList(t *testing.T) {
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
allPages, err := tenantnetworks.List(client).AllPages()
th.AssertNoErr(t, err)
allTenantNetworks, err := tenantnetworks.ExtractNetworks(allPages)
th.AssertNoErr(t, err)
var found bool
for _, network := range allTenantNetworks {
tools.PrintResource(t, network)
if network.Name == choices.NetworkName {
found = true
}
}
th.AssertEquals(t, found, true)
}
func TestTenantNetworksGet(t *testing.T) {
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
networkID, err := GetNetworkIDFromTenantNetworks(t, client, choices.NetworkName)
th.AssertNoErr(t, err)
network, err := tenantnetworks.Get(client, networkID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, network)
}

View File

@@ -1,91 +0,0 @@
// +build acceptance compute usage
package v2
import (
"strings"
"testing"
"time"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/usage"
"github.com/gophercloud/gophercloud/pagination"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestUsageSingleTenant(t *testing.T) {
t.Skip("This is not passing in OpenLab. Works locally")
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
DeleteServer(t, client, server)
endpointParts := strings.Split(client.Endpoint, "/")
tenantID := endpointParts[4]
end := time.Now()
start := end.AddDate(0, -1, 0)
opts := usage.SingleTenantOpts{
Start: &start,
End: &end,
}
err = usage.SingleTenant(client, tenantID, opts).EachPage(func(page pagination.Page) (bool, error) {
tenantUsage, err := usage.ExtractSingleTenant(page)
th.AssertNoErr(t, err)
tools.PrintResource(t, tenantUsage)
if tenantUsage.TotalHours == 0 {
t.Fatalf("TotalHours should not be 0")
}
return true, nil
})
th.AssertNoErr(t, err)
}
func TestUsageAllTenants(t *testing.T) {
t.Skip("This is not passing in OpenLab. Works locally")
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
DeleteServer(t, client, server)
end := time.Now()
start := end.AddDate(0, -1, 0)
opts := usage.AllTenantsOpts{
Detailed: true,
Start: &start,
End: &end,
}
err = usage.AllTenants(client, opts).EachPage(func(page pagination.Page) (bool, error) {
allUsage, err := usage.ExtractAllTenants(page)
th.AssertNoErr(t, err)
tools.PrintResource(t, allUsage)
if len(allUsage) == 0 {
t.Fatalf("No usage returned")
}
if allUsage[0].TotalHours == 0 {
t.Fatalf("TotalHours should not be 0")
}
return true, nil
})
th.AssertNoErr(t, err)
}

View File

@@ -1,38 +0,0 @@
// +build acceptance compute volumeattach
package v2
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
bs "github.com/gophercloud/gophercloud/acceptance/openstack/blockstorage/v2"
"github.com/gophercloud/gophercloud/acceptance/tools"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestVolumeAttachAttachment(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
th.AssertNoErr(t, err)
blockClient, err := clients.NewBlockStorageV2Client()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
volume, err := bs.CreateVolume(t, blockClient)
th.AssertNoErr(t, err)
defer bs.DeleteVolume(t, blockClient, volume)
volumeAttachment, err := CreateVolumeAttachment(t, client, blockClient, server, volume)
th.AssertNoErr(t, err)
defer DeleteVolumeAttachment(t, client, blockClient, server, volumeAttachment)
tools.PrintResource(t, volumeAttachment)
th.AssertEquals(t, volumeAttachment.ServerID, server.ID)
}

View File

@@ -1,47 +0,0 @@
package v1
import (
"fmt"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/container/v1/capsules"
)
// WaitForCapsuleStatus will poll a capsule's status until it either matches
// the specified status or the status becomes Failed.
func WaitForCapsuleStatus(client *gophercloud.ServiceClient, uuid, status string) error {
return tools.WaitFor(func() (bool, error) {
v, err := capsules.Get(client, uuid).Extract()
if err != nil {
return false, err
}
var newStatus string
if capsule, ok := v.(*capsules.Capsule); ok {
newStatus = capsule.Status
}
if capsule, ok := v.(*capsules.CapsuleV132); ok {
newStatus = capsule.Status
}
fmt.Println(status)
fmt.Println(newStatus)
if newStatus == status {
// Success!
return true, nil
}
if newStatus == "Failed" {
return false, fmt.Errorf("Capsule in FAILED state")
}
if newStatus == "Error" {
return false, fmt.Errorf("Capsule in ERROR state")
}
return false, nil
})
}

View File

@@ -1,98 +0,0 @@
// +build acceptance containers capsules
package v1
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/openstack/container/v1/capsules"
"github.com/gophercloud/gophercloud/pagination"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestCapsuleBase(t *testing.T) {
client, err := clients.NewContainerV1Client()
th.AssertNoErr(t, err)
template := new(capsules.Template)
template.Bin = []byte(capsuleTemplate)
createOpts := capsules.CreateOpts{
TemplateOpts: template,
}
v, err := capsules.Create(client, createOpts).Extract()
th.AssertNoErr(t, err)
capsule := v.(*capsules.Capsule)
err = WaitForCapsuleStatus(client, capsule.UUID, "Running")
th.AssertNoErr(t, err)
pager := capsules.List(client, nil)
err = pager.EachPage(func(page pagination.Page) (bool, error) {
v, err := capsules.ExtractCapsules(page)
th.AssertNoErr(t, err)
allCapsules := v.([]capsules.Capsule)
for _, m := range allCapsules {
capsuleUUID := m.UUID
if capsuleUUID != capsule.UUID {
continue
}
capsule, err := capsules.Get(client, capsuleUUID).ExtractBase()
th.AssertNoErr(t, err)
th.AssertEquals(t, capsule.MetaName, "template")
err = capsules.Delete(client, capsuleUUID).ExtractErr()
th.AssertNoErr(t, err)
}
return true, nil
})
th.AssertNoErr(t, err)
}
func TestCapsuleV132(t *testing.T) {
client, err := clients.NewContainerV1Client()
th.AssertNoErr(t, err)
client.Microversion = "1.32"
template := new(capsules.Template)
template.Bin = []byte(capsuleTemplate)
createOpts := capsules.CreateOpts{
TemplateOpts: template,
}
capsule, err := capsules.Create(client, createOpts).ExtractV132()
th.AssertNoErr(t, err)
err = WaitForCapsuleStatus(client, capsule.UUID, "Running")
th.AssertNoErr(t, err)
pager := capsules.List(client, nil)
err = pager.EachPage(func(page pagination.Page) (bool, error) {
allCapsules, err := capsules.ExtractCapsulesV132(page)
th.AssertNoErr(t, err)
for _, m := range allCapsules {
capsuleUUID := m.UUID
if capsuleUUID != capsule.UUID {
continue
}
capsule, err := capsules.Get(client, capsuleUUID).ExtractV132()
th.AssertNoErr(t, err)
th.AssertEquals(t, capsule.MetaName, "template")
err = capsules.Delete(client, capsuleUUID).ExtractErr()
th.AssertNoErr(t, err)
}
return true, nil
})
th.AssertNoErr(t, err)
}

View File

@@ -1,46 +0,0 @@
package v1
const capsuleTemplate = `
{
"capsuleVersion": "beta",
"kind": "capsule",
"metadata": {
"labels": {
"app": "web",
"app1": "web1"
},
"name": "template"
},
"spec": {
"restartPolicy": "Always",
"containers": [
{
"command": [
"sleep",
"1000000"
],
"env": {
"ENV1": "/usr/local/bin",
"ENV2": "/usr/bin"
},
"image": "ubuntu",
"ports": [
{
"containerPort": 80,
"hostPort": 80,
"name": "nginx-port",
"protocol": "TCP"
}
],
"resources": {
"requests": {
"cpu": 1,
"memory": 1024
}
},
"workDir": "/root"
}
]
}
}
`

View File

@@ -1,45 +0,0 @@
// +build acceptance containerinfra
package v1
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/openstack/containerinfra/v1/certificates"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestCertificatesCRUD(t *testing.T) {
client, err := clients.NewContainerInfraV1Client()
th.AssertNoErr(t, err)
clusterUUID := "8934d2d1-6bce-4ffa-a017-fb437777269d"
opts := certificates.CreateOpts{
BayUUID: clusterUUID,
CSR: "-----BEGIN CERTIFICATE REQUEST-----\n" +
"MIIByjCCATMCAQAwgYkxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh" +
"MRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUgSW5jMR8w" +
"HQYDVQQLExZJbmZvcm1hdGlvbiBUZWNobm9sb2d5MRcwFQYDVQQDEw53d3cuZ29v" +
"Z2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApZtYJCHJ4VpVXHfV" +
"IlstQTlO4qC03hjX+ZkPyvdYd1Q4+qbAeTwXmCUKYHThVRd5aXSqlPzyIBwieMZr" +
"WFlRQddZ1IzXAlVRDWwAo60KecqeAXnnUK+5fXoTI/UgWshre8tJ+x/TMHaQKR/J" +
"cIWPhqaQhsJuzZbvAdGA80BLxdMCAwEAAaAAMA0GCSqGSIb3DQEBBQUAA4GBAIhl" +
"4PvFq+e7ipARgI5ZM+GZx6mpCz44DTo0JkwfRDf+BtrsaC0q68eTf2XhYOsq4fkH" +
"Q0uA0aVog3f5iJxCa3Hp5gxbJQ6zV6kJ0TEsuaaOhEko9sdpCoPOnRBm2i/XRD2D" +
"6iNh8f8z0ShGsFqjDgFHyF3o+lUyj+UC6H1QW7bn\n" +
"-----END CERTIFICATE REQUEST-----",
}
createResponse, err := certificates.Create(client, opts).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, opts.CSR, createResponse.CSR)
certificate, err := certificates.Get(client, clusterUUID).Extract()
th.AssertNoErr(t, err)
t.Log(certificate.PEM)
err = certificates.Update(client, clusterUUID).ExtractErr()
th.AssertNoErr(t, err)
}

View File

@@ -1,78 +0,0 @@
// +build acceptance containerinfra
package v1
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/containerinfra/v1/clusters"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestClustersCRUD(t *testing.T) {
client, err := clients.NewContainerInfraV1Client()
th.AssertNoErr(t, err)
clusterTemplate, err := CreateClusterTemplate(t, client)
th.AssertNoErr(t, err)
defer DeleteClusterTemplate(t, client, clusterTemplate.UUID)
clusterID, err := CreateCluster(t, client, clusterTemplate.UUID)
tools.PrintResource(t, clusterID)
defer DeleteCluster(t, client, clusterID)
allPages, err := clusters.List(client, nil).AllPages()
th.AssertNoErr(t, err)
allClusters, err := clusters.ExtractClusters(allPages)
th.AssertNoErr(t, err)
var found bool
for _, v := range allClusters {
if v.UUID == clusterID {
found = true
}
}
th.AssertEquals(t, found, true)
updateOpts := []clusters.UpdateOptsBuilder{
clusters.UpdateOpts{
Op: clusters.ReplaceOp,
Path: "/node_count",
Value: "2",
},
}
updateResult := clusters.Update(client, clusterID, updateOpts)
th.AssertNoErr(t, updateResult.Err)
if len(updateResult.Header["X-Openstack-Request-Id"]) > 0 {
t.Logf("Cluster Update Request ID: %s", updateResult.Header["X-Openstack-Request-Id"][0])
}
clusterID, err = updateResult.Extract()
th.AssertNoErr(t, err)
err = WaitForCluster(client, clusterID, "UPDATE_COMPLETE")
th.AssertNoErr(t, err)
newCluster, err := clusters.Get(client, clusterID).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, newCluster.UUID, clusterID)
allPagesDetail, err := clusters.ListDetail(client, nil).AllPages()
th.AssertNoErr(t, err)
allClustersDetail, err := clusters.ExtractClusters(allPagesDetail)
th.AssertNoErr(t, err)
var foundDetail bool
for _, v := range allClustersDetail {
if v.UUID == clusterID {
foundDetail = true
}
}
th.AssertEquals(t, foundDetail, true)
tools.PrintResource(t, newCluster)
}

View File

@@ -1,70 +0,0 @@
// +build acceptance containerinfra
package v1
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/containerinfra/v1/clustertemplates"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestClusterTemplatesCRUD(t *testing.T) {
client, err := clients.NewContainerInfraV1Client()
th.AssertNoErr(t, err)
clusterTemplate, err := CreateClusterTemplate(t, client)
th.AssertNoErr(t, err)
t.Log(clusterTemplate.Name)
defer DeleteClusterTemplate(t, client, clusterTemplate.UUID)
// Test clusters list
allPages, err := clustertemplates.List(client, nil).AllPages()
th.AssertNoErr(t, err)
allClusterTemplates, err := clustertemplates.ExtractClusterTemplates(allPages)
th.AssertNoErr(t, err)
var found bool
for _, v := range allClusterTemplates {
if v.UUID == clusterTemplate.UUID {
found = true
}
}
th.AssertEquals(t, found, true)
template, err := clustertemplates.Get(client, clusterTemplate.UUID).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, clusterTemplate.UUID, template.UUID)
// Test cluster update
updateOpts := []clustertemplates.UpdateOptsBuilder{
clustertemplates.UpdateOpts{
Op: clustertemplates.ReplaceOp,
Path: "/master_lb_enabled",
Value: "false",
},
clustertemplates.UpdateOpts{
Op: clustertemplates.ReplaceOp,
Path: "/registry_enabled",
Value: "false",
},
clustertemplates.UpdateOpts{
Op: clustertemplates.AddOp,
Path: "/labels/test",
Value: "test",
},
}
updateClusterTemplate, err := clustertemplates.Update(client, clusterTemplate.UUID, updateOpts).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, false, updateClusterTemplate.MasterLBEnabled)
th.AssertEquals(t, false, updateClusterTemplate.RegistryEnabled)
th.AssertEquals(t, "test", updateClusterTemplate.Labels["test"])
tools.PrintResource(t, updateClusterTemplate)
}

View File

@@ -1,224 +0,0 @@
package v1
import (
"fmt"
"strings"
"testing"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/acceptance/clients"
idv3 "github.com/gophercloud/gophercloud/acceptance/openstack/identity/v3"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/containerinfra/v1/clusters"
"github.com/gophercloud/gophercloud/openstack/containerinfra/v1/clustertemplates"
"github.com/gophercloud/gophercloud/openstack/containerinfra/v1/quotas"
th "github.com/gophercloud/gophercloud/testhelper"
)
// CreateClusterTemplate will create a random cluster tempalte. An error will be returned if the
// cluster-template could not be created.
func CreateClusterTemplate(t *testing.T, client *gophercloud.ServiceClient) (*clustertemplates.ClusterTemplate, error) {
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
return nil, err
}
name := tools.RandomString("TESTACC-", 8)
t.Logf("Attempting to create cluster template: %s", name)
boolFalse := false
createOpts := clustertemplates.CreateOpts{
COE: "swarm",
DNSNameServer: "8.8.8.8",
DockerStorageDriver: "devicemapper",
ExternalNetworkID: choices.ExternalNetworkID,
FlavorID: choices.FlavorID,
FloatingIPEnabled: &boolFalse,
ImageID: choices.MagnumImageID,
MasterFlavorID: choices.FlavorID,
MasterLBEnabled: &boolFalse,
Name: name,
Public: &boolFalse,
RegistryEnabled: &boolFalse,
ServerType: "vm",
}
res := clustertemplates.Create(client, createOpts)
if res.Err != nil {
return nil, res.Err
}
requestID := res.Header.Get("X-OpenStack-Request-Id")
th.AssertEquals(t, true, requestID != "")
t.Logf("Cluster Template %s request ID: %s", name, requestID)
clusterTemplate, err := res.Extract()
if err != nil {
return nil, err
}
t.Logf("Successfully created cluster template: %s", clusterTemplate.Name)
tools.PrintResource(t, clusterTemplate)
tools.PrintResource(t, clusterTemplate.CreatedAt)
th.AssertEquals(t, name, clusterTemplate.Name)
th.AssertEquals(t, choices.ExternalNetworkID, clusterTemplate.ExternalNetworkID)
th.AssertEquals(t, choices.MagnumImageID, clusterTemplate.ImageID)
return clusterTemplate, nil
}
// DeleteClusterTemplate will delete a given cluster-template. A fatal error will occur if the
// cluster-template could not be deleted. This works best as a deferred function.
func DeleteClusterTemplate(t *testing.T, client *gophercloud.ServiceClient, id string) {
t.Logf("Attempting to delete cluster-template: %s", id)
err := clustertemplates.Delete(client, id).ExtractErr()
if err != nil {
t.Fatalf("Error deleting cluster-template %s: %s:", id, err)
}
t.Logf("Successfully deleted cluster-template: %s", id)
return
}
// CreateCluster will create a random cluster. An error will be returned if the
// cluster could not be created.
func CreateCluster(t *testing.T, client *gophercloud.ServiceClient, clusterTemplateID string) (string, error) {
clusterName := tools.RandomString("TESTACC-", 8)
t.Logf("Attempting to create cluster: %s using template %s", clusterName, clusterTemplateID)
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
return "", err
}
masterCount := 1
nodeCount := 1
createTimeout := 100
createOpts := clusters.CreateOpts{
ClusterTemplateID: clusterTemplateID,
CreateTimeout: &createTimeout,
FlavorID: choices.FlavorID,
Keypair: choices.MagnumKeypair,
Labels: map[string]string{},
MasterCount: &masterCount,
MasterFlavorID: choices.FlavorID,
Name: clusterName,
NodeCount: &nodeCount,
}
createResult := clusters.Create(client, createOpts)
th.AssertNoErr(t, createResult.Err)
if len(createResult.Header["X-Openstack-Request-Id"]) > 0 {
t.Logf("Cluster Create Request ID: %s", createResult.Header["X-Openstack-Request-Id"][0])
}
clusterID, err := createResult.Extract()
if err != nil {
return "", err
}
t.Logf("Cluster created: %+v", clusterID)
err = WaitForCluster(client, clusterID, "CREATE_COMPLETE")
if err != nil {
return clusterID, err
}
t.Logf("Successfully created cluster: %s id: %s", clusterName, clusterID)
return clusterID, nil
}
func DeleteCluster(t *testing.T, client *gophercloud.ServiceClient, id string) {
t.Logf("Attempting to delete cluster: %s", id)
r := clusters.Delete(client, id)
err := clusters.Delete(client, id).ExtractErr()
deleteRequestID := ""
idKey := "X-Openstack-Request-Id"
if len(r.Header[idKey]) > 0 {
deleteRequestID = r.Header[idKey][0]
}
if err != nil {
t.Fatalf("Error deleting cluster. requestID=%s clusterID=%s: err%s:", deleteRequestID, id, err)
}
err = WaitForCluster(client, id, "DELETE_COMPLETE")
if err != nil {
t.Fatalf("Error deleting cluster %s: %s:", id, err)
}
t.Logf("Successfully deleted cluster: %s", id)
return
}
func WaitForCluster(client *gophercloud.ServiceClient, clusterID string, status string) error {
return tools.WaitFor(func() (bool, error) {
cluster, err := clusters.Get(client, clusterID).Extract()
if err != nil {
if _, ok := err.(gophercloud.ErrDefault404); ok && status == "DELETE_COMPLETE" {
return true, nil
}
return false, err
}
if cluster.Status == status {
return true, nil
}
if strings.Contains(cluster.Status, "FAILED") {
return false, fmt.Errorf("Cluster %s FAILED. Status=%s StatusReason=%s", clusterID, cluster.Status, cluster.StatusReason)
}
return false, nil
})
}
// CreateQuota will create a random quota. An error will be returned if the
// quota could not be created.
func CreateQuota(t *testing.T, client *gophercloud.ServiceClient) (*quotas.Quotas, error) {
name := tools.RandomString("TESTACC-", 8)
t.Logf("Attempting to create quota: %s", name)
idClient, err := clients.NewIdentityV3Client()
th.AssertNoErr(t, err)
project, err := idv3.CreateProject(t, idClient, nil)
th.AssertNoErr(t, err)
defer idv3.DeleteProject(t, idClient, project.ID)
createOpts := quotas.CreateOpts{
Resource: "Cluster",
ProjectID: project.ID,
HardLimit: 10,
}
res := quotas.Create(client, createOpts)
if res.Err != nil {
return nil, res.Err
}
requestID := res.Header.Get("X-OpenStack-Request-Id")
th.AssertEquals(t, true, requestID != "")
t.Logf("Quota %s request ID: %s", name, requestID)
quota, err := res.Extract()
if err == nil {
t.Logf("Successfully created quota: %s", quota.ProjectID)
tools.PrintResource(t, quota)
th.AssertEquals(t, project.ID, quota.ProjectID)
th.AssertEquals(t, "Cluster", quota.Resource)
th.AssertEquals(t, 10, quota.HardLimit)
}
return quota, err
}

View File

@@ -1 +0,0 @@
package v1

View File

@@ -1,20 +0,0 @@
// +build acceptance containerinfra
package v1
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestQuotasCRUD(t *testing.T) {
client, err := clients.NewContainerInfraV1Client()
th.AssertNoErr(t, err)
quota, err := CreateQuota(t, client)
th.AssertNoErr(t, err)
tools.PrintResource(t, quota)
}

Some files were not shown because too many files have changed in this diff Show More