From 8ea400b1bf693ac9da9dbb3e33d141bc33aaf67c Mon Sep 17 00:00:00 2001 From: Mathieu Velten Date: Tue, 6 Sep 2016 16:52:42 +0200 Subject: [PATCH] bump(github.com/rackspace/gophercloud): e00690e87603abe613e9f02c816c7c4bef82e063 --- Godeps/Godeps.json | 145 ++++++------ Godeps/LICENSES | 199 +++++++++++++++++ .../gophercloud/openstack/auth_env.go | 19 +- .../rackspace/gophercloud/openstack/client.go | 82 ++++--- .../v2/extensions/bootfromvolume/requests.go | 4 +- .../identity/v3/extensions/trust/request.go | 83 +++++++ .../openstack/identity/v3/tokens/errors.go | 4 +- .../openstack/identity/v3/tokens/requests.go | 210 +++++++++--------- .../rackspace/gophercloud/provider_client.go | 24 +- .../gophercloud/testhelper/convenience.go | 41 ++++ 10 files changed, 590 insertions(+), 221 deletions(-) create mode 100644 vendor/github.com/rackspace/gophercloud/openstack/identity/v3/extensions/trust/request.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index bd68c5b0284..5d7d1711c83 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -1868,178 +1868,183 @@ }, { "ImportPath": "github.com/rackspace/gophercloud", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/common/extensions", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/flavors", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/images", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/servers", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/identity/v2/tenants", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/identity/v2/tokens", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" + }, + { + "ImportPath": "github.com/rackspace/gophercloud/openstack/identity/v3/extensions/trust", + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/identity/v3/tokens", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/vips", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/ports", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/openstack/utils", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/pagination", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/rackspace", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumes", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/rackspace/compute/v2/servers", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/rackspace/compute/v2/volumeattach", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/rackspace/identity/v2/tokens", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/testhelper", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/rackspace/gophercloud/testhelper/client", - "Comment": "v1.0.0-920-g934dbf8", - "Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04" + "Comment": "v1.0.0-1012-ge00690e", + "Rev": "e00690e87603abe613e9f02c816c7c4bef82e063" }, { "ImportPath": "github.com/renstrom/dedent", diff --git a/Godeps/LICENSES b/Godeps/LICENSES index d44afb46eca..f5185206aee 100644 --- a/Godeps/LICENSES +++ b/Godeps/LICENSES @@ -60770,6 +60770,205 @@ specific language governing permissions and limitations under the License. ================================================================================ +================================================================================ += vendor/github.com/rackspace/gophercloud/openstack/identity/v3/extensions/trust licensed under: = + +Copyright 2012-2013 Rackspace, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. + +------ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + += vendor/github.com/rackspace/gophercloud/LICENSE dd19699707373c2ca31531a659130416 - +================================================================================ + + ================================================================================ = vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens licensed under: = diff --git a/vendor/github.com/rackspace/gophercloud/openstack/auth_env.go b/vendor/github.com/rackspace/gophercloud/openstack/auth_env.go index a4402b6f06d..2d226d6090c 100644 --- a/vendor/github.com/rackspace/gophercloud/openstack/auth_env.go +++ b/vendor/github.com/rackspace/gophercloud/openstack/auth_env.go @@ -13,14 +13,15 @@ var nilOptions = gophercloud.AuthOptions{} // environment variables, respectively, remain undefined. See the AuthOptions() function for more details. var ( ErrNoAuthURL = fmt.Errorf("Environment variable OS_AUTH_URL needs to be set.") - ErrNoUsername = fmt.Errorf("Environment variable OS_USERNAME needs to be set.") - ErrNoPassword = fmt.Errorf("Environment variable OS_PASSWORD needs to be set.") + ErrNoUsername = fmt.Errorf("Environment variable OS_USERNAME, OS_USERID, or OS_TOKEN needs to be set.") + ErrNoPassword = fmt.Errorf("Environment variable OS_PASSWORD or OS_TOKEN needs to be set.") ) -// AuthOptions fills out an identity.AuthOptions structure with the settings found on the various OpenStack -// OS_* environment variables. The following variables provide sources of truth: OS_AUTH_URL, OS_USERNAME, -// OS_PASSWORD, OS_TENANT_ID, and OS_TENANT_NAME. Of these, OS_USERNAME, OS_PASSWORD, and OS_AUTH_URL must -// have settings, or an error will result. OS_TENANT_ID and OS_TENANT_NAME are optional. +// AuthOptionsFromEnv fills out an AuthOptions structure from the environment +// variables: OS_AUTH_URL, OS_USERNAME, OS_USERID, OS_PASSWORD, OS_TENANT_ID, +// OS_TENANT_NAME, OS_DOMAIN_ID, OS_DOMAIN_NAME, OS_TOKEN. It checks that +// (1) OS_AUTH_URL is set, (2) OS_USERNAME, OS_USERID, or OS_TOKEN is set, +// (3) OS_PASSWORD or OS_TOKEN is set. func AuthOptionsFromEnv() (gophercloud.AuthOptions, error) { authURL := os.Getenv("OS_AUTH_URL") username := os.Getenv("OS_USERNAME") @@ -30,16 +31,17 @@ func AuthOptionsFromEnv() (gophercloud.AuthOptions, error) { tenantName := os.Getenv("OS_TENANT_NAME") domainID := os.Getenv("OS_DOMAIN_ID") domainName := os.Getenv("OS_DOMAIN_NAME") + tokenID := os.Getenv("OS_TOKEN") if authURL == "" { return nilOptions, ErrNoAuthURL } - if username == "" && userID == "" { + if username == "" && userID == "" && tokenID == "" { return nilOptions, ErrNoUsername } - if password == "" { + if password == "" && tokenID == "" { return nilOptions, ErrNoPassword } @@ -52,6 +54,7 @@ func AuthOptionsFromEnv() (gophercloud.AuthOptions, error) { TenantName: tenantName, DomainID: domainID, DomainName: domainName, + TokenID: tokenID, } return ao, nil diff --git a/vendor/github.com/rackspace/gophercloud/openstack/client.go b/vendor/github.com/rackspace/gophercloud/openstack/client.go index b533e834e50..a323e9b2caf 100644 --- a/vendor/github.com/rackspace/gophercloud/openstack/client.go +++ b/vendor/github.com/rackspace/gophercloud/openstack/client.go @@ -3,6 +3,7 @@ package openstack import ( "fmt" "net/url" + "strconv" "strings" "github.com/rackspace/gophercloud" @@ -25,18 +26,40 @@ func NewClient(endpoint string) (*gophercloud.ProviderClient, error) { if err != nil { return nil, err } - hadPath := u.Path != "" - u.Path, u.RawQuery, u.Fragment = "", "", "" - base := u.String() + u.RawQuery, u.Fragment = "", "" + + // Base is url with path endpoint = gophercloud.NormalizeURL(endpoint) - base = gophercloud.NormalizeURL(base) + base := gophercloud.NormalizeURL(u.String()) - if hadPath { - return &gophercloud.ProviderClient{ - IdentityBase: base, - IdentityEndpoint: endpoint, - }, nil + path := u.Path + if !strings.HasSuffix(path, "/") { + path = path + "/" + } + + parts := strings.Split(path[0:len(path)-1], "/") + for index, version := range parts { + if 2 <= len(version) && len(version) <= 4 && strings.HasPrefix(version, "v") { + _, err := strconv.ParseFloat(version[1:], 64) + if err == nil { + // post version suffixes in path are not supported + // version must be on the last index + if index < len(parts)-1 { + return nil, fmt.Errorf("Path suffixes (after version) are not supported.") + } + switch version { + case "v2.0", "v3": + // valid version found, strip from base + return &gophercloud.ProviderClient{ + IdentityBase: base[0 : len(base)-len(version)-1], + IdentityEndpoint: endpoint, + }, nil + default: + return nil, fmt.Errorf("Invalid identity endpoint version %v. Supported versions: v2.0, v3", version) + } + } + } } return &gophercloud.ProviderClient{ @@ -156,7 +179,7 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, options gopherc } } - result := tokens3.Create(v3Client, v3Options, scope) + result := tokens3.Create(v3Client, tokens3.AuthOptions{AuthOptions: v3Options}, scope) token, err := result.ExtractToken() if err != nil { @@ -283,25 +306,12 @@ func NewBlockStorageV1(client *gophercloud.ProviderClient, eo gophercloud.Endpoi // NewBlockStorageV2 creates a ServiceClient that may be used to access the v2 block storage service. func NewBlockStorageV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { - eo.ApplyDefaults("volume") + eo.ApplyDefaults("volumev2") url, err := client.EndpointLocator(eo) if err != nil { return nil, err } - - // Force using v2 API - if strings.Contains(url, "/v1") { - url = strings.Replace(url, "/v1", "/v2", -1) - } - if !strings.Contains(url, "/v2") { - return nil, fmt.Errorf("Block Storage v2 endpoint not found") - } - - return &gophercloud.ServiceClient{ - ProviderClient: client, - Endpoint: url, - ResourceBase: url, - }, nil + return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil } // NewCDNV1 creates a ServiceClient that may be used to access the OpenStack v1 @@ -334,3 +344,25 @@ func NewDBV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (* } return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil } + +// NewImageServiceV2 creates a ServiceClient that may be used to access the v2 image service. +func NewImageServiceV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { + eo.ApplyDefaults("image") + url, err := client.EndpointLocator(eo) + if err != nil { + return nil, err + } + return &gophercloud.ServiceClient{ProviderClient: client, + Endpoint: url, + ResourceBase: url + "v2/"}, nil +} + +// NewTelemetryV2 creates a ServiceClient that may be used to access the v2 telemetry service. +func NewTelemetryV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { + eo.ApplyDefaults("metering") + url, err := client.EndpointLocator(eo) + if err != nil { + return nil, err + } + return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/requests.go index dceff3d87eb..a15c98d39bc 100644 --- a/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/requests.go +++ b/vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/requests.go @@ -79,7 +79,9 @@ func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) { blockDevice[i]["source_type"] = bd.SourceType blockDevice[i]["boot_index"] = strconv.Itoa(bd.BootIndex) blockDevice[i]["delete_on_termination"] = strconv.FormatBool(bd.DeleteOnTermination) - blockDevice[i]["volume_size"] = strconv.Itoa(bd.VolumeSize) + if bd.VolumeSize > 0 { + blockDevice[i]["volume_size"] = strconv.Itoa(bd.VolumeSize) + } if bd.UUID != "" { blockDevice[i]["uuid"] = bd.UUID } diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/extensions/trust/request.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/extensions/trust/request.go new file mode 100644 index 00000000000..89469e1c950 --- /dev/null +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/extensions/trust/request.go @@ -0,0 +1,83 @@ +package trust + +import ( + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/openstack" + token3 "github.com/rackspace/gophercloud/openstack/identity/v3/tokens" +) + +type AuthOptionsExt struct { + token3.AuthOptions + TrustID string +} + +func (ao AuthOptionsExt) ToAuthOptionsV3Map(c *gophercloud.ServiceClient, scope *token3.Scope) (map[string]interface{}, error) { + //Passing scope value to nil to add scope later in this function. + authMap, err := ao.AuthOptions.ToAuthOptionsV3Map(c, nil) + if err != nil { + return nil, err + } + authMap = authMap["auth"].(map[string]interface{}) + + // Add a "scope" element if a Scope has been provided. + if ao.TrustID != "" { + // TrustID provided. + authMap["scope"] = map[string]interface{}{ + "OS-TRUST:trust": map[string]interface{}{ + "id": ao.TrustID, + }, + } + } else { + return nil, token3.ErrScopeEmpty + } + return map[string]interface{}{"auth": authMap}, nil +} + +// AuthenticateV3 explicitly authenticates against the identity v3 service. +func AuthenticateV3Trust(client *gophercloud.ProviderClient, options AuthOptionsExt) error { + return trustv3auth(client, "", options) +} + +func trustv3auth(client *gophercloud.ProviderClient, endpoint string, options AuthOptionsExt) error { + //In case of Trust TokenId would be Provided so we have to populate the value in service client + //to not throw password error,also if it is not provided it will be empty which maintains + //the current implementation. + client.TokenID = options.AuthOptions.TokenID + // Override the generated service endpoint with the one returned by the version endpoint. + v3Client := openstack.NewIdentityV3(client) + if endpoint != "" { + v3Client.Endpoint = endpoint + } + + // copy the auth options to a local variable that we can change. `options` + // needs to stay as-is for reauth purposes + v3Options := options + + var scope *token3.Scope + + result := token3.Create(v3Client, v3Options, scope) + + token, err := result.ExtractToken() + if err != nil { + return err + } + + catalog, err := result.ExtractServiceCatalog() + if err != nil { + return err + } + + client.TokenID = token.ID + + if options.AuthOptions.AllowReauth { + client.ReauthFunc = func() error { + client.TokenID = "" + return trustv3auth(client, endpoint, options) + } + } + client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) { + return openstack.V3EndpointURL(catalog, opts) + } + + return nil +} diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/errors.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/errors.go index 44761092bb9..a9e1d5c2f5c 100644 --- a/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/errors.go +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/errors.go @@ -52,8 +52,8 @@ var ( // It may also indicate that both a DomainID and a DomainName were provided at once. ErrDomainIDOrDomainName = errors.New("You must provide exactly one of DomainID or DomainName to authenticate by Username") - // ErrMissingPassword indicates that no password was provided and no token is available. - ErrMissingPassword = errors.New("You must provide a password to authenticate") + // ErrMissingPassword indicates that no password and no token were provided and no token is available. + ErrMissingPassword = errors.New("You must provide a password or a token to authenticate") // ErrScopeDomainIDOrDomainName indicates that a domain ID or Name was required in a Scope, but not present. ErrScopeDomainIDOrDomainName = errors.New("You must provide exactly one of DomainID or DomainName in a Scope with ProjectName") diff --git a/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/requests.go b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/requests.go index d63b1bb51f7..b32e694da81 100644 --- a/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/requests.go +++ b/vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/requests.go @@ -20,155 +20,142 @@ func subjectTokenHeaders(c *gophercloud.ServiceClient, subjectToken string) map[ } } -// Create authenticates and either generates a new token, or changes the Scope of an existing token. -func Create(c *gophercloud.ServiceClient, options gophercloud.AuthOptions, scope *Scope) CreateResult { - type domainReq struct { - ID *string `json:"id,omitempty"` - Name *string `json:"name,omitempty"` - } +// AuthOptionsV3er describes any argument that may be passed to the Create call. +type AuthOptionsV3er interface { - type projectReq struct { - Domain *domainReq `json:"domain,omitempty"` - Name *string `json:"name,omitempty"` - ID *string `json:"id,omitempty"` - } + // ToTokenCreateMap assembles the Create request body, returning an error if parameters are + // missing or inconsistent. + ToAuthOptionsV3Map(c *gophercloud.ServiceClient, scope *Scope) (map[string]interface{}, error) +} - type userReq struct { - ID *string `json:"id,omitempty"` - Name *string `json:"name,omitempty"` - Password string `json:"password"` - Domain *domainReq `json:"domain,omitempty"` - } +// AuthOptions wraps a gophercloud AuthOptions in order to adhere to the AuthOptionsV3er +// interface. +type AuthOptions struct { + gophercloud.AuthOptions +} - type passwordReq struct { - User userReq `json:"user"` - } - - type tokenReq struct { - ID string `json:"id"` - } - - type identityReq struct { - Methods []string `json:"methods"` - Password *passwordReq `json:"password,omitempty"` - Token *tokenReq `json:"token,omitempty"` - } - - type scopeReq struct { - Domain *domainReq `json:"domain,omitempty"` - Project *projectReq `json:"project,omitempty"` - } - - type authReq struct { - Identity identityReq `json:"identity"` - Scope *scopeReq `json:"scope,omitempty"` - } - - type request struct { - Auth authReq `json:"auth"` - } +func (options AuthOptions) ToAuthOptionsV3Map(c *gophercloud.ServiceClient, scope *Scope) (map[string]interface{}, error) { + // tokens3.Create logic // Populate the request structure based on the provided arguments. Create and return an error // if insufficient or incompatible information is present. - var req request + authMap := make(map[string]interface{}) // Test first for unrecognized arguments. if options.APIKey != "" { - return createErr(ErrAPIKeyProvided) + return nil, ErrAPIKeyProvided } if options.TenantID != "" { - return createErr(ErrTenantIDProvided) + return nil, ErrTenantIDProvided } if options.TenantName != "" { - return createErr(ErrTenantNameProvided) + return nil, ErrTenantNameProvided } if options.Password == "" { + if options.TokenID != "" { + c.TokenID = options.TokenID + } if c.TokenID != "" { // Because we aren't using password authentication, it's an error to also provide any of the user-based authentication // parameters. if options.Username != "" { - return createErr(ErrUsernameWithToken) + return nil, ErrUsernameWithToken } if options.UserID != "" { - return createErr(ErrUserIDWithToken) - } - if options.DomainID != "" { - return createErr(ErrDomainIDWithToken) - } - if options.DomainName != "" { - return createErr(ErrDomainNameWithToken) + return nil, ErrUserIDWithToken } // Configure the request for Token authentication. - req.Auth.Identity.Methods = []string{"token"} - req.Auth.Identity.Token = &tokenReq{ - ID: c.TokenID, + authMap["identity"] = map[string]interface{}{ + "methods": []string{"token"}, + "token": map[string]interface{}{ + "id": c.TokenID, + }, } + } else { // If no password or token ID are available, authentication can't continue. - return createErr(ErrMissingPassword) + return nil, ErrMissingPassword } } else { // Password authentication. - req.Auth.Identity.Methods = []string{"password"} // At least one of Username and UserID must be specified. if options.Username == "" && options.UserID == "" { - return createErr(ErrUsernameOrUserID) + return nil, ErrUsernameOrUserID } if options.Username != "" { // If Username is provided, UserID may not be provided. if options.UserID != "" { - return createErr(ErrUsernameOrUserID) + return nil, ErrUsernameOrUserID } // Either DomainID or DomainName must also be specified. if options.DomainID == "" && options.DomainName == "" { - return createErr(ErrDomainIDOrDomainName) + return nil, ErrDomainIDOrDomainName } if options.DomainID != "" { if options.DomainName != "" { - return createErr(ErrDomainIDOrDomainName) + return nil, ErrDomainIDOrDomainName } // Configure the request for Username and Password authentication with a DomainID. - req.Auth.Identity.Password = &passwordReq{ - User: userReq{ - Name: &options.Username, - Password: options.Password, - Domain: &domainReq{ID: &options.DomainID}, + authMap["identity"] = map[string]interface{}{ + "methods": []string{"password"}, + "password" : map[string]interface{}{ + "user": map[string]interface{}{ + "name": &options.Username, + "password": options.Password, + "domain": map[string]interface{}{ + "id": &options.DomainID, + }, + }, }, } + } if options.DomainName != "" { // Configure the request for Username and Password authentication with a DomainName. - req.Auth.Identity.Password = &passwordReq{ - User: userReq{ - Name: &options.Username, - Password: options.Password, - Domain: &domainReq{Name: &options.DomainName}, - }, - } + authMap["identity"] = map[string]interface{}{ + "methods": []string{"password"}, + "password": map[string]interface{}{ + "user": map[string]interface{}{ + "name": &options.Username, + "password": options.Password, + "domain": map[string]interface{}{ + "name": &options.DomainName, + }, + }, + }, + } + } } if options.UserID != "" { // If UserID is specified, neither DomainID nor DomainName may be. if options.DomainID != "" { - return createErr(ErrDomainIDWithUserID) + return nil, ErrDomainIDWithUserID } if options.DomainName != "" { - return createErr(ErrDomainNameWithUserID) + return nil, ErrDomainNameWithUserID } // Configure the request for UserID and Password authentication. - req.Auth.Identity.Password = &passwordReq{ - User: userReq{ID: &options.UserID, Password: options.Password}, + authMap["identity"] = map[string]interface{}{ + "methods": []string{"password"}, + "password" : map[string]interface{}{ + "user": map[string]interface{}{ + "id": &options.UserID, + "password": options.Password, + }, + }, } + } } @@ -178,64 +165,81 @@ func Create(c *gophercloud.ServiceClient, options gophercloud.AuthOptions, scope // ProjectName provided: either DomainID or DomainName must also be supplied. // ProjectID may not be supplied. if scope.DomainID == "" && scope.DomainName == "" { - return createErr(ErrScopeDomainIDOrDomainName) + return nil, ErrScopeDomainIDOrDomainName } if scope.ProjectID != "" { - return createErr(ErrScopeProjectIDOrProjectName) + return nil, ErrScopeProjectIDOrProjectName } if scope.DomainID != "" { // ProjectName + DomainID - req.Auth.Scope = &scopeReq{ - Project: &projectReq{ - Name: &scope.ProjectName, - Domain: &domainReq{ID: &scope.DomainID}, - }, + authMap["scope"] = map[string]interface{}{ + "project": map[string]interface{}{ + "domain": map[string]interface{}{ + "id": &scope.DomainID, + }, + "name": &scope.ProjectName, + }, } } if scope.DomainName != "" { // ProjectName + DomainName - req.Auth.Scope = &scopeReq{ - Project: &projectReq{ - Name: &scope.ProjectName, - Domain: &domainReq{Name: &scope.DomainName}, - }, + authMap["scope"] = map[string]interface{}{ + "project": map[string]interface{}{ + "domain": map[string]interface{}{ + "name": &scope.DomainName, + }, + "name": &scope.ProjectName, + }, } } } else if scope.ProjectID != "" { // ProjectID provided. ProjectName, DomainID, and DomainName may not be provided. if scope.DomainID != "" { - return createErr(ErrScopeProjectIDAlone) + return nil, ErrScopeProjectIDAlone } if scope.DomainName != "" { - return createErr(ErrScopeProjectIDAlone) + return nil, ErrScopeProjectIDAlone } // ProjectID - req.Auth.Scope = &scopeReq{ - Project: &projectReq{ID: &scope.ProjectID}, + authMap["scope"] = map[string]interface{}{ + "project": map[string]interface{}{ + "id": &scope.ProjectID, + }, } } else if scope.DomainID != "" { // DomainID provided. ProjectID, ProjectName, and DomainName may not be provided. if scope.DomainName != "" { - return createErr(ErrScopeDomainIDOrDomainName) + return nil, ErrScopeDomainIDOrDomainName } // DomainID - req.Auth.Scope = &scopeReq{ - Domain: &domainReq{ID: &scope.DomainID}, + authMap["scope"] = map[string]interface{}{ + "domain": map[string]interface{}{ + "id": &scope.DomainID, + }, } } else if scope.DomainName != "" { - return createErr(ErrScopeDomainName) + return nil, ErrScopeDomainName } else { - return createErr(ErrScopeEmpty) + return nil, ErrScopeEmpty } } + return map[string]interface{}{"auth": authMap}, nil +} + +// Create authenticates and either generates a new token, or changes the Scope of an existing token. +func Create(c *gophercloud.ServiceClient, options AuthOptionsV3er, scope *Scope) CreateResult { + request, err := options.ToAuthOptionsV3Map(c, scope) + if err != nil { + return CreateResult{commonResult{gophercloud.Result{Err: err}}} + } var result CreateResult var response *http.Response - response, result.Err = c.Post(tokenURL(c), req, &result.Body, nil) + response, result.Err = c.Post(tokenURL(c), request, &result.Body, nil) if result.Err != nil { return result } diff --git a/vendor/github.com/rackspace/gophercloud/provider_client.go b/vendor/github.com/rackspace/gophercloud/provider_client.go index 53fce73705b..08fd0ca84f5 100644 --- a/vendor/github.com/rackspace/gophercloud/provider_client.go +++ b/vendor/github.com/rackspace/gophercloud/provider_client.go @@ -102,6 +102,14 @@ type RequestOpts struct { MoreHeaders map[string]string } +func (opts *RequestOpts) setBody(body interface{}) { + if v, ok := (body).(io.ReadSeeker); ok { + opts.RawBody = v + } else if body != nil { + opts.JSONBody = body + } +} + // UnexpectedResponseCodeError is returned by the Request method when a response code other than // those listed in OkCodes is encountered. type UnexpectedResponseCodeError struct { @@ -268,16 +276,12 @@ func (client *ProviderClient) Get(url string, JSONResponse *interface{}, opts *R return client.Request("GET", url, *opts) } -func (client *ProviderClient) Post(url string, JSONBody interface{}, JSONResponse *interface{}, opts *RequestOpts) (*http.Response, error) { +func (client *ProviderClient) Post(url string, body interface{}, JSONResponse *interface{}, opts *RequestOpts) (*http.Response, error) { if opts == nil { opts = &RequestOpts{} } - if v, ok := (JSONBody).(io.ReadSeeker); ok { - opts.RawBody = v - } else if JSONBody != nil { - opts.JSONBody = JSONBody - } + opts.setBody(body) if JSONResponse != nil { opts.JSONResponse = JSONResponse @@ -286,16 +290,12 @@ func (client *ProviderClient) Post(url string, JSONBody interface{}, JSONRespons return client.Request("POST", url, *opts) } -func (client *ProviderClient) Put(url string, JSONBody interface{}, JSONResponse *interface{}, opts *RequestOpts) (*http.Response, error) { +func (client *ProviderClient) Put(url string, body interface{}, JSONResponse *interface{}, opts *RequestOpts) (*http.Response, error) { if opts == nil { opts = &RequestOpts{} } - if v, ok := (JSONBody).(io.ReadSeeker); ok { - opts.RawBody = v - } else if JSONBody != nil { - opts.JSONBody = JSONBody - } + opts.setBody(body) if JSONResponse != nil { opts.JSONResponse = JSONResponse diff --git a/vendor/github.com/rackspace/gophercloud/testhelper/convenience.go b/vendor/github.com/rackspace/gophercloud/testhelper/convenience.go index cf33e1ad1a6..f5659172ea7 100644 --- a/vendor/github.com/rackspace/gophercloud/testhelper/convenience.go +++ b/vendor/github.com/rackspace/gophercloud/testhelper/convenience.go @@ -1,6 +1,7 @@ package testhelper import ( + "bytes" "encoding/json" "fmt" "path/filepath" @@ -224,6 +225,21 @@ func CheckEquals(t *testing.T, expected, actual interface{}) { } } +// AssertErr is a convenience function for checking that an error occurred +func AssertErr(t *testing.T, e error) { + if e == nil { + logFatal(t, fmt.Sprintf("expected an error but none occurred")) + } +} + +// CheckErr is a convenience function for checking that an error occurred, +// except with a non-fatal error +func CheckErr(t *testing.T, e error) { + if e == nil { + logError(t, fmt.Sprintf("expected an error but none occurred")) + } +} + // AssertDeepEquals - like Equals - performs a comparison - but on more complex // structures that requires deeper inspection func AssertDeepEquals(t *testing.T, expected, actual interface{}) { @@ -256,6 +272,24 @@ func CheckDeepEquals(t *testing.T, expected, actual interface{}) { }) } +func isByteArrayEquals(t *testing.T, expectedBytes []byte, actualBytes []byte) bool { + return bytes.Equal(expectedBytes, actualBytes) +} + +// AssertByteArrayEquals a convenience function for checking whether two byte arrays are equal +func AssertByteArrayEquals(t *testing.T, expectedBytes []byte, actualBytes []byte) { + if !isByteArrayEquals(t, expectedBytes, actualBytes) { + logFatal(t, "The bytes differed.") + } +} + +// CheckByteArrayEquals a convenience function for silent checking whether two byte arrays are equal +func CheckByteArrayEquals(t *testing.T, expectedBytes []byte, actualBytes []byte) { + if !isByteArrayEquals(t, expectedBytes, actualBytes) { + logError(t, "The bytes differed.") + } +} + // isJSONEquals is a utility function that implements JSON comparison for AssertJSONEquals and // CheckJSONEquals. func isJSONEquals(t *testing.T, expectedJSON string, actual interface{}) bool { @@ -321,6 +355,13 @@ func AssertNoErr(t *testing.T, e error) { } } +// AssertNotNil is a convenience function for checking whether given value is not nil +func AssertNotNil(t *testing.T, actual interface{}) { + if actual == nil || !reflect.ValueOf(actual).Elem().IsValid() { + logFatal(t, fmt.Sprintf("Not nil expexted, but was %v", actual)) + } +} + // CheckNoErr is similar to AssertNoErr, except with a non-fatal error func CheckNoErr(t *testing.T, e error) { if e != nil {