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

bump(*): kubernetes release-1.16.0 dependencies

This commit is contained in:
Mike Dame
2019-10-12 11:11:43 -04:00
parent 5af668e89a
commit 1652ba7976
28121 changed files with 3491095 additions and 2280257 deletions

View File

@@ -1,14 +1,67 @@
# 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)
- [3 ways to get involved](#5-ways-to-get-involved)
## Setting up your git workspace
## 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 installation instructions:
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
@@ -46,9 +99,19 @@ need to checkout a new feature branch:
git checkout -b my-new-feature
```
Another thing to bear in mind is that you will need to add a few extra
environment variables for acceptance tests - this is documented in our
[acceptance tests readme](/acceptance).
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
@@ -101,7 +164,7 @@ import (
th "github.com/gophercloud/gophercloud/testhelper"
fake "github.com/gophercloud/gophercloud/testhelper/client"
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
)
func TestGet(t *testing.T) {
@@ -159,77 +222,35 @@ 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 ./...
```
```bash
go test -tags fixtures ./...
```
To run all tests with verbose output:
```bash
go test -v -tags fixtures ./...
```
```bash
go test -v -tags fixtures ./...
```
To run tests that match certain [build tags]():
```bash
go test -tags "fixtures foo bar" ./...
```
```bash
go test -tags "fixtures foo bar" ./...
```
To run tests for a particular sub-package:
```bash
cd ./path/to/package && go test -tags fixtures .
```
```bash
cd ./path/to/package && go test -tags fixtures ./...
```
## Style guide
See [here](/STYLEGUIDE.md)
## 3 ways to get involved
There are five main ways you can get involved in our open-source project, and
each is described briefly below. Once you've made up your mind and decided on
your fix, you will need to follow the same basic steps that all submissions are
required to adhere to:
1. [fork](https://help.github.com/articles/fork-a-repo/) the `gophercloud/gophercloud` repository
2. checkout a [new branch](https://github.com/Kunena/Kunena-Forum/wiki/Create-a-new-branch-with-git-and-manage-branches)
3. submit your branch as a [pull request](https://help.github.com/articles/creating-a-pull-request/)
### 1. Fixing bugs
If you want to start fixing open bugs, we'd really appreciate that! Bug fixing
is central to any project. The best way to get started is by heading to our
[bug tracker](https://github.com/gophercloud/gophercloud/issues) and finding open
bugs that you think nobody is working on. It might be useful to comment on the
thread to see the current state of the issue and if anybody has made any
breakthroughs on it so far.
### 2. Improving documentation
The best source of documentation is on [godoc.org](http://godoc.org). It is
automatically generated from the source code.
If you feel that a certain section could be improved - whether it's to clarify
ambiguity, correct a technical mistake, or to fix a grammatical error - please
feel entitled to do so! We welcome doc pull requests with the same childlike
enthusiasm as any other contribution!
### 3. Working on a new feature
If you've found something we've left out, definitely feel free to start work on
introducing that feature. It's always useful to open an issue or submit a pull
request early on to indicate your intent to a core contributor - this enables
quick/early feedback and can help steer you in the right direction by avoiding
known issues. It might also help you avoid losing time implementing something
that might not ever work. One tip is to prefix your Pull Request issue title
with [wip] - then people know it's a work in progress.
You must ensure that all of your work is well tested - both in terms of unit
and acceptance tests. Untested code will not be merged because it introduces
too much of a risk to end-users.
Happy hacking!
See [here](/docs/STYLEGUIDE.md)

View File

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

View File

@@ -1,3 +1,6 @@
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.

View File

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

View File

@@ -1,21 +1,25 @@
language: go
sudo: false
install:
- go get golang.org/x/crypto/ssh
- go get -v -tags 'fixtures acceptance' ./...
- go get github.com/wadey/gocovmerge
- go get github.com/mattn/goveralls
- go get golang.org/x/tools/cmd/goimports
- 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.8
- tip
- "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,12 +1,114 @@
- 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

@@ -0,0 +1,26 @@
- 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

@@ -0,0 +1,27 @@
- 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

@@ -0,0 +1,16 @@
- 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

@@ -127,7 +127,7 @@ new resource in the `server` variable (a
## Advanced Usage
Have a look at the [FAQ](./FAQ.md) for some tips on customizing the way Gophercloud works.
Have a look at the [FAQ](./docs/FAQ.md) for some tips on customizing the way Gophercloud works.
## Backwards-Compatibility Guarantees
@@ -140,4 +140,20 @@ 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](/issues).
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

@@ -75,7 +75,8 @@ to set them manually.
#### Shared file systems
|Name|Description|
|---|---|
|`OS_SHARE_NETWORK_ID`| The share network ID to use when creating shares|
|`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

View File

@@ -5,12 +5,14 @@ package clients
import (
"fmt"
"net/http"
"os"
"strings"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack"
"github.com/gophercloud/gophercloud/openstack/blockstorage/noauth"
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.
@@ -28,15 +30,24 @@ type AcceptanceTestChoices struct {
// 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
// ShareNetworkID is the Manila Share network ID
ShareNetworkID string
// DBDatastoreType is the datastore type for DB tests.
DBDatastoreType string
@@ -50,10 +61,13 @@ 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")
shareNetworkID := os.Getenv("OS_SHARE_NETWORK_ID")
dbDatastoreType := os.Getenv("OS_DB_DATASTORE_TYPE")
dbDatastoreVersion := os.Getenv("OS_DB_DATASTORE_VERSION")
@@ -73,12 +87,19 @@ func AcceptanceTestChoicesFromEnv() (*AcceptanceTestChoices, error) {
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"
}
if shareNetworkID == "" {
missing = append(missing, "OS_SHARE_NETWORK_ID")
}
notDistinct := ""
if flavorID == flavorIDResize {
notDistinct = "OS_FLAVOR_ID and OS_FLAVOR_ID_RESIZE must be distinct."
@@ -101,9 +122,12 @@ func AcceptanceTestChoicesFromEnv() (*AcceptanceTestChoices, error) {
FlavorID: flavorID,
FlavorIDResize: flavorIDResize,
FloatingIPPoolName: floatingIPPoolName,
MagnumImageID: magnumImageID,
MagnumKeypair: magnumKeypair,
NetworkName: networkName,
NetworkID: networkID,
SubnetID: subnetID,
ExternalNetworkID: externalNetworkID,
ShareNetworkID: shareNetworkID,
DBDatastoreType: dbDatastoreType,
DBDatastoreVersion: dbDatastoreVersion,
}, nil
@@ -123,6 +147,8 @@ func NewBlockStorageV1Client() (*gophercloud.ServiceClient, error) {
return nil, err
}
client = configureDebug(client)
return openstack.NewBlockStorageV1(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
@@ -142,6 +168,8 @@ func NewBlockStorageV2Client() (*gophercloud.ServiceClient, error) {
return nil, err
}
client = configureDebug(client)
return openstack.NewBlockStorageV2(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
@@ -161,6 +189,8 @@ func NewBlockStorageV3Client() (*gophercloud.ServiceClient, error) {
return nil, err
}
client = configureDebug(client)
return openstack.NewBlockStorageV3(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
@@ -170,7 +200,7 @@ func NewBlockStorageV3Client() (*gophercloud.ServiceClient, error) {
// 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 := noauth.NewClient(gophercloud.AuthOptions{
client, err := blockstorageNoAuth.NewClient(gophercloud.AuthOptions{
Username: os.Getenv("OS_USERNAME"),
TenantName: os.Getenv("OS_TENANT_NAME"),
})
@@ -178,7 +208,9 @@ func NewBlockStorageV2NoAuthClient() (*gophercloud.ServiceClient, error) {
return nil, err
}
return noauth.NewBlockStorageNoAuth(client, noauth.EndpointOpts{
client = configureDebug(client)
return blockstorageNoAuth.NewBlockStorageNoAuth(client, blockstorageNoAuth.EndpointOpts{
CinderEndpoint: os.Getenv("CINDER_ENDPOINT"),
})
}
@@ -187,7 +219,7 @@ func NewBlockStorageV2NoAuthClient() (*gophercloud.ServiceClient, error) {
// 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 := noauth.NewClient(gophercloud.AuthOptions{
client, err := blockstorageNoAuth.NewClient(gophercloud.AuthOptions{
Username: os.Getenv("OS_USERNAME"),
TenantName: os.Getenv("OS_TENANT_NAME"),
})
@@ -195,7 +227,9 @@ func NewBlockStorageV3NoAuthClient() (*gophercloud.ServiceClient, error) {
return nil, err
}
return noauth.NewBlockStorageNoAuth(client, noauth.EndpointOpts{
client = configureDebug(client)
return blockstorageNoAuth.NewBlockStorageNoAuth(client, blockstorageNoAuth.EndpointOpts{
CinderEndpoint: os.Getenv("CINDER_ENDPOINT"),
})
}
@@ -214,11 +248,64 @@ func NewComputeV2Client() (*gophercloud.ServiceClient, error) {
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.
@@ -233,6 +320,8 @@ func NewDBV1Client() (*gophercloud.ServiceClient, error) {
return nil, err
}
client = configureDebug(client)
return openstack.NewDBV1(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
@@ -252,6 +341,8 @@ func NewDNSV2Client() (*gophercloud.ServiceClient, error) {
return nil, err
}
client = configureDebug(client)
return openstack.NewDNSV2(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
@@ -271,6 +362,8 @@ func NewIdentityV2Client() (*gophercloud.ServiceClient, error) {
return nil, err
}
client = configureDebug(client)
return openstack.NewIdentityV2(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
@@ -290,6 +383,8 @@ func NewIdentityV2AdminClient() (*gophercloud.ServiceClient, error) {
return nil, err
}
client = configureDebug(client)
return openstack.NewIdentityV2(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
Availability: gophercloud.AvailabilityAdmin,
@@ -310,6 +405,8 @@ func NewIdentityV2UnauthenticatedClient() (*gophercloud.ServiceClient, error) {
return nil, err
}
client = configureDebug(client)
return openstack.NewIdentityV2(client, gophercloud.EndpointOpts{})
}
@@ -327,6 +424,8 @@ func NewIdentityV3Client() (*gophercloud.ServiceClient, error) {
return nil, err
}
client = configureDebug(client)
return openstack.NewIdentityV3(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
@@ -346,6 +445,8 @@ func NewIdentityV3UnauthenticatedClient() (*gophercloud.ServiceClient, error) {
return nil, err
}
client = configureDebug(client)
return openstack.NewIdentityV3(client, gophercloud.EndpointOpts{})
}
@@ -363,6 +464,8 @@ func NewImageServiceV2Client() (*gophercloud.ServiceClient, error) {
return nil, err
}
client = configureDebug(client)
return openstack.NewImageServiceV2(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
@@ -382,6 +485,8 @@ func NewNetworkV2Client() (*gophercloud.ServiceClient, error) {
return nil, err
}
client = configureDebug(client)
return openstack.NewNetworkV2(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
@@ -401,6 +506,8 @@ func NewObjectStorageV1Client() (*gophercloud.ServiceClient, error) {
return nil, err
}
client = configureDebug(client)
return openstack.NewObjectStorageV1(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
@@ -420,7 +527,191 @@ func NewSharedFileSystemV2Client() (*gophercloud.ServiceClient, error) {
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

@@ -0,0 +1,75 @@
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

@@ -0,0 +1,185 @@
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

@@ -0,0 +1,45 @@
// +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

@@ -0,0 +1,8 @@
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

@@ -0,0 +1,95 @@
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

@@ -0,0 +1,73 @@
// +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

@@ -0,0 +1,44 @@
// +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

@@ -0,0 +1,115 @@
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

@@ -0,0 +1,96 @@
// +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

@@ -0,0 +1,72 @@
// +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

@@ -0,0 +1,41 @@
// +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

@@ -8,10 +8,12 @@ import (
"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
@@ -171,3 +173,64 @@ func ExtendVolumeSize(t *testing.T, client *gophercloud.ServiceClient, volume *v
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

@@ -0,0 +1,59 @@
// +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

@@ -8,27 +8,24 @@ import (
"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()
if err != nil {
t.Fatalf("Unable to create a blockstorage client: %v", err)
}
th.AssertNoErr(t, err)
listOpts := schedulerstats.ListOpts{
Detail: true,
}
allPages, err := schedulerstats.List(blockClient, listOpts).AllPages()
if err != nil {
t.Fatalf("Unable to query schedulerstats: %v", err)
}
th.AssertNoErr(t, err)
allStats, err := schedulerstats.ExtractStoragePools(allPages)
if err != nil {
t.Fatalf("Unable to extract pools: %v", err)
}
th.AssertNoErr(t, err)
for _, stat := range allStats {
tools.PrintResource(t, stat)

View File

@@ -0,0 +1,29 @@
// +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

@@ -6,120 +6,87 @@ import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes"
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()
if err != nil {
t.Fatalf("Unable to create a blockstorage client: %v", err)
}
th.AssertNoErr(t, err)
computeClient, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
volume, err := blockstorage.CreateVolume(t, blockClient)
if err != nil {
t.Fatalf("Unable to create volume: %v", err)
}
th.AssertNoErr(t, err)
defer blockstorage.DeleteVolume(t, blockClient, volume)
volumeImage, err := CreateUploadImage(t, blockClient, volume)
if err != nil {
t.Fatalf("Unable to upload volume-backed image: %v", err)
}
th.AssertNoErr(t, err)
tools.PrintResource(t, volumeImage)
err = DeleteUploadedImage(t, computeClient, volumeImage.ImageName)
if err != nil {
t.Fatalf("Unable to delete volume-backed image: %v", err)
}
th.AssertNoErr(t, err)
}
func TestVolumeActionsAttachCreateDestroy(t *testing.T) {
blockClient, err := clients.NewBlockStorageV2Client()
if err != nil {
t.Fatalf("Unable to create a blockstorage client: %v", err)
}
th.AssertNoErr(t, err)
computeClient, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
server, err := compute.CreateServer(t, computeClient)
if err != nil {
t.Fatalf("Unable to create server: %v", err)
}
th.AssertNoErr(t, err)
defer compute.DeleteServer(t, computeClient, server)
volume, err := blockstorage.CreateVolume(t, blockClient)
if err != nil {
t.Fatalf("Unable to create volume: %v", err)
}
th.AssertNoErr(t, err)
defer blockstorage.DeleteVolume(t, blockClient, volume)
err = CreateVolumeAttach(t, blockClient, volume, server)
if err != nil {
t.Fatalf("Unable to attach volume: %v", err)
}
th.AssertNoErr(t, err)
newVolume, err := volumes.Get(blockClient, volume.ID).Extract()
if err != nil {
t.Fatal("Unable to get updated volume information: %v", err)
}
th.AssertNoErr(t, err)
DeleteVolumeAttach(t, blockClient, newVolume)
}
func TestVolumeActionsReserveUnreserve(t *testing.T) {
client, err := clients.NewBlockStorageV2Client()
if err != nil {
t.Fatalf("Unable to create blockstorage client: %v", err)
}
th.AssertNoErr(t, err)
volume, err := blockstorage.CreateVolume(t, client)
if err != nil {
t.Fatalf("Unable to create volume: %v", err)
}
th.AssertNoErr(t, err)
defer blockstorage.DeleteVolume(t, client, volume)
err = CreateVolumeReserve(t, client, volume)
if err != nil {
t.Fatalf("Unable to create volume reserve: %v", err)
}
th.AssertNoErr(t, err)
defer DeleteVolumeReserve(t, client, volume)
}
func TestVolumeActionsExtendSize(t *testing.T) {
blockClient, err := clients.NewBlockStorageV2Client()
if err != nil {
t.Fatalf("Unable to create a blockstorage client: %v", err)
}
th.AssertNoErr(t, err)
volume, err := blockstorage.CreateVolume(t, blockClient)
if err != nil {
t.Fatalf("Unable to create volume: %v", err)
}
th.AssertNoErr(t, err)
defer blockstorage.DeleteVolume(t, blockClient, volume)
tools.PrintResource(t, volume)
err = ExtendVolumeSize(t, blockClient, volume)
if err != nil {
t.Fatalf("Unable to resize volume: %v", err)
}
th.AssertNoErr(t, err)
newVolume, err := volumes.Get(blockClient, volume.ID).Extract()
if err != nil {
t.Fatal("Unable to get updated volume information: %v", err)
}
th.AssertNoErr(t, err)
tools.PrintResource(t, newVolume)
}
@@ -143,7 +110,7 @@ func TestVolumeConns(t *testing.T) {
th.AssertNoErr(t, err)
t.Logf("Deleting volume")
err = volumes.Delete(client, cv.ID).ExtractErr()
err = volumes.Delete(client, cv.ID, volumes.DeleteOpts{}).ExtractErr()
th.AssertNoErr(t, err)
}()

View File

@@ -0,0 +1,46 @@
// +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

@@ -78,7 +78,7 @@ func CreateVolumeFromImage(t *testing.T, client *gophercloud.ServiceClient) (*vo
// 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()
err := volumes.Delete(client, volume.ID, volumes.DeleteOpts{}).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete volume %s: %v", volume.ID, err)
}

View File

@@ -50,11 +50,13 @@ func CreateVolume(t *testing.T, client *gophercloud.ServiceClient) (*volumes.Vol
}
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,
Size: 1,
Name: volumeName,
Description: volumeDescription,
}
volume, err := volumes.Create(client, createOpts).Extract()

View File

@@ -8,6 +8,7 @@ import (
"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) {
@@ -49,4 +50,20 @@ func TestVolumesCreateDestroy(t *testing.T) {
}
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

@@ -11,21 +11,48 @@ import (
"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) {
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,
Size: 1,
Name: volumeName,
Description: volumeDescription,
}
volume, err := volumes.Create(client, createOpts).Extract()
@@ -38,16 +65,19 @@ func CreateVolume(t *testing.T, client *gophercloud.ServiceClient) (*volumes.Vol
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) {
if testing.Short() {
t.Skip("Skipping test that requires volume creation in short mode.")
}
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
t.Fatal(err)
@@ -72,53 +102,37 @@ func CreateVolumeFromImage(t *testing.T, client *gophercloud.ServiceClient) (*vo
return volume, err
}
return volume, nil
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) {
err := volumes.Delete(client, volume.ID).ExtractErr()
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("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
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)
@@ -138,5 +152,5 @@ func DeleteSnapshot(t *testing.T, client *gophercloud.ServiceClient, snapshot *s
t.Fatalf("Error waiting for snapshot to delete: %v", err)
}
t.Logf("Deleted snapshot: %s", snapshot.ID)
t.Logf("Successfully deleted snapshot: %s", snapshot.ID)
}

View File

@@ -8,51 +8,39 @@ import (
"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 TestSnapshotsList(t *testing.T) {
func TestSnapshots(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewBlockStorageV2Client()
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.NewBlockStorageV2Client()
if err != nil {
t.Fatalf("Unable to create a blockstorage client: %v", err)
}
th.AssertNoErr(t, err)
volume, err := CreateVolume(t, client)
if err != nil {
t.Fatalf("Unable to create volume: %v", err)
}
th.AssertNoErr(t, err)
defer DeleteVolume(t, client, volume)
snapshot, err := CreateSnapshot(t, client, volume)
if err != nil {
t.Fatalf("Unable to create snapshot: %v", err)
}
th.AssertNoErr(t, 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)
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
}
}
tools.PrintResource(t, newSnapshot)
th.AssertEquals(t, found, true)
}

View File

@@ -5,48 +5,124 @@ 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 TestVolumesList(t *testing.T) {
client, err := clients.NewBlockStorageV2Client()
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) {
clients.RequireLong(t)
client, err := clients.NewBlockStorageV2Client()
if err != nil {
t.Fatalf("Unable to create blockstorage client: %v", err)
}
th.AssertNoErr(t, err)
volume, err := CreateVolume(t, client)
if err != nil {
t.Fatalf("Unable to create volume: %v", err)
}
th.AssertNoErr(t, 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)
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
}
}
tools.PrintResource(t, newVolume)
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

@@ -0,0 +1,163 @@
// 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

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

View File

@@ -0,0 +1,145 @@
// +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

@@ -0,0 +1,58 @@
// +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

@@ -0,0 +1,145 @@
// +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

@@ -0,0 +1,56 @@
// +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

@@ -0,0 +1,31 @@
// +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

@@ -0,0 +1,472 @@
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

@@ -0,0 +1,510 @@
// +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

@@ -0,0 +1,31 @@
// +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

@@ -0,0 +1,215 @@
// +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

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

View File

@@ -0,0 +1,69 @@
// +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

@@ -0,0 +1,64 @@
// +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

@@ -0,0 +1,76 @@
// +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

@@ -0,0 +1,47 @@
// +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

@@ -0,0 +1,82 @@
// +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

@@ -0,0 +1,64 @@
// +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

@@ -0,0 +1,146 @@
// +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

@@ -0,0 +1,51 @@
// +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

@@ -0,0 +1,58 @@
// +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

@@ -9,22 +9,18 @@ import (
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) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
blockDevices := []bootfromvolume.BlockDevice{
bootfromvolume.BlockDevice{
@@ -37,28 +33,22 @@ func TestBootFromImage(t *testing.T) {
}
server, err := CreateBootableVolumeServer(t, client, blockDevices)
if err != nil {
t.Fatalf("Unable to create server: %v", err)
}
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) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
blockDevices := []bootfromvolume.BlockDevice{
bootfromvolume.BlockDevice{
@@ -71,33 +61,40 @@ func TestBootFromNewVolume(t *testing.T) {
}
server, err := CreateBootableVolumeServer(t, client, blockDevices)
if err != nil {
t.Fatalf("Unable to create server: %v", err)
}
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) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
clients.RequireLong(t)
computeClient, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
blockStorageClient, err := clients.NewBlockStorageV2Client()
if err != nil {
t.Fatalf("Unable to create a block storage client: %v", err)
}
th.AssertNoErr(t, err)
volume, err := blockstorage.CreateVolumeFromImage(t, blockStorageClient)
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
tools.PrintResource(t, volume)
blockDevices := []bootfromvolume.BlockDevice{
bootfromvolume.BlockDevice{
@@ -109,28 +106,35 @@ func TestBootFromExistingVolume(t *testing.T) {
}
server, err := CreateBootableVolumeServer(t, computeClient, blockDevices)
if err != nil {
t.Fatalf("Unable to create server: %v", err)
}
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) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
blockDevices := []bootfromvolume.BlockDevice{
bootfromvolume.BlockDevice{
@@ -160,28 +164,20 @@ func TestBootFromMultiEphemeralServer(t *testing.T) {
}
server, err := CreateMultiEphemeralServer(t, client, blockDevices)
if err != nil {
t.Fatalf("Unable to create server: %v", err)
}
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
tools.PrintResource(t, server)
}
func TestAttachNewVolume(t *testing.T) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
blockDevices := []bootfromvolume.BlockDevice{
bootfromvolume.BlockDevice{
@@ -201,38 +197,38 @@ func TestAttachNewVolume(t *testing.T) {
}
server, err := CreateBootableVolumeServer(t, client, blockDevices)
if err != nil {
t.Fatalf("Unable to create server: %v", err)
}
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) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
clients.RequireLong(t)
computeClient, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
blockStorageClient, err := clients.NewBlockStorageV2Client()
if err != nil {
t.Fatalf("Unable to create a block storage client: %v", err)
}
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
volume, err := blockstorage.CreateVolume(t, blockStorageClient)
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
blockDevices := []bootfromvolume.BlockDevice{
bootfromvolume.BlockDevice{
@@ -252,10 +248,57 @@ func TestAttachExistingVolume(t *testing.T) {
}
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, computeClient, server)
defer DeleteServer(t, client, server)
tools.PrintResource(t, server)
}

View File

@@ -11,13 +11,17 @@ import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/aggregates"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/bootfromvolume"
dsr "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/defsecrules"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/floatingips"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/networks"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/quotasets"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/remoteconsoles"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/rescueunrescue"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/secgroups"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
@@ -25,6 +29,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach"
"github.com/gophercloud/gophercloud/openstack/compute/v2/flavors"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
th "github.com/gophercloud/gophercloud/testhelper"
"golang.org/x/crypto/ssh"
)
@@ -63,14 +68,69 @@ func AssociateFloatingIPWithFixedIP(t *testing.T, client *gophercloud.ServiceCli
return nil
}
// AttachInterface will create and attach an interface on a given server.
// An error will returned if the interface could not be created.
func AttachInterface(t *testing.T, client *gophercloud.ServiceClient, serverID string) (*attachinterfaces.Interface, error) {
t.Logf("Attempting to attach interface to server %s", serverID)
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
t.Fatal(err)
}
networkID, err := GetNetworkIDFromTenantNetworks(t, client, choices.NetworkName)
if err != nil {
return nil, err
}
createOpts := attachinterfaces.CreateOpts{
NetworkID: networkID,
}
iface, err := attachinterfaces.Create(client, serverID, createOpts).Extract()
if err != nil {
return nil, err
}
t.Logf("Successfully created interface %s on server %s", iface.PortID, serverID)
return iface, nil
}
// CreateAggregate will create an aggregate with random name and available zone.
// An error will be returned if the aggregate could not be created.
func CreateAggregate(t *testing.T, client *gophercloud.ServiceClient) (*aggregates.Aggregate, error) {
aggregateName := tools.RandomString("aggregate_", 5)
availabilityZone := tools.RandomString("zone_", 5)
t.Logf("Attempting to create aggregate %s", aggregateName)
createOpts := aggregates.CreateOpts{
Name: aggregateName,
AvailabilityZone: availabilityZone,
}
aggregate, err := aggregates.Create(client, createOpts).Extract()
if err != nil {
return nil, err
}
t.Logf("Successfully created aggregate %d", aggregate.ID)
aggregate, err = aggregates.Get(client, aggregate.ID).Extract()
if err != nil {
return nil, err
}
th.AssertEquals(t, aggregate.Name, aggregateName)
th.AssertEquals(t, aggregate.AvailabilityZone, availabilityZone)
return aggregate, nil
}
// CreateBootableVolumeServer works like CreateServer but is configured with
// one or more block devices defined by passing in []bootfromvolume.BlockDevice.
// An error will be returned if a server was unable to be created.
func CreateBootableVolumeServer(t *testing.T, client *gophercloud.ServiceClient, blockDevices []bootfromvolume.BlockDevice) (*servers.Server, error) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
var server *servers.Server
choices, err := clients.AcceptanceTestChoicesFromEnv()
@@ -112,6 +172,12 @@ func CreateBootableVolumeServer(t *testing.T, client *gophercloud.ServiceClient,
}
newServer, err := servers.Get(client, server.ID).Extract()
if err != nil {
return nil, err
}
th.AssertEquals(t, newServer.Name, name)
th.AssertEquals(t, newServer.Flavor["id"], choices.FlavorID)
return newServer, nil
}
@@ -159,6 +225,12 @@ func CreateFlavor(t *testing.T, client *gophercloud.ServiceClient) (*flavors.Fla
t.Logf("Successfully created flavor %s", flavor.ID)
th.AssertEquals(t, flavor.Name, flavorName)
th.AssertEquals(t, flavor.RAM, 1)
th.AssertEquals(t, flavor.Disk, 1)
th.AssertEquals(t, flavor.VCPUs, 1)
th.AssertEquals(t, flavor.IsPublic, true)
return flavor, nil
}
@@ -215,6 +287,9 @@ func CreateKeyPair(t *testing.T, client *gophercloud.ServiceClient) (*keypairs.K
}
t.Logf("Created keypair: %s", keyPairName)
th.AssertEquals(t, keyPair.Name, keyPairName)
return keyPair, nil
}
@@ -224,10 +299,6 @@ func CreateKeyPair(t *testing.T, client *gophercloud.ServiceClient) (*keypairs.K
// are actually local ephemeral disks.
// An error will be returned if a server was unable to be created.
func CreateMultiEphemeralServer(t *testing.T, client *gophercloud.ServiceClient, blockDevices []bootfromvolume.BlockDevice) (*servers.Server, error) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
var server *servers.Server
choices, err := clients.AcceptanceTestChoicesFromEnv()
@@ -267,6 +338,10 @@ func CreateMultiEphemeralServer(t *testing.T, client *gophercloud.ServiceClient,
newServer, err := servers.Get(client, server.ID).Extract()
th.AssertEquals(t, newServer.Name, name)
th.AssertEquals(t, newServer.Flavor["id"], choices.FlavorID)
th.AssertEquals(t, newServer.Image["id"], choices.ImageID)
return newServer, nil
}
@@ -292,45 +367,63 @@ func CreatePrivateFlavor(t *testing.T, client *gophercloud.ServiceClient) (*flav
t.Logf("Successfully created flavor %s", flavor.ID)
th.AssertEquals(t, flavor.Name, flavorName)
th.AssertEquals(t, flavor.RAM, 1)
th.AssertEquals(t, flavor.Disk, 1)
th.AssertEquals(t, flavor.VCPUs, 1)
th.AssertEquals(t, flavor.IsPublic, false)
return flavor, nil
}
// CreateSecurityGroup will create a security group with a random name.
// An error will be returned if one was failed to be created.
func CreateSecurityGroup(t *testing.T, client *gophercloud.ServiceClient) (secgroups.SecurityGroup, error) {
func CreateSecurityGroup(t *testing.T, client *gophercloud.ServiceClient) (*secgroups.SecurityGroup, error) {
name := tools.RandomString("secgroup_", 5)
createOpts := secgroups.CreateOpts{
Name: tools.RandomString("secgroup_", 5),
Name: name,
Description: "something",
}
securityGroup, err := secgroups.Create(client, createOpts).Extract()
if err != nil {
return *securityGroup, err
return nil, err
}
t.Logf("Created security group: %s", securityGroup.ID)
return *securityGroup, nil
th.AssertEquals(t, securityGroup.Name, name)
return securityGroup, nil
}
// CreateSecurityGroupRule will create a security group rule with a random name
// and a random TCP port range between port 80 and 99. An error will be
// returned if the rule failed to be created.
func CreateSecurityGroupRule(t *testing.T, client *gophercloud.ServiceClient, securityGroupID string) (secgroups.Rule, error) {
func CreateSecurityGroupRule(t *testing.T, client *gophercloud.ServiceClient, securityGroupID string) (*secgroups.Rule, error) {
fromPort := tools.RandomInt(80, 89)
toPort := tools.RandomInt(90, 99)
createOpts := secgroups.CreateRuleOpts{
ParentGroupID: securityGroupID,
FromPort: tools.RandomInt(80, 89),
ToPort: tools.RandomInt(90, 99),
FromPort: fromPort,
ToPort: toPort,
IPProtocol: "TCP",
CIDR: "0.0.0.0/0",
}
rule, err := secgroups.CreateRule(client, createOpts).Extract()
if err != nil {
return *rule, err
return nil, err
}
t.Logf("Created security group rule: %s", rule.ID)
return *rule, nil
th.AssertEquals(t, rule.FromPort, fromPort)
th.AssertEquals(t, rule.ToPort, toPort)
th.AssertEquals(t, rule.ParentGroupID, securityGroupID)
return rule, nil
}
// CreateServer creates a basic instance with a randomly generated name.
@@ -339,12 +432,6 @@ func CreateSecurityGroupRule(t *testing.T, client *gophercloud.ServiceClient, se
// The instance will be launched on the network specified in OS_NETWORK_NAME.
// An error will be returned if the instance was unable to be created.
func CreateServer(t *testing.T, client *gophercloud.ServiceClient) (*servers.Server, error) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
var server *servers.Server
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
t.Fatal(err)
@@ -352,7 +439,7 @@ func CreateServer(t *testing.T, client *gophercloud.ServiceClient) (*servers.Ser
networkID, err := GetNetworkIDFromTenantNetworks(t, client, choices.NetworkName)
if err != nil {
return server, err
return nil, err
}
name := tools.RandomString("ACPTTEST", 16)
@@ -360,7 +447,7 @@ func CreateServer(t *testing.T, client *gophercloud.ServiceClient) (*servers.Ser
pwd := tools.MakeNewPassword("")
server, err = servers.Create(client, servers.CreateOpts{
server, err := servers.Create(client, servers.CreateOpts{
Name: name,
FlavorRef: choices.FlavorID,
ImageRef: choices.ImageID,
@@ -383,10 +470,19 @@ func CreateServer(t *testing.T, client *gophercloud.ServiceClient) (*servers.Ser
}
if err := WaitForComputeStatus(client, server, "ACTIVE"); err != nil {
return server, err
return nil, err
}
return server, nil
newServer, err := servers.Get(client, server.ID).Extract()
if err != nil {
return nil, err
}
th.AssertEquals(t, newServer.Name, name)
th.AssertEquals(t, newServer.Flavor["id"], choices.FlavorID)
th.AssertEquals(t, newServer.Image["id"], choices.ImageID)
return newServer, nil
}
// CreateServerWithoutImageRef creates a basic instance with a randomly generated name.
@@ -395,12 +491,6 @@ func CreateServer(t *testing.T, client *gophercloud.ServiceClient) (*servers.Ser
// The instance will be launched on the network specified in OS_NETWORK_NAME.
// An error will be returned if the instance was unable to be created.
func CreateServerWithoutImageRef(t *testing.T, client *gophercloud.ServiceClient) (*servers.Server, error) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
var server *servers.Server
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
t.Fatal(err)
@@ -408,7 +498,7 @@ func CreateServerWithoutImageRef(t *testing.T, client *gophercloud.ServiceClient
networkID, err := GetNetworkIDFromTenantNetworks(t, client, choices.NetworkName)
if err != nil {
return server, err
return nil, err
}
name := tools.RandomString("ACPTTEST", 16)
@@ -416,7 +506,7 @@ func CreateServerWithoutImageRef(t *testing.T, client *gophercloud.ServiceClient
pwd := tools.MakeNewPassword("")
server, err = servers.Create(client, servers.CreateOpts{
server, err := servers.Create(client, servers.CreateOpts{
Name: name,
FlavorRef: choices.FlavorID,
AdminPass: pwd,
@@ -431,40 +521,102 @@ func CreateServerWithoutImageRef(t *testing.T, client *gophercloud.ServiceClient
},
}).Extract()
if err != nil {
return server, err
return nil, err
}
if err := WaitForComputeStatus(client, server, "ACTIVE"); err != nil {
return server, err
return nil, err
}
return server, nil
}
// CreateServerWithTags creates a basic instance with a randomly generated name.
// The flavor of the instance will be the value of the OS_FLAVOR_ID environment variable.
// The image will be the value of the OS_IMAGE_ID environment variable.
// The instance will be launched on the network specified in OS_NETWORK_NAME.
// Two tags will be assigned to the server.
// An error will be returned if the instance was unable to be created.
func CreateServerWithTags(t *testing.T, client *gophercloud.ServiceClient, networkID string) (*servers.Server, error) {
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
t.Fatal(err)
}
name := tools.RandomString("ACPTTEST", 16)
t.Logf("Attempting to create server: %s", name)
pwd := tools.MakeNewPassword("")
server, err := servers.Create(client, servers.CreateOpts{
Name: name,
FlavorRef: choices.FlavorID,
ImageRef: choices.ImageID,
AdminPass: pwd,
Networks: []servers.Network{
servers.Network{UUID: networkID},
},
Metadata: map[string]string{
"abc": "def",
},
Personality: servers.Personality{
&servers.File{
Path: "/etc/test",
Contents: []byte("hello world"),
},
},
Tags: []string{"tag1", "tag2"},
}).Extract()
if err != nil {
return server, err
}
if err := WaitForComputeStatus(client, server, "ACTIVE"); err != nil {
return nil, err
}
res := servers.Get(client, server.ID)
if res.Err != nil {
return nil, res.Err
}
newServer, err := res.Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, newServer.Name, name)
tags, err := res.ExtractTags()
th.AssertNoErr(t, err)
th.AssertDeepEquals(t, tags, []string{"tag1", "tag2"})
return newServer, nil
}
// CreateServerGroup will create a server with a random name. An error will be
// returned if the server group failed to be created.
func CreateServerGroup(t *testing.T, client *gophercloud.ServiceClient, policy string) (*servergroups.ServerGroup, error) {
name := tools.RandomString("ACPTTEST", 16)
t.Logf("Attempting to create server group %s", name)
sg, err := servergroups.Create(client, &servergroups.CreateOpts{
Name: "test",
Name: name,
Policies: []string{policy},
}).Extract()
if err != nil {
return sg, err
return nil, err
}
t.Logf("Successfully created server group %s", name)
th.AssertEquals(t, sg.Name, name)
return sg, nil
}
// CreateServerInServerGroup works like CreateServer but places the instance in
// a specified Server Group.
func CreateServerInServerGroup(t *testing.T, client *gophercloud.ServiceClient, serverGroup *servergroups.ServerGroup) (*servers.Server, error) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
var server *servers.Server
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
t.Fatal(err)
@@ -472,7 +624,7 @@ func CreateServerInServerGroup(t *testing.T, client *gophercloud.ServiceClient,
networkID, err := GetNetworkIDFromTenantNetworks(t, client, choices.NetworkName)
if err != nil {
return server, err
return nil, err
}
name := tools.RandomString("ACPTTEST", 16)
@@ -496,23 +648,30 @@ func CreateServerInServerGroup(t *testing.T, client *gophercloud.ServiceClient,
Group: serverGroup.ID,
},
}
server, err = servers.Create(client, schedulerHintsOpts).Extract()
server, err := servers.Create(client, schedulerHintsOpts).Extract()
if err != nil {
return server, err
return nil, err
}
return server, nil
if err := WaitForComputeStatus(client, server, "ACTIVE"); err != nil {
return nil, err
}
newServer, err := servers.Get(client, server.ID).Extract()
if err != nil {
return nil, err
}
th.AssertEquals(t, newServer.Name, name)
th.AssertEquals(t, newServer.Flavor["id"], choices.FlavorID)
th.AssertEquals(t, newServer.Image["id"], choices.ImageID)
return newServer, nil
}
// CreateServerWithPublicKey works the same as CreateServer, but additionally
// configures the server with a specified Key Pair name.
func CreateServerWithPublicKey(t *testing.T, client *gophercloud.ServiceClient, keyPairName string) (*servers.Server, error) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
var server *servers.Server
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
t.Fatal(err)
@@ -520,7 +679,7 @@ func CreateServerWithPublicKey(t *testing.T, client *gophercloud.ServiceClient,
networkID, err := GetNetworkIDFromTenantNetworks(t, client, choices.NetworkName)
if err != nil {
return server, err
return nil, err
}
name := tools.RandomString("ACPTTEST", 16)
@@ -535,19 +694,28 @@ func CreateServerWithPublicKey(t *testing.T, client *gophercloud.ServiceClient,
},
}
server, err = servers.Create(client, keypairs.CreateOptsExt{
server, err := servers.Create(client, keypairs.CreateOptsExt{
CreateOptsBuilder: serverCreateOpts,
KeyName: keyPairName,
}).Extract()
if err != nil {
return server, err
return nil, err
}
if err := WaitForComputeStatus(client, server, "ACTIVE"); err != nil {
return server, err
return nil, err
}
return server, nil
newServer, err := servers.Get(client, server.ID).Extract()
if err != nil {
return nil, err
}
th.AssertEquals(t, newServer.Name, name)
th.AssertEquals(t, newServer.Flavor["id"], choices.FlavorID)
th.AssertEquals(t, newServer.Image["id"], choices.ImageID)
return newServer, nil
}
// CreateVolumeAttachment will attach a volume to a server. An error will be
@@ -570,6 +738,18 @@ func CreateVolumeAttachment(t *testing.T, client *gophercloud.ServiceClient, blo
return volumeAttachment, nil
}
// DeleteAggregate will delete a given host aggregate. A fatal error will occur if
// the aggregate deleting is failed. This works best when using it as a
// deferred function.
func DeleteAggregate(t *testing.T, client *gophercloud.ServiceClient, aggregate *aggregates.Aggregate) {
err := aggregates.Delete(client, aggregate.ID).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete aggregate %d", aggregate.ID)
}
t.Logf("Deleted aggregate: %d", aggregate.ID)
}
// DeleteDefaultRule deletes a default security group rule.
// A fatal error will occur if the rule failed to delete. This works best when
// using it as a deferred function.
@@ -619,25 +799,25 @@ func DeleteKeyPair(t *testing.T, client *gophercloud.ServiceClient, keyPair *key
// DeleteSecurityGroup will delete a security group. A fatal error will occur
// if the group failed to be deleted. This works best as a deferred function.
func DeleteSecurityGroup(t *testing.T, client *gophercloud.ServiceClient, securityGroup secgroups.SecurityGroup) {
err := secgroups.Delete(client, securityGroup.ID).ExtractErr()
func DeleteSecurityGroup(t *testing.T, client *gophercloud.ServiceClient, securityGroupID string) {
err := secgroups.Delete(client, securityGroupID).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete security group %s: %s", securityGroup.ID, err)
t.Fatalf("Unable to delete security group %s: %s", securityGroupID, err)
}
t.Logf("Deleted security group: %s", securityGroup.ID)
t.Logf("Deleted security group: %s", securityGroupID)
}
// DeleteSecurityGroupRule will delete a security group rule. A fatal error
// will occur if the rule failed to be deleted. This works best when used
// as a deferred function.
func DeleteSecurityGroupRule(t *testing.T, client *gophercloud.ServiceClient, rule secgroups.Rule) {
err := secgroups.DeleteRule(client, rule.ID).ExtractErr()
func DeleteSecurityGroupRule(t *testing.T, client *gophercloud.ServiceClient, ruleID string) {
err := secgroups.DeleteRule(client, ruleID).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete rule: %v", err)
}
t.Logf("Deleted security group rule: %s", rule.ID)
t.Logf("Deleted security group rule: %s", ruleID)
}
// DeleteServer deletes an instance via its UUID.
@@ -649,6 +829,16 @@ func DeleteServer(t *testing.T, client *gophercloud.ServiceClient, server *serve
t.Fatalf("Unable to delete server %s: %s", server.ID, err)
}
if err := WaitForComputeStatus(client, server, "DELETED"); err != nil {
if _, ok := err.(gophercloud.ErrDefault404); ok {
t.Logf("Deleted server: %s", server.ID)
return
}
t.Fatalf("Error deleting server %s: %s", server.ID, err)
}
// If we reach this point, the API returned an actual DELETED status
// which is a very short window of time, but happens occasionally.
t.Logf("Deleted server: %s", server.ID)
}
@@ -680,6 +870,20 @@ func DeleteVolumeAttachment(t *testing.T, client *gophercloud.ServiceClient, blo
t.Logf("Deleted volume: %s", volumeAttachment.VolumeID)
}
// DetachInterface will detach an interface from a server. A fatal
// error will occur if the interface could not be detached. This works best
// when used as a deferred function.
func DetachInterface(t *testing.T, client *gophercloud.ServiceClient, serverID, portID string) {
t.Logf("Attempting to detach interface %s from server %s", portID, serverID)
err := attachinterfaces.Delete(client, serverID, portID).ExtractErr()
if err != nil {
t.Fatalf("Unable to detach interface %s from server %s", portID, serverID)
}
t.Logf("Detached interface %s from server %s", portID, serverID)
}
// DisassociateFloatingIP will disassociate a floating IP from an instance. A
// fatal error will occur if the floating IP failed to disassociate. This works
// best when using it as a deferred function.
@@ -762,6 +966,10 @@ func ImportPublicKey(t *testing.T, client *gophercloud.ServiceClient, publicKey
}
t.Logf("Created keypair: %s", keyPairName)
th.AssertEquals(t, keyPair.Name, keyPairName)
th.AssertEquals(t, keyPair.PublicKey, publicKey)
return keyPair, nil
}
@@ -827,3 +1035,49 @@ func FillUpdateOptsFromQuotaSet(src quotasets.QuotaSet, dest *quotasets.UpdateOp
dest.ServerGroupMembers = &src.ServerGroupMembers
dest.MetadataItems = &src.MetadataItems
}
// RescueServer will place the specified server into rescue mode.
func RescueServer(t *testing.T, client *gophercloud.ServiceClient, server *servers.Server) error {
t.Logf("Attempting to put server %s into rescue mode", server.ID)
_, err := rescueunrescue.Rescue(client, server.ID, rescueunrescue.RescueOpts{}).Extract()
if err != nil {
return err
}
if err := WaitForComputeStatus(client, server, "RESCUE"); err != nil {
return err
}
return nil
}
// UnrescueServer will return server from rescue mode.
func UnrescueServer(t *testing.T, client *gophercloud.ServiceClient, server *servers.Server) error {
t.Logf("Attempting to return server %s from rescue mode", server.ID)
if err := rescueunrescue.Unrescue(client, server.ID).ExtractErr(); err != nil {
return err
}
if err := WaitForComputeStatus(client, server, "ACTIVE"); err != nil {
return err
}
return nil
}
// CreateRemoteConsole will create a remote noVNC console for the specified server.
func CreateRemoteConsole(t *testing.T, client *gophercloud.ServiceClient, serverID string) (*remoteconsoles.RemoteConsole, error) {
createOpts := remoteconsoles.CreateOpts{
Protocol: remoteconsoles.ConsoleProtocolVNC,
Type: remoteconsoles.ConsoleTypeNoVNC,
}
t.Logf("Attempting to create a %s console for the server %s", createOpts.Type, serverID)
remoteConsole, err := remoteconsoles.Create(client, serverID, createOpts).Extract()
if err != nil {
return nil, err
}
t.Logf("Successfully created console: %s", remoteConsole.URL)
return remoteConsole, nil
}

View File

@@ -8,23 +8,21 @@ import (
"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()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
allPages, err := dsr.List(client).AllPages()
if err != nil {
t.Fatalf("Unable to list default rules: %v", err)
}
th.AssertNoErr(t, err)
allDefaultRules, err := dsr.ExtractDefaultRules(allPages)
if err != nil {
t.Fatalf("Unable to extract default rules: %v", err)
}
th.AssertNoErr(t, err)
for _, defaultRule := range allDefaultRules {
tools.PrintResource(t, defaultRule)
@@ -32,36 +30,32 @@ func TestDefSecRulesList(t *testing.T) {
}
func TestDefSecRulesCreate(t *testing.T) {
clients.RequireAdmin(t)
clients.RequireNovaNetwork(t)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
defaultRule, err := CreateDefaultRule(t, client)
if err != nil {
t.Fatalf("Unable to create default rule: %v", err)
}
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()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
defaultRule, err := CreateDefaultRule(t, client)
if err != nil {
t.Fatalf("Unable to create default rule: %v", err)
}
th.AssertNoErr(t, err)
defer DeleteDefaultRule(t, client, defaultRule)
newDefaultRule, err := dsr.Get(client, defaultRule.ID).Extract()
if err != nil {
t.Fatalf("Unable to get default rule %s: %v", defaultRule.ID, err)
}
th.AssertNoErr(t, err)
tools.PrintResource(t, newDefaultRule)
}

View File

@@ -8,39 +8,39 @@ import (
"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()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
allPages, err := extensions.List(client).AllPages()
if err != nil {
t.Fatalf("Unable to list extensions: %v", err)
}
th.AssertNoErr(t, err)
allExtensions, err := extensions.ExtractExtensions(allPages)
if err != nil {
t.Fatalf("Unable to extract extensions: %v", err)
}
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 TestExtensionGet(t *testing.T) {
func TestExtensionsGet(t *testing.T) {
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
extension, err := extensions.Get(client, "os-admin-actions").Extract()
if err != nil {
t.Fatalf("Unable to get extension os-admin-actions: %v", err)
}
th.AssertNoErr(t, err)
tools.PrintResource(t, extension)
th.AssertEquals(t, extension.Name, "AdminActions")
}

View File

@@ -6,111 +6,196 @@ 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) {
t.Logf("** Default flavors (same as Project flavors): **")
t.Logf("")
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
allPages, err := flavors.ListDetail(client, nil).AllPages()
if err != nil {
t.Fatalf("Unable to retrieve flavors: %v", err)
}
th.AssertNoErr(t, err)
allFlavors, err := flavors.ExtractFlavors(allPages)
if err != nil {
t.Fatalf("Unable to extract flavor results: %v", err)
}
th.AssertNoErr(t, err)
var found bool
for _, flavor := range allFlavors {
tools.PrintResource(t, flavor)
if flavor.ID == choices.FlavorID {
found = true
}
}
flavorAccessTypes := [3]flavors.AccessType{flavors.PublicAccess, flavors.PrivateAccess, flavors.AllAccess}
for _, flavorAccessType := range flavorAccessTypes {
t.Logf("** %s flavors: **", flavorAccessType)
t.Logf("")
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()
if err != nil {
t.Fatalf("Unable to retrieve flavors: %v", err)
}
th.AssertNoErr(t, err)
allFlavors, err := flavors.ExtractFlavors(allPages)
if err != nil {
t.Fatalf("Unable to extract flavor results: %v", err)
}
th.AssertNoErr(t, err)
for _, flavor := range allFlavors {
tools.PrintResource(t, flavor)
t.Logf("")
}
}
}
func TestFlavorsGet(t *testing.T) {
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
flavor, err := flavors.Get(client, choices.FlavorID).Extract()
if err != nil {
t.Fatalf("Unable to get flavor information: %v", err)
}
th.AssertNoErr(t, err)
tools.PrintResource(t, flavor)
th.AssertEquals(t, flavor.ID, choices.FlavorID)
}
func TestFlavorCreateDelete(t *testing.T) {
func TestFlavorsCreateDelete(t *testing.T) {
clients.RequireAdmin(t)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
flavor, err := CreateFlavor(t, client)
if err != nil {
t.Fatalf("Unable to create flavor: %v", err)
}
th.AssertNoErr(t, err)
defer DeleteFlavor(t, client, flavor)
tools.PrintResource(t, flavor)
}
func TestFlavorAccessesList(t *testing.T) {
func TestFlavorsAccessesList(t *testing.T) {
clients.RequireAdmin(t)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
flavor, err := CreatePrivateFlavor(t, client)
if err != nil {
t.Fatalf("Unable to create flavor: %v", err)
}
th.AssertNoErr(t, err)
defer DeleteFlavor(t, client, flavor)
allPages, err := flavors.ListAccesses(client, flavor.ID).AllPages()
if err != nil {
t.Fatalf("Unable to list flavor accesses: %v", err)
}
th.AssertNoErr(t, err)
allAccesses, err := flavors.ExtractAccesses(allPages)
if err != nil {
t.Fatalf("Unable to extract accesses: %v", err)
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,
}
for _, access := range allAccesses {
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

@@ -9,114 +9,90 @@ import (
"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 TestFloatingIPsList(t *testing.T) {
func TestFloatingIPsCreateDelete(t *testing.T) {
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
allPages, err := floatingips.List(client).AllPages()
if err != nil {
t.Fatalf("Unable to retrieve floating IPs: %v", err)
}
allFloatingIPs, err := floatingips.ExtractFloatingIPs(allPages)
if err != nil {
t.Fatalf("Unable to extract floating IPs: %v", err)
}
for _, floatingIP := range allFloatingIPs {
tools.PrintResource(t, floatingIP)
}
}
func TestFloatingIPsCreate(t *testing.T) {
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
floatingIP, err := CreateFloatingIP(t, client)
if err != nil {
t.Fatalf("Unable to create floating IP: %v", err)
}
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) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
if err != nil {
t.Fatalf("Unable to create server: %v", err)
}
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
floatingIP, err := CreateFloatingIP(t, client)
if err != nil {
t.Fatalf("Unable to create floating IP: %v", err)
}
th.AssertNoErr(t, err)
defer DeleteFloatingIP(t, client, floatingIP)
tools.PrintResource(t, floatingIP)
err = AssociateFloatingIP(t, client, floatingIP, server)
if err != nil {
t.Fatalf("Unable to associate floating IP %s with server %s: %v", floatingIP.IP, server.ID, err)
}
th.AssertNoErr(t, err)
defer DisassociateFloatingIP(t, client, floatingIP, server)
newFloatingIP, err := floatingips.Get(client, floatingIP.ID).Extract()
if err != nil {
t.Fatalf("Unable to get floating IP %s: %v", floatingIP.ID, err)
}
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) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
if err != nil {
t.Fatalf("Unable to create server: %v", err)
}
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
newServer, err := servers.Get(client, server.ID).Extract()
if err != nil {
t.Fatalf("Unable to get server %s: %v", server.ID, err)
}
th.AssertNoErr(t, err)
floatingIP, err := CreateFloatingIP(t, client)
if err != nil {
t.Fatalf("Unable to create floating IP: %v", err)
}
th.AssertNoErr(t, err)
defer DeleteFloatingIP(t, client, floatingIP)
tools.PrintResource(t, floatingIP)
@@ -132,17 +108,16 @@ func TestFloatingIPsFixedIPAssociate(t *testing.T) {
}
err = AssociateFloatingIPWithFixedIP(t, client, floatingIP, newServer, fixedIP)
if err != nil {
t.Fatalf("Unable to associate floating IP %s with server %s: %v", floatingIP.IP, newServer.ID, err)
}
th.AssertNoErr(t, err)
defer DisassociateFloatingIP(t, client, floatingIP, newServer)
newFloatingIP, err := floatingips.Get(client, floatingIP.ID).Extract()
if err != nil {
t.Fatalf("Unable to get floating IP %s: %v", floatingIP.ID, err)
}
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

@@ -3,30 +3,93 @@
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()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
allPages, err := hypervisors.List(client).AllPages()
if err != nil {
t.Fatalf("Unable to list hypervisors: %v", err)
}
th.AssertNoErr(t, err)
allHypervisors, err := hypervisors.ExtractHypervisors(allPages)
if err != nil {
t.Fatalf("Unable to extract hypervisors")
}
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

@@ -8,44 +8,45 @@ import (
"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()
if err != nil {
t.Fatalf("Unable to create a compute: client: %v", err)
}
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
allPages, err := images.ListDetail(client, nil).AllPages()
if err != nil {
t.Fatalf("Unable to retrieve images: %v", err)
}
th.AssertNoErr(t, err)
allImages, err := images.ExtractImages(allPages)
if err != nil {
t.Fatalf("Unable to extract image results: %v", err)
}
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()
if err != nil {
t.Fatalf("Unable to create a compute: client: %v", err)
}
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
image, err := images.Get(client, choices.ImageID).Extract()
if err != nil {
t.Fatalf("Unable to get image information: %v", err)
}
th.AssertNoErr(t, err)
tools.PrintResource(t, image)
th.AssertEquals(t, choices.ImageID, image.ID)
}

View File

@@ -9,99 +9,93 @@ import (
"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 TestKeypairsList(t *testing.T) {
func TestKeypairsParse(t *testing.T) {
clients.SkipRelease(t, "stable/mitaka")
clients.SkipRelease(t, "stable/newton")
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
allPages, err := keypairs.List(client).AllPages()
if err != nil {
t.Fatalf("Unable to retrieve keypairs: %s", err)
}
allKeys, err := keypairs.ExtractKeyPairs(allPages)
if err != nil {
t.Fatalf("Unable to extract keypairs results: %s", err)
}
for _, keypair := range allKeys {
tools.PrintResource(t, keypair)
}
}
func TestKeypairsCreate(t *testing.T) {
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
keyPair, err := CreateKeyPair(t, client)
if err != nil {
t.Fatalf("Unable to create key pair: %v", err)
}
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()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
publicKey, err := createKey()
if err != nil {
t.Fatalf("Unable to create public key: %s", err)
}
th.AssertNoErr(t, err)
keyPair, err := ImportPublicKey(t, client, publicKey)
if err != nil {
t.Fatalf("Unable to create keypair: %s", err)
}
th.AssertNoErr(t, err)
defer DeleteKeyPair(t, client, keyPair)
tools.PrintResource(t, keyPair)
}
func TestKeypairsServerCreateWithKey(t *testing.T) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
publicKey, err := createKey()
if err != nil {
t.Fatalf("Unable to create public key: %s", err)
}
th.AssertNoErr(t, err)
keyPair, err := ImportPublicKey(t, client, publicKey)
if err != nil {
t.Fatalf("Unable to create keypair: %s", err)
}
th.AssertNoErr(t, err)
defer DeleteKeyPair(t, client, keyPair)
server, err := CreateServerWithPublicKey(t, client, keyPair.Name)
if err != nil {
t.Fatalf("Unable to create server: %s", err)
}
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
server, err = servers.Get(client, server.ID).Extract()
if err != nil {
t.Fatalf("Unable to retrieve server: %s", err)
}
th.AssertNoErr(t, err)
if server.KeyName != keyPair.Name {
t.Fatalf("key name of server %s is %s, not %s", server.ID, server.KeyName, keyPair.Name)
}
th.AssertEquals(t, server.KeyName, keyPair.Name)
}

View File

@@ -7,29 +7,28 @@ import (
"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()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
limits, err := limits.Get(client, nil).Extract()
if err != nil {
t.Fatalf("Unable to get limits: %v", err)
}
th.AssertNoErr(t, err)
t.Logf("Limits for scoped user:")
t.Logf("%#v", limits)
tools.PrintResource(t, limits)
th.AssertEquals(t, limits.Absolute.MaxPersonalitySize, 10240)
}
func TestLimitsForTenant(t *testing.T) {
clients.RequireAdmin(t)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
// I think this is the easiest way to get the tenant ID while being
// agnostic to Identity v2 and v3.
@@ -43,10 +42,9 @@ func TestLimitsForTenant(t *testing.T) {
}
limits, err := limits.Get(client, getOpts).Extract()
if err != nil {
t.Fatalf("Unable to get absolute limits: %v", err)
}
th.AssertNoErr(t, err)
t.Logf("Limits for tenant %s:", tenantID)
t.Logf("%#v", limits)
tools.PrintResource(t, limits)
th.AssertEquals(t, limits.Absolute.MaxPersonalitySize, 10240)
}

View File

@@ -7,24 +7,50 @@ import (
"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()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
if err != nil {
t.Fatalf("Unable to create server: %v", err)
}
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()
if err != nil {
t.Fatalf("Error during migration: %v", err)
}
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

@@ -8,49 +8,48 @@ import (
"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()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
allPages, err := networks.List(client).AllPages()
if err != nil {
t.Fatalf("Unable to list networks: %v", err)
}
th.AssertNoErr(t, err)
allNetworks, err := networks.ExtractNetworks(allPages)
if err != nil {
t.Fatalf("Unable to list networks: %v", err)
}
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()
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
networkID, err := GetNetworkIDFromNetworks(t, client, choices.NetworkName)
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
network, err := networks.Get(client, networkID).Extract()
if err != nil {
t.Fatalf("Unable to get network %s: %v", networkID, err)
}
th.AssertNoErr(t, err)
tools.PrintResource(t, network)
th.AssertEquals(t, network.Label, choices.NetworkName)
}

View File

@@ -16,39 +16,34 @@ import (
)
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()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
identityClient, err := clients.NewIdentityV2Client()
if err != nil {
t.Fatalf("Unable to get a new identity client: %v", err)
}
th.AssertNoErr(t, err)
tenantID, err := getTenantID(t, identityClient)
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
quotaSet, err := quotasets.Get(client, tenantID).Extract()
if err != nil {
t.Fatal(err)
}
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()
if err != nil {
t.Fatalf("Unable to get list of tenants: %v", err)
}
th.AssertNoErr(t, err)
allTenants, err := tenants.ExtractTenants(allPages)
if err != nil {
t.Fatalf("Unable to extract tenants: %v", err)
}
th.AssertNoErr(t, err)
for _, tenant := range allTenants {
return tenant.ID, nil
@@ -59,14 +54,10 @@ func getTenantID(t *testing.T, client *gophercloud.ServiceClient) (string, error
func getTenantIDByName(t *testing.T, client *gophercloud.ServiceClient, name string) (string, error) {
allPages, err := tenants.List(client, nil).AllPages()
if err != nil {
t.Fatalf("Unable to get list of tenants: %v", err)
}
th.AssertNoErr(t, err)
allTenants, err := tenants.ExtractTenants(allPages)
if err != nil {
t.Fatalf("Unable to extract tenants: %v", err)
}
th.AssertNoErr(t, err)
for _, tenant := range allTenants {
if tenant.Name == name {
@@ -77,8 +68,8 @@ func getTenantIDByName(t *testing.T, client *gophercloud.ServiceClient, name str
return "", fmt.Errorf("Unable to get tenant ID")
}
//What will be sent as desired Quotas to the Server
var UpdatQuotaOpts = quotasets.UpdateOpts{
// 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),
@@ -95,7 +86,7 @@ var UpdatQuotaOpts = quotasets.UpdateOpts{
ServerGroupMembers: gophercloud.IntToPointer(3),
}
//What the Server hopefully returns as the new Quotas
// What the Server hopefully returns as the new Quotas
var UpdatedQuotas = quotasets.QuotaSet{
FixedIPs: 10,
FloatingIPs: 10,
@@ -114,71 +105,49 @@ var UpdatedQuotas = quotasets.QuotaSet{
}
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()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
idclient, err := clients.NewIdentityV2Client()
if err != nil {
t.Fatalf("Could not create IdentityClient to look up tenant id!")
}
th.AssertNoErr(t, err)
tenantid, err := getTenantIDByName(t, idclient, os.Getenv("OS_TENANT_NAME"))
if err != nil {
t.Fatalf("Id for Tenant named '%' not found. Please set OS_TENANT_NAME appropriately", os.Getenv("OS_TENANT_NAME"))
}
th.AssertNoErr(t, err)
//save original quotas
// save original quotas
orig, err := quotasets.Get(client, tenantid).Extract()
th.AssertNoErr(t, err)
//Test Update
res, err := quotasets.Update(client, tenantid, UpdatQuotaOpts).Extract()
// Test Update
res, err := quotasets.Update(client, tenantid, UpdateQuotaOpts).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, UpdatedQuotas, *res)
//Test Delete
// 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
// 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()
if newres == res {
t.Fatalf("Quotas after delete equal quotas before delete!")
th.AssertNoErr(t, err)
if newres.RAM == res.RAM {
t.Fatalf("Failed to update quotas")
}
restore := quotasets.UpdateOpts{}
FillUpdateOptsFromQuotaSet(*orig, &restore)
//restore original quotas
// restore original quotas
res, err = quotasets.Update(client, tenantid, restore).Extract()
th.AssertNoErr(t, err)
orig.ID = ""
th.AssertEquals(t, *orig, *res)
}
// Makes sure that the FillUpdateOptsFromQuotaSet() helper function works properly
func TestFillFromQuotaSetHelperFunction(t *testing.T) {
op := &quotasets.UpdateOpts{}
expected := `
{
"fixed_ips": 10,
"floating_ips": 10,
"injected_file_content_bytes": 10240,
"injected_file_path_bytes": 255,
"injected_files": 5,
"key_pairs": 10,
"metadata_items": 128,
"ram": 20000,
"security_group_rules": 20,
"security_groups": 10,
"cores": 10,
"instances": 4,
"server_groups": 2,
"server_group_members": 3
}`
FillUpdateOptsFromQuotaSet(UpdatedQuotas, op)
th.AssertJSONEquals(t, expected, op)
th.AssertDeepEquals(t, orig, res)
}

View File

@@ -0,0 +1,29 @@
// +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

@@ -0,0 +1,25 @@
// +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

@@ -8,130 +8,135 @@ import (
"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()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
allPages, err := secgroups.List(client).AllPages()
if err != nil {
t.Fatalf("Unable to retrieve security groups: %v", err)
}
th.AssertNoErr(t, err)
allSecGroups, err := secgroups.ExtractSecurityGroups(allPages)
if err != nil {
t.Fatalf("Unable to extract security groups: %v", err)
}
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 TestSecGroupsCreate(t *testing.T) {
func TestSecGroupsCRUD(t *testing.T) {
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
securityGroup, err := CreateSecurityGroup(t, client)
if err != nil {
t.Fatalf("Unable to create security group: %v", err)
}
defer DeleteSecurityGroup(t, client, securityGroup)
}
th.AssertNoErr(t, err)
defer DeleteSecurityGroup(t, client, securityGroup.ID)
func TestSecGroupsUpdate(t *testing.T) {
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
securityGroup, err := CreateSecurityGroup(t, client)
if err != nil {
t.Fatalf("Unable to create security group: %v", err)
}
defer DeleteSecurityGroup(t, client, securityGroup)
tools.PrintResource(t, securityGroup)
newName := tools.RandomString("secgroup_", 4)
description := ""
updateOpts := secgroups.UpdateOpts{
Name: tools.RandomString("secgroup_", 4),
Description: tools.RandomString("dec_", 10),
Name: newName,
Description: &description,
}
updatedSecurityGroup, err := secgroups.Update(client, securityGroup.ID, updateOpts).Extract()
if err != nil {
t.Fatalf("Unable to update security group: %v", err)
}
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()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
securityGroup, err := CreateSecurityGroup(t, client)
if err != nil {
t.Fatalf("Unable to create security group: %v", err)
}
defer DeleteSecurityGroup(t, client, securityGroup)
th.AssertNoErr(t, err)
defer DeleteSecurityGroup(t, client, securityGroup.ID)
tools.PrintResource(t, securityGroup)
rule, err := CreateSecurityGroupRule(t, client, securityGroup.ID)
if err != nil {
t.Fatalf("Unable to create rule: %v", err)
}
defer DeleteSecurityGroupRule(t, client, rule)
th.AssertNoErr(t, err)
defer DeleteSecurityGroupRule(t, client, rule.ID)
tools.PrintResource(t, rule)
newSecurityGroup, err := secgroups.Get(client, securityGroup.ID).Extract()
if err != nil {
t.Fatalf("Unable to obtain security group: %v", err)
}
th.AssertNoErr(t, err)
tools.PrintResource(t, newSecurityGroup)
th.AssertEquals(t, len(newSecurityGroup.Rules), 1)
}
func TestSecGroupsAddGroupToServer(t *testing.T) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
if err != nil {
t.Fatalf("Unable to create server: %v", err)
}
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
securityGroup, err := CreateSecurityGroup(t, client)
if err != nil {
t.Fatalf("Unable to create security group: %v", err)
}
defer DeleteSecurityGroup(t, client, securityGroup)
th.AssertNoErr(t, err)
defer DeleteSecurityGroup(t, client, securityGroup.ID)
rule, err := CreateSecurityGroupRule(t, client, securityGroup.ID)
if err != nil {
t.Fatalf("Unable to create rule: %v", err)
}
defer DeleteSecurityGroupRule(t, client, rule)
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()
if err != nil && err.Error() != "EOF" {
t.Fatalf("Unable to add group %s to server %s: %s", securityGroup.ID, server.ID, err)
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()
if err != nil && err.Error() != "EOF" {
t.Fatalf("Unable to remove group %s from server %s: %s", securityGroup.ID, server.ID, err)
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

@@ -9,85 +9,63 @@ import (
"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 TestServergroupsList(t *testing.T) {
func TestServergroupsCreateDelete(t *testing.T) {
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
allPages, err := servergroups.List(client).AllPages()
if err != nil {
t.Fatalf("Unable to list server groups: %v", err)
}
allServerGroups, err := servergroups.ExtractServerGroups(allPages)
if err != nil {
t.Fatalf("Unable to extract server groups: %v", err)
}
for _, serverGroup := range allServerGroups {
tools.PrintResource(t, serverGroup)
}
}
func TestServergroupsCreate(t *testing.T) {
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
serverGroup, err := CreateServerGroup(t, client, "anti-affinity")
if err != nil {
t.Fatalf("Unable to create server group: %v", err)
}
th.AssertNoErr(t, err)
defer DeleteServerGroup(t, client, serverGroup)
serverGroup, err = servergroups.Get(client, serverGroup.ID).Extract()
if err != nil {
t.Fatalf("Unable to get server group: %v", err)
}
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()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
serverGroup, err := CreateServerGroup(t, client, "affinity")
if err != nil {
t.Fatalf("Unable to create server group: %v", err)
}
th.AssertNoErr(t, err)
defer DeleteServerGroup(t, client, serverGroup)
firstServer, err := CreateServerInServerGroup(t, client, serverGroup)
if err != nil {
t.Fatalf("Unable to create server: %v", err)
}
if err = WaitForComputeStatus(client, firstServer, "ACTIVE"); err != nil {
t.Fatalf("Unable to wait for server: %v", err)
}
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)
if err != nil {
t.Fatalf("Unable to create server: %v", err)
}
if err = WaitForComputeStatus(client, secondServer, "ACTIVE"); err != nil {
t.Fatalf("Unable to wait for server: %v", err)
}
th.AssertNoErr(t, err)
defer DeleteServer(t, client, secondServer)
secondServer, err = servers.Get(client, secondServer.ID).Extract()
th.AssertNoErr(t, err)
if firstServer.HostID != secondServer.HostID {
t.Fatalf("%s and %s were not scheduled on the same host.", firstServer.ID, secondServer.ID)
}
th.AssertEquals(t, firstServer.HostID, secondServer.HostID)
}

View File

@@ -11,95 +11,72 @@ import (
"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 TestServersList(t *testing.T) {
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
allPages, err := servers.List(client, servers.ListOpts{}).AllPages()
if err != nil {
t.Fatalf("Unable to retrieve servers: %v", err)
}
allServers, err := servers.ExtractServers(allPages)
if err != nil {
t.Fatalf("Unable to extract servers: %v", err)
}
for _, server := range allServers {
tools.PrintResource(t, server)
}
}
func TestServersCreateDestroy(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
if err != nil {
t.Fatalf("Unable to create server: %v", err)
}
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
newServer, err := servers.Get(client, server.ID).Extract()
if err != nil {
t.Errorf("Unable to retrieve server: %v", err)
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
}
}
tools.PrintResource(t, newServer)
th.AssertEquals(t, found, true)
allAddressPages, err := servers.ListAddresses(client, server.ID).AllPages()
if err != nil {
t.Errorf("Unable to list server addresses: %v", err)
}
th.AssertNoErr(t, err)
allAddresses, err := servers.ExtractAddresses(allAddressPages)
if err != nil {
t.Errorf("Unable to extract server addresses: %v", err)
}
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()
if err != nil {
t.Errorf("Unable to list server Interfaces: %v", err)
}
th.AssertNoErr(t, err)
allInterfaces, err := attachinterfaces.ExtractInterfaces(allInterfacePages)
if err != nil {
t.Errorf("Unable to extract server Interfaces: %v", err)
}
th.AssertNoErr(t, err)
for _, Interface := range allInterfaces {
t.Logf("Interfaces: %+v", Interface)
for _, iface := range allInterfaces {
t.Logf("Interfaces: %+v", iface)
}
allNetworkAddressPages, err := servers.ListAddressesByNetwork(client, server.ID, choices.NetworkName).AllPages()
if err != nil {
t.Errorf("Unable to list server addresses: %v", err)
}
th.AssertNoErr(t, err)
allNetworkAddresses, err := servers.ExtractNetworkAddresses(allNetworkAddressPages)
if err != nil {
t.Errorf("Unable to extract server addresses: %v", err)
}
th.AssertNoErr(t, err)
t.Logf("Addresses on %s:", choices.NetworkName)
for _, address := range allNetworkAddresses {
@@ -107,42 +84,43 @@ func TestServersCreateDestroy(t *testing.T) {
}
}
func TestServersCreateDestroyWithExtensions(t *testing.T) {
func TestServersWithExtensionsCreateDestroy(t *testing.T) {
clients.RequireLong(t)
var extendedServer struct {
servers.Server
availabilityzones.ServerAvailabilityZoneExt
extendedstatus.ServerExtendedStatusExt
serverusage.UsageExt
}
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
if err != nil {
t.Fatalf("Unable to create server: %v", err)
}
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
err = servers.Get(client, server.ID).ExtractInto(&extendedServer)
if err != nil {
t.Errorf("Unable to retrieve server: %v", err)
}
th.AssertNoErr(t, err)
tools.PrintResource(t, extendedServer)
t.Logf("Availability Zone: %s\n", extendedServer.AvailabilityZone)
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()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
server, err := CreateServerWithoutImageRef(t, client)
if err != nil {
if err400, ok := err.(*gophercloud.ErrUnexpectedResponseCode); ok {
if !strings.Contains("Missing imageRef attribute", string(err400.Body)) {
if !strings.Contains(string(err400.Body), "Missing imageRef attribute") {
defer DeleteServer(t, client, server)
}
}
@@ -150,15 +128,13 @@ func TestServersWithoutImageRef(t *testing.T) {
}
func TestServersUpdate(t *testing.T) {
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
alternateName := tools.RandomString("ACPTTEST", 16)
@@ -173,13 +149,9 @@ func TestServersUpdate(t *testing.T) {
}
updated, err := servers.Update(client, server.ID, updateOpts).Extract()
if err != nil {
t.Fatalf("Unable to rename server: %v", err)
}
th.AssertNoErr(t, err)
if updated.ID != server.ID {
t.Errorf("Updated server ID [%s] didn't match original server ID [%s]!", updated.ID, server.ID)
}
th.AssertEquals(t, updated.ID, server.ID)
err = tools.WaitFor(func() (bool, error) {
latest, err := servers.Get(client, updated.ID).Extract()
@@ -192,81 +164,99 @@ func TestServersUpdate(t *testing.T) {
}
func TestServersMetadata(t *testing.T) {
t.Parallel()
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
if err != nil {
t.Fatal(err)
}
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()
if err != nil {
t.Fatalf("Unable to update metadata: %v", err)
}
th.AssertNoErr(t, err)
t.Logf("UpdateMetadata result: %+v\n", metadata)
err = servers.DeleteMetadatum(client, server.ID, "foo").ExtractErr()
if err != nil {
t.Fatalf("Unable to delete metadatum: %v", err)
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()
if err != nil {
t.Fatalf("Unable to create metadatum: %v", err)
}
th.AssertNoErr(t, err)
t.Logf("CreateMetadatum result: %+v\n", metadata)
metadata, err = servers.Metadatum(client, server.ID, "foo").Extract()
if err != nil {
t.Fatalf("Unable to get metadatum: %v", 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",
"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()
if err != nil {
t.Fatalf("Unable to get metadata: %v", err)
}
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()
if err != nil {
t.Fatalf("Unable to reset metadata: %v", err)
}
th.AssertNoErr(t, err)
t.Logf("ResetMetadata result: %+v\n", metadata)
th.AssertDeepEquals(t, map[string]string{}, metadata)
}
func TestServersActionChangeAdminPassword(t *testing.T) {
t.Parallel()
clients.RequireLong(t)
clients.RequireGuestAgent(t)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
randomPassword := tools.MakeNewPassword(server.AdminPass)
res := servers.ChangeAdminPassword(client, server.ID, randomPassword)
if res.Err != nil {
t.Fatal(res.Err)
}
th.AssertNoErr(t, res.Err)
if err = WaitForComputeStatus(client, server, "PASSWORD"); err != nil {
t.Fatal(err)
@@ -278,28 +268,22 @@ func TestServersActionChangeAdminPassword(t *testing.T) {
}
func TestServersActionReboot(t *testing.T) {
t.Parallel()
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
rebootOpts := &servers.RebootOpts{
rebootOpts := servers.RebootOpts{
Type: servers.SoftReboot,
}
t.Logf("Attempting reboot of server %s", server.ID)
res := servers.Reboot(client, server.ID, rebootOpts)
if res.Err != nil {
t.Fatalf("Unable to reboot server: %v", res.Err)
}
th.AssertNoErr(t, res.Err)
if err = WaitForComputeStatus(client, server, "REBOOT"); err != nil {
t.Fatal(err)
@@ -311,22 +295,16 @@ func TestServersActionReboot(t *testing.T) {
}
func TestServersActionRebuild(t *testing.T) {
t.Parallel()
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
t.Logf("Attempting to rebuild server %s", server.ID)
@@ -338,13 +316,9 @@ func TestServersActionRebuild(t *testing.T) {
}
rebuilt, err := servers.Rebuild(client, server.ID, rebuildOpts).Extract()
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
if rebuilt.ID != server.ID {
t.Errorf("Expected rebuilt server ID of [%s]; got [%s]", server.ID, rebuilt.ID)
}
th.AssertEquals(t, rebuilt.ID, server.ID)
if err = WaitForComputeStatus(client, rebuilt, "REBUILD"); err != nil {
t.Fatal(err)
@@ -356,17 +330,16 @@ func TestServersActionRebuild(t *testing.T) {
}
func TestServersActionResizeConfirm(t *testing.T) {
t.Parallel()
clients.RequireLong(t)
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
t.Logf("Attempting to resize server %s", server.ID)
@@ -380,20 +353,24 @@ func TestServersActionResizeConfirm(t *testing.T) {
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) {
t.Parallel()
clients.RequireLong(t)
choices, err := clients.AcceptanceTestChoicesFromEnv()
th.AssertNoErr(t, err)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
t.Logf("Attempting to resize server %s", server.ID)
@@ -407,112 +384,179 @@ func TestServersActionResizeRevert(t *testing.T) {
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) {
t.Parallel()
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
if err != nil {
t.Fatal(err)
}
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()
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
err = WaitForComputeStatus(client, server, "PAUSED")
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
err = pauseunpause.Unpause(client, server.ID).ExtractErr()
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
err = WaitForComputeStatus(client, server, "ACTIVE")
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
}
func TestServersActionSuspend(t *testing.T) {
t.Parallel()
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
if err != nil {
t.Fatal(err)
}
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()
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
err = WaitForComputeStatus(client, server, "SUSPENDED")
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
err = suspendresume.Resume(client, server.ID).ExtractErr()
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
err = WaitForComputeStatus(client, server, "ACTIVE")
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
}
func TestServersActionLock(t *testing.T) {
t.Parallel()
clients.RequireLong(t)
clients.RequireNonAdmin(t)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
if err != nil {
t.Fatal(err)
}
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()
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
t.Logf("Attempting to delete locked server %s", server.ID)
err = servers.Delete(client, server.ID).ExtractErr()
if err == nil {
t.Fatalf("Should not have been able to delete the server")
}
th.AssertEquals(t, err != nil, true)
t.Logf("Attempting to unlock server %s", server.ID)
err = lockunlock.Unlock(client, server.ID).ExtractErr()
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
err = WaitForComputeStatus(client, server, "ACTIVE")
if err != nil {
t.Fatal(err)
}
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

@@ -0,0 +1,36 @@
// +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

@@ -8,49 +8,46 @@ import (
"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()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
allPages, err := tenantnetworks.List(client).AllPages()
if err != nil {
t.Fatalf("Unable to list networks: %v", err)
}
th.AssertNoErr(t, err)
allTenantNetworks, err := tenantnetworks.ExtractNetworks(allPages)
if err != nil {
t.Fatalf("Unable to list networks: %v", err)
}
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()
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
networkID, err := GetNetworkIDFromTenantNetworks(t, client, choices.NetworkName)
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
network, err := tenantnetworks.Get(client, networkID).Extract()
if err != nil {
t.Fatalf("Unable to get network %s: %v", networkID, err)
}
th.AssertNoErr(t, err)
tools.PrintResource(t, network)
}

View File

@@ -0,0 +1,91 @@
// +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

@@ -5,74 +5,34 @@ package v2
import (
"testing"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/acceptance/clients"
bs "github.com/gophercloud/gophercloud/acceptance/openstack/blockstorage/v2"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestVolumeAttachAttachment(t *testing.T) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
clients.RequireLong(t)
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
th.AssertNoErr(t, err)
blockClient, err := clients.NewBlockStorageV1Client()
if err != nil {
t.Fatalf("Unable to create a blockstorage client: %v", err)
}
blockClient, err := clients.NewBlockStorageV2Client()
th.AssertNoErr(t, err)
server, err := CreateServer(t, client)
if err != nil {
t.Fatalf("Unable to create server: %v", err)
}
th.AssertNoErr(t, err)
defer DeleteServer(t, client, server)
volume, err := createVolume(t, blockClient)
if err != nil {
t.Fatalf("Unable to create volume: %v", err)
}
if err = volumes.WaitForStatus(blockClient, volume.ID, "available", 60); err != nil {
t.Fatalf("Unable to wait for volume: %v", err)
}
defer deleteVolume(t, blockClient, volume)
volume, err := bs.CreateVolume(t, blockClient)
th.AssertNoErr(t, err)
defer bs.DeleteVolume(t, blockClient, volume)
volumeAttachment, err := CreateVolumeAttachment(t, client, blockClient, server, volume)
if err != nil {
t.Fatalf("Unable to attach volume: %v", err)
}
th.AssertNoErr(t, err)
defer DeleteVolumeAttachment(t, client, blockClient, server, volumeAttachment)
tools.PrintResource(t, volumeAttachment)
}
func createVolume(t *testing.T, blockClient *gophercloud.ServiceClient) (*volumes.Volume, error) {
volumeName := tools.RandomString("ACPTTEST", 16)
createOpts := volumes.CreateOpts{
Size: 1,
Name: volumeName,
}
volume, err := volumes.Create(blockClient, createOpts).Extract()
if err != nil {
return volume, err
}
t.Logf("Created volume: %s", volume.ID)
return volume, nil
}
func deleteVolume(t *testing.T, blockClient *gophercloud.ServiceClient, volume *volumes.Volume) {
err := volumes.Delete(blockClient, volume.ID).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete volume: %v", err)
}
t.Logf("Deleted volume: %s", volume.ID)
th.AssertEquals(t, volumeAttachment.ServerID, server.ID)
}

View File

@@ -0,0 +1,47 @@
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

@@ -0,0 +1,98 @@
// +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

@@ -0,0 +1,46 @@
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

@@ -0,0 +1,45 @@
// +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

@@ -0,0 +1,78 @@
// +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

@@ -0,0 +1,70 @@
// +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

@@ -0,0 +1,224 @@
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

@@ -0,0 +1,20 @@
// +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)
}

View File

@@ -0,0 +1,79 @@
// +build acceptance db
package v1
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/db/v1/configurations"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestConfigurationsCRUD(t *testing.T) {
client, err := clients.NewDBV1Client()
if err != nil {
t.Fatalf("Unable to create a DB client: %v", err)
}
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
t.Fatalf("Unable to get environment settings")
}
createOpts := &configurations.CreateOpts{
Name: "test",
Description: "description",
}
datastore := configurations.DatastoreOpts{
Type: choices.DBDatastoreType,
Version: choices.DBDatastoreVersion,
}
createOpts.Datastore = &datastore
values := make(map[string]interface{})
values["collation_server"] = "latin1_swedish_ci"
createOpts.Values = values
cgroup, err := configurations.Create(client, createOpts).Extract()
if err != nil {
t.Fatalf("Unable to create configuration: %v", err)
}
readCgroup, err := configurations.Get(client, cgroup.ID).Extract()
if err != nil {
t.Fatalf("Unable to read configuration: %v", err)
}
tools.PrintResource(t, readCgroup)
th.AssertEquals(t, readCgroup.Name, createOpts.Name)
th.AssertEquals(t, readCgroup.Description, createOpts.Description)
// TODO: verify datastore
//th.AssertDeepEquals(t, readCgroup.Datastore, datastore)
// Update cgroup
newCgroupName := "New configuration name"
newCgroupDescription := ""
updateOpts := configurations.UpdateOpts{
Name: newCgroupName,
Description: &newCgroupDescription,
}
err = configurations.Update(client, cgroup.ID, updateOpts).ExtractErr()
th.AssertNoErr(t, err)
newCgroup, err := configurations.Get(client, cgroup.ID).Extract()
if err != nil {
t.Fatalf("Unable to read updated configuration: %v", err)
}
tools.PrintResource(t, newCgroup)
th.AssertEquals(t, newCgroup.Name, newCgroupName)
th.AssertEquals(t, newCgroup.Description, newCgroupDescription)
err = configurations.Delete(client, cgroup.ID).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete configuration: %v", err)
}
}

View File

@@ -7,6 +7,7 @@ import (
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets"
"github.com/gophercloud/gophercloud/openstack/dns/v2/zones"
th "github.com/gophercloud/gophercloud/testhelper"
)
// CreateRecordSet will create a RecordSet with a random name. An error will
@@ -38,6 +39,8 @@ func CreateRecordSet(t *testing.T, client *gophercloud.ServiceClient, zone *zone
t.Logf("Created record set: %s", newRS.Name)
th.AssertEquals(t, newRS.Name, zone.Name)
return rs, nil
}
@@ -70,6 +73,10 @@ func CreateZone(t *testing.T, client *gophercloud.ServiceClient) (*zones.Zone, e
}
t.Logf("Created Zone: %s", zoneName)
th.AssertEquals(t, newZone.Name, zoneName)
th.AssertEquals(t, newZone.TTL, 7200)
return newZone, nil
}
@@ -102,6 +109,10 @@ func CreateSecondaryZone(t *testing.T, client *gophercloud.ServiceClient) (*zone
}
t.Logf("Created Zone: %s", zoneName)
th.AssertEquals(t, newZone.Name, zoneName)
th.AssertEquals(t, newZone.Masters[0], "10.0.0.1")
return newZone, nil
}
@@ -132,7 +143,7 @@ func DeleteZone(t *testing.T, client *gophercloud.ServiceClient, zone *zones.Zon
// WaitForRecordSetStatus will poll a record set's status until it either matches
// the specified status or the status becomes ERROR.
func WaitForRecordSetStatus(client *gophercloud.ServiceClient, rs *recordsets.RecordSet, status string) error {
return gophercloud.WaitFor(60, func() (bool, error) {
return gophercloud.WaitFor(600, func() (bool, error) {
current, err := recordsets.Get(client, rs.ZoneID, rs.ID).Extract()
if err != nil {
return false, err
@@ -149,7 +160,7 @@ func WaitForRecordSetStatus(client *gophercloud.ServiceClient, rs *recordsets.Re
// WaitForZoneStatus will poll a zone's status until it either matches
// the specified status or the status becomes ERROR.
func WaitForZoneStatus(client *gophercloud.ServiceClient, zone *zones.Zone, status string) error {
return gophercloud.WaitFor(60, func() (bool, error) {
return gophercloud.WaitFor(600, func() (bool, error) {
current, err := zones.Get(client, zone.ID).Extract()
if err != nil {
return false, err

View File

@@ -8,98 +8,105 @@ import (
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets"
"github.com/gophercloud/gophercloud/pagination"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestRecordSetsListByZone(t *testing.T) {
clients.RequireDNS(t)
client, err := clients.NewDNSV2Client()
if err != nil {
t.Fatalf("Unable to create a DNS client: %v", err)
}
th.AssertNoErr(t, err)
zone, err := CreateZone(t, client)
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
defer DeleteZone(t, client, zone)
var allRecordSets []recordsets.RecordSet
allPages, err := recordsets.ListByZone(client, zone.ID, nil).AllPages()
if err != nil {
t.Fatalf("Unable to retrieve recordsets: %v", err)
}
th.AssertNoErr(t, err)
allRecordSets, err = recordsets.ExtractRecordSets(allPages)
if err != nil {
t.Fatalf("Unable to extract recordsets: %v", err)
}
allRecordSets, err := recordsets.ExtractRecordSets(allPages)
th.AssertNoErr(t, err)
var found bool
for _, recordset := range allRecordSets {
tools.PrintResource(t, &recordset)
}
}
func TestRecordSetsListByZoneLimited(t *testing.T) {
client, err := clients.NewDNSV2Client()
if err != nil {
t.Fatalf("Unable to create a DNS client: %v", err)
if recordset.ZoneID == zone.ID {
found = true
}
}
zone, err := CreateZone(t, client)
if err != nil {
t.Fatal(err)
}
defer DeleteZone(t, client, zone)
th.AssertEquals(t, found, true)
var allRecordSets []recordsets.RecordSet
listOpts := recordsets.ListOpts{
Limit: 1,
}
allPages, err := recordsets.ListByZone(client, zone.ID, listOpts).AllPages()
if err != nil {
t.Fatalf("Unable to retrieve recordsets: %v", err)
}
allRecordSets, err = recordsets.ExtractRecordSets(allPages)
if err != nil {
t.Fatalf("Unable to extract recordsets: %v", err)
}
for _, recordset := range allRecordSets {
tools.PrintResource(t, &recordset)
}
err = recordsets.ListByZone(client, zone.ID, listOpts).EachPage(
func(page pagination.Page) (bool, error) {
rr, err := recordsets.ExtractRecordSets(page)
th.AssertNoErr(t, err)
th.AssertEquals(t, len(rr), 1)
return true, nil
},
)
th.AssertNoErr(t, err)
}
func TestRecordSetCRUD(t *testing.T) {
func TestRecordSetsCRUD(t *testing.T) {
clients.RequireDNS(t)
client, err := clients.NewDNSV2Client()
if err != nil {
t.Fatalf("Unable to create a DNS client: %v", err)
}
th.AssertNoErr(t, err)
zone, err := CreateZone(t, client)
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
defer DeleteZone(t, client, zone)
tools.PrintResource(t, &zone)
rs, err := CreateRecordSet(t, client, zone)
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
defer DeleteRecordSet(t, client, rs)
tools.PrintResource(t, &rs)
description := ""
updateOpts := recordsets.UpdateOpts{
Description: "New description",
TTL: 0,
Description: &description,
}
newRS, err := recordsets.Update(client, rs.ZoneID, rs.ID, updateOpts).Extract()
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
tools.PrintResource(t, &newRS)
th.AssertEquals(t, newRS.Description, description)
records := []string{"10.1.0.3"}
updateOpts = recordsets.UpdateOpts{
Records: records,
}
newRS, err = recordsets.Update(client, rs.ZoneID, rs.ID, updateOpts).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, &newRS)
th.AssertDeepEquals(t, newRS.Records, records)
th.AssertEquals(t, newRS.TTL, 3600)
ttl := 0
updateOpts = recordsets.UpdateOpts{
TTL: &ttl,
}
newRS, err = recordsets.Update(client, rs.ZoneID, rs.ID, updateOpts).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, &newRS)
th.AssertDeepEquals(t, newRS.Records, records)
th.AssertEquals(t, newRS.TTL, ttl)
}

View File

@@ -8,53 +8,48 @@ import (
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/dns/v2/zones"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestZonesList(t *testing.T) {
client, err := clients.NewDNSV2Client()
if err != nil {
t.Fatalf("Unable to create a DNS client: %v", err)
}
var allZones []zones.Zone
allPages, err := zones.List(client, nil).AllPages()
if err != nil {
t.Fatalf("Unable to retrieve zones: %v", err)
}
allZones, err = zones.ExtractZones(allPages)
if err != nil {
t.Fatalf("Unable to extract zones: %v", err)
}
for _, zone := range allZones {
tools.PrintResource(t, &zone)
}
}
func TestZonesCRUD(t *testing.T) {
clients.RequireDNS(t)
client, err := clients.NewDNSV2Client()
if err != nil {
t.Fatalf("Unable to create a DNS client: %v", err)
}
th.AssertNoErr(t, err)
zone, err := CreateZone(t, client)
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
defer DeleteZone(t, client, zone)
tools.PrintResource(t, &zone)
allPages, err := zones.List(client, nil).AllPages()
th.AssertNoErr(t, err)
allZones, err := zones.ExtractZones(allPages)
th.AssertNoErr(t, err)
var found bool
for _, z := range allZones {
tools.PrintResource(t, &z)
if zone.Name == z.Name {
found = true
}
}
th.AssertEquals(t, found, true)
description := ""
updateOpts := zones.UpdateOpts{
Description: "New description",
Description: &description,
TTL: 0,
}
newZone, err := zones.Update(client, zone.ID, updateOpts).Extract()
if err != nil {
t.Fatal(err)
}
th.AssertNoErr(t, err)
tools.PrintResource(t, &newZone)
th.AssertEquals(t, newZone.Description, description)
}

View File

@@ -8,39 +8,42 @@ import (
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/identity/v2/extensions"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestExtensionsList(t *testing.T) {
clients.RequireIdentityV2(t)
clients.RequireAdmin(t)
client, err := clients.NewIdentityV2Client()
if err != nil {
t.Fatalf("Unable to create an identity client: %v", err)
}
th.AssertNoErr(t, err)
allPages, err := extensions.List(client).AllPages()
if err != nil {
t.Fatalf("Unable to list extensions: %v", err)
}
th.AssertNoErr(t, err)
allExtensions, err := extensions.ExtractExtensions(allPages)
if err != nil {
t.Fatalf("Unable to extract extensions: %v", err)
}
th.AssertNoErr(t, err)
var found bool
for _, extension := range allExtensions {
tools.PrintResource(t, extension)
if extension.Name == "OS-KSCRUD" {
found = true
}
}
th.AssertEquals(t, found, true)
}
func TestExtensionsGet(t *testing.T) {
clients.RequireIdentityV2(t)
clients.RequireAdmin(t)
client, err := clients.NewIdentityV2Client()
if err != nil {
t.Fatalf("Unable to create an identity client: %v", err)
}
th.AssertNoErr(t, err)
extension, err := extensions.Get(client, "OS-KSCRUD").Extract()
if err != nil {
t.Fatalf("Unable to get extension OS-KSCRUD: %v", err)
}
th.AssertNoErr(t, err)
tools.PrintResource(t, extension)
}

View File

@@ -10,6 +10,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/identity/v2/extensions/admin/roles"
"github.com/gophercloud/gophercloud/openstack/identity/v2/tenants"
"github.com/gophercloud/gophercloud/openstack/identity/v2/users"
th "github.com/gophercloud/gophercloud/testhelper"
)
// AddUserRole will grant a role to a user in a tenant. An error will be
@@ -33,6 +34,7 @@ func AddUserRole(t *testing.T, client *gophercloud.ServiceClient, tenant *tenant
// unable to be created.
func CreateTenant(t *testing.T, client *gophercloud.ServiceClient, c *tenants.CreateOpts) (*tenants.Tenant, error) {
name := tools.RandomString("ACPTTEST", 8)
description := tools.RandomString("ACPTTEST-DESC", 8)
t.Logf("Attempting to create tenant: %s", name)
var createOpts tenants.CreateOpts
@@ -43,15 +45,18 @@ func CreateTenant(t *testing.T, client *gophercloud.ServiceClient, c *tenants.Cr
}
createOpts.Name = name
createOpts.Description = description
tenant, err := tenants.Create(client, createOpts).Extract()
if err != nil {
t.Logf("Foo")
return tenant, err
}
t.Logf("Successfully created project %s with ID %s", name, tenant.ID)
th.AssertEquals(t, name, tenant.Name)
th.AssertEquals(t, description, tenant.Description)
return tenant, nil
}
@@ -74,6 +79,8 @@ func CreateUser(t *testing.T, client *gophercloud.ServiceClient, tenant *tenants
return user, err
}
th.AssertEquals(t, userName, user.Name)
return user, nil
}
@@ -182,5 +189,7 @@ func UpdateUser(t *testing.T, client *gophercloud.ServiceClient, user *users.Use
return newUser, err
}
th.AssertEquals(t, userName, newUser.Name)
return newUser, nil
}

View File

@@ -9,69 +9,68 @@ import (
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/identity/v2/extensions/admin/roles"
"github.com/gophercloud/gophercloud/openstack/identity/v2/users"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestRolesAddToUser(t *testing.T) {
clients.RequireIdentityV2(t)
clients.RequireAdmin(t)
client, err := clients.NewIdentityV2AdminClient()
if err != nil {
t.Fatalf("Unable to obtain an identity client: %v", err)
}
th.AssertNoErr(t, err)
tenant, err := FindTenant(t, client)
if err != nil {
t.Fatalf("Unable to get a tenant: %v", err)
}
th.AssertNoErr(t, err)
role, err := FindRole(t, client)
if err != nil {
t.Fatalf("Unable to get a role: %v", err)
}
th.AssertNoErr(t, err)
user, err := CreateUser(t, client, tenant)
if err != nil {
t.Fatalf("Unable to create a user: %v", err)
}
th.AssertNoErr(t, err)
defer DeleteUser(t, client, user)
err = AddUserRole(t, client, tenant, user, role)
if err != nil {
t.Fatalf("Unable to add role to user: %v", err)
}
th.AssertNoErr(t, err)
defer DeleteUserRole(t, client, tenant, user, role)
allPages, err := users.ListRoles(client, tenant.ID, user.ID).AllPages()
if err != nil {
t.Fatalf("Unable to obtain roles for user: %v", err)
}
th.AssertNoErr(t, err)
allRoles, err := users.ExtractRoles(allPages)
if err != nil {
t.Fatalf("Unable to extract roles: %v", err)
}
th.AssertNoErr(t, err)
t.Logf("Roles of user %s:", user.Name)
for _, role := range allRoles {
var found bool
for _, r := range allRoles {
tools.PrintResource(t, role)
if r.Name == role.Name {
found = true
}
}
th.AssertEquals(t, found, true)
}
func TestRolesList(t *testing.T) {
clients.RequireIdentityV2(t)
clients.RequireAdmin(t)
client, err := clients.NewIdentityV2AdminClient()
if err != nil {
t.Fatalf("Unable to create an identity client: %v", err)
}
th.AssertNoErr(t, err)
allPages, err := roles.List(client).AllPages()
if err != nil {
t.Fatalf("Unable to list all roles: %v", err)
}
th.AssertNoErr(t, err)
allRoles, err := roles.ExtractRoles(allPages)
if err != nil {
t.Fatalf("Unable to extract roles: %v", err)
}
th.AssertNoErr(t, err)
var found bool
for _, r := range allRoles {
tools.PrintResource(t, r)
if r.Name == "admin" {
found = true
}
}
th.AssertEquals(t, found, true)
}

View File

@@ -8,56 +8,59 @@ import (
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/identity/v2/tenants"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestTenantsList(t *testing.T) {
clients.RequireIdentityV2(t)
clients.RequireAdmin(t)
client, err := clients.NewIdentityV2Client()
if err != nil {
t.Fatalf("Unable to obtain an identity client: %v")
}
th.AssertNoErr(t, err)
allPages, err := tenants.List(client, nil).AllPages()
if err != nil {
t.Fatalf("Unable to list tenants: %v", err)
}
th.AssertNoErr(t, err)
allTenants, err := tenants.ExtractTenants(allPages)
if err != nil {
t.Fatalf("Unable to extract tenants: %v", err)
}
th.AssertNoErr(t, err)
var found bool
for _, tenant := range allTenants {
tools.PrintResource(t, tenant)
if tenant.Name == "admin" {
found = true
}
}
th.AssertEquals(t, found, true)
}
func TestTenantsCRUD(t *testing.T) {
clients.RequireIdentityV2(t)
clients.RequireAdmin(t)
client, err := clients.NewIdentityV2AdminClient()
if err != nil {
t.Fatalf("Unable to obtain an identity client: %v")
}
th.AssertNoErr(t, err)
tenant, err := CreateTenant(t, client, nil)
if err != nil {
t.Fatalf("Unable to create tenant: %v", err)
}
th.AssertNoErr(t, err)
defer DeleteTenant(t, client, tenant.ID)
tenant, err = tenants.Get(client, tenant.ID).Extract()
if err != nil {
t.Fatalf("Unable to get tenant: %v", err)
}
th.AssertNoErr(t, err)
tools.PrintResource(t, tenant)
description := ""
updateOpts := tenants.UpdateOpts{
Description: "some tenant",
Description: &description,
}
newTenant, err := tenants.Update(client, tenant.ID, updateOpts).Extract()
if err != nil {
t.Fatalf("Unable to update tenant: %v", err)
}
th.AssertNoErr(t, err)
tools.PrintResource(t, newTenant)
th.AssertEquals(t, newTenant.Description, description)
}

View File

@@ -9,31 +9,27 @@ import (
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack"
"github.com/gophercloud/gophercloud/openstack/identity/v2/tokens"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestTokenAuthenticate(t *testing.T) {
clients.RequireIdentityV2(t)
clients.RequireAdmin(t)
client, err := clients.NewIdentityV2UnauthenticatedClient()
if err != nil {
t.Fatalf("Unable to obtain an identity client: %v", err)
}
th.AssertNoErr(t, err)
authOptions, err := openstack.AuthOptionsFromEnv()
if err != nil {
t.Fatalf("Unable to obtain authentication options: %v", err)
}
th.AssertNoErr(t, err)
result := tokens.Create(client, authOptions)
token, err := result.ExtractToken()
if err != nil {
t.Fatalf("Unable to extract token: %v", err)
}
th.AssertNoErr(t, err)
tools.PrintResource(t, token)
catalog, err := result.ExtractServiceCatalog()
if err != nil {
t.Fatalf("Unable to extract service catalog: %v", err)
}
th.AssertNoErr(t, err)
for _, entry := range catalog.Entries {
tools.PrintResource(t, entry)
@@ -41,29 +37,24 @@ func TestTokenAuthenticate(t *testing.T) {
}
func TestTokenValidate(t *testing.T) {
clients.RequireIdentityV2(t)
clients.RequireAdmin(t)
client, err := clients.NewIdentityV2Client()
if err != nil {
t.Fatalf("Unable to obtain an identity client: %v", err)
}
th.AssertNoErr(t, err)
authOptions, err := openstack.AuthOptionsFromEnv()
if err != nil {
t.Fatalf("Unable to obtain authentication options: %v", err)
}
th.AssertNoErr(t, err)
result := tokens.Create(client, authOptions)
token, err := result.ExtractToken()
if err != nil {
t.Fatalf("Unable to extract token: %v", err)
}
th.AssertNoErr(t, err)
tools.PrintResource(t, token)
getResult := tokens.Get(client, token.ID)
user, err := getResult.ExtractUser()
if err != nil {
t.Fatalf("Unable to extract user: %v", err)
}
th.AssertNoErr(t, err)
tools.PrintResource(t, user)
}

View File

@@ -8,52 +8,52 @@ import (
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/identity/v2/users"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestUsersList(t *testing.T) {
clients.RequireIdentityV2(t)
clients.RequireAdmin(t)
client, err := clients.NewIdentityV2AdminClient()
if err != nil {
t.Fatalf("Unable to obtain an identity client: %v", err)
}
th.AssertNoErr(t, err)
allPages, err := users.List(client).AllPages()
if err != nil {
t.Fatalf("Unable to list users: %v", err)
}
th.AssertNoErr(t, err)
allUsers, err := users.ExtractUsers(allPages)
if err != nil {
t.Fatalf("Unable to extract users: %v", err)
}
th.AssertNoErr(t, err)
var found bool
for _, user := range allUsers {
tools.PrintResource(t, user)
if user.Name == "admin" {
found = true
}
}
th.AssertEquals(t, found, true)
}
func TestUsersCreateUpdateDelete(t *testing.T) {
clients.RequireIdentityV2(t)
clients.RequireAdmin(t)
client, err := clients.NewIdentityV2AdminClient()
if err != nil {
t.Fatalf("Unable to obtain an identity client: %v", err)
}
th.AssertNoErr(t, err)
tenant, err := FindTenant(t, client)
if err != nil {
t.Fatalf("Unable to get a tenant: %v", err)
}
th.AssertNoErr(t, err)
user, err := CreateUser(t, client, tenant)
if err != nil {
t.Fatalf("Unable to create a user: %v", err)
}
th.AssertNoErr(t, err)
defer DeleteUser(t, client, user)
tools.PrintResource(t, user)
newUser, err := UpdateUser(t, client, user)
if err != nil {
t.Fatalf("Unable to update user: %v", err)
}
th.AssertNoErr(t, err)
tools.PrintResource(t, newUser)
}

View File

@@ -0,0 +1,168 @@
// +build acceptance
package v3
import (
"testing"
"time"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack"
"github.com/gophercloud/gophercloud/openstack/identity/v3/applicationcredentials"
"github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestApplicationCredentialsCRD(t *testing.T) {
clients.RequireAdmin(t)
// maps are required, because Application Credential roles are returned in a random order
rolesToMap := func(roles []applicationcredentials.Role) map[string]string {
rolesMap := map[string]string{}
for _, role := range roles {
rolesMap[role.Name] = role.Name
rolesMap[role.ID] = role.ID
}
return rolesMap
}
client, err := clients.NewIdentityV3Client()
th.AssertNoErr(t, err)
ao, err := openstack.AuthOptionsFromEnv()
th.AssertNoErr(t, err)
authOptions := tokens.AuthOptions{
Username: ao.Username,
Password: ao.Password,
DomainName: ao.DomainName,
DomainID: ao.DomainID,
// We need a scope to get the token roles list
Scope: tokens.Scope{
ProjectID: ao.TenantID,
ProjectName: ao.TenantName,
DomainID: ao.DomainID,
DomainName: ao.DomainName,
},
}
token, err := tokens.Create(client, &authOptions).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, token)
user, err := tokens.Get(client, token.ID).ExtractUser()
th.AssertNoErr(t, err)
tools.PrintResource(t, user)
roles, err := tokens.Get(client, token.ID).ExtractRoles()
th.AssertNoErr(t, err)
tools.PrintResource(t, roles)
project, err := tokens.Get(client, token.ID).ExtractProject()
th.AssertNoErr(t, err)
tools.PrintResource(t, project)
// prepare create parameters
var apRoles []applicationcredentials.Role
for i, role := range roles {
if i%2 == 0 {
apRoles = append(apRoles, applicationcredentials.Role{Name: role.Name})
} else {
apRoles = append(apRoles, applicationcredentials.Role{ID: role.ID})
}
if i > 4 {
break
}
}
tools.PrintResource(t, apRoles)
// restricted, limited TTL, with limited roles, autogenerated secret
createOpts := applicationcredentials.CreateOpts{
Name: "test-ac",
Description: "test application credential",
Roles: apRoles,
ExpiresAt: "2119-01-01T12:12:12Z",
}
applicationCredential, err := applicationcredentials.Create(client, user.ID, createOpts).Extract()
th.AssertNoErr(t, err)
defer applicationcredentials.Delete(client, user.ID, applicationCredential.ID)
tools.PrintResource(t, applicationCredential)
if applicationCredential.Secret == "" {
t.Fatalf("Application credential secret was not generated")
}
th.AssertEquals(t, applicationCredential.ExpiresAt.UTC().Format(time.RFC3339), createOpts.ExpiresAt)
th.AssertEquals(t, applicationCredential.Name, createOpts.Name)
th.AssertEquals(t, applicationCredential.Description, createOpts.Description)
th.AssertEquals(t, applicationCredential.Unrestricted, false)
th.AssertEquals(t, applicationCredential.ProjectID, project.ID)
checkACroles := rolesToMap(applicationCredential.Roles)
for i, role := range roles {
if i%2 == 0 {
th.AssertEquals(t, checkACroles[role.Name], role.Name)
} else {
th.AssertEquals(t, checkACroles[role.ID], role.ID)
}
if i > 4 {
break
}
}
// Get an application credential
getApplicationCredential, err := applicationcredentials.Get(client, user.ID, applicationCredential.ID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, getApplicationCredential)
if getApplicationCredential.Secret != "" {
t.Fatalf("Application credential secret should not be returned by a GET request")
}
th.AssertEquals(t, getApplicationCredential.ExpiresAt.UTC().Format(time.RFC3339), createOpts.ExpiresAt)
th.AssertEquals(t, getApplicationCredential.Name, createOpts.Name)
th.AssertEquals(t, getApplicationCredential.Description, createOpts.Description)
th.AssertEquals(t, getApplicationCredential.Unrestricted, false)
th.AssertEquals(t, getApplicationCredential.ProjectID, project.ID)
checkACroles = rolesToMap(getApplicationCredential.Roles)
for i, role := range roles {
if i%2 == 0 {
th.AssertEquals(t, checkACroles[role.Name], role.Name)
} else {
th.AssertEquals(t, checkACroles[role.ID], role.ID)
}
if i > 4 {
break
}
}
// unrestricted, unlimited TTL, with all possible roles, with a custom secret
createOpts = applicationcredentials.CreateOpts{
Name: "super-test-ac",
Description: "test unrestricted application credential",
Unrestricted: true,
Secret: "myprecious",
}
newApplicationCredential, err := applicationcredentials.Create(client, user.ID, createOpts).Extract()
th.AssertNoErr(t, err)
defer applicationcredentials.Delete(client, user.ID, newApplicationCredential.ID)
tools.PrintResource(t, newApplicationCredential)
th.AssertEquals(t, newApplicationCredential.ExpiresAt.UTC(), time.Time{})
th.AssertEquals(t, newApplicationCredential.Name, createOpts.Name)
th.AssertEquals(t, newApplicationCredential.Description, createOpts.Description)
th.AssertEquals(t, newApplicationCredential.Secret, createOpts.Secret)
th.AssertEquals(t, newApplicationCredential.Unrestricted, true)
th.AssertEquals(t, newApplicationCredential.ExpiresAt.UTC(), time.Time{})
th.AssertEquals(t, newApplicationCredential.ProjectID, project.ID)
checkACroles = rolesToMap(newApplicationCredential.Roles)
for _, role := range roles {
th.AssertEquals(t, checkACroles[role.Name], role.Name)
th.AssertEquals(t, checkACroles[role.ID], role.ID)
}
}

View File

@@ -0,0 +1,94 @@
// +build acceptance
package v3
import (
"testing"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack"
"github.com/gophercloud/gophercloud/openstack/identity/v3/credentials"
"github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestCredentialsCRUD(t *testing.T) {
clients.RequireAdmin(t)
client, err := clients.NewIdentityV3Client()
th.AssertNoErr(t, err)
ao, err := openstack.AuthOptionsFromEnv()
th.AssertNoErr(t, err)
authOptions := tokens.AuthOptions{
Username: ao.Username,
Password: ao.Password,
DomainName: ao.DomainName,
DomainID: ao.DomainID,
// We need a scope to get the token roles list
Scope: tokens.Scope{
ProjectID: ao.TenantID,
ProjectName: ao.TenantName,
DomainID: ao.DomainID,
DomainName: ao.DomainName,
},
}
token, err := tokens.Create(client, &authOptions).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, token)
user, err := tokens.Get(client, token.ID).ExtractUser()
th.AssertNoErr(t, err)
tools.PrintResource(t, user)
project, err := tokens.Get(client, token.ID).ExtractProject()
th.AssertNoErr(t, err)
tools.PrintResource(t, project)
createOpts := credentials.CreateOpts{
ProjectID: project.ID,
Type: "ec2",
UserID: user.ID,
Blob: "{\"access\":\"181920\",\"secret\":\"secretKey\"}",
}
// Create a credential
credential, err := credentials.Create(client, createOpts).Extract()
th.AssertNoErr(t, err)
// Delete a credential
defer credentials.Delete(client, credential.ID)
tools.PrintResource(t, credential)
th.AssertEquals(t, credential.Blob, createOpts.Blob)
th.AssertEquals(t, credential.Type, createOpts.Type)
th.AssertEquals(t, credential.UserID, createOpts.UserID)
th.AssertEquals(t, credential.ProjectID, createOpts.ProjectID)
// Get a credential
getCredential, err := credentials.Get(client, credential.ID).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, getCredential)
th.AssertEquals(t, getCredential.Blob, createOpts.Blob)
th.AssertEquals(t, getCredential.Type, createOpts.Type)
th.AssertEquals(t, getCredential.UserID, createOpts.UserID)
th.AssertEquals(t, getCredential.ProjectID, createOpts.ProjectID)
updateOpts := credentials.UpdateOpts{
ProjectID: project.ID,
Type: "ec2",
UserID: user.ID,
Blob: "{\"access\":\"181920\",\"secret\":\"mySecret\"}",
}
// Update a credential
updateCredential, err := credentials.Update(client, credential.ID, updateOpts).Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, updateCredential)
th.AssertEquals(t, updateCredential.Blob, updateOpts.Blob)
}

View File

@@ -8,13 +8,14 @@ import (
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/identity/v3/domains"
th "github.com/gophercloud/gophercloud/testhelper"
)
func TestDomainsList(t *testing.T) {
clients.RequireAdmin(t)
client, err := clients.NewIdentityV3Client()
if err != nil {
t.Fatalf("Unable to obtain an identity client: %v", err)
}
th.AssertNoErr(t, err)
var iTrue bool = true
listOpts := domains.ListOpts{
@@ -22,75 +23,69 @@ func TestDomainsList(t *testing.T) {
}
allPages, err := domains.List(client, listOpts).AllPages()
if err != nil {
t.Fatalf("Unable to list domains: %v", err)
}
th.AssertNoErr(t, err)
allDomains, err := domains.ExtractDomains(allPages)
if err != nil {
t.Fatalf("Unable to extract domains: %v", err)
}
th.AssertNoErr(t, err)
var found bool
for _, domain := range allDomains {
tools.PrintResource(t, domain)
if domain.Name == "Default" {
found = true
}
}
th.AssertEquals(t, found, true)
}
func TestDomainsGet(t *testing.T) {
clients.RequireAdmin(t)
client, err := clients.NewIdentityV3Client()
if err != nil {
t.Fatalf("Unable to obtain an identity client: %v", err)
}
th.AssertNoErr(t, err)
allPages, err := domains.List(client, nil).AllPages()
if err != nil {
t.Fatalf("Unable to list domains: %v", err)
}
allDomains, err := domains.ExtractDomains(allPages)
if err != nil {
t.Fatalf("Unable to extract domains: %v", err)
}
domain := allDomains[0]
p, err := domains.Get(client, domain.ID).Extract()
if err != nil {
t.Fatalf("Unable to get domain: %v", err)
}
p, err := domains.Get(client, "default").Extract()
th.AssertNoErr(t, err)
tools.PrintResource(t, p)
th.AssertEquals(t, p.Name, "Default")
}
func TestDomainsCRUD(t *testing.T) {
clients.RequireAdmin(t)
client, err := clients.NewIdentityV3Client()
if err != nil {
t.Fatalf("Unable to obtain an identity client: %v", err)
}
th.AssertNoErr(t, err)
var iTrue bool = true
var description = "Testing Domain"
createOpts := domains.CreateOpts{
Description: "Testing Domain",
Description: description,
Enabled: &iTrue,
}
domain, err := CreateDomain(t, client, &createOpts)
if err != nil {
t.Fatalf("Unable to create domain: %v", err)
}
th.AssertNoErr(t, err)
defer DeleteDomain(t, client, domain.ID)
tools.PrintResource(t, domain)
th.AssertEquals(t, domain.Description, description)
var iFalse bool = false
description = ""
updateOpts := domains.UpdateOpts{
Description: "Staging Test Domain",
Description: &description,
Enabled: &iFalse,
}
newDomain, err := domains.Update(client, domain.ID, updateOpts).Extract()
if err != nil {
t.Fatalf("Unable to update domain: %v", err)
}
th.AssertNoErr(t, err)
tools.PrintResource(t, newDomain)
th.AssertEquals(t, newDomain.Description, description)
}

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