mirror of https://github.com/k3s-io/k3s
Merge pull request #73437 from dims/update-to-latest-gophercloud
Update to latest gophercloudpull/564/head
commit
35b09e5370
|
@ -2101,123 +2101,127 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/common/extensions",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/flavors",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/images",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/servers",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/trusts",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/l7policies",
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/networks",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/ports",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/utils",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/pagination",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gorilla/websocket",
|
||||
|
|
|
@ -65927,6 +65927,205 @@ specific language governing permissions and limitations under the License.
|
|||
================================================================================
|
||||
|
||||
|
||||
================================================================================
|
||||
= vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/l7policies 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/gophercloud/gophercloud/LICENSE dd19699707373c2ca31531a659130416
|
||||
================================================================================
|
||||
|
||||
|
||||
================================================================================
|
||||
= vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners licensed under: =
|
||||
|
||||
|
|
|
@ -256,7 +256,7 @@ func (volumes *VolumesV1) deleteVolume(volumeID string) error {
|
|||
|
||||
func (volumes *VolumesV2) deleteVolume(volumeID string) error {
|
||||
startTime := time.Now()
|
||||
err := volumes_v2.Delete(volumes.blockstorage, volumeID).ExtractErr()
|
||||
err := volumes_v2.Delete(volumes.blockstorage, volumeID, nil).ExtractErr()
|
||||
timeTaken := time.Since(startTime).Seconds()
|
||||
recordOpenstackOperationMetric("delete_v2_volume", timeTaken, err)
|
||||
return err
|
||||
|
@ -264,7 +264,7 @@ func (volumes *VolumesV2) deleteVolume(volumeID string) error {
|
|||
|
||||
func (volumes *VolumesV3) deleteVolume(volumeID string) error {
|
||||
startTime := time.Now()
|
||||
err := volumes_v3.Delete(volumes.blockstorage, volumeID).ExtractErr()
|
||||
err := volumes_v3.Delete(volumes.blockstorage, volumeID, nil).ExtractErr()
|
||||
timeTaken := time.Since(startTime).Seconds()
|
||||
recordOpenstackOperationMetric("delete_v3_volume", timeTaken, err)
|
||||
return err
|
||||
|
|
|
@ -112,31 +112,31 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/utils",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/pagination",
|
||||
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
|
||||
"Rev": "c818fa66e4c88b30db28038fe3f18f2f4a0db9a8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gregjones/httpcache",
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
**/*.swp
|
||||
.idea
|
||||
.vscode
|
||||
|
|
|
@ -7,8 +7,8 @@ install:
|
|||
- go get github.com/mattn/goveralls
|
||||
- go get golang.org/x/tools/cmd/goimports
|
||||
go:
|
||||
- 1.8
|
||||
- tip
|
||||
- "1.10"
|
||||
- "tip"
|
||||
env:
|
||||
global:
|
||||
- secure: "xSQsAG5wlL9emjbCdxzz/hYQsSpJ/bABO1kkbwMSISVcJ3Nk0u4ywF+LS4bgeOnwPfmFvNTOqVDu3RwEvMeWXSI76t1piCPcObutb2faKLVD/hLoAS76gYX+Z8yGWGHrSB7Do5vTPj1ERe2UljdrnsSeOXzoDwFxYRaZLX4bBOB4AyoGvRniil5QXPATiA1tsWX1VMicj8a4F8X+xeESzjt1Q5Iy31e7vkptu71bhvXCaoo5QhYwT+pLR9dN0S1b7Ro0KVvkRefmr1lUOSYd2e74h6Lc34tC1h3uYZCS4h47t7v5cOXvMNxinEj2C51RvbjvZI1RLVdkuAEJD1Iz4+Ote46nXbZ//6XRZMZz/YxQ13l7ux1PFjgEB6HAapmF5Xd8PRsgeTU9LRJxpiTJ3P5QJ3leS1va8qnziM5kYipj/Rn+V8g2ad/rgkRox9LSiR9VYZD2Pe45YCb1mTKSl2aIJnV7nkOqsShY5LNB4JZSg7xIffA+9YVDktw8dJlATjZqt7WvJJ49g6A61mIUV4C15q2JPGKTkZzDiG81NtmS7hFa7k0yaE2ELgYocbcuyUcAahhxntYTC0i23nJmEHVNiZmBO3u7EgpWe4KGVfumU+lt12tIn5b3dZRBBUk3QakKKozSK1QPHGpk/AZGrhu7H6l8to6IICKWtDcyMPQ="
|
||||
|
|
|
@ -1,3 +1,73 @@
|
|||
- 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-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-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-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:
|
||||
|
@ -7,6 +77,22 @@
|
|||
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
|
||||
periodic:
|
||||
jobs:
|
||||
- gophercloud-unittest
|
||||
- gophercloud-acceptance-test
|
||||
|
|
|
@ -1,148 +0,0 @@
|
|||
# Tips
|
||||
|
||||
## Implementing default logging and re-authentication attempts
|
||||
|
||||
You can implement custom logging and/or limit re-auth attempts by creating a custom HTTP client
|
||||
like the following and setting it as the provider client's HTTP Client (via the
|
||||
`gophercloud.ProviderClient.HTTPClient` field):
|
||||
|
||||
```go
|
||||
//...
|
||||
|
||||
// LogRoundTripper satisfies the http.RoundTripper interface and is used to
|
||||
// customize the default Gophercloud RoundTripper to allow for logging.
|
||||
type LogRoundTripper struct {
|
||||
rt http.RoundTripper
|
||||
numReauthAttempts int
|
||||
}
|
||||
|
||||
// newHTTPClient return a custom HTTP client that allows for logging relevant
|
||||
// information before and after the HTTP request.
|
||||
func newHTTPClient() http.Client {
|
||||
return http.Client{
|
||||
Transport: &LogRoundTripper{
|
||||
rt: http.DefaultTransport,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// RoundTrip performs a round-trip HTTP request and logs relevant information about it.
|
||||
func (lrt *LogRoundTripper) RoundTrip(request *http.Request) (*http.Response, error) {
|
||||
glog.Infof("Request URL: %s\n", request.URL)
|
||||
|
||||
response, err := lrt.rt.RoundTrip(request)
|
||||
if response == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if response.StatusCode == http.StatusUnauthorized {
|
||||
if lrt.numReauthAttempts == 3 {
|
||||
return response, fmt.Errorf("Tried to re-authenticate 3 times with no success.")
|
||||
}
|
||||
lrt.numReauthAttempts++
|
||||
}
|
||||
|
||||
glog.Debugf("Response Status: %s\n", response.Status)
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
endpoint := "https://127.0.0.1/auth"
|
||||
pc := openstack.NewClient(endpoint)
|
||||
pc.HTTPClient = newHTTPClient()
|
||||
|
||||
//...
|
||||
```
|
||||
|
||||
|
||||
## Implementing custom objects
|
||||
|
||||
OpenStack request/response objects may differ among variable names or types.
|
||||
|
||||
### Custom request objects
|
||||
|
||||
To pass custom options to a request, implement the desired `<ACTION>OptsBuilder` interface. For
|
||||
example, to pass in
|
||||
|
||||
```go
|
||||
type MyCreateServerOpts struct {
|
||||
Name string
|
||||
Size int
|
||||
}
|
||||
```
|
||||
|
||||
to `servers.Create`, simply implement the `servers.CreateOptsBuilder` interface:
|
||||
|
||||
```go
|
||||
func (o MyCreateServeropts) ToServerCreateMap() (map[string]interface{}, error) {
|
||||
return map[string]interface{}{
|
||||
"name": o.Name,
|
||||
"size": o.Size,
|
||||
}, nil
|
||||
}
|
||||
```
|
||||
|
||||
create an instance of your custom options object, and pass it to `servers.Create`:
|
||||
|
||||
```go
|
||||
// ...
|
||||
myOpts := MyCreateServerOpts{
|
||||
Name: "s1",
|
||||
Size: "100",
|
||||
}
|
||||
server, err := servers.Create(computeClient, myOpts).Extract()
|
||||
// ...
|
||||
```
|
||||
|
||||
### Custom response objects
|
||||
|
||||
Some OpenStack services have extensions. Extensions that are supported in Gophercloud can be
|
||||
combined to create a custom object:
|
||||
|
||||
```go
|
||||
// ...
|
||||
type MyVolume struct {
|
||||
volumes.Volume
|
||||
tenantattr.VolumeExt
|
||||
}
|
||||
|
||||
var v struct {
|
||||
MyVolume `json:"volume"`
|
||||
}
|
||||
|
||||
err := volumes.Get(client, volID).ExtractInto(&v)
|
||||
// ...
|
||||
```
|
||||
|
||||
## Overriding default `UnmarshalJSON` method
|
||||
|
||||
For some response objects, a field may be a custom type or may be allowed to take on
|
||||
different types. In these cases, overriding the default `UnmarshalJSON` method may be
|
||||
necessary. To do this, declare the JSON `struct` field tag as "-" and create an `UnmarshalJSON`
|
||||
method on the type:
|
||||
|
||||
```go
|
||||
// ...
|
||||
type MyVolume struct {
|
||||
ID string `json: "id"`
|
||||
TimeCreated time.Time `json: "-"`
|
||||
}
|
||||
|
||||
func (r *MyVolume) UnmarshalJSON(b []byte) error {
|
||||
type tmp MyVolume
|
||||
var s struct {
|
||||
tmp
|
||||
TimeCreated gophercloud.JSONRFC3339MilliNoZ `json:"created_at"`
|
||||
}
|
||||
err := json.Unmarshal(b, &s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*r = Volume(s.tmp)
|
||||
|
||||
r.TimeCreated = time.Time(s.CreatedAt)
|
||||
|
||||
return err
|
||||
}
|
||||
// ...
|
||||
```
|
|
@ -1,32 +0,0 @@
|
|||
# Compute
|
||||
|
||||
## Floating IPs
|
||||
|
||||
* `github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/floatingip` is now `github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/floatingips`
|
||||
* `floatingips.Associate` and `floatingips.Disassociate` have been removed.
|
||||
* `floatingips.DisassociateOpts` is now required to disassociate a Floating IP.
|
||||
|
||||
## Security Groups
|
||||
|
||||
* `secgroups.AddServerToGroup` is now `secgroups.AddServer`.
|
||||
* `secgroups.RemoveServerFromGroup` is now `secgroups.RemoveServer`.
|
||||
|
||||
## Servers
|
||||
|
||||
* `servers.Reboot` now requires a `servers.RebootOpts` struct:
|
||||
|
||||
```golang
|
||||
rebootOpts := &servers.RebootOpts{
|
||||
Type: servers.SoftReboot,
|
||||
}
|
||||
res := servers.Reboot(client, server.ID, rebootOpts)
|
||||
```
|
||||
|
||||
# Identity
|
||||
|
||||
## V3
|
||||
|
||||
### Tokens
|
||||
|
||||
* `Token.ExpiresAt` is now of type `gophercloud.JSONRFC3339Milli` instead of
|
||||
`time.Time`
|
|
@ -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,7 +140,7 @@ 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
|
||||
|
||||
|
@ -148,12 +148,12 @@ We'd like to extend special thanks and appreciation to the following:
|
|||
|
||||
### OpenLab
|
||||
|
||||
<a href="http://openlabtesting.org/"><img src="assets/openlab.png" width="600px"></a>
|
||||
<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="assets/vexxhost.png" width="600px"></a>
|
||||
<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.
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
|
||||
## On Pull Requests
|
||||
|
||||
- Please make sure to read our [contributing guide](/.github/CONTRIBUTING.md).
|
||||
|
||||
- Before you start a PR there needs to be a Github issue and a discussion about it
|
||||
on that issue with a core contributor, even if it's just a 'SGTM'.
|
||||
|
||||
- A PR's description must reference the issue it closes with a `For <ISSUE NUMBER>` (e.g. For #293).
|
||||
|
||||
- A PR's description must contain link(s) to the line(s) in the OpenStack
|
||||
source code (on Github) that prove(s) the PR code to be valid. Links to documentation
|
||||
are not good enough. The link(s) should be to a non-`master` branch. For example,
|
||||
a pull request implementing the creation of a Neutron v2 subnet might put the
|
||||
following link in the description:
|
||||
|
||||
https://github.com/openstack/neutron/blob/stable/mitaka/neutron/api/v2/attributes.py#L749
|
||||
|
||||
From that link, a reviewer (or user) can verify the fields in the request/response
|
||||
objects in the PR.
|
||||
|
||||
- A PR that is in-progress should have `[wip]` in front of the PR's title. When
|
||||
ready for review, remove the `[wip]` and ping a core contributor with an `@`.
|
||||
|
||||
- Forcing PRs to be small can have the effect of users submitting PRs in a hierarchical chain, with
|
||||
one depending on the next. If a PR depends on another one, it should have a [Pending #PRNUM]
|
||||
prefix in the PR title. In addition, it will be the PR submitter's responsibility to remove the
|
||||
[Pending #PRNUM] tag once the PR has been updated with the merged, dependent PR. That will
|
||||
let reviewers know it is ready to review.
|
||||
|
||||
- A PR should be small. Even if you intend on implementing an entire
|
||||
service, a PR should only be one route of that service
|
||||
(e.g. create server or get server, but not both).
|
||||
|
||||
- Unless explicitly asked, do not squash commits in the middle of a review; only
|
||||
append. It makes it difficult for the reviewer to see what's changed from one
|
||||
review to the next.
|
||||
|
||||
- See [#583](https://github.com/gophercloud/gophercloud/issues/583) as an example of a
|
||||
well-formatted issue which contains all relevant information we need to review and approve.
|
||||
|
||||
## On Code
|
||||
|
||||
- In re design: follow as closely as is reasonable the code already in the library.
|
||||
Most operations (e.g. create, delete) admit the same design.
|
||||
|
||||
- Unit tests and acceptance (integration) tests must be written to cover each PR.
|
||||
Tests for operations with several options (e.g. list, create) should include all
|
||||
the options in the tests. This will allow users to verify an operation on their
|
||||
own infrastructure and see an example of usage.
|
||||
|
||||
- If in doubt, ask in-line on the PR.
|
||||
|
||||
### File Structure
|
||||
|
||||
- The following should be used in most cases:
|
||||
|
||||
- `requests.go`: contains all the functions that make HTTP requests and the
|
||||
types associated with the HTTP request (parameters for URL, body, etc)
|
||||
- `results.go`: contains all the response objects and their methods
|
||||
- `urls.go`: contains the endpoints to which the requests are made
|
||||
|
||||
### Naming
|
||||
|
||||
- For methods on a type in `results.go`, the receiver should be named `r` and the
|
||||
variable into which it will be unmarshalled `s`.
|
||||
|
||||
- Functions in `requests.go`, with the exception of functions that return a
|
||||
`pagination.Pager`, should be named returns of the name `r`.
|
||||
|
||||
- Functions in `requests.go` that accept request bodies should accept as their
|
||||
last parameter an `interface` named `<Action>OptsBuilder` (eg `CreateOptsBuilder`).
|
||||
This `interface` should have at the least a method named `To<Resource><Action>Map`
|
||||
(eg `ToPortCreateMap`).
|
||||
|
||||
- Functions in `requests.go` that accept query strings should accept as their
|
||||
last parameter an `interface` named `<Action>OptsBuilder` (eg `ListOptsBuilder`).
|
||||
This `interface` should have at the least a method named `To<Resource><Action>Query`
|
||||
(eg `ToServerListQuery`).
|
|
@ -81,6 +81,23 @@ type AuthOptions struct {
|
|||
// TokenID allows users to authenticate (possibly as another user) with an
|
||||
// authentication token ID.
|
||||
TokenID string `json:"-"`
|
||||
|
||||
// Scope determines the scoping of the authentication request.
|
||||
Scope *AuthScope `json:"-"`
|
||||
|
||||
// Authentication through Application Credentials requires supplying name, project and secret
|
||||
// For project we can use TenantID
|
||||
ApplicationCredentialID string `json:"-"`
|
||||
ApplicationCredentialName string `json:"-"`
|
||||
ApplicationCredentialSecret string `json:"-"`
|
||||
}
|
||||
|
||||
// AuthScope allows a created token to be limited to a specific domain or project.
|
||||
type AuthScope struct {
|
||||
ProjectID string
|
||||
ProjectName string
|
||||
DomainID string
|
||||
DomainName string
|
||||
}
|
||||
|
||||
// ToTokenV2CreateMap allows AuthOptions to satisfy the AuthOptionsBuilder
|
||||
|
@ -131,7 +148,7 @@ func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[s
|
|||
type userReq struct {
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Password string `json:"password"`
|
||||
Password string `json:"password,omitempty"`
|
||||
Domain *domainReq `json:"domain,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -143,10 +160,18 @@ func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[s
|
|||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
type applicationCredentialReq struct {
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
User *userReq `json:"user,omitempty"`
|
||||
Secret *string `json:"secret,omitempty"`
|
||||
}
|
||||
|
||||
type identityReq struct {
|
||||
Methods []string `json:"methods"`
|
||||
Password *passwordReq `json:"password,omitempty"`
|
||||
Token *tokenReq `json:"token,omitempty"`
|
||||
Methods []string `json:"methods"`
|
||||
Password *passwordReq `json:"password,omitempty"`
|
||||
Token *tokenReq `json:"token,omitempty"`
|
||||
ApplicationCredential *applicationCredentialReq `json:"application_credential,omitempty"`
|
||||
}
|
||||
|
||||
type authReq struct {
|
||||
|
@ -183,8 +208,68 @@ func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[s
|
|||
req.Auth.Identity.Token = &tokenReq{
|
||||
ID: opts.TokenID,
|
||||
}
|
||||
|
||||
} else if opts.ApplicationCredentialID != "" {
|
||||
// Configure the request for ApplicationCredentialID authentication.
|
||||
// https://github.com/openstack/keystoneauth/blob/stable/rocky/keystoneauth1/identity/v3/application_credential.py#L48-L67
|
||||
// There are three kinds of possible application_credential requests
|
||||
// 1. application_credential id + secret
|
||||
// 2. application_credential name + secret + user_id
|
||||
// 3. application_credential name + secret + username + domain_id / domain_name
|
||||
if opts.ApplicationCredentialSecret == "" {
|
||||
return nil, ErrAppCredMissingSecret{}
|
||||
}
|
||||
req.Auth.Identity.Methods = []string{"application_credential"}
|
||||
req.Auth.Identity.ApplicationCredential = &applicationCredentialReq{
|
||||
ID: &opts.ApplicationCredentialID,
|
||||
Secret: &opts.ApplicationCredentialSecret,
|
||||
}
|
||||
} else if opts.ApplicationCredentialName != "" {
|
||||
if opts.ApplicationCredentialSecret == "" {
|
||||
return nil, ErrAppCredMissingSecret{}
|
||||
}
|
||||
|
||||
var userRequest *userReq
|
||||
|
||||
if opts.UserID != "" {
|
||||
// UserID could be used without the domain information
|
||||
userRequest = &userReq{
|
||||
ID: &opts.UserID,
|
||||
}
|
||||
}
|
||||
|
||||
if userRequest == nil && opts.Username == "" {
|
||||
// Make sure that Username or UserID are provided
|
||||
return nil, ErrUsernameOrUserID{}
|
||||
}
|
||||
|
||||
if userRequest == nil && opts.DomainID != "" {
|
||||
userRequest = &userReq{
|
||||
Name: &opts.Username,
|
||||
Domain: &domainReq{ID: &opts.DomainID},
|
||||
}
|
||||
}
|
||||
|
||||
if userRequest == nil && opts.DomainName != "" {
|
||||
userRequest = &userReq{
|
||||
Name: &opts.Username,
|
||||
Domain: &domainReq{Name: &opts.DomainName},
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure that DomainID or DomainName are provided among Username
|
||||
if userRequest == nil {
|
||||
return nil, ErrDomainIDOrDomainName{}
|
||||
}
|
||||
|
||||
req.Auth.Identity.Methods = []string{"application_credential"}
|
||||
req.Auth.Identity.ApplicationCredential = &applicationCredentialReq{
|
||||
Name: &opts.ApplicationCredentialName,
|
||||
User: userRequest,
|
||||
Secret: &opts.ApplicationCredentialSecret,
|
||||
}
|
||||
} else {
|
||||
// If no password or token ID are available, authentication can't continue.
|
||||
// If no password or token ID or ApplicationCredential are available, authentication can't continue.
|
||||
return nil, ErrMissingPassword{}
|
||||
}
|
||||
} else {
|
||||
|
@ -263,85 +348,83 @@ func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[s
|
|||
}
|
||||
|
||||
func (opts *AuthOptions) ToTokenV3ScopeMap() (map[string]interface{}, error) {
|
||||
|
||||
var scope struct {
|
||||
ProjectID string
|
||||
ProjectName string
|
||||
DomainID string
|
||||
DomainName string
|
||||
}
|
||||
|
||||
if opts.TenantID != "" {
|
||||
scope.ProjectID = opts.TenantID
|
||||
} else {
|
||||
if opts.TenantName != "" {
|
||||
scope.ProjectName = opts.TenantName
|
||||
scope.DomainID = opts.DomainID
|
||||
scope.DomainName = opts.DomainName
|
||||
// For backwards compatibility.
|
||||
// If AuthOptions.Scope was not set, try to determine it.
|
||||
// This works well for common scenarios.
|
||||
if opts.Scope == nil {
|
||||
opts.Scope = new(AuthScope)
|
||||
if opts.TenantID != "" {
|
||||
opts.Scope.ProjectID = opts.TenantID
|
||||
} else {
|
||||
if opts.TenantName != "" {
|
||||
opts.Scope.ProjectName = opts.TenantName
|
||||
opts.Scope.DomainID = opts.DomainID
|
||||
opts.Scope.DomainName = opts.DomainName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if scope.ProjectName != "" {
|
||||
if opts.Scope.ProjectName != "" {
|
||||
// ProjectName provided: either DomainID or DomainName must also be supplied.
|
||||
// ProjectID may not be supplied.
|
||||
if scope.DomainID == "" && scope.DomainName == "" {
|
||||
if opts.Scope.DomainID == "" && opts.Scope.DomainName == "" {
|
||||
return nil, ErrScopeDomainIDOrDomainName{}
|
||||
}
|
||||
if scope.ProjectID != "" {
|
||||
if opts.Scope.ProjectID != "" {
|
||||
return nil, ErrScopeProjectIDOrProjectName{}
|
||||
}
|
||||
|
||||
if scope.DomainID != "" {
|
||||
if opts.Scope.DomainID != "" {
|
||||
// ProjectName + DomainID
|
||||
return map[string]interface{}{
|
||||
"project": map[string]interface{}{
|
||||
"name": &scope.ProjectName,
|
||||
"domain": map[string]interface{}{"id": &scope.DomainID},
|
||||
"name": &opts.Scope.ProjectName,
|
||||
"domain": map[string]interface{}{"id": &opts.Scope.DomainID},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
if scope.DomainName != "" {
|
||||
if opts.Scope.DomainName != "" {
|
||||
// ProjectName + DomainName
|
||||
return map[string]interface{}{
|
||||
"project": map[string]interface{}{
|
||||
"name": &scope.ProjectName,
|
||||
"domain": map[string]interface{}{"name": &scope.DomainName},
|
||||
"name": &opts.Scope.ProjectName,
|
||||
"domain": map[string]interface{}{"name": &opts.Scope.DomainName},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
} else if scope.ProjectID != "" {
|
||||
} else if opts.Scope.ProjectID != "" {
|
||||
// ProjectID provided. ProjectName, DomainID, and DomainName may not be provided.
|
||||
if scope.DomainID != "" {
|
||||
if opts.Scope.DomainID != "" {
|
||||
return nil, ErrScopeProjectIDAlone{}
|
||||
}
|
||||
if scope.DomainName != "" {
|
||||
if opts.Scope.DomainName != "" {
|
||||
return nil, ErrScopeProjectIDAlone{}
|
||||
}
|
||||
|
||||
// ProjectID
|
||||
return map[string]interface{}{
|
||||
"project": map[string]interface{}{
|
||||
"id": &scope.ProjectID,
|
||||
"id": &opts.Scope.ProjectID,
|
||||
},
|
||||
}, nil
|
||||
} else if scope.DomainID != "" {
|
||||
} else if opts.Scope.DomainID != "" {
|
||||
// DomainID provided. ProjectID, ProjectName, and DomainName may not be provided.
|
||||
if scope.DomainName != "" {
|
||||
if opts.Scope.DomainName != "" {
|
||||
return nil, ErrScopeDomainIDOrDomainName{}
|
||||
}
|
||||
|
||||
// DomainID
|
||||
return map[string]interface{}{
|
||||
"domain": map[string]interface{}{
|
||||
"id": &scope.DomainID,
|
||||
"id": &opts.Scope.DomainID,
|
||||
},
|
||||
}, nil
|
||||
} else if scope.DomainName != "" {
|
||||
} else if opts.Scope.DomainName != "" {
|
||||
// DomainName
|
||||
return map[string]interface{}{
|
||||
"domain": map[string]interface{}{
|
||||
"name": &scope.DomainName,
|
||||
"name": &opts.Scope.DomainName,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ pass in the parent provider, like so:
|
|||
|
||||
opts := gophercloud.EndpointOpts{Region: "RegionOne"}
|
||||
|
||||
client := openstack.NewComputeV2(provider, opts)
|
||||
client, err := openstack.NewComputeV2(provider, opts)
|
||||
|
||||
Resources
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package gophercloud
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// BaseError is an error type that all other error types embed.
|
||||
type BaseError struct {
|
||||
|
@ -43,6 +46,33 @@ func (e ErrInvalidInput) Error() string {
|
|||
return e.choseErrString()
|
||||
}
|
||||
|
||||
// ErrMissingEnvironmentVariable is the error when environment variable is required
|
||||
// in a particular situation but not provided by the user
|
||||
type ErrMissingEnvironmentVariable struct {
|
||||
BaseError
|
||||
EnvironmentVariable string
|
||||
}
|
||||
|
||||
func (e ErrMissingEnvironmentVariable) Error() string {
|
||||
e.DefaultErrString = fmt.Sprintf("Missing environment variable [%s]", e.EnvironmentVariable)
|
||||
return e.choseErrString()
|
||||
}
|
||||
|
||||
// ErrMissingAnyoneOfEnvironmentVariables is the error when anyone of the environment variables
|
||||
// is required in a particular situation but not provided by the user
|
||||
type ErrMissingAnyoneOfEnvironmentVariables struct {
|
||||
BaseError
|
||||
EnvironmentVariables []string
|
||||
}
|
||||
|
||||
func (e ErrMissingAnyoneOfEnvironmentVariables) Error() string {
|
||||
e.DefaultErrString = fmt.Sprintf(
|
||||
"Missing one of the following environment variables [%s]",
|
||||
strings.Join(e.EnvironmentVariables, ", "),
|
||||
)
|
||||
return e.choseErrString()
|
||||
}
|
||||
|
||||
// ErrUnexpectedResponseCode is returned by the Request method when a response code other than
|
||||
// those listed in OkCodes is encountered.
|
||||
type ErrUnexpectedResponseCode struct {
|
||||
|
@ -108,7 +138,11 @@ type ErrDefault503 struct {
|
|||
}
|
||||
|
||||
func (e ErrDefault400) Error() string {
|
||||
return "Invalid request due to incorrect syntax or missing required parameters."
|
||||
e.DefaultErrString = fmt.Sprintf(
|
||||
"Bad request with: [%s %s], error message: %s",
|
||||
e.Method, e.URL, e.Body,
|
||||
)
|
||||
return e.choseErrString()
|
||||
}
|
||||
func (e ErrDefault401) Error() string {
|
||||
return "Authentication failed"
|
||||
|
@ -417,3 +451,10 @@ type ErrScopeEmpty struct{ BaseError }
|
|||
func (e ErrScopeEmpty) Error() string {
|
||||
return "You must provide either a Project or Domain in a Scope"
|
||||
}
|
||||
|
||||
// ErrAppCredMissingSecret indicates that no Application Credential Secret was provided with Application Credential ID or Name
|
||||
type ErrAppCredMissingSecret struct{ BaseError }
|
||||
|
||||
func (e ErrAppCredMissingSecret) Error() string {
|
||||
return "You must provide an Application Credential Secret"
|
||||
}
|
||||
|
|
|
@ -38,6 +38,9 @@ func AuthOptionsFromEnv() (gophercloud.AuthOptions, error) {
|
|||
tenantName := os.Getenv("OS_TENANT_NAME")
|
||||
domainID := os.Getenv("OS_DOMAIN_ID")
|
||||
domainName := os.Getenv("OS_DOMAIN_NAME")
|
||||
applicationCredentialID := os.Getenv("OS_APPLICATION_CREDENTIAL_ID")
|
||||
applicationCredentialName := os.Getenv("OS_APPLICATION_CREDENTIAL_NAME")
|
||||
applicationCredentialSecret := os.Getenv("OS_APPLICATION_CREDENTIAL_SECRET")
|
||||
|
||||
// If OS_PROJECT_ID is set, overwrite tenantID with the value.
|
||||
if v := os.Getenv("OS_PROJECT_ID"); v != "" {
|
||||
|
@ -50,29 +53,61 @@ func AuthOptionsFromEnv() (gophercloud.AuthOptions, error) {
|
|||
}
|
||||
|
||||
if authURL == "" {
|
||||
err := gophercloud.ErrMissingInput{Argument: "authURL"}
|
||||
err := gophercloud.ErrMissingEnvironmentVariable{
|
||||
EnvironmentVariable: "OS_AUTH_URL",
|
||||
}
|
||||
return nilOptions, err
|
||||
}
|
||||
|
||||
if username == "" && userID == "" {
|
||||
err := gophercloud.ErrMissingInput{Argument: "username"}
|
||||
if userID == "" && username == "" {
|
||||
// Empty username and userID could be ignored, when applicationCredentialID and applicationCredentialSecret are set
|
||||
if applicationCredentialID == "" && applicationCredentialSecret == "" {
|
||||
err := gophercloud.ErrMissingAnyoneOfEnvironmentVariables{
|
||||
EnvironmentVariables: []string{"OS_USERID", "OS_USERNAME"},
|
||||
}
|
||||
return nilOptions, err
|
||||
}
|
||||
}
|
||||
|
||||
if password == "" && applicationCredentialID == "" && applicationCredentialName == "" {
|
||||
err := gophercloud.ErrMissingEnvironmentVariable{
|
||||
EnvironmentVariable: "OS_PASSWORD",
|
||||
}
|
||||
return nilOptions, err
|
||||
}
|
||||
|
||||
if password == "" {
|
||||
err := gophercloud.ErrMissingInput{Argument: "password"}
|
||||
if (applicationCredentialID != "" || applicationCredentialName != "") && applicationCredentialSecret == "" {
|
||||
err := gophercloud.ErrMissingEnvironmentVariable{
|
||||
EnvironmentVariable: "OS_APPLICATION_CREDENTIAL_SECRET",
|
||||
}
|
||||
return nilOptions, err
|
||||
}
|
||||
|
||||
if applicationCredentialID == "" && applicationCredentialName != "" && applicationCredentialSecret != "" {
|
||||
if userID == "" && username == "" {
|
||||
return nilOptions, gophercloud.ErrMissingAnyoneOfEnvironmentVariables{
|
||||
EnvironmentVariables: []string{"OS_USERID", "OS_USERNAME"},
|
||||
}
|
||||
}
|
||||
if username != "" && domainID == "" && domainName == "" {
|
||||
return nilOptions, gophercloud.ErrMissingAnyoneOfEnvironmentVariables{
|
||||
EnvironmentVariables: []string{"OS_DOMAIN_ID", "OS_DOMAIN_NAME"},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ao := gophercloud.AuthOptions{
|
||||
IdentityEndpoint: authURL,
|
||||
UserID: userID,
|
||||
Username: username,
|
||||
Password: password,
|
||||
TenantID: tenantID,
|
||||
TenantName: tenantName,
|
||||
DomainID: domainID,
|
||||
DomainName: domainName,
|
||||
IdentityEndpoint: authURL,
|
||||
UserID: userID,
|
||||
Username: username,
|
||||
Password: password,
|
||||
TenantID: tenantID,
|
||||
TenantName: tenantName,
|
||||
DomainID: domainID,
|
||||
DomainName: domainName,
|
||||
ApplicationCredentialID: applicationCredentialID,
|
||||
ApplicationCredentialName: applicationCredentialName,
|
||||
ApplicationCredentialSecret: applicationCredentialSecret,
|
||||
}
|
||||
|
||||
return ao, nil
|
||||
|
|
11
vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes/requests.go
generated
vendored
11
vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes/requests.go
generated
vendored
|
@ -110,8 +110,8 @@ type UpdateOptsBuilder interface {
|
|||
// to the volumes.Update function. For more information about the parameters, see
|
||||
// the Volume object.
|
||||
type UpdateOpts struct {
|
||||
Name string `json:"display_name,omitempty"`
|
||||
Description string `json:"display_description,omitempty"`
|
||||
Name *string `json:"display_name,omitempty"`
|
||||
Description *string `json:"display_description,omitempty"`
|
||||
Metadata map[string]string `json:"metadata,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,12 @@ func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder
|
|||
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
|
||||
count := 0
|
||||
id := ""
|
||||
pages, err := List(client, nil).AllPages()
|
||||
|
||||
listOpts := ListOpts{
|
||||
Name: name,
|
||||
}
|
||||
|
||||
pages, err := List(client, listOpts).AllPages()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
58
vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes/requests.go
generated
vendored
58
vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes/requests.go
generated
vendored
|
@ -61,9 +61,37 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r Create
|
|||
return
|
||||
}
|
||||
|
||||
// DeleteOptsBuilder allows extensions to add additional parameters to the
|
||||
// Delete request.
|
||||
type DeleteOptsBuilder interface {
|
||||
ToVolumeDeleteQuery() (string, error)
|
||||
}
|
||||
|
||||
// DeleteOpts contains options for deleting a Volume. This object is passed to
|
||||
// the volumes.Delete function.
|
||||
type DeleteOpts struct {
|
||||
// Delete all snapshots of this volume as well.
|
||||
Cascade bool `q:"cascade"`
|
||||
}
|
||||
|
||||
// ToLoadBalancerDeleteQuery formats a DeleteOpts into a query string.
|
||||
func (opts DeleteOpts) ToVolumeDeleteQuery() (string, error) {
|
||||
q, err := gophercloud.BuildQueryString(opts)
|
||||
return q.String(), err
|
||||
}
|
||||
|
||||
// Delete will delete the existing Volume with the provided ID.
|
||||
func Delete(client *gophercloud.ServiceClient, id string) (r DeleteResult) {
|
||||
_, r.Err = client.Delete(deleteURL(client, id), nil)
|
||||
func Delete(client *gophercloud.ServiceClient, id string, opts DeleteOptsBuilder) (r DeleteResult) {
|
||||
url := deleteURL(client, id)
|
||||
if opts != nil {
|
||||
query, err := opts.ToVolumeDeleteQuery()
|
||||
if err != nil {
|
||||
r.Err = err
|
||||
return
|
||||
}
|
||||
url += query
|
||||
}
|
||||
_, r.Err = client.Delete(url, nil)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -98,6 +126,19 @@ type ListOpts struct {
|
|||
// TenantID will filter by a specific tenant/project ID.
|
||||
// Setting AllTenants is required for this.
|
||||
TenantID string `q:"project_id"`
|
||||
|
||||
// Comma-separated list of sort keys and optional sort directions in the
|
||||
// form of <key>[:<direction>].
|
||||
Sort string `q:"sort"`
|
||||
|
||||
// Requests a page size of items.
|
||||
Limit int `q:"limit"`
|
||||
|
||||
// Used in conjunction with limit to return a slice of items.
|
||||
Offset int `q:"offset"`
|
||||
|
||||
// The ID of the last-seen item.
|
||||
Marker string `q:"marker"`
|
||||
}
|
||||
|
||||
// ToVolumeListQuery formats a ListOpts into a query string.
|
||||
|
@ -118,7 +159,7 @@ func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pa
|
|||
}
|
||||
|
||||
return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
|
||||
return VolumePage{pagination.SinglePageBase(r)}
|
||||
return VolumePage{pagination.LinkedPageBase{PageResult: r}}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -132,8 +173,8 @@ type UpdateOptsBuilder interface {
|
|||
// to the volumes.Update function. For more information about the parameters, see
|
||||
// the Volume object.
|
||||
type UpdateOpts struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
Metadata map[string]string `json:"metadata,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -161,7 +202,12 @@ func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder
|
|||
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
|
||||
count := 0
|
||||
id := ""
|
||||
pages, err := List(client, nil).AllPages()
|
||||
|
||||
listOpts := ListOpts{
|
||||
Name: name,
|
||||
}
|
||||
|
||||
pages, err := List(client, listOpts).AllPages()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
15
vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes/results.go
generated
vendored
15
vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes/results.go
generated
vendored
|
@ -98,7 +98,7 @@ func (r *Volume) UnmarshalJSON(b []byte) error {
|
|||
|
||||
// VolumePage is a pagination.pager that is returned from a call to the List function.
|
||||
type VolumePage struct {
|
||||
pagination.SinglePageBase
|
||||
pagination.LinkedPageBase
|
||||
}
|
||||
|
||||
// IsEmpty returns true if a ListResult contains no Volumes.
|
||||
|
@ -107,6 +107,19 @@ func (r VolumePage) IsEmpty() (bool, error) {
|
|||
return len(volumes) == 0, err
|
||||
}
|
||||
|
||||
// NextPageURL uses the response's embedded link reference to navigate to the
|
||||
// next page of results.
|
||||
func (r VolumePage) NextPageURL() (string, error) {
|
||||
var s struct {
|
||||
Links []gophercloud.Link `json:"volumes_links"`
|
||||
}
|
||||
err := r.ExtractInto(&s)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return gophercloud.ExtractNextURL(s.Links)
|
||||
}
|
||||
|
||||
// ExtractVolumes extracts and returns Volumes. It is used while iterating over a volumes.List call.
|
||||
func ExtractVolumes(r pagination.Page) ([]Volume, error) {
|
||||
var s []Volume
|
||||
|
|
45
vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes/requests.go
generated
vendored
45
vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes/requests.go
generated
vendored
|
@ -38,6 +38,8 @@ type CreateOpts struct {
|
|||
ImageID string `json:"imageRef,omitempty"`
|
||||
// The associated volume type
|
||||
VolumeType string `json:"volume_type,omitempty"`
|
||||
// Multiattach denotes if the volume is multi-attach capable.
|
||||
Multiattach bool `json:"multiattach,omitempty"`
|
||||
}
|
||||
|
||||
// ToVolumeCreateMap assembles a request body based on the contents of a
|
||||
|
@ -61,9 +63,37 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r Create
|
|||
return
|
||||
}
|
||||
|
||||
// DeleteOptsBuilder allows extensions to add additional parameters to the
|
||||
// Delete request.
|
||||
type DeleteOptsBuilder interface {
|
||||
ToVolumeDeleteQuery() (string, error)
|
||||
}
|
||||
|
||||
// DeleteOpts contains options for deleting a Volume. This object is passed to
|
||||
// the volumes.Delete function.
|
||||
type DeleteOpts struct {
|
||||
// Delete all snapshots of this volume as well.
|
||||
Cascade bool `q:"cascade"`
|
||||
}
|
||||
|
||||
// ToLoadBalancerDeleteQuery formats a DeleteOpts into a query string.
|
||||
func (opts DeleteOpts) ToVolumeDeleteQuery() (string, error) {
|
||||
q, err := gophercloud.BuildQueryString(opts)
|
||||
return q.String(), err
|
||||
}
|
||||
|
||||
// Delete will delete the existing Volume with the provided ID.
|
||||
func Delete(client *gophercloud.ServiceClient, id string) (r DeleteResult) {
|
||||
_, r.Err = client.Delete(deleteURL(client, id), nil)
|
||||
func Delete(client *gophercloud.ServiceClient, id string, opts DeleteOptsBuilder) (r DeleteResult) {
|
||||
url := deleteURL(client, id)
|
||||
if opts != nil {
|
||||
query, err := opts.ToVolumeDeleteQuery()
|
||||
if err != nil {
|
||||
r.Err = err
|
||||
return
|
||||
}
|
||||
url += query
|
||||
}
|
||||
_, r.Err = client.Delete(url, nil)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -145,8 +175,8 @@ type UpdateOptsBuilder interface {
|
|||
// to the volumes.Update function. For more information about the parameters, see
|
||||
// the Volume object.
|
||||
type UpdateOpts struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
Metadata map[string]string `json:"metadata,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -174,7 +204,12 @@ func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder
|
|||
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
|
||||
count := 0
|
||||
id := ""
|
||||
pages, err := List(client, nil).AllPages()
|
||||
|
||||
listOpts := ListOpts{
|
||||
Name: name,
|
||||
}
|
||||
|
||||
pages, err := List(client, listOpts).AllPages()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
@ -2,10 +2,7 @@ package openstack
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/gophercloud/gophercloud"
|
||||
tokens2 "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens"
|
||||
|
@ -38,21 +35,11 @@ A basic example of using this would be:
|
|||
client, err := openstack.NewIdentityV3(provider, gophercloud.EndpointOpts{})
|
||||
*/
|
||||
func NewClient(endpoint string) (*gophercloud.ProviderClient, error) {
|
||||
u, err := url.Parse(endpoint)
|
||||
base, err := utils.BaseEndpoint(endpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
u.RawQuery, u.Fragment = "", ""
|
||||
|
||||
var base string
|
||||
versionRe := regexp.MustCompile("v[0-9.]+/?")
|
||||
if version := versionRe.FindString(u.Path); version != "" {
|
||||
base = strings.Replace(u.String(), version, "", -1)
|
||||
} else {
|
||||
base = u.String()
|
||||
}
|
||||
|
||||
endpoint = gophercloud.NormalizeURL(endpoint)
|
||||
base = gophercloud.NormalizeURL(base)
|
||||
|
||||
|
@ -163,6 +150,7 @@ func v2auth(client *gophercloud.ProviderClient, endpoint string, options gopherc
|
|||
// with the token and reauth func zeroed out. combined with setting `AllowReauth` to `false`,
|
||||
// this should retry authentication only once
|
||||
tac := *client
|
||||
tac.IsThrowaway = true
|
||||
tac.ReauthFunc = nil
|
||||
tac.TokenID = ""
|
||||
tao := options
|
||||
|
@ -219,6 +207,7 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, opts tokens3.Au
|
|||
// with the token and reauth func zeroed out. combined with setting `AllowReauth` to `false`,
|
||||
// this should retry authentication only once
|
||||
tac := *client
|
||||
tac.IsThrowaway = true
|
||||
tac.ReauthFunc = nil
|
||||
tac.TokenID = ""
|
||||
var tao tokens3.AuthOptionsBuilder
|
||||
|
@ -287,11 +276,17 @@ func NewIdentityV3(client *gophercloud.ProviderClient, eo gophercloud.EndpointOp
|
|||
|
||||
// Ensure endpoint still has a suffix of v3.
|
||||
// This is because EndpointLocator might have found a versionless
|
||||
// endpoint and requests will fail unless targeted at /v3.
|
||||
if !strings.HasSuffix(endpoint, "v3/") {
|
||||
endpoint = endpoint + "v3/"
|
||||
// endpoint or the published endpoint is still /v2.0. In both
|
||||
// cases, we need to fix the endpoint to point to /v3.
|
||||
base, err := utils.BaseEndpoint(endpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
base = gophercloud.NormalizeURL(base)
|
||||
|
||||
endpoint = base + "v3/"
|
||||
|
||||
return &gophercloud.ServiceClient{
|
||||
ProviderClient: client,
|
||||
Endpoint: endpoint,
|
||||
|
@ -400,3 +395,35 @@ func NewLoadBalancerV2(client *gophercloud.ProviderClient, eo gophercloud.Endpoi
|
|||
func NewClusteringV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
return initClientOpts(client, eo, "clustering")
|
||||
}
|
||||
|
||||
// NewMessagingV2 creates a ServiceClient that may be used with the v2 messaging
|
||||
// service.
|
||||
func NewMessagingV2(client *gophercloud.ProviderClient, clientID string, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
sc, err := initClientOpts(client, eo, "messaging")
|
||||
sc.MoreHeaders = map[string]string{"Client-ID": clientID}
|
||||
return sc, err
|
||||
}
|
||||
|
||||
// NewContainerV1 creates a ServiceClient that may be used with v1 container package
|
||||
func NewContainerV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
return initClientOpts(client, eo, "container")
|
||||
}
|
||||
|
||||
// NewKeyManagerV1 creates a ServiceClient that may be used with the v1 key
|
||||
// manager service.
|
||||
func NewKeyManagerV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
sc, err := initClientOpts(client, eo, "key-manager")
|
||||
sc.ResourceBase = sc.Endpoint + "v1/"
|
||||
return sc, err
|
||||
}
|
||||
|
||||
// NewContainerInfraV1 creates a ServiceClient that may be used with the v1 container infra management
|
||||
// package.
|
||||
func NewContainerInfraV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
return initClientOpts(client, eo, "container-infra")
|
||||
}
|
||||
|
||||
// NewWorkflowV2 creates a ServiceClient that may be used with the v2 workflow management package.
|
||||
func NewWorkflowV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
return initClientOpts(client, eo, "workflowv2")
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ type CreateOptsBuilder interface {
|
|||
|
||||
// CreateOpts specifies parameters of a new interface attachment.
|
||||
type CreateOpts struct {
|
||||
|
||||
// PortID is the ID of the port for which you want to create an interface.
|
||||
// The NetworkID and PortID parameters are mutually exclusive.
|
||||
// If you do not specify the PortID parameter, the OpenStack Networking API
|
||||
|
@ -43,6 +42,7 @@ type CreateOpts struct {
|
|||
|
||||
// Slice of FixedIPs. If you request a specific FixedIP address without a
|
||||
// NetworkID, the request returns a Bad Request (400) response code.
|
||||
// Note: this uses the FixedIP struct, but only the IPAddress field can be used.
|
||||
FixedIPs []FixedIP `json:"fixed_ips,omitempty"`
|
||||
}
|
||||
|
||||
|
|
|
@ -37,8 +37,10 @@ type DeleteResult struct {
|
|||
}
|
||||
|
||||
// FixedIP represents a Fixed IP Address.
|
||||
// This struct is also used when creating an attachment,
|
||||
// but it is not possible to specify a SubnetID.
|
||||
type FixedIP struct {
|
||||
SubnetID string `json:"subnet_id"`
|
||||
SubnetID string `json:"subnet_id,omitempty"`
|
||||
IPAddress string `json:"ip_address"`
|
||||
}
|
||||
|
||||
|
|
8
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/requests.go
generated
vendored
8
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/requests.go
generated
vendored
|
@ -52,6 +52,14 @@ type ListOpts struct {
|
|||
MinDisk int `q:"minDisk"`
|
||||
MinRAM int `q:"minRam"`
|
||||
|
||||
// SortDir allows to select sort direction.
|
||||
// It can be "asc" or "desc" (default).
|
||||
SortDir string `q:"sort_dir"`
|
||||
|
||||
// SortKey allows to sort by one of the flavors attributes.
|
||||
// Default is flavorid.
|
||||
SortKey string `q:"sort_key"`
|
||||
|
||||
// Marker and Limit control paging.
|
||||
// Marker instructs List where to start listing from.
|
||||
Marker string `q:"marker"`
|
||||
|
|
2
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/results.go
generated
vendored
2
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/results.go
generated
vendored
|
@ -59,7 +59,7 @@ type Flavor struct {
|
|||
RxTxFactor float64 `json:"rxtx_factor"`
|
||||
|
||||
// Swap is the amount of swap space, measured in MB.
|
||||
Swap int `json:"swap"`
|
||||
Swap int `json:"-"`
|
||||
|
||||
// VCPUs indicates how many (virtual) CPUs are available for this flavor.
|
||||
VCPUs int `json:"vcpus"`
|
||||
|
|
73
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/requests.go
generated
vendored
73
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/requests.go
generated
vendored
|
@ -383,7 +383,7 @@ type RebootOpts struct {
|
|||
}
|
||||
|
||||
// ToServerRebootMap builds a body for the reboot request.
|
||||
func (opts *RebootOpts) ToServerRebootMap() (map[string]interface{}, error) {
|
||||
func (opts RebootOpts) ToServerRebootMap() (map[string]interface{}, error) {
|
||||
return gophercloud.BuildRequestBody(opts, "reboot")
|
||||
}
|
||||
|
||||
|
@ -545,39 +545,6 @@ func RevertResize(client *gophercloud.ServiceClient, id string) (r ActionResult)
|
|||
return
|
||||
}
|
||||
|
||||
// RescueOptsBuilder is an interface that allows extensions to override the
|
||||
// default structure of a Rescue request.
|
||||
type RescueOptsBuilder interface {
|
||||
ToServerRescueMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// RescueOpts represents the configuration options used to control a Rescue
|
||||
// option.
|
||||
type RescueOpts struct {
|
||||
// AdminPass is the desired administrative password for the instance in
|
||||
// RESCUE mode. If it's left blank, the server will generate a password.
|
||||
AdminPass string `json:"adminPass,omitempty"`
|
||||
}
|
||||
|
||||
// ToServerRescueMap formats a RescueOpts as a map that can be used as a JSON
|
||||
// request body for the Rescue request.
|
||||
func (opts RescueOpts) ToServerRescueMap() (map[string]interface{}, error) {
|
||||
return gophercloud.BuildRequestBody(opts, "rescue")
|
||||
}
|
||||
|
||||
// Rescue instructs the provider to place the server into RESCUE mode.
|
||||
func Rescue(client *gophercloud.ServiceClient, id string, opts RescueOptsBuilder) (r RescueResult) {
|
||||
b, err := opts.ToServerRescueMap()
|
||||
if err != nil {
|
||||
r.Err = err
|
||||
return
|
||||
}
|
||||
_, r.Err = client.Post(actionURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// ResetMetadataOptsBuilder allows extensions to add additional parameters to
|
||||
// the Reset request.
|
||||
type ResetMetadataOptsBuilder interface {
|
||||
|
@ -756,7 +723,12 @@ func CreateImage(client *gophercloud.ServiceClient, id string, opts CreateImageO
|
|||
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
|
||||
count := 0
|
||||
id := ""
|
||||
allPages, err := List(client, nil).AllPages()
|
||||
|
||||
listOpts := ListOpts{
|
||||
Name: name,
|
||||
}
|
||||
|
||||
allPages, err := List(client, listOpts).AllPages()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -789,3 +761,34 @@ func GetPassword(client *gophercloud.ServiceClient, serverId string) (r GetPassw
|
|||
_, r.Err = client.Get(passwordURL(client, serverId), &r.Body, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// ShowConsoleOutputOptsBuilder is the interface types must satisfy in order to be
|
||||
// used as ShowConsoleOutput options
|
||||
type ShowConsoleOutputOptsBuilder interface {
|
||||
ToServerShowConsoleOutputMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// ShowConsoleOutputOpts satisfies the ShowConsoleOutputOptsBuilder
|
||||
type ShowConsoleOutputOpts struct {
|
||||
// The number of lines to fetch from the end of console log.
|
||||
// All lines will be returned if this is not specified.
|
||||
Length int `json:"length,omitempty"`
|
||||
}
|
||||
|
||||
// ToServerShowConsoleOutputMap formats a ShowConsoleOutputOpts structure into a request body.
|
||||
func (opts ShowConsoleOutputOpts) ToServerShowConsoleOutputMap() (map[string]interface{}, error) {
|
||||
return gophercloud.BuildRequestBody(opts, "os-getConsoleOutput")
|
||||
}
|
||||
|
||||
// ShowConsoleOutput makes a request against the nova API to get console log from the server
|
||||
func ShowConsoleOutput(client *gophercloud.ServiceClient, id string, opts ShowConsoleOutputOptsBuilder) (r ShowConsoleOutputResult) {
|
||||
b, err := opts.ToServerShowConsoleOutputMap()
|
||||
if err != nil {
|
||||
r.Err = err
|
||||
return
|
||||
}
|
||||
_, r.Err = client.Post(actionURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
|
30
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/results.go
generated
vendored
30
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/results.go
generated
vendored
|
@ -68,18 +68,27 @@ type ActionResult struct {
|
|||
gophercloud.ErrResult
|
||||
}
|
||||
|
||||
// RescueResult is the response from a Rescue operation. Call its ExtractErr
|
||||
// method to determine if the call succeeded or failed.
|
||||
type RescueResult struct {
|
||||
ActionResult
|
||||
}
|
||||
|
||||
// CreateImageResult is the response from a CreateImage operation. Call its
|
||||
// ExtractImageID method to retrieve the ID of the newly created image.
|
||||
type CreateImageResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// ShowConsoleOutputResult represents the result of console output from a server
|
||||
type ShowConsoleOutputResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// Extract will return the console output from a ShowConsoleOutput request.
|
||||
func (r ShowConsoleOutputResult) Extract() (string, error) {
|
||||
var s struct {
|
||||
Output string `json:"output"`
|
||||
}
|
||||
|
||||
err := r.ExtractInto(&s)
|
||||
return s.Output, err
|
||||
}
|
||||
|
||||
// GetPasswordResult represent the result of a get os-server-password operation.
|
||||
// Call its ExtractPassword method to retrieve the password.
|
||||
type GetPasswordResult struct {
|
||||
|
@ -134,15 +143,6 @@ func (r CreateImageResult) ExtractImageID() (string, error) {
|
|||
return imageID, nil
|
||||
}
|
||||
|
||||
// Extract interprets any RescueResult as an AdminPass, if possible.
|
||||
func (r RescueResult) Extract() (string, error) {
|
||||
var s struct {
|
||||
AdminPass string `json:"adminPass"`
|
||||
}
|
||||
err := r.ExtractInto(&s)
|
||||
return s.AdminPass, err
|
||||
}
|
||||
|
||||
// Server represents a server/instance in the OpenStack cloud.
|
||||
type Server struct {
|
||||
// ID uniquely identifies this server amongst all other servers,
|
||||
|
|
2
vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tenants/requests.go
generated
vendored
2
vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tenants/requests.go
generated
vendored
|
@ -85,7 +85,7 @@ type UpdateOpts struct {
|
|||
Name string `json:"name,omitempty"`
|
||||
|
||||
// Description is the description of the tenant.
|
||||
Description string `json:"description,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
|
||||
// Enabled sets the tenant status to enabled or disabled.
|
||||
Enabled *bool `json:"enabled,omitempty"`
|
||||
|
|
94
vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/requests.go
generated
vendored
94
vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/requests.go
generated
vendored
|
@ -52,19 +52,28 @@ type AuthOptions struct {
|
|||
// authentication token ID.
|
||||
TokenID string `json:"-"`
|
||||
|
||||
// Authentication through Application Credentials requires supplying name, project and secret
|
||||
// For project we can use TenantID
|
||||
ApplicationCredentialID string `json:"-"`
|
||||
ApplicationCredentialName string `json:"-"`
|
||||
ApplicationCredentialSecret string `json:"-"`
|
||||
|
||||
Scope Scope `json:"-"`
|
||||
}
|
||||
|
||||
// ToTokenV3CreateMap builds a request body from AuthOptions.
|
||||
func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[string]interface{}, error) {
|
||||
gophercloudAuthOpts := gophercloud.AuthOptions{
|
||||
Username: opts.Username,
|
||||
UserID: opts.UserID,
|
||||
Password: opts.Password,
|
||||
DomainID: opts.DomainID,
|
||||
DomainName: opts.DomainName,
|
||||
AllowReauth: opts.AllowReauth,
|
||||
TokenID: opts.TokenID,
|
||||
Username: opts.Username,
|
||||
UserID: opts.UserID,
|
||||
Password: opts.Password,
|
||||
DomainID: opts.DomainID,
|
||||
DomainName: opts.DomainName,
|
||||
AllowReauth: opts.AllowReauth,
|
||||
TokenID: opts.TokenID,
|
||||
ApplicationCredentialID: opts.ApplicationCredentialID,
|
||||
ApplicationCredentialName: opts.ApplicationCredentialName,
|
||||
ApplicationCredentialSecret: opts.ApplicationCredentialSecret,
|
||||
}
|
||||
|
||||
return gophercloudAuthOpts.ToTokenV3CreateMap(scope)
|
||||
|
@ -72,72 +81,15 @@ func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[s
|
|||
|
||||
// ToTokenV3CreateMap builds a scope request body from AuthOptions.
|
||||
func (opts *AuthOptions) ToTokenV3ScopeMap() (map[string]interface{}, error) {
|
||||
if opts.Scope.ProjectName != "" {
|
||||
// ProjectName provided: either DomainID or DomainName must also be supplied.
|
||||
// ProjectID may not be supplied.
|
||||
if opts.Scope.DomainID == "" && opts.Scope.DomainName == "" {
|
||||
return nil, gophercloud.ErrScopeDomainIDOrDomainName{}
|
||||
}
|
||||
if opts.Scope.ProjectID != "" {
|
||||
return nil, gophercloud.ErrScopeProjectIDOrProjectName{}
|
||||
}
|
||||
scope := gophercloud.AuthScope(opts.Scope)
|
||||
|
||||
if opts.Scope.DomainID != "" {
|
||||
// ProjectName + DomainID
|
||||
return map[string]interface{}{
|
||||
"project": map[string]interface{}{
|
||||
"name": &opts.Scope.ProjectName,
|
||||
"domain": map[string]interface{}{"id": &opts.Scope.DomainID},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
if opts.Scope.DomainName != "" {
|
||||
// ProjectName + DomainName
|
||||
return map[string]interface{}{
|
||||
"project": map[string]interface{}{
|
||||
"name": &opts.Scope.ProjectName,
|
||||
"domain": map[string]interface{}{"name": &opts.Scope.DomainName},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
} else if opts.Scope.ProjectID != "" {
|
||||
// ProjectID provided. ProjectName, DomainID, and DomainName may not be provided.
|
||||
if opts.Scope.DomainID != "" {
|
||||
return nil, gophercloud.ErrScopeProjectIDAlone{}
|
||||
}
|
||||
if opts.Scope.DomainName != "" {
|
||||
return nil, gophercloud.ErrScopeProjectIDAlone{}
|
||||
}
|
||||
|
||||
// ProjectID
|
||||
return map[string]interface{}{
|
||||
"project": map[string]interface{}{
|
||||
"id": &opts.Scope.ProjectID,
|
||||
},
|
||||
}, nil
|
||||
} else if opts.Scope.DomainID != "" {
|
||||
// DomainID provided. ProjectID, ProjectName, and DomainName may not be provided.
|
||||
if opts.Scope.DomainName != "" {
|
||||
return nil, gophercloud.ErrScopeDomainIDOrDomainName{}
|
||||
}
|
||||
|
||||
// DomainID
|
||||
return map[string]interface{}{
|
||||
"domain": map[string]interface{}{
|
||||
"id": &opts.Scope.DomainID,
|
||||
},
|
||||
}, nil
|
||||
} else if opts.Scope.DomainName != "" {
|
||||
// DomainName
|
||||
return map[string]interface{}{
|
||||
"domain": map[string]interface{}{
|
||||
"name": &opts.Scope.DomainName,
|
||||
},
|
||||
}, nil
|
||||
gophercloudAuthOpts := gophercloud.AuthOptions{
|
||||
Scope: &scope,
|
||||
DomainID: opts.DomainID,
|
||||
DomainName: opts.DomainName,
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
return gophercloudAuthOpts.ToTokenV3ScopeMap()
|
||||
}
|
||||
|
||||
func (opts *AuthOptions) CanReauth() bool {
|
||||
|
@ -190,7 +142,7 @@ func Get(c *gophercloud.ServiceClient, token string) (r GetResult) {
|
|||
|
||||
// Validate determines if a specified token is valid or not.
|
||||
func Validate(c *gophercloud.ServiceClient, token string) (bool, error) {
|
||||
resp, err := c.Request("HEAD", tokenURL(c), &gophercloud.RequestOpts{
|
||||
resp, err := c.Head(tokenURL(c), &gophercloud.RequestOpts{
|
||||
MoreHeaders: subjectTokenHeaders(c, token),
|
||||
OkCodes: []int{200, 204, 404},
|
||||
})
|
||||
|
|
1
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/BUILD
generated
vendored
1
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/BUILD
generated
vendored
|
@ -27,6 +27,7 @@ filegroup(
|
|||
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external:all-srcs",
|
||||
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips:all-srcs",
|
||||
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers:all-srcs",
|
||||
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/l7policies:all-srcs",
|
||||
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners:all-srcs",
|
||||
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers:all-srcs",
|
||||
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors:all-srcs",
|
||||
|
|
|
@ -10,7 +10,10 @@ go_library(
|
|||
importmap = "k8s.io/kubernetes/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external",
|
||||
importpath = "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks:go_default_library"],
|
||||
deps = [
|
||||
"//vendor/github.com/gophercloud/gophercloud:go_default_library",
|
||||
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
|
|
|
@ -4,6 +4,13 @@ extension for the OpenStack Networking service.
|
|||
|
||||
Example to List Networks with External Information
|
||||
|
||||
iTrue := true
|
||||
networkListOpts := networks.ListOpts{}
|
||||
listOpts := external.ListOptsExt{
|
||||
ListOptsBuilder: networkListOpts,
|
||||
External: &iTrue,
|
||||
}
|
||||
|
||||
type NetworkWithExternalExt struct {
|
||||
networks.Network
|
||||
external.NetworkExternalExt
|
||||
|
@ -11,7 +18,7 @@ Example to List Networks with External Information
|
|||
|
||||
var allNetworks []NetworkWithExternalExt
|
||||
|
||||
allPages, err := networks.List(networkClient, nil).AllPages()
|
||||
allPages, err := networks.List(networkClient, listOpts).AllPages()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
|
@ -1,9 +1,37 @@
|
|||
package external
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/gophercloud/gophercloud"
|
||||
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
|
||||
)
|
||||
|
||||
// ListOptsExt adds the external network options to the base ListOpts.
|
||||
type ListOptsExt struct {
|
||||
networks.ListOptsBuilder
|
||||
External *bool `q:"router:external"`
|
||||
}
|
||||
|
||||
// ToNetworkListQuery adds the router:external option to the base network
|
||||
// list options.
|
||||
func (opts ListOptsExt) ToNetworkListQuery() (string, error) {
|
||||
q, err := gophercloud.BuildQueryString(opts.ListOptsBuilder)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
params := q.Query()
|
||||
if opts.External != nil {
|
||||
v := strconv.FormatBool(*opts.External)
|
||||
params.Add("router:external", v)
|
||||
}
|
||||
|
||||
q = &url.URL{RawQuery: params.Encode()}
|
||||
return q.String(), err
|
||||
}
|
||||
|
||||
// CreateOptsExt is the structure used when creating new external network
|
||||
// resources. It embeds networks.CreateOpts and so inherits all of its required
|
||||
// and optional fields, with the addition of the External field.
|
||||
|
|
|
@ -52,7 +52,7 @@ Example to Disassociate a Floating IP with a Port
|
|||
fipID := "2f245a7b-796b-4f26-9cf9-9e82d248fda7"
|
||||
|
||||
updateOpts := floatingips.UpdateOpts{
|
||||
PortID: nil,
|
||||
PortID: new(string),
|
||||
}
|
||||
|
||||
fip, err := floatingips.Update(networkingClient, fipID, updateOpts).Extract()
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
// either `asc' or `desc'. Marker and Limit are used for pagination.
|
||||
type ListOpts struct {
|
||||
ID string `q:"id"`
|
||||
Description string `q:"description"`
|
||||
FloatingNetworkID string `q:"floating_network_id"`
|
||||
PortID string `q:"port_id"`
|
||||
FixedIP string `q:"fixed_ip_address"`
|
||||
|
@ -24,6 +25,10 @@ type ListOpts struct {
|
|||
SortDir string `q:"sort_dir"`
|
||||
RouterID string `q:"router_id"`
|
||||
Status string `q:"status"`
|
||||
Tags string `q:"tags"`
|
||||
TagsAny string `q:"tags-any"`
|
||||
NotTags string `q:"not-tags"`
|
||||
NotTagsAny string `q:"not-tags-any"`
|
||||
}
|
||||
|
||||
// List returns a Pager which allows you to iterate over a collection of
|
||||
|
@ -50,6 +55,7 @@ type CreateOptsBuilder interface {
|
|||
// resource. The only required fields are FloatingNetworkID and PortID which
|
||||
// refer to the external network and internal port respectively.
|
||||
type CreateOpts struct {
|
||||
Description string `json:"description,omitempty"`
|
||||
FloatingNetworkID string `json:"floating_network_id" required:"true"`
|
||||
FloatingIP string `json:"floating_ip_address,omitempty"`
|
||||
PortID string `json:"port_id,omitempty"`
|
||||
|
@ -116,13 +122,23 @@ type UpdateOptsBuilder interface {
|
|||
// linked to. To associate the floating IP with a new internal port, provide its
|
||||
// ID. To disassociate the floating IP from all ports, provide an empty string.
|
||||
type UpdateOpts struct {
|
||||
PortID *string `json:"port_id"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
PortID *string `json:"port_id,omitempty"`
|
||||
}
|
||||
|
||||
// ToFloatingIPUpdateMap allows UpdateOpts to satisfy the UpdateOptsBuilder
|
||||
// interface
|
||||
func (opts UpdateOpts) ToFloatingIPUpdateMap() (map[string]interface{}, error) {
|
||||
return gophercloud.BuildRequestBody(opts, "floatingip")
|
||||
b, err := gophercloud.BuildRequestBody(opts, "floatingip")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if m := b["floatingip"].(map[string]interface{}); m["port_id"] == "" {
|
||||
m["port_id"] = nil
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// Update allows floating IP resources to be updated. Currently, the only way to
|
||||
|
|
|
@ -15,6 +15,9 @@ type FloatingIP struct {
|
|||
// ID is the unique identifier for the floating IP instance.
|
||||
ID string `json:"id"`
|
||||
|
||||
// Description for the floating IP instance.
|
||||
Description string `json:"description"`
|
||||
|
||||
// FloatingNetworkID is the UUID of the external network where the floating
|
||||
// IP is to be created.
|
||||
FloatingNetworkID string `json:"floating_network_id"`
|
||||
|
@ -42,6 +45,9 @@ type FloatingIP struct {
|
|||
|
||||
// RouterID is the ID of the router used for this floating IP.
|
||||
RouterID string `json:"router_id"`
|
||||
|
||||
// Tags optionally set via extensions/attributestags
|
||||
Tags []string `json:"tags"`
|
||||
}
|
||||
|
||||
type commonResult struct {
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
type ListOpts struct {
|
||||
ID string `q:"id"`
|
||||
Name string `q:"name"`
|
||||
Description string `q:"description"`
|
||||
AdminStateUp *bool `q:"admin_state_up"`
|
||||
Distributed *bool `q:"distributed"`
|
||||
Status string `q:"status"`
|
||||
|
@ -22,6 +23,10 @@ type ListOpts struct {
|
|||
Marker string `q:"marker"`
|
||||
SortKey string `q:"sort_key"`
|
||||
SortDir string `q:"sort_dir"`
|
||||
Tags string `q:"tags"`
|
||||
TagsAny string `q:"tags-any"`
|
||||
NotTags string `q:"not-tags"`
|
||||
NotTagsAny string `q:"not-tags-any"`
|
||||
}
|
||||
|
||||
// List returns a Pager which allows you to iterate over a collection of
|
||||
|
@ -51,6 +56,7 @@ type CreateOptsBuilder interface {
|
|||
// no required values.
|
||||
type CreateOpts struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
AdminStateUp *bool `json:"admin_state_up,omitempty"`
|
||||
Distributed *bool `json:"distributed,omitempty"`
|
||||
TenantID string `json:"tenant_id,omitempty"`
|
||||
|
@ -97,6 +103,7 @@ type UpdateOptsBuilder interface {
|
|||
// UpdateOpts contains the values used when updating a router.
|
||||
type UpdateOpts struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
AdminStateUp *bool `json:"admin_state_up,omitempty"`
|
||||
Distributed *bool `json:"distributed,omitempty"`
|
||||
GatewayInfo *GatewayInfo `json:"external_gateway_info,omitempty"`
|
||||
|
|
|
@ -16,7 +16,7 @@ type GatewayInfo struct {
|
|||
// ExternalFixedIP is the IP address and subnet ID of the external gateway of a
|
||||
// router.
|
||||
type ExternalFixedIP struct {
|
||||
IPAddress string `json:"ip_address"`
|
||||
IPAddress string `json:"ip_address,omitempty"`
|
||||
SubnetID string `json:"subnet_id"`
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,9 @@ type Router struct {
|
|||
// unique.
|
||||
Name string `json:"name"`
|
||||
|
||||
// Description for the router.
|
||||
Description string `json:"description"`
|
||||
|
||||
// ID is the unique identifier for the router.
|
||||
ID string `json:"id"`
|
||||
|
||||
|
@ -67,6 +70,9 @@ type Router struct {
|
|||
// Availability zone hints groups network nodes that run services like DHCP, L3, FW, and others.
|
||||
// Used to make network resources highly available.
|
||||
AvailabilityZoneHints []string `json:"availability_zone_hints"`
|
||||
|
||||
// Tags optionally set via extensions/attributestags
|
||||
Tags []string `json:"tags"`
|
||||
}
|
||||
|
||||
// RouterPage is the page returned by a pager when traversing over a
|
||||
|
|
32
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/l7policies/BUILD
generated
vendored
Normal file
32
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/l7policies/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"requests.go",
|
||||
"results.go",
|
||||
"urls.go",
|
||||
],
|
||||
importmap = "k8s.io/kubernetes/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/l7policies",
|
||||
importpath = "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/l7policies",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//vendor/github.com/gophercloud/gophercloud:go_default_library",
|
||||
"//vendor/github.com/gophercloud/gophercloud/pagination:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
123
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/l7policies/doc.go
generated
vendored
Normal file
123
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/l7policies/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
Package l7policies provides information and interaction with L7Policies and
|
||||
Rules of the LBaaS v2 extension for the OpenStack Networking service.
|
||||
|
||||
Example to Create a L7Policy
|
||||
|
||||
createOpts := l7policies.CreateOpts{
|
||||
Name: "redirect-example.com",
|
||||
ListenerID: "023f2e34-7806-443b-bfae-16c324569a3d",
|
||||
Action: l7policies.ActionRedirectToURL,
|
||||
RedirectURL: "http://www.example.com",
|
||||
}
|
||||
l7policy, err := l7policies.Create(lbClient, createOpts).Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to List L7Policies
|
||||
|
||||
listOpts := l7policies.ListOpts{
|
||||
ListenerID: "c79a4468-d788-410c-bf79-9a8ef6354852",
|
||||
}
|
||||
allPages, err := l7policies.List(lbClient, listOpts).AllPages()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
allL7Policies, err := l7policies.ExtractL7Policies(allPages)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, l7policy := range allL7Policies {
|
||||
fmt.Printf("%+v\n", l7policy)
|
||||
}
|
||||
|
||||
Example to Get a L7Policy
|
||||
|
||||
l7policy, err := l7policies.Get(lbClient, "023f2e34-7806-443b-bfae-16c324569a3d").Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Delete a L7Policy
|
||||
|
||||
l7policyID := "d67d56a6-4a86-4688-a282-f46444705c64"
|
||||
err := l7policies.Delete(lbClient, l7policyID).ExtractErr()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Update a L7Policy
|
||||
|
||||
l7policyID := "d67d56a6-4a86-4688-a282-f46444705c64"
|
||||
name := "new-name"
|
||||
updateOpts := l7policies.UpdateOpts{
|
||||
Name: &name,
|
||||
}
|
||||
l7policy, err := l7policies.Update(lbClient, l7policyID, updateOpts).Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Create a Rule
|
||||
|
||||
l7policyID := "d67d56a6-4a86-4688-a282-f46444705c64"
|
||||
createOpts := l7policies.CreateRuleOpts{
|
||||
RuleType: l7policies.TypePath,
|
||||
CompareType: l7policies.CompareTypeRegex,
|
||||
Value: "/images*",
|
||||
}
|
||||
rule, err := l7policies.CreateRule(lbClient, l7policyID, createOpts).Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to List L7 Rules
|
||||
|
||||
l7policyID := "d67d56a6-4a86-4688-a282-f46444705c64"
|
||||
listOpts := l7policies.ListRulesOpts{
|
||||
RuleType: l7policies.TypePath,
|
||||
}
|
||||
allPages, err := l7policies.ListRules(lbClient, l7policyID, listOpts).AllPages()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
allRules, err := l7policies.ExtractRules(allPages)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, rule := allRules {
|
||||
fmt.Printf("%+v\n", rule)
|
||||
}
|
||||
|
||||
Example to Get a l7 rule
|
||||
|
||||
l7rule, err := l7policies.GetRule(lbClient, "023f2e34-7806-443b-bfae-16c324569a3d", "53ad8ab8-40fa-11e8-a508-00224d6b7bc1").Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Delete a l7 rule
|
||||
|
||||
l7policyID := "d67d56a6-4a86-4688-a282-f46444705c64"
|
||||
ruleID := "64dba99f-8af8-4200-8882-e32a0660f23e"
|
||||
err := l7policies.DeleteRule(lbClient, l7policyID, ruleID).ExtractErr()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Update a Rule
|
||||
|
||||
l7policyID := "d67d56a6-4a86-4688-a282-f46444705c64"
|
||||
ruleID := "64dba99f-8af8-4200-8882-e32a0660f23e"
|
||||
updateOpts := l7policies.UpdateRuleOpts{
|
||||
RuleType: l7policies.TypePath,
|
||||
CompareType: l7policies.CompareTypeRegex,
|
||||
Value: "/images/special*",
|
||||
}
|
||||
rule, err := l7policies.UpdateRule(lbClient, l7policyID, ruleID, updateOpts).Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
*/
|
||||
package l7policies
|
376
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/l7policies/requests.go
generated
vendored
Normal file
376
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/l7policies/requests.go
generated
vendored
Normal file
|
@ -0,0 +1,376 @@
|
|||
package l7policies
|
||||
|
||||
import (
|
||||
"github.com/gophercloud/gophercloud"
|
||||
"github.com/gophercloud/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// CreateOptsBuilder allows extensions to add additional parameters to the
|
||||
// Create request.
|
||||
type CreateOptsBuilder interface {
|
||||
ToL7PolicyCreateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
type Action string
|
||||
type RuleType string
|
||||
type CompareType string
|
||||
|
||||
const (
|
||||
ActionRedirectToPool Action = "REDIRECT_TO_POOL"
|
||||
ActionRedirectToURL Action = "REDIRECT_TO_URL"
|
||||
ActionReject Action = "REJECT"
|
||||
|
||||
TypeCookie RuleType = "COOKIE"
|
||||
TypeFileType RuleType = "FILE_TYPE"
|
||||
TypeHeader RuleType = "HEADER"
|
||||
TypeHostName RuleType = "HOST_NAME"
|
||||
TypePath RuleType = "PATH"
|
||||
|
||||
CompareTypeContains CompareType = "CONTAINS"
|
||||
CompareTypeEndWith CompareType = "ENDS_WITH"
|
||||
CompareTypeEqual CompareType = "EQUAL_TO"
|
||||
CompareTypeRegex CompareType = "REGEX"
|
||||
CompareTypeStartWith CompareType = "STARTS_WITH"
|
||||
)
|
||||
|
||||
// CreateOpts is the common options struct used in this package's Create
|
||||
// operation.
|
||||
type CreateOpts struct {
|
||||
// Name of the L7 policy.
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// The ID of the listener.
|
||||
ListenerID string `json:"listener_id" required:"true"`
|
||||
|
||||
// The L7 policy action. One of REDIRECT_TO_POOL, REDIRECT_TO_URL, or REJECT.
|
||||
Action Action `json:"action" required:"true"`
|
||||
|
||||
// The position of this policy on the listener.
|
||||
Position int32 `json:"position,omitempty"`
|
||||
|
||||
// A human-readable description for the resource.
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// TenantID is the UUID of the tenant who owns the L7 policy in octavia.
|
||||
// Only administrative users can specify a project UUID other than their own.
|
||||
TenantID string `json:"tenant_id,omitempty"`
|
||||
|
||||
// Requests matching this policy will be redirected to the pool with this ID.
|
||||
// Only valid if action is REDIRECT_TO_POOL.
|
||||
RedirectPoolID string `json:"redirect_pool_id,omitempty"`
|
||||
|
||||
// Requests matching this policy will be redirected to this URL.
|
||||
// Only valid if action is REDIRECT_TO_URL.
|
||||
RedirectURL string `json:"redirect_url,omitempty"`
|
||||
|
||||
// The administrative state of the Loadbalancer. A valid value is true (UP)
|
||||
// or false (DOWN).
|
||||
AdminStateUp *bool `json:"admin_state_up,omitempty"`
|
||||
}
|
||||
|
||||
// ToL7PolicyCreateMap builds a request body from CreateOpts.
|
||||
func (opts CreateOpts) ToL7PolicyCreateMap() (map[string]interface{}, error) {
|
||||
return gophercloud.BuildRequestBody(opts, "l7policy")
|
||||
}
|
||||
|
||||
// Create accepts a CreateOpts struct and uses the values to create a new l7policy.
|
||||
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
|
||||
b, err := opts.ToL7PolicyCreateMap()
|
||||
if err != nil {
|
||||
r.Err = err
|
||||
return
|
||||
}
|
||||
_, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// ListOptsBuilder allows extensions to add additional parameters to the
|
||||
// List request.
|
||||
type ListOptsBuilder interface {
|
||||
ToL7PolicyListQuery() (string, error)
|
||||
}
|
||||
|
||||
// ListOpts allows the filtering and sorting of paginated collections through
|
||||
// the API.
|
||||
type ListOpts struct {
|
||||
Name string `q:"name"`
|
||||
Description string `q:"description"`
|
||||
ListenerID string `q:"listener_id"`
|
||||
Action string `q:"action"`
|
||||
TenantID string `q:"tenant_id"`
|
||||
RedirectPoolID string `q:"redirect_pool_id"`
|
||||
RedirectURL string `q:"redirect_url"`
|
||||
Position int32 `q:"position"`
|
||||
AdminStateUp bool `q:"admin_state_up"`
|
||||
ID string `q:"id"`
|
||||
Limit int `q:"limit"`
|
||||
Marker string `q:"marker"`
|
||||
SortKey string `q:"sort_key"`
|
||||
SortDir string `q:"sort_dir"`
|
||||
}
|
||||
|
||||
// ToL7PolicyListQuery formats a ListOpts into a query string.
|
||||
func (opts ListOpts) ToL7PolicyListQuery() (string, error) {
|
||||
q, err := gophercloud.BuildQueryString(opts)
|
||||
return q.String(), err
|
||||
}
|
||||
|
||||
// List returns a Pager which allows you to iterate over a collection of
|
||||
// l7policies. It accepts a ListOpts struct, which allows you to filter and sort
|
||||
// the returned collection for greater efficiency.
|
||||
//
|
||||
// Default policy settings return only those l7policies that are owned by the
|
||||
// project who submits the request, unless an admin user submits the request.
|
||||
func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
|
||||
url := rootURL(c)
|
||||
if opts != nil {
|
||||
query, err := opts.ToL7PolicyListQuery()
|
||||
if err != nil {
|
||||
return pagination.Pager{Err: err}
|
||||
}
|
||||
url += query
|
||||
}
|
||||
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
|
||||
return L7PolicyPage{pagination.LinkedPageBase{PageResult: r}}
|
||||
})
|
||||
}
|
||||
|
||||
// Get retrieves a particular l7policy based on its unique ID.
|
||||
func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
|
||||
_, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete will permanently delete a particular l7policy based on its unique ID.
|
||||
func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
|
||||
_, r.Err = c.Delete(resourceURL(c, id), nil)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateOptsBuilder allows extensions to add additional parameters to the
|
||||
// Update request.
|
||||
type UpdateOptsBuilder interface {
|
||||
ToL7PolicyUpdateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// UpdateOpts is the common options struct used in this package's Update
|
||||
// operation.
|
||||
type UpdateOpts struct {
|
||||
// Name of the L7 policy, empty string is allowed.
|
||||
Name *string `json:"name,omitempty"`
|
||||
|
||||
// The L7 policy action. One of REDIRECT_TO_POOL, REDIRECT_TO_URL, or REJECT.
|
||||
Action Action `json:"action,omitempty"`
|
||||
|
||||
// The position of this policy on the listener.
|
||||
Position int32 `json:"position,omitempty"`
|
||||
|
||||
// A human-readable description for the resource, empty string is allowed.
|
||||
Description *string `json:"description,omitempty"`
|
||||
|
||||
// Requests matching this policy will be redirected to the pool with this ID.
|
||||
// Only valid if action is REDIRECT_TO_POOL.
|
||||
RedirectPoolID *string `json:"redirect_pool_id,omitempty"`
|
||||
|
||||
// Requests matching this policy will be redirected to this URL.
|
||||
// Only valid if action is REDIRECT_TO_URL.
|
||||
RedirectURL *string `json:"redirect_url,omitempty"`
|
||||
|
||||
// The administrative state of the Loadbalancer. A valid value is true (UP)
|
||||
// or false (DOWN).
|
||||
AdminStateUp *bool `json:"admin_state_up,omitempty"`
|
||||
}
|
||||
|
||||
// ToL7PolicyUpdateMap builds a request body from UpdateOpts.
|
||||
func (opts UpdateOpts) ToL7PolicyUpdateMap() (map[string]interface{}, error) {
|
||||
b, err := gophercloud.BuildRequestBody(opts, "l7policy")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m := b["l7policy"].(map[string]interface{})
|
||||
|
||||
if m["redirect_pool_id"] == "" {
|
||||
m["redirect_pool_id"] = nil
|
||||
}
|
||||
|
||||
if m["redirect_url"] == "" {
|
||||
m["redirect_url"] = nil
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// Update allows l7policy to be updated.
|
||||
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
|
||||
b, err := opts.ToL7PolicyUpdateMap()
|
||||
if err != nil {
|
||||
r.Err = err
|
||||
return
|
||||
}
|
||||
_, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// CreateRuleOpts is the common options struct used in this package's CreateRule
|
||||
// operation.
|
||||
type CreateRuleOpts struct {
|
||||
// The L7 rule type. One of COOKIE, FILE_TYPE, HEADER, HOST_NAME, or PATH.
|
||||
RuleType RuleType `json:"type" required:"true"`
|
||||
|
||||
// The comparison type for the L7 rule. One of CONTAINS, ENDS_WITH, EQUAL_TO, REGEX, or STARTS_WITH.
|
||||
CompareType CompareType `json:"compare_type" required:"true"`
|
||||
|
||||
// The value to use for the comparison. For example, the file type to compare.
|
||||
Value string `json:"value" required:"true"`
|
||||
|
||||
// TenantID is the UUID of the tenant who owns the rule in octavia.
|
||||
// Only administrative users can specify a project UUID other than their own.
|
||||
TenantID string `json:"tenant_id,omitempty"`
|
||||
|
||||
// The key to use for the comparison. For example, the name of the cookie to evaluate.
|
||||
Key string `json:"key,omitempty"`
|
||||
|
||||
// When true the logic of the rule is inverted. For example, with invert true,
|
||||
// equal to would become not equal to. Default is false.
|
||||
Invert bool `json:"invert,omitempty"`
|
||||
|
||||
// The administrative state of the Loadbalancer. A valid value is true (UP)
|
||||
// or false (DOWN).
|
||||
AdminStateUp *bool `json:"admin_state_up,omitempty"`
|
||||
}
|
||||
|
||||
// ToRuleCreateMap builds a request body from CreateRuleOpts.
|
||||
func (opts CreateRuleOpts) ToRuleCreateMap() (map[string]interface{}, error) {
|
||||
return gophercloud.BuildRequestBody(opts, "rule")
|
||||
}
|
||||
|
||||
// CreateRule will create and associate a Rule with a particular L7Policy.
|
||||
func CreateRule(c *gophercloud.ServiceClient, policyID string, opts CreateRuleOpts) (r CreateRuleResult) {
|
||||
b, err := opts.ToRuleCreateMap()
|
||||
if err != nil {
|
||||
r.Err = err
|
||||
return
|
||||
}
|
||||
_, r.Err = c.Post(ruleRootURL(c, policyID), b, &r.Body, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// ListRulesOptsBuilder allows extensions to add additional parameters to the
|
||||
// ListRules request.
|
||||
type ListRulesOptsBuilder interface {
|
||||
ToRulesListQuery() (string, error)
|
||||
}
|
||||
|
||||
// ListRulesOpts allows the filtering and sorting of paginated collections
|
||||
// through the API.
|
||||
type ListRulesOpts struct {
|
||||
RuleType RuleType `q:"type"`
|
||||
TenantID string `q:"tenant_id"`
|
||||
CompareType CompareType `q:"compare_type"`
|
||||
Value string `q:"value"`
|
||||
Key string `q:"key"`
|
||||
Invert bool `q:"invert"`
|
||||
AdminStateUp bool `q:"admin_state_up"`
|
||||
ID string `q:"id"`
|
||||
Limit int `q:"limit"`
|
||||
Marker string `q:"marker"`
|
||||
SortKey string `q:"sort_key"`
|
||||
SortDir string `q:"sort_dir"`
|
||||
}
|
||||
|
||||
// ToRulesListQuery formats a ListOpts into a query string.
|
||||
func (opts ListRulesOpts) ToRulesListQuery() (string, error) {
|
||||
q, err := gophercloud.BuildQueryString(opts)
|
||||
return q.String(), err
|
||||
}
|
||||
|
||||
// ListRules returns a Pager which allows you to iterate over a collection of
|
||||
// rules. It accepts a ListRulesOptsBuilder, which allows you to filter and
|
||||
// sort the returned collection for greater efficiency.
|
||||
//
|
||||
// Default policy settings return only those rules that are owned by the
|
||||
// project who submits the request, unless an admin user submits the request.
|
||||
func ListRules(c *gophercloud.ServiceClient, policyID string, opts ListRulesOptsBuilder) pagination.Pager {
|
||||
url := ruleRootURL(c, policyID)
|
||||
if opts != nil {
|
||||
query, err := opts.ToRulesListQuery()
|
||||
if err != nil {
|
||||
return pagination.Pager{Err: err}
|
||||
}
|
||||
url += query
|
||||
}
|
||||
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
|
||||
return RulePage{pagination.LinkedPageBase{PageResult: r}}
|
||||
})
|
||||
}
|
||||
|
||||
// GetRule retrieves a particular L7Policy Rule based on its unique ID.
|
||||
func GetRule(c *gophercloud.ServiceClient, policyID string, ruleID string) (r GetRuleResult) {
|
||||
_, r.Err = c.Get(ruleResourceURL(c, policyID, ruleID), &r.Body, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteRule will remove a Rule from a particular L7Policy.
|
||||
func DeleteRule(c *gophercloud.ServiceClient, policyID string, ruleID string) (r DeleteRuleResult) {
|
||||
_, r.Err = c.Delete(ruleResourceURL(c, policyID, ruleID), nil)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateRuleOptsBuilder allows to add additional parameters to the PUT request.
|
||||
type UpdateRuleOptsBuilder interface {
|
||||
ToRuleUpdateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// UpdateRuleOpts is the common options struct used in this package's Update
|
||||
// operation.
|
||||
type UpdateRuleOpts struct {
|
||||
// The L7 rule type. One of COOKIE, FILE_TYPE, HEADER, HOST_NAME, or PATH.
|
||||
RuleType RuleType `json:"type,omitempty"`
|
||||
|
||||
// The comparison type for the L7 rule. One of CONTAINS, ENDS_WITH, EQUAL_TO, REGEX, or STARTS_WITH.
|
||||
CompareType CompareType `json:"compare_type,omitempty"`
|
||||
|
||||
// The value to use for the comparison. For example, the file type to compare.
|
||||
Value string `json:"value,omitempty"`
|
||||
|
||||
// The key to use for the comparison. For example, the name of the cookie to evaluate.
|
||||
Key *string `json:"key,omitempty"`
|
||||
|
||||
// When true the logic of the rule is inverted. For example, with invert true,
|
||||
// equal to would become not equal to. Default is false.
|
||||
Invert *bool `json:"invert,omitempty"`
|
||||
|
||||
// The administrative state of the Loadbalancer. A valid value is true (UP)
|
||||
// or false (DOWN).
|
||||
AdminStateUp *bool `json:"admin_state_up,omitempty"`
|
||||
}
|
||||
|
||||
// ToRuleUpdateMap builds a request body from UpdateRuleOpts.
|
||||
func (opts UpdateRuleOpts) ToRuleUpdateMap() (map[string]interface{}, error) {
|
||||
b, err := gophercloud.BuildRequestBody(opts, "rule")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if m := b["rule"].(map[string]interface{}); m["key"] == "" {
|
||||
m["key"] = nil
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// UpdateRule allows Rule to be updated.
|
||||
func UpdateRule(c *gophercloud.ServiceClient, policyID string, ruleID string, opts UpdateRuleOptsBuilder) (r UpdateRuleResult) {
|
||||
b, err := opts.ToRuleUpdateMap()
|
||||
if err != nil {
|
||||
r.Err = err
|
||||
return
|
||||
}
|
||||
_, r.Err = c.Put(ruleResourceURL(c, policyID, ruleID), b, &r.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200, 201, 202},
|
||||
})
|
||||
return
|
||||
}
|
245
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/l7policies/results.go
generated
vendored
Normal file
245
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/l7policies/results.go
generated
vendored
Normal file
|
@ -0,0 +1,245 @@
|
|||
package l7policies
|
||||
|
||||
import (
|
||||
"github.com/gophercloud/gophercloud"
|
||||
"github.com/gophercloud/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// L7Policy is a collection of L7 rules associated with a Listener, and which
|
||||
// may also have an association to a back-end pool.
|
||||
type L7Policy struct {
|
||||
// The unique ID for the L7 policy.
|
||||
ID string `json:"id"`
|
||||
|
||||
// Name of the L7 policy.
|
||||
Name string `json:"name"`
|
||||
|
||||
// The ID of the listener.
|
||||
ListenerID string `json:"listener_id"`
|
||||
|
||||
// The L7 policy action. One of REDIRECT_TO_POOL, REDIRECT_TO_URL, or REJECT.
|
||||
Action string `json:"action"`
|
||||
|
||||
// The position of this policy on the listener.
|
||||
Position int32 `json:"position"`
|
||||
|
||||
// A human-readable description for the resource.
|
||||
Description string `json:"description"`
|
||||
|
||||
// TenantID is the UUID of the tenant who owns the L7 policy in octavia.
|
||||
// Only administrative users can specify a project UUID other than their own.
|
||||
TenantID string `json:"tenant_id"`
|
||||
|
||||
// Requests matching this policy will be redirected to the pool with this ID.
|
||||
// Only valid if action is REDIRECT_TO_POOL.
|
||||
RedirectPoolID string `json:"redirect_pool_id"`
|
||||
|
||||
// Requests matching this policy will be redirected to this URL.
|
||||
// Only valid if action is REDIRECT_TO_URL.
|
||||
RedirectURL string `json:"redirect_url"`
|
||||
|
||||
// The administrative state of the L7 policy, which is up (true) or down (false).
|
||||
AdminStateUp bool `json:"admin_state_up"`
|
||||
|
||||
// The provisioning status of the L7 policy.
|
||||
// This value is ACTIVE, PENDING_* or ERROR.
|
||||
// This field seems to only be returned during a call to a load balancer's /status
|
||||
// see: https://github.com/gophercloud/gophercloud/issues/1362
|
||||
ProvisioningStatus string `json:"provisioning_status"`
|
||||
|
||||
// The operating status of the L7 policy.
|
||||
// This field seems to only be returned during a call to a load balancer's /status
|
||||
// see: https://github.com/gophercloud/gophercloud/issues/1362
|
||||
OperatingStatus string `json:"operating_status"`
|
||||
|
||||
// Rules are List of associated L7 rule IDs.
|
||||
Rules []Rule `json:"rules"`
|
||||
}
|
||||
|
||||
// Rule represents layer 7 load balancing rule.
|
||||
type Rule struct {
|
||||
// The unique ID for the L7 rule.
|
||||
ID string `json:"id"`
|
||||
|
||||
// The L7 rule type. One of COOKIE, FILE_TYPE, HEADER, HOST_NAME, or PATH.
|
||||
RuleType string `json:"type"`
|
||||
|
||||
// The comparison type for the L7 rule. One of CONTAINS, ENDS_WITH, EQUAL_TO, REGEX, or STARTS_WITH.
|
||||
CompareType string `json:"compare_type"`
|
||||
|
||||
// The value to use for the comparison. For example, the file type to compare.
|
||||
Value string `json:"value"`
|
||||
|
||||
// TenantID is the UUID of the tenant who owns the rule in octavia.
|
||||
// Only administrative users can specify a project UUID other than their own.
|
||||
TenantID string `json:"tenant_id"`
|
||||
|
||||
// The key to use for the comparison. For example, the name of the cookie to evaluate.
|
||||
Key string `json:"key"`
|
||||
|
||||
// When true the logic of the rule is inverted. For example, with invert true,
|
||||
// equal to would become not equal to. Default is false.
|
||||
Invert bool `json:"invert"`
|
||||
|
||||
// The administrative state of the L7 rule, which is up (true) or down (false).
|
||||
AdminStateUp bool `json:"admin_state_up"`
|
||||
|
||||
// The provisioning status of the L7 rule.
|
||||
// This value is ACTIVE, PENDING_* or ERROR.
|
||||
// This field seems to only be returned during a call to a load balancer's /status
|
||||
// see: https://github.com/gophercloud/gophercloud/issues/1362
|
||||
ProvisioningStatus string `json:"provisioning_status"`
|
||||
|
||||
// The operating status of the L7 policy.
|
||||
// This field seems to only be returned during a call to a load balancer's /status
|
||||
// see: https://github.com/gophercloud/gophercloud/issues/1362
|
||||
OperatingStatus string `json:"operating_status"`
|
||||
}
|
||||
|
||||
type commonResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// Extract is a function that accepts a result and extracts a l7policy.
|
||||
func (r commonResult) Extract() (*L7Policy, error) {
|
||||
var s struct {
|
||||
L7Policy *L7Policy `json:"l7policy"`
|
||||
}
|
||||
err := r.ExtractInto(&s)
|
||||
return s.L7Policy, err
|
||||
}
|
||||
|
||||
// CreateResult represents the result of a Create operation. Call its Extract
|
||||
// method to interpret the result as a L7Policy.
|
||||
type CreateResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// L7PolicyPage is the page returned by a pager when traversing over a
|
||||
// collection of l7policies.
|
||||
type L7PolicyPage struct {
|
||||
pagination.LinkedPageBase
|
||||
}
|
||||
|
||||
// NextPageURL is invoked when a paginated collection of l7policies has reached
|
||||
// the end of a page and the pager seeks to traverse over a new one. In order
|
||||
// to do this, it needs to construct the next page's URL.
|
||||
func (r L7PolicyPage) NextPageURL() (string, error) {
|
||||
var s struct {
|
||||
Links []gophercloud.Link `json:"l7policies_links"`
|
||||
}
|
||||
err := r.ExtractInto(&s)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return gophercloud.ExtractNextURL(s.Links)
|
||||
}
|
||||
|
||||
// IsEmpty checks whether a L7PolicyPage struct is empty.
|
||||
func (r L7PolicyPage) IsEmpty() (bool, error) {
|
||||
is, err := ExtractL7Policies(r)
|
||||
return len(is) == 0, err
|
||||
}
|
||||
|
||||
// ExtractL7Policies accepts a Page struct, specifically a L7PolicyPage struct,
|
||||
// and extracts the elements into a slice of L7Policy structs. In other words,
|
||||
// a generic collection is mapped into a relevant slice.
|
||||
func ExtractL7Policies(r pagination.Page) ([]L7Policy, error) {
|
||||
var s struct {
|
||||
L7Policies []L7Policy `json:"l7policies"`
|
||||
}
|
||||
err := (r.(L7PolicyPage)).ExtractInto(&s)
|
||||
return s.L7Policies, err
|
||||
}
|
||||
|
||||
// GetResult represents the result of a Get operation. Call its Extract
|
||||
// method to interpret the result as a L7Policy.
|
||||
type GetResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// DeleteResult represents the result of a Delete operation. Call its
|
||||
// ExtractErr method to determine if the request succeeded or failed.
|
||||
type DeleteResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
|
||||
// UpdateResult represents the result of an Update operation. Call its Extract
|
||||
// method to interpret the result as a L7Policy.
|
||||
type UpdateResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
type commonRuleResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// Extract is a function that accepts a result and extracts a rule.
|
||||
func (r commonRuleResult) Extract() (*Rule, error) {
|
||||
var s struct {
|
||||
Rule *Rule `json:"rule"`
|
||||
}
|
||||
err := r.ExtractInto(&s)
|
||||
return s.Rule, err
|
||||
}
|
||||
|
||||
// CreateRuleResult represents the result of a CreateRule operation.
|
||||
// Call its Extract method to interpret it as a Rule.
|
||||
type CreateRuleResult struct {
|
||||
commonRuleResult
|
||||
}
|
||||
|
||||
// RulePage is the page returned by a pager when traversing over a
|
||||
// collection of Rules in a L7Policy.
|
||||
type RulePage struct {
|
||||
pagination.LinkedPageBase
|
||||
}
|
||||
|
||||
// NextPageURL is invoked when a paginated collection of rules has reached
|
||||
// the end of a page and the pager seeks to traverse over a new one. In order
|
||||
// to do this, it needs to construct the next page's URL.
|
||||
func (r RulePage) NextPageURL() (string, error) {
|
||||
var s struct {
|
||||
Links []gophercloud.Link `json:"rules_links"`
|
||||
}
|
||||
err := r.ExtractInto(&s)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return gophercloud.ExtractNextURL(s.Links)
|
||||
}
|
||||
|
||||
// IsEmpty checks whether a RulePage struct is empty.
|
||||
func (r RulePage) IsEmpty() (bool, error) {
|
||||
is, err := ExtractRules(r)
|
||||
return len(is) == 0, err
|
||||
}
|
||||
|
||||
// ExtractRules accepts a Page struct, specifically a RulePage struct,
|
||||
// and extracts the elements into a slice of Rules structs. In other words,
|
||||
// a generic collection is mapped into a relevant slice.
|
||||
func ExtractRules(r pagination.Page) ([]Rule, error) {
|
||||
var s struct {
|
||||
Rules []Rule `json:"rules"`
|
||||
}
|
||||
err := (r.(RulePage)).ExtractInto(&s)
|
||||
return s.Rules, err
|
||||
}
|
||||
|
||||
// GetRuleResult represents the result of a GetRule operation.
|
||||
// Call its Extract method to interpret it as a Rule.
|
||||
type GetRuleResult struct {
|
||||
commonRuleResult
|
||||
}
|
||||
|
||||
// DeleteRuleResult represents the result of a DeleteRule operation.
|
||||
// Call its ExtractErr method to determine if the request succeeded or failed.
|
||||
type DeleteRuleResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
|
||||
// UpdateRuleResult represents the result of an UpdateRule operation.
|
||||
// Call its Extract method to interpret it as a Rule.
|
||||
type UpdateRuleResult struct {
|
||||
commonRuleResult
|
||||
}
|
25
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/l7policies/urls.go
generated
vendored
Normal file
25
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/l7policies/urls.go
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
package l7policies
|
||||
|
||||
import "github.com/gophercloud/gophercloud"
|
||||
|
||||
const (
|
||||
rootPath = "lbaas"
|
||||
resourcePath = "l7policies"
|
||||
rulePath = "rules"
|
||||
)
|
||||
|
||||
func rootURL(c *gophercloud.ServiceClient) string {
|
||||
return c.ServiceURL(rootPath, resourcePath)
|
||||
}
|
||||
|
||||
func resourceURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return c.ServiceURL(rootPath, resourcePath, id)
|
||||
}
|
||||
|
||||
func ruleRootURL(c *gophercloud.ServiceClient, policyID string) string {
|
||||
return c.ServiceURL(rootPath, resourcePath, policyID, rulePath)
|
||||
}
|
||||
|
||||
func ruleResourceURL(c *gophercloud.ServiceClient, policyID string, ruleID string) string {
|
||||
return c.ServiceURL(rootPath, resourcePath, policyID, rulePath, ruleID)
|
||||
}
|
|
@ -13,6 +13,7 @@ go_library(
|
|||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//vendor/github.com/gophercloud/gophercloud:go_default_library",
|
||||
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/l7policies:go_default_library",
|
||||
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools:go_default_library",
|
||||
"//vendor/github.com/gophercloud/gophercloud/pagination:go_default_library",
|
||||
],
|
||||
|
|
|
@ -10,9 +10,10 @@ type Protocol string
|
|||
|
||||
// Supported attributes for create/update operations.
|
||||
const (
|
||||
ProtocolTCP Protocol = "TCP"
|
||||
ProtocolHTTP Protocol = "HTTP"
|
||||
ProtocolHTTPS Protocol = "HTTPS"
|
||||
ProtocolTCP Protocol = "TCP"
|
||||
ProtocolHTTP Protocol = "HTTP"
|
||||
ProtocolHTTPS Protocol = "HTTPS"
|
||||
ProtocolTerminatedHTTPS Protocol = "TERMINATED_HTTPS"
|
||||
)
|
||||
|
||||
// ListOptsBuilder allows extensions to add additional parameters to the
|
||||
|
@ -154,10 +155,13 @@ type UpdateOptsBuilder interface {
|
|||
// UpdateOpts represents options for updating a Listener.
|
||||
type UpdateOpts struct {
|
||||
// Human-readable name for the Listener. Does not have to be unique.
|
||||
Name string `json:"name,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
|
||||
// The ID of the default pool with which the Listener is associated.
|
||||
DefaultPoolID *string `json:"default_pool_id,omitempty"`
|
||||
|
||||
// Human-readable description for the Listener.
|
||||
Description string `json:"description,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
|
||||
// The maximum number of connections allowed for the Listener.
|
||||
ConnLimit *int `json:"connection_limit,omitempty"`
|
||||
|
@ -175,7 +179,16 @@ type UpdateOpts struct {
|
|||
|
||||
// ToListenerUpdateMap builds a request body from UpdateOpts.
|
||||
func (opts UpdateOpts) ToListenerUpdateMap() (map[string]interface{}, error) {
|
||||
return gophercloud.BuildRequestBody(opts, "listener")
|
||||
b, err := gophercloud.BuildRequestBody(opts, "listener")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if m := b["listener"].(map[string]interface{}); m["default_pool_id"] == "" {
|
||||
m["default_pool_id"] = nil
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// Update is an operation which modifies the attributes of the specified
|
||||
|
|
|
@ -2,6 +2,7 @@ package listeners
|
|||
|
||||
import (
|
||||
"github.com/gophercloud/gophercloud"
|
||||
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/l7policies"
|
||||
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools"
|
||||
"github.com/gophercloud/gophercloud/pagination"
|
||||
)
|
||||
|
@ -54,6 +55,15 @@ type Listener struct {
|
|||
|
||||
// Pools are the pools which are part of this listener.
|
||||
Pools []pools.Pool `json:"pools"`
|
||||
|
||||
// L7policies are the L7 policies which are part of this listener.
|
||||
// This field seems to only be returned during a call to a load balancer's /status
|
||||
// see: https://github.com/gophercloud/gophercloud/issues/1352
|
||||
L7Policies []l7policies.L7Policy `json:"l7policies"`
|
||||
|
||||
// The provisioning status of the listener.
|
||||
// This value is ACTIVE, PENDING_* or ERROR.
|
||||
ProvisioningStatus string `json:"provisioning_status"`
|
||||
}
|
||||
|
||||
// ListenerPage is the page returned by a pager when traversing over a
|
||||
|
|
|
@ -14,6 +14,7 @@ go_library(
|
|||
deps = [
|
||||
"//vendor/github.com/gophercloud/gophercloud:go_default_library",
|
||||
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners:go_default_library",
|
||||
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools:go_default_library",
|
||||
"//vendor/github.com/gophercloud/gophercloud/pagination:go_default_library",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -67,5 +67,13 @@ Example to Get the Status of a Load Balancer
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Get the Statistics of a Load Balancer
|
||||
|
||||
lbID := "d67d56a6-4a86-4688-a282-f46444705c64"
|
||||
stats, err := loadbalancers.GetStats(networkClient, LBID).Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
*/
|
||||
package loadbalancers
|
||||
|
|
|
@ -141,10 +141,10 @@ type UpdateOptsBuilder interface {
|
|||
// operation.
|
||||
type UpdateOpts struct {
|
||||
// Human-readable name for the Loadbalancer. Does not have to be unique.
|
||||
Name string `json:"name,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
|
||||
// Human-readable description for the Loadbalancer.
|
||||
Description string `json:"description,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
|
||||
// The administrative state of the Loadbalancer. A valid value is true (UP)
|
||||
// or false (DOWN).
|
||||
|
@ -196,3 +196,9 @@ func GetStatuses(c *gophercloud.ServiceClient, id string) (r GetStatusesResult)
|
|||
_, r.Err = c.Get(statusRootURL(c, id), &r.Body, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// GetStats will return the shows the current statistics of a particular LoadBalancer.
|
||||
func GetStats(c *gophercloud.ServiceClient, id string) (r StatsResult) {
|
||||
_, r.Err = c.Get(statisticsRootURL(c, id), &r.Body, nil)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package loadbalancers
|
|||
import (
|
||||
"github.com/gophercloud/gophercloud"
|
||||
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners"
|
||||
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools"
|
||||
"github.com/gophercloud/gophercloud/pagination"
|
||||
)
|
||||
|
||||
|
@ -51,6 +52,9 @@ type LoadBalancer struct {
|
|||
|
||||
// Listeners are the listeners related to this Loadbalancer.
|
||||
Listeners []listeners.Listener `json:"listeners"`
|
||||
|
||||
// Pools are the pools related to this Loadbalancer.
|
||||
Pools []pools.Pool `json:"pools"`
|
||||
}
|
||||
|
||||
// StatusTree represents the status of a loadbalancer.
|
||||
|
@ -58,6 +62,23 @@ type StatusTree struct {
|
|||
Loadbalancer *LoadBalancer `json:"loadbalancer"`
|
||||
}
|
||||
|
||||
type Stats struct {
|
||||
// The currently active connections.
|
||||
ActiveConnections int `json:"active_connections"`
|
||||
|
||||
// The total bytes received.
|
||||
BytesIn int `json:"bytes_in"`
|
||||
|
||||
// The total bytes sent.
|
||||
BytesOut int `json:"bytes_out"`
|
||||
|
||||
// The total requests that were unable to be fulfilled.
|
||||
RequestErrors int `json:"request_errors"`
|
||||
|
||||
// The total connections handled.
|
||||
TotalConnections int `json:"total_connections"`
|
||||
}
|
||||
|
||||
// LoadBalancerPage is the page returned by a pager when traversing over a
|
||||
// collection of load balancers.
|
||||
type LoadBalancerPage struct {
|
||||
|
@ -124,6 +145,22 @@ func (r GetStatusesResult) Extract() (*StatusTree, error) {
|
|||
return s.Statuses, err
|
||||
}
|
||||
|
||||
// StatsResult represents the result of a GetStats operation.
|
||||
// Call its Extract method to interpret it as a Stats.
|
||||
type StatsResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// Extract is a function that accepts a result and extracts the status of
|
||||
// a Loadbalancer.
|
||||
func (r StatsResult) Extract() (*Stats, error) {
|
||||
var s struct {
|
||||
Stats *Stats `json:"stats"`
|
||||
}
|
||||
err := r.ExtractInto(&s)
|
||||
return s.Stats, err
|
||||
}
|
||||
|
||||
// CreateResult represents the result of a create operation. Call its Extract
|
||||
// method to interpret it as a LoadBalancer.
|
||||
type CreateResult struct {
|
||||
|
|
|
@ -3,9 +3,10 @@ package loadbalancers
|
|||
import "github.com/gophercloud/gophercloud"
|
||||
|
||||
const (
|
||||
rootPath = "lbaas"
|
||||
resourcePath = "loadbalancers"
|
||||
statusPath = "statuses"
|
||||
rootPath = "lbaas"
|
||||
resourcePath = "loadbalancers"
|
||||
statusPath = "statuses"
|
||||
statisticsPath = "stats"
|
||||
)
|
||||
|
||||
func rootURL(c *gophercloud.ServiceClient) string {
|
||||
|
@ -19,3 +20,7 @@ func resourceURL(c *gophercloud.ServiceClient, id string) string {
|
|||
func statusRootURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return c.ServiceURL(rootPath, resourcePath, id, statusPath)
|
||||
}
|
||||
|
||||
func statisticsRootURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return c.ServiceURL(rootPath, resourcePath, id, statisticsPath)
|
||||
}
|
||||
|
|
|
@ -223,7 +223,7 @@ type UpdateOpts struct {
|
|||
ExpectedCodes string `json:"expected_codes,omitempty"`
|
||||
|
||||
// The Name of the Monitor.
|
||||
Name string `json:"name,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
|
||||
// The administrative state of the Monitor. A valid value is true (UP)
|
||||
// or false (DOWN).
|
||||
|
|
|
@ -70,6 +70,10 @@ type Monitor struct {
|
|||
|
||||
// List of pools that are associated with the health monitor.
|
||||
Pools []PoolID `json:"pools"`
|
||||
|
||||
// The provisioning status of the monitor.
|
||||
// This value is ACTIVE, PENDING_* or ERROR.
|
||||
ProvisioningStatus string `json:"provisioning_status"`
|
||||
}
|
||||
|
||||
// MonitorPage is the page returned by a pager when traversing over a
|
||||
|
|
|
@ -13,7 +13,7 @@ Example to List Pools
|
|||
panic(err)
|
||||
}
|
||||
|
||||
allPools, err := pools.ExtractMonitors(allPages)
|
||||
allPools, err := pools.ExtractPools(allPages)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -83,12 +83,13 @@ Example to Create a Member
|
|||
|
||||
poolID := "d67d56a6-4a86-4688-a282-f46444705c64"
|
||||
|
||||
weight := 10
|
||||
createOpts := pools.CreateMemberOpts{
|
||||
Name: "db",
|
||||
SubnetID: "1981f108-3c48-48d2-b908-30f7d28532c9",
|
||||
Address: "10.0.2.11",
|
||||
ProtocolPort: 80,
|
||||
Weight: 10,
|
||||
Weight: &weight,
|
||||
}
|
||||
|
||||
member, err := pools.CreateMember(networkClient, poolID, createOpts).Extract()
|
||||
|
@ -101,9 +102,10 @@ Example to Update a Member
|
|||
poolID := "d67d56a6-4a86-4688-a282-f46444705c64"
|
||||
memberID := "64dba99f-8af8-4200-8882-e32a0660f23e"
|
||||
|
||||
weight := 4
|
||||
updateOpts := pools.UpdateMemberOpts{
|
||||
Name: "new-name",
|
||||
Weight: 4,
|
||||
Weight: &weight,
|
||||
}
|
||||
|
||||
member, err := pools.UpdateMember(networkClient, poolID, memberID, updateOpts).Extract()
|
||||
|
|
|
@ -154,10 +154,10 @@ type UpdateOptsBuilder interface {
|
|||
// operation.
|
||||
type UpdateOpts struct {
|
||||
// Name of the pool.
|
||||
Name string `json:"name,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
|
||||
// Human-readable description for the pool.
|
||||
Description string `json:"description,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
|
||||
// The algorithm used to distribute load between the members of the pool. The
|
||||
// current specification supports LBMethodRoundRobin, LBMethodLeastConnections
|
||||
|
@ -274,7 +274,7 @@ type CreateMemberOpts struct {
|
|||
// that this member should receive from the pool. For example, a member with
|
||||
// a weight of 10 receives five times as much traffic as a member with a
|
||||
// weight of 2.
|
||||
Weight int `json:"weight,omitempty"`
|
||||
Weight *int `json:"weight,omitempty"`
|
||||
|
||||
// If you omit this parameter, LBaaS uses the vip_subnet_id parameter value
|
||||
// for the subnet UUID.
|
||||
|
@ -317,13 +317,13 @@ type UpdateMemberOptsBuilder interface {
|
|||
// operation.
|
||||
type UpdateMemberOpts struct {
|
||||
// Name of the Member.
|
||||
Name string `json:"name,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
|
||||
// A positive integer value that indicates the relative portion of traffic
|
||||
// that this member should receive from the pool. For example, a member with
|
||||
// a weight of 10 receives five times as much traffic as a member with a
|
||||
// weight of 2.
|
||||
Weight int `json:"weight,omitempty"`
|
||||
Weight *int `json:"weight,omitempty"`
|
||||
|
||||
// The administrative state of the Pool. A valid value is true (UP)
|
||||
// or false (DOWN).
|
||||
|
|
|
@ -92,6 +92,15 @@ type Pool struct {
|
|||
|
||||
// The Monitor associated with this Pool.
|
||||
Monitor monitors.Monitor `json:"healthmonitor"`
|
||||
|
||||
// The provisioning status of the pool.
|
||||
// This value is ACTIVE, PENDING_* or ERROR.
|
||||
ProvisioningStatus string `json:"provisioning_status"`
|
||||
|
||||
// The operating status of the pool.
|
||||
// This field seems to only be returned during a call to a load balancer's /status
|
||||
// see: https://github.com/gophercloud/gophercloud/issues/1362
|
||||
OperatingStatus string `json:"operating_status"`
|
||||
}
|
||||
|
||||
// PoolPage is the page returned by a pager when traversing over a
|
||||
|
@ -196,6 +205,15 @@ type Member struct {
|
|||
|
||||
// The unique ID for the Member.
|
||||
ID string `json:"id"`
|
||||
|
||||
// The provisioning status of the member.
|
||||
// This value is ACTIVE, PENDING_* or ERROR.
|
||||
ProvisioningStatus string `json:"provisioning_status"`
|
||||
|
||||
// The operating status of the member.
|
||||
// This field seems to only be returned during a call to a load balancer's /status
|
||||
// see: https://github.com/gophercloud/gophercloud/issues/1362
|
||||
OperatingStatus string `json:"operating_status"`
|
||||
}
|
||||
|
||||
// MemberPage is the page returned by a pager when traversing over a
|
||||
|
|
|
@ -11,14 +11,19 @@ import (
|
|||
// sort by a particular network attribute. SortDir sets the direction, and is
|
||||
// either `asc' or `desc'. Marker and Limit are used for pagination.
|
||||
type ListOpts struct {
|
||||
ID string `q:"id"`
|
||||
Name string `q:"name"`
|
||||
TenantID string `q:"tenant_id"`
|
||||
ProjectID string `q:"project_id"`
|
||||
Limit int `q:"limit"`
|
||||
Marker string `q:"marker"`
|
||||
SortKey string `q:"sort_key"`
|
||||
SortDir string `q:"sort_dir"`
|
||||
ID string `q:"id"`
|
||||
Name string `q:"name"`
|
||||
Description string `q:"description"`
|
||||
TenantID string `q:"tenant_id"`
|
||||
ProjectID string `q:"project_id"`
|
||||
Limit int `q:"limit"`
|
||||
Marker string `q:"marker"`
|
||||
SortKey string `q:"sort_key"`
|
||||
SortDir string `q:"sort_dir"`
|
||||
Tags string `q:"tags"`
|
||||
TagsAny string `q:"tags-any"`
|
||||
NotTags string `q:"not-tags"`
|
||||
NotTagsAny string `q:"not-tags-any"`
|
||||
}
|
||||
|
||||
// List returns a Pager which allows you to iterate over a collection of
|
||||
|
@ -88,7 +93,7 @@ type UpdateOpts struct {
|
|||
Name string `json:"name,omitempty"`
|
||||
|
||||
// Describes the security group.
|
||||
Description string `json:"description,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
}
|
||||
|
||||
// ToSecGroupUpdateMap builds a request body from UpdateOpts.
|
||||
|
@ -128,7 +133,12 @@ func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
|
|||
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
|
||||
count := 0
|
||||
id := ""
|
||||
pages, err := List(client, ListOpts{}).AllPages()
|
||||
|
||||
listOpts := ListOpts{
|
||||
Name: name,
|
||||
}
|
||||
|
||||
pages, err := List(client, listOpts).AllPages()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
@ -27,6 +27,9 @@ type SecGroup struct {
|
|||
|
||||
// ProjectID is the project owner of the security group.
|
||||
ProjectID string `json:"project_id"`
|
||||
|
||||
// Tags optionally set via extensions/attributestags
|
||||
Tags []string `json:"tags"`
|
||||
}
|
||||
|
||||
// SecGroupPage is the page returned by a pager when traversing over a
|
||||
|
|
|
@ -14,6 +14,7 @@ type ListOpts struct {
|
|||
Direction string `q:"direction"`
|
||||
EtherType string `q:"ethertype"`
|
||||
ID string `q:"id"`
|
||||
Description string `q:"description"`
|
||||
PortRangeMax int `q:"port_range_max"`
|
||||
PortRangeMin int `q:"port_range_min"`
|
||||
Protocol string `q:"protocol"`
|
||||
|
@ -88,6 +89,9 @@ type CreateOpts struct {
|
|||
// group rule is applied.
|
||||
Direction RuleDirection `json:"direction" required:"true"`
|
||||
|
||||
// String description of each rule, optional
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// Must be "IPv4" or "IPv6", and addresses represented in CIDR must match the
|
||||
// ingress or egress rules.
|
||||
EtherType RuleEtherType `json:"ethertype" required:"true"`
|
||||
|
|
|
@ -17,6 +17,9 @@ type SecGroupRule struct {
|
|||
// instance. An egress rule is applied to traffic leaving the instance.
|
||||
Direction string
|
||||
|
||||
// Descripton of the rule
|
||||
Description string `json:"description"`
|
||||
|
||||
// Must be IPv4 or IPv6, and addresses represented in CIDR must match the
|
||||
// ingress or egress rules.
|
||||
EtherType string `json:"ethertype"`
|
||||
|
|
20
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/requests.go
generated
vendored
20
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/requests.go
generated
vendored
|
@ -19,6 +19,7 @@ type ListOptsBuilder interface {
|
|||
type ListOpts struct {
|
||||
Status string `q:"status"`
|
||||
Name string `q:"name"`
|
||||
Description string `q:"description"`
|
||||
AdminStateUp *bool `q:"admin_state_up"`
|
||||
TenantID string `q:"tenant_id"`
|
||||
ProjectID string `q:"project_id"`
|
||||
|
@ -28,6 +29,10 @@ type ListOpts struct {
|
|||
Limit int `q:"limit"`
|
||||
SortKey string `q:"sort_key"`
|
||||
SortDir string `q:"sort_dir"`
|
||||
Tags string `q:"tags"`
|
||||
TagsAny string `q:"tags-any"`
|
||||
NotTags string `q:"not-tags"`
|
||||
NotTagsAny string `q:"not-tags-any"`
|
||||
}
|
||||
|
||||
// ToNetworkListQuery formats a ListOpts into a query string.
|
||||
|
@ -69,6 +74,7 @@ type CreateOptsBuilder interface {
|
|||
type CreateOpts struct {
|
||||
AdminStateUp *bool `json:"admin_state_up,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Shared *bool `json:"shared,omitempty"`
|
||||
TenantID string `json:"tenant_id,omitempty"`
|
||||
ProjectID string `json:"project_id,omitempty"`
|
||||
|
@ -105,9 +111,10 @@ type UpdateOptsBuilder interface {
|
|||
|
||||
// UpdateOpts represents options used to update a network.
|
||||
type UpdateOpts struct {
|
||||
AdminStateUp *bool `json:"admin_state_up,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Shared *bool `json:"shared,omitempty"`
|
||||
AdminStateUp *bool `json:"admin_state_up,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
Shared *bool `json:"shared,omitempty"`
|
||||
}
|
||||
|
||||
// ToNetworkUpdateMap builds a request body from UpdateOpts.
|
||||
|
@ -140,7 +147,12 @@ func Delete(c *gophercloud.ServiceClient, networkID string) (r DeleteResult) {
|
|||
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
|
||||
count := 0
|
||||
id := ""
|
||||
pages, err := List(client, nil).AllPages()
|
||||
|
||||
listOpts := ListOpts{
|
||||
Name: name,
|
||||
}
|
||||
|
||||
pages, err := List(client, listOpts).AllPages()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
@ -52,6 +52,9 @@ type Network struct {
|
|||
// Human-readable name for the network. Might not be unique.
|
||||
Name string `json:"name"`
|
||||
|
||||
// Description for the network
|
||||
Description string `json:"description"`
|
||||
|
||||
// The administrative state of network. If false (down), the network does not
|
||||
// forward packets.
|
||||
AdminStateUp bool `json:"admin_state_up"`
|
||||
|
@ -76,6 +79,9 @@ type Network struct {
|
|||
// Availability zone hints groups network nodes that run services like DHCP, L3, FW, and others.
|
||||
// Used to make network resources highly available.
|
||||
AvailabilityZoneHints []string `json:"availability_zone_hints"`
|
||||
|
||||
// Tags optionally set via extensions/attributestags
|
||||
Tags []string `json:"tags"`
|
||||
}
|
||||
|
||||
// NetworkPage is the page returned by a pager when traversing over a
|
||||
|
|
20
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports/requests.go
generated
vendored
20
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports/requests.go
generated
vendored
|
@ -19,6 +19,7 @@ type ListOptsBuilder interface {
|
|||
type ListOpts struct {
|
||||
Status string `q:"status"`
|
||||
Name string `q:"name"`
|
||||
Description string `q:"description"`
|
||||
AdminStateUp *bool `q:"admin_state_up"`
|
||||
NetworkID string `q:"network_id"`
|
||||
TenantID string `q:"tenant_id"`
|
||||
|
@ -31,6 +32,10 @@ type ListOpts struct {
|
|||
Marker string `q:"marker"`
|
||||
SortKey string `q:"sort_key"`
|
||||
SortDir string `q:"sort_dir"`
|
||||
Tags string `q:"tags"`
|
||||
TagsAny string `q:"tags-any"`
|
||||
NotTags string `q:"not-tags"`
|
||||
NotTagsAny string `q:"not-tags-any"`
|
||||
}
|
||||
|
||||
// ToPortListQuery formats a ListOpts into a query string.
|
||||
|
@ -76,6 +81,7 @@ type CreateOptsBuilder interface {
|
|||
type CreateOpts struct {
|
||||
NetworkID string `json:"network_id" required:"true"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
AdminStateUp *bool `json:"admin_state_up,omitempty"`
|
||||
MACAddress string `json:"mac_address,omitempty"`
|
||||
FixedIPs interface{} `json:"fixed_ips,omitempty"`
|
||||
|
@ -112,11 +118,12 @@ type UpdateOptsBuilder interface {
|
|||
|
||||
// UpdateOpts represents the attributes used when updating an existing port.
|
||||
type UpdateOpts struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
AdminStateUp *bool `json:"admin_state_up,omitempty"`
|
||||
FixedIPs interface{} `json:"fixed_ips,omitempty"`
|
||||
DeviceID string `json:"device_id,omitempty"`
|
||||
DeviceOwner string `json:"device_owner,omitempty"`
|
||||
DeviceID *string `json:"device_id,omitempty"`
|
||||
DeviceOwner *string `json:"device_owner,omitempty"`
|
||||
SecurityGroups *[]string `json:"security_groups,omitempty"`
|
||||
AllowedAddressPairs *[]AddressPair `json:"allowed_address_pairs,omitempty"`
|
||||
}
|
||||
|
@ -151,7 +158,12 @@ func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
|
|||
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
|
||||
count := 0
|
||||
id := ""
|
||||
pages, err := List(client, nil).AllPages()
|
||||
|
||||
listOpts := ListOpts{
|
||||
Name: name,
|
||||
}
|
||||
|
||||
pages, err := List(client, listOpts).AllPages()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
6
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports/results.go
generated
vendored
6
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports/results.go
generated
vendored
|
@ -68,6 +68,9 @@ type Port struct {
|
|||
// Human-readable name for the port. Might not be unique.
|
||||
Name string `json:"name"`
|
||||
|
||||
// Describes the port.
|
||||
Description string `json:"description"`
|
||||
|
||||
// Administrative state of port. If false (down), port does not forward
|
||||
// packets.
|
||||
AdminStateUp bool `json:"admin_state_up"`
|
||||
|
@ -101,6 +104,9 @@ type Port struct {
|
|||
|
||||
// Identifies the list of IP addresses the port will recognize/accept
|
||||
AllowedAddressPairs []AddressPair `json:"allowed_address_pairs"`
|
||||
|
||||
// Tags optionally set via extensions/attributestags
|
||||
Tags []string `json:"tags"`
|
||||
}
|
||||
|
||||
// PortPage is the page returned by a pager when traversing over a collection
|
||||
|
|
|
@ -2,7 +2,10 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["choose_version.go"],
|
||||
srcs = [
|
||||
"base_endpoint.go",
|
||||
"choose_version.go",
|
||||
],
|
||||
importmap = "k8s.io/kubernetes/vendor/github.com/gophercloud/gophercloud/openstack/utils",
|
||||
importpath = "github.com/gophercloud/gophercloud/openstack/utils",
|
||||
visibility = ["//visibility:public"],
|
||||
|
|
28
vendor/github.com/gophercloud/gophercloud/openstack/utils/base_endpoint.go
generated
vendored
Normal file
28
vendor/github.com/gophercloud/gophercloud/openstack/utils/base_endpoint.go
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// BaseEndpoint will return a URL without the /vX.Y
|
||||
// portion of the URL.
|
||||
func BaseEndpoint(endpoint string) (string, error) {
|
||||
u, err := url.Parse(endpoint)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
u.RawQuery, u.Fragment = "", ""
|
||||
|
||||
path := u.Path
|
||||
versionRe := regexp.MustCompile("v[0-9.]+/?")
|
||||
|
||||
if version := versionRe.FindString(path); version != "" {
|
||||
versionIndex := strings.Index(path, version)
|
||||
u.Path = path[:versionIndex]
|
||||
}
|
||||
|
||||
return u.String(), nil
|
||||
}
|
|
@ -41,6 +41,8 @@ type Pager struct {
|
|||
|
||||
createPage func(r PageResult) Page
|
||||
|
||||
firstPage Page
|
||||
|
||||
Err error
|
||||
|
||||
// Headers supplies additional HTTP headers to populate on each paged request.
|
||||
|
@ -89,9 +91,18 @@ func (p Pager) EachPage(handler func(Page) (bool, error)) error {
|
|||
}
|
||||
currentURL := p.initialURL
|
||||
for {
|
||||
currentPage, err := p.fetchNextPage(currentURL)
|
||||
if err != nil {
|
||||
return err
|
||||
var currentPage Page
|
||||
|
||||
// if first page has already been fetched, no need to fetch it again
|
||||
if p.firstPage != nil {
|
||||
currentPage = p.firstPage
|
||||
p.firstPage = nil
|
||||
} else {
|
||||
var err error
|
||||
currentPage, err = p.fetchNextPage(currentURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
empty, err := currentPage.IsEmpty()
|
||||
|
@ -128,23 +139,26 @@ func (p Pager) AllPages() (Page, error) {
|
|||
// body will contain the final concatenated Page body.
|
||||
var body reflect.Value
|
||||
|
||||
// Grab a test page to ascertain the page body type.
|
||||
testPage, err := p.fetchNextPage(p.initialURL)
|
||||
// Grab a first page to ascertain the page body type.
|
||||
firstPage, err := p.fetchNextPage(p.initialURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Store the page type so we can use reflection to create a new mega-page of
|
||||
// that type.
|
||||
pageType := reflect.TypeOf(testPage)
|
||||
pageType := reflect.TypeOf(firstPage)
|
||||
|
||||
// if it's a single page, just return the testPage (first page)
|
||||
// if it's a single page, just return the firstPage (first page)
|
||||
if _, found := pageType.FieldByName("SinglePageBase"); found {
|
||||
return testPage, nil
|
||||
return firstPage, nil
|
||||
}
|
||||
|
||||
// store the first page to avoid getting it twice
|
||||
p.firstPage = firstPage
|
||||
|
||||
// Switch on the page body type. Recognized types are `map[string]interface{}`,
|
||||
// `[]byte`, and `[]interface{}`.
|
||||
switch pb := testPage.GetBody().(type) {
|
||||
switch pb := firstPage.GetBody().(type) {
|
||||
case map[string]interface{}:
|
||||
// key is the map key for the page body if the body type is `map[string]interface{}`.
|
||||
var key string
|
||||
|
|
|
@ -120,6 +120,22 @@ func BuildRequestBody(opts interface{}, parent string) (map[string]interface{},
|
|||
continue
|
||||
}
|
||||
|
||||
if v.Kind() == reflect.Slice || (v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Slice) {
|
||||
sliceValue := v
|
||||
if sliceValue.Kind() == reflect.Ptr {
|
||||
sliceValue = sliceValue.Elem()
|
||||
}
|
||||
|
||||
for i := 0; i < sliceValue.Len(); i++ {
|
||||
element := sliceValue.Index(i)
|
||||
if element.Kind() == reflect.Struct || (element.Kind() == reflect.Ptr && element.Elem().Kind() == reflect.Struct) {
|
||||
_, err := BuildRequestBody(element.Interface(), "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if v.Kind() == reflect.Struct || (v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct) {
|
||||
if zero {
|
||||
//fmt.Printf("value before change: %+v\n", optsValue.Field(i))
|
||||
|
@ -363,9 +379,8 @@ func BuildQueryString(opts interface{}) (*url.URL, error) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
// Otherwise, the field is not set.
|
||||
if len(tags) == 2 && tags[1] == "required" {
|
||||
// And the field is required. Return an error.
|
||||
// if the field has a 'required' tag, it can't have a zero-value
|
||||
if requiredTag := f.Tag.Get("required"); requiredTag == "true" {
|
||||
return &url.URL{}, fmt.Errorf("Required query parameter [%s] not set.", f.Name)
|
||||
}
|
||||
}
|
||||
|
@ -439,10 +454,9 @@ func BuildHeaders(opts interface{}) (map[string]string, error) {
|
|||
optsMap[tags[0]] = strconv.FormatBool(v.Bool())
|
||||
}
|
||||
} else {
|
||||
// Otherwise, the field is not set.
|
||||
if len(tags) == 2 && tags[1] == "required" {
|
||||
// And the field is required. Return an error.
|
||||
return optsMap, fmt.Errorf("Required header not set.")
|
||||
// if the field has a 'required' tag, it can't have a zero-value
|
||||
if requiredTag := f.Tag.Get("required"); requiredTag == "true" {
|
||||
return optsMap, fmt.Errorf("Required header [%s] not set.", f.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package gophercloud
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
@ -71,6 +72,10 @@ type ProviderClient struct {
|
|||
// authentication functions for different Identity service versions.
|
||||
ReauthFunc func() error
|
||||
|
||||
// IsThrowaway determines whether if this client is a throw-away client. It's a copy of user's provider client
|
||||
// with the token and reauth func zeroed. Such client can be used to perform reauthorization.
|
||||
IsThrowaway bool
|
||||
|
||||
mut *sync.RWMutex
|
||||
|
||||
reauthmut *reauthlock
|
||||
|
@ -78,19 +83,23 @@ type ProviderClient struct {
|
|||
|
||||
type reauthlock struct {
|
||||
sync.RWMutex
|
||||
reauthing bool
|
||||
reauthing bool
|
||||
reauthingErr error
|
||||
done *sync.Cond
|
||||
}
|
||||
|
||||
// AuthenticatedHeaders returns a map of HTTP headers that are common for all
|
||||
// authenticated service requests.
|
||||
// authenticated service requests. Blocks if Reauthenticate is in progress.
|
||||
func (client *ProviderClient) AuthenticatedHeaders() (m map[string]string) {
|
||||
if client.IsThrowaway {
|
||||
return
|
||||
}
|
||||
if client.reauthmut != nil {
|
||||
client.reauthmut.RLock()
|
||||
if client.reauthmut.reauthing {
|
||||
client.reauthmut.RUnlock()
|
||||
return
|
||||
client.reauthmut.Lock()
|
||||
for client.reauthmut.reauthing {
|
||||
client.reauthmut.done.Wait()
|
||||
}
|
||||
client.reauthmut.RUnlock()
|
||||
client.reauthmut.Unlock()
|
||||
}
|
||||
t := client.Token()
|
||||
if t == "" {
|
||||
|
@ -126,11 +135,11 @@ func (client *ProviderClient) SetToken(t string) {
|
|||
client.TokenID = t
|
||||
}
|
||||
|
||||
//Reauthenticate calls client.ReauthFunc in a thread-safe way. If this is
|
||||
//called because of a 401 response, the caller may pass the previous token. In
|
||||
//this case, the reauthentication can be skipped if another thread has already
|
||||
//reauthenticated in the meantime. If no previous token is known, an empty
|
||||
//string should be passed instead to force unconditional reauthentication.
|
||||
// Reauthenticate calls client.ReauthFunc in a thread-safe way. If this is
|
||||
// called because of a 401 response, the caller may pass the previous token. In
|
||||
// this case, the reauthentication can be skipped if another thread has already
|
||||
// reauthenticated in the meantime. If no previous token is known, an empty
|
||||
// string should be passed instead to force unconditional reauthentication.
|
||||
func (client *ProviderClient) Reauthenticate(previousToken string) (err error) {
|
||||
if client.ReauthFunc == nil {
|
||||
return nil
|
||||
|
@ -139,11 +148,25 @@ func (client *ProviderClient) Reauthenticate(previousToken string) (err error) {
|
|||
if client.mut == nil {
|
||||
return client.ReauthFunc()
|
||||
}
|
||||
|
||||
client.reauthmut.Lock()
|
||||
if client.reauthmut.reauthing {
|
||||
for !client.reauthmut.reauthing {
|
||||
client.reauthmut.done.Wait()
|
||||
}
|
||||
err = client.reauthmut.reauthingErr
|
||||
client.reauthmut.Unlock()
|
||||
return err
|
||||
}
|
||||
client.reauthmut.Unlock()
|
||||
|
||||
client.mut.Lock()
|
||||
defer client.mut.Unlock()
|
||||
|
||||
client.reauthmut.Lock()
|
||||
client.reauthmut.reauthing = true
|
||||
client.reauthmut.done = sync.NewCond(client.reauthmut)
|
||||
client.reauthmut.reauthingErr = nil
|
||||
client.reauthmut.Unlock()
|
||||
|
||||
if previousToken == "" || client.TokenID == previousToken {
|
||||
|
@ -152,6 +175,8 @@ func (client *ProviderClient) Reauthenticate(previousToken string) (err error) {
|
|||
|
||||
client.reauthmut.Lock()
|
||||
client.reauthmut.reauthing = false
|
||||
client.reauthmut.reauthingErr = err
|
||||
client.reauthmut.done.Broadcast()
|
||||
client.reauthmut.Unlock()
|
||||
return
|
||||
}
|
||||
|
@ -192,7 +217,7 @@ func (client *ProviderClient) Request(method, url string, options *RequestOpts)
|
|||
// io.ReadSeeker as-is. Default the content-type to application/json.
|
||||
if options.JSONBody != nil {
|
||||
if options.RawBody != nil {
|
||||
panic("Please provide only one of JSONBody or RawBody to gophercloud.Request().")
|
||||
return nil, errors.New("please provide only one of JSONBody or RawBody to gophercloud.Request()")
|
||||
}
|
||||
|
||||
rendered, err := json.Marshal(options.JSONBody)
|
||||
|
@ -378,7 +403,7 @@ func defaultOkCodes(method string) []int {
|
|||
case method == "PUT":
|
||||
return []int{201, 202}
|
||||
case method == "PATCH":
|
||||
return []int{200, 204}
|
||||
return []int{200, 202, 204}
|
||||
case method == "DELETE":
|
||||
return []int{202, 204}
|
||||
}
|
||||
|
|
|
@ -89,23 +89,47 @@ func (r Result) extractIntoPtr(to interface{}, label string) error {
|
|||
if typeOfV.Kind() == reflect.Struct {
|
||||
if typeOfV.NumField() > 0 && typeOfV.Field(0).Anonymous {
|
||||
newSlice := reflect.MakeSlice(reflect.SliceOf(typeOfV), 0, 0)
|
||||
newType := reflect.New(typeOfV).Elem()
|
||||
|
||||
for _, v := range m[label].([]interface{}) {
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if mSlice, ok := m[label].([]interface{}); ok {
|
||||
for _, v := range mSlice {
|
||||
// For each iteration of the slice, we create a new struct.
|
||||
// This is to work around a bug where elements of a slice
|
||||
// are reused and not overwritten when the same copy of the
|
||||
// struct is used:
|
||||
//
|
||||
// https://github.com/golang/go/issues/21092
|
||||
// https://github.com/golang/go/issues/24155
|
||||
// https://play.golang.org/p/NHo3ywlPZli
|
||||
newType := reflect.New(typeOfV).Elem()
|
||||
|
||||
for i := 0; i < newType.NumField(); i++ {
|
||||
s := newType.Field(i).Addr().Interface()
|
||||
err = json.NewDecoder(bytes.NewReader(b)).Decode(s)
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// This is needed for structs with an UnmarshalJSON method.
|
||||
// Technically this is just unmarshalling the response into
|
||||
// a struct that is never used, but it's good enough to
|
||||
// trigger the UnmarshalJSON method.
|
||||
for i := 0; i < newType.NumField(); i++ {
|
||||
s := newType.Field(i).Addr().Interface()
|
||||
|
||||
// Unmarshal is used rather than NewDecoder to also work
|
||||
// around the above-mentioned bug.
|
||||
err = json.Unmarshal(b, s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
newSlice = reflect.Append(newSlice, newType)
|
||||
}
|
||||
newSlice = reflect.Append(newSlice, newType)
|
||||
}
|
||||
|
||||
// "to" should now be properly modeled to receive the
|
||||
// JSON response body and unmarshal into all the correct
|
||||
// fields of the struct or composed extension struct
|
||||
// at the end of this method.
|
||||
toValue.Set(newSlice)
|
||||
}
|
||||
}
|
||||
|
@ -345,6 +369,48 @@ func (jt *JSONRFC3339NoZ) UnmarshalJSON(data []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// RFC3339ZNoT is the time format used in Zun (Containers Service).
|
||||
const RFC3339ZNoT = "2006-01-02 15:04:05-07:00"
|
||||
|
||||
type JSONRFC3339ZNoT time.Time
|
||||
|
||||
func (jt *JSONRFC3339ZNoT) UnmarshalJSON(data []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(data, &s); err != nil {
|
||||
return err
|
||||
}
|
||||
if s == "" {
|
||||
return nil
|
||||
}
|
||||
t, err := time.Parse(RFC3339ZNoT, s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*jt = JSONRFC3339ZNoT(t)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RFC3339ZNoTNoZ is another time format used in Zun (Containers Service).
|
||||
const RFC3339ZNoTNoZ = "2006-01-02 15:04:05"
|
||||
|
||||
type JSONRFC3339ZNoTNoZ time.Time
|
||||
|
||||
func (jt *JSONRFC3339ZNoTNoZ) UnmarshalJSON(data []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(data, &s); err != nil {
|
||||
return err
|
||||
}
|
||||
if s == "" {
|
||||
return nil
|
||||
}
|
||||
t, err := time.Parse(RFC3339ZNoTNoZ, s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*jt = JSONRFC3339ZNoTNoZ(t)
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
Link is an internal type to be used in packages of collection resources that are
|
||||
paginated in a certain way.
|
||||
|
|
|
@ -28,6 +28,10 @@ type ServiceClient struct {
|
|||
|
||||
// The microversion of the service to use. Set this to use a particular microversion.
|
||||
Microversion string
|
||||
|
||||
// MoreHeaders allows users (or Gophercloud) to set service-wide headers on requests. Put another way,
|
||||
// values set in this field will be set on all the HTTP requests the service client sends.
|
||||
MoreHeaders map[string]string
|
||||
}
|
||||
|
||||
// ResourceBaseURL returns the base URL of any resources used by this service. It MUST end with a /.
|
||||
|
@ -108,6 +112,15 @@ func (client *ServiceClient) Delete(url string, opts *RequestOpts) (*http.Respon
|
|||
return client.Request("DELETE", url, opts)
|
||||
}
|
||||
|
||||
// Head calls `Request` with the "HEAD" HTTP verb.
|
||||
func (client *ServiceClient) Head(url string, opts *RequestOpts) (*http.Response, error) {
|
||||
if opts == nil {
|
||||
opts = new(RequestOpts)
|
||||
}
|
||||
client.initReqOpts(url, nil, nil, opts)
|
||||
return client.Request("HEAD", url, opts)
|
||||
}
|
||||
|
||||
func (client *ServiceClient) setMicroversionHeader(opts *RequestOpts) {
|
||||
switch client.Type {
|
||||
case "compute":
|
||||
|
@ -122,3 +135,16 @@ func (client *ServiceClient) setMicroversionHeader(opts *RequestOpts) {
|
|||
opts.MoreHeaders["OpenStack-API-Version"] = client.Type + " " + client.Microversion
|
||||
}
|
||||
}
|
||||
|
||||
// Request carries out the HTTP operation for the service client
|
||||
func (client *ServiceClient) Request(method, url string, options *RequestOpts) (*http.Response, error) {
|
||||
if len(client.MoreHeaders) > 0 {
|
||||
if options == nil {
|
||||
options = new(RequestOpts)
|
||||
}
|
||||
for k, v := range client.MoreHeaders {
|
||||
options.MoreHeaders[k] = v
|
||||
}
|
||||
}
|
||||
return client.ProviderClient.Request(method, url, options)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue