diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index fe43770a94f..d89bc78af29 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -442,47 +442,47 @@ }, { "ImportPath": "github.com/containerd/containerd/api/services/containers/v1", - "Comment": "v1.0.0-beta.2-159-g27d450a0", + "Comment": "v1.0.0-beta.2-159-g27d450a", "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" }, { "ImportPath": "github.com/containerd/containerd/api/services/tasks/v1", - "Comment": "v1.0.0-beta.2-159-g27d450a0", + "Comment": "v1.0.0-beta.2-159-g27d450a", "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" }, { "ImportPath": "github.com/containerd/containerd/api/services/version/v1", - "Comment": "v1.0.0-beta.2-159-g27d450a0", + "Comment": "v1.0.0-beta.2-159-g27d450a", "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" }, { "ImportPath": "github.com/containerd/containerd/api/types", - "Comment": "v1.0.0-beta.2-159-g27d450a0", + "Comment": "v1.0.0-beta.2-159-g27d450a", "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" }, { "ImportPath": "github.com/containerd/containerd/api/types/task", - "Comment": "v1.0.0-beta.2-159-g27d450a0", + "Comment": "v1.0.0-beta.2-159-g27d450a", "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" }, { "ImportPath": "github.com/containerd/containerd/containers", - "Comment": "v1.0.0-beta.2-159-g27d450a0", + "Comment": "v1.0.0-beta.2-159-g27d450a", "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" }, { "ImportPath": "github.com/containerd/containerd/dialer", - "Comment": "v1.0.0-beta.2-159-g27d450a0", + "Comment": "v1.0.0-beta.2-159-g27d450a", "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" }, { "ImportPath": "github.com/containerd/containerd/errdefs", - "Comment": "v1.0.0-beta.2-159-g27d450a0", + "Comment": "v1.0.0-beta.2-159-g27d450a", "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" }, { "ImportPath": "github.com/containerd/containerd/namespaces", - "Comment": "v1.0.0-beta.2-159-g27d450a0", + "Comment": "v1.0.0-beta.2-159-g27d450a", "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" }, { @@ -1319,7 +1319,7 @@ }, { "ImportPath": "github.com/gogo/protobuf/types", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { @@ -1633,115 +1633,123 @@ }, { "ImportPath": "github.com/gophercloud/gophercloud", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/common/extensions", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/flavors", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/images", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/servers", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/trusts", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" + }, + { + "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external", + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" + }, + { + "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/networks", + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/ports", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/utils", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/pagination", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gorilla/context", diff --git a/Godeps/LICENSES b/Godeps/LICENSES index 95d876a70f6..41b5664763f 100644 --- a/Godeps/LICENSES +++ b/Godeps/LICENSES @@ -58330,6 +58330,205 @@ specific language governing permissions and limitations under the License. ================================================================================ +================================================================================ += vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external 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/layer3/floatingips licensed under: = @@ -59922,6 +60121,205 @@ specific language governing permissions and limitations under the License. ================================================================================ +================================================================================ += vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks 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/ports licensed under: = diff --git a/cmd/kube-apiserver/app/options/BUILD b/cmd/kube-apiserver/app/options/BUILD index 7c46be368bf..96087a582eb 100644 --- a/cmd/kube-apiserver/app/options/BUILD +++ b/cmd/kube-apiserver/app/options/BUILD @@ -74,6 +74,7 @@ go_test( "//vendor/k8s.io/apiserver/pkg/server/options:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/storagebackend:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library", + "//vendor/k8s.io/apiserver/plugin/pkg/audit/webhook:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", ], ) diff --git a/cmd/kube-apiserver/app/options/options_test.go b/cmd/kube-apiserver/app/options/options_test.go index 716398a4e63..30979d10524 100644 --- a/cmd/kube-apiserver/app/options/options_test.go +++ b/cmd/kube-apiserver/app/options/options_test.go @@ -28,6 +28,7 @@ import ( apiserveroptions "k8s.io/apiserver/pkg/server/options" "k8s.io/apiserver/pkg/storage/storagebackend" utilconfig "k8s.io/apiserver/pkg/util/flag" + auditwebhook "k8s.io/apiserver/plugin/pkg/audit/webhook" restclient "k8s.io/client-go/rest" "k8s.io/kubernetes/pkg/api/legacyscheme" kapi "k8s.io/kubernetes/pkg/apis/core" @@ -55,6 +56,12 @@ func TestAddFlags(t *testing.T) { "--audit-policy-file=/policy", "--audit-webhook-config-file=/webhook-config", "--audit-webhook-mode=blocking", + "--audit-webhook-batch-buffer-size=42", + "--audit-webhook-batch-max-size=43", + "--audit-webhook-batch-max-wait=1s", + "--audit-webhook-batch-throttle-qps=43.5", + "--audit-webhook-batch-throttle-burst=44", + "--audit-webhook-batch-initial-backoff=2s", "--authentication-token-webhook-cache-ttl=3m", "--authentication-token-webhook-config-file=/token-webhook-config", "--authorization-mode=AlwaysDeny", @@ -170,6 +177,14 @@ func TestAddFlags(t *testing.T) { WebhookOptions: apiserveroptions.AuditWebhookOptions{ Mode: "blocking", ConfigFile: "/webhook-config", + BatchConfig: auditwebhook.BatchBackendConfig{ + BufferSize: 42, + MaxBatchSize: 43, + MaxBatchWait: 1 * time.Second, + ThrottleQPS: 43.5, + ThrottleBurst: 44, + InitialBackoff: 2 * time.Second, + }, }, PolicyFile: "/policy", }, diff --git a/pkg/cloudprovider/providers/openstack/BUILD b/pkg/cloudprovider/providers/openstack/BUILD index b295842adc9..117014a5a20 100644 --- a/pkg/cloudprovider/providers/openstack/BUILD +++ b/pkg/cloudprovider/providers/openstack/BUILD @@ -39,6 +39,7 @@ go_library( "//vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/trusts:go_default_library", "//vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens:go_default_library", "//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions:go_default_library", + "//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external:go_default_library", "//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips:go_default_library", "//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers:go_default_library", "//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners:go_default_library", @@ -47,6 +48,7 @@ go_library( "//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools:go_default_library", "//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups:go_default_library", "//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules:go_default_library", + "//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks:go_default_library", "//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports:go_default_library", "//vendor/github.com/gophercloud/gophercloud/pagination:go_default_library", "//vendor/github.com/mitchellh/mapstructure:go_default_library", diff --git a/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go b/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go index 471fdc31a61..31c1985072a 100644 --- a/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go +++ b/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go @@ -25,6 +25,7 @@ import ( "github.com/golang/glog" "github.com/gophercloud/gophercloud" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions" + "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers" @@ -32,6 +33,7 @@ import ( v2pools "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules" + "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" neutronports "github.com/gophercloud/gophercloud/openstack/networking/v2/ports" "github.com/gophercloud/gophercloud/pagination" @@ -566,6 +568,52 @@ func getNodeSecurityGroupIDForLB(compute *gophercloud.ServiceClient, nodes []*v1 return nodeSecurityGroupIDs.List(), nil } +// getFloatingNetworkIdForLB returns a floating-network-id for cluster. +func getFloatingNetworkIdForLB(client *gophercloud.ServiceClient) (string, error) { + var floatingNetworkIds []string + + type NetworkWithExternalExt struct { + networks.Network + external.NetworkExternalExt + } + + err := networks.List(client, networks.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) { + var externalNetwork []NetworkWithExternalExt + err := networks.ExtractNetworksInto(page, &externalNetwork) + if err != nil { + return false, err + } + + for _, externalNet := range externalNetwork { + if externalNet.External { + floatingNetworkIds = append(floatingNetworkIds, externalNet.ID) + } + } + + if len(floatingNetworkIds) > 1 { + return false, ErrMultipleResults + } + return true, nil + }) + if err != nil { + if isNotFound(err) { + return "", ErrNotFound + } + + if err == ErrMultipleResults { + glog.V(4).Infof("find multiple external networks, pick the first one when there are no explicit configuration.") + return floatingNetworkIds[0], nil + } + return "", err + } + + if len(floatingNetworkIds) == 0 { + return "", ErrNotFound + } + + return floatingNetworkIds[0], nil +} + // TODO: This code currently ignores 'region' and always creates a // loadbalancer in only the current OpenStack region. We should take // a list of regions (from config) and query/create loadbalancers in @@ -596,7 +644,13 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv } floatingPool := getStringFromServiceAnnotation(apiService, ServiceAnnotationLoadBalancerFloatingNetworkId, lbaas.opts.FloatingNetworkId) - glog.V(4).Infof("EnsureLoadBalancer using floatingPool: %v", floatingPool) + if len(floatingPool) == 0 { + var err error + floatingPool, err = getFloatingNetworkIdForLB(lbaas.network) + if err != nil { + glog.Warningf("Failed to find floating-network-id for loadbalancer service %s/%s: %v", apiService.Namespace, apiService.Name, err) + } + } var internalAnnotation bool internal := getStringFromServiceAnnotation(apiService, ServiceAnnotationLoadBalancerInternal, "false") @@ -606,7 +660,7 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv internalAnnotation = true case "false": if len(floatingPool) != 0 { - glog.V(4).Infof("Ensure an external loadbalancer service.") + glog.V(4).Infof("Ensure an external loadbalancer service, using floatingPool: %v", floatingPool) internalAnnotation = false } else { return nil, fmt.Errorf("floating-network-id or loadbalancer.openstack.org/floating-network-id should be specified when ensuring an external loadbalancer service") diff --git a/pkg/kubectl/cmd/apply.go b/pkg/kubectl/cmd/apply.go index 3c39f61998b..e132743231c 100644 --- a/pkg/kubectl/cmd/apply.go +++ b/pkg/kubectl/cmd/apply.go @@ -604,42 +604,44 @@ func (p *patcher) patchSimple(obj runtime.Object, modified []byte, source, names var lookupPatchMeta strategicpatch.LookupPatchMeta var schema oapi.Schema createPatchErrFormat := "creating patch with:\noriginal:\n%s\nmodified:\n%s\ncurrent:\n%s\nfor:" - // Try to use openapi first if the openapi spec is available and can successfully calculate the patch. - // Otherwise, fall back to baked-in types. - if p.openapiSchema != nil { - if schema = p.openapiSchema.LookupResource(p.mapping.GroupVersionKind); schema != nil { - lookupPatchMeta = strategicpatch.PatchMetaFromOpenAPI{Schema: schema} - if openapiPatch, err := strategicpatch.CreateThreeWayMergePatch(original, modified, current, lookupPatchMeta, p.overwrite); err != nil { - fmt.Fprintf(errOut, "warning: error calculating patch from openapi spec: %v\n", err) - } else { - patchType = types.StrategicMergePatchType - patch = openapiPatch + + // Create the versioned struct from the type defined in the restmapping + // (which is the API version we'll be submitting the patch to) + versionedObject, err := scheme.Scheme.New(p.mapping.GroupVersionKind) + switch { + case runtime.IsNotRegisteredError(err): + // fall back to generic JSON merge patch + patchType = types.MergePatchType + preconditions := []mergepatch.PreconditionFunc{mergepatch.RequireKeyUnchanged("apiVersion"), + mergepatch.RequireKeyUnchanged("kind"), mergepatch.RequireMetadataKeyUnchanged("name")} + patch, err = jsonmergepatch.CreateThreeWayJSONMergePatch(original, modified, current, preconditions...) + if err != nil { + if mergepatch.IsPreconditionFailed(err) { + return nil, nil, fmt.Errorf("%s", "At least one of apiVersion, kind and name was changed") + } + return nil, nil, cmdutil.AddSourceToErr(fmt.Sprintf(createPatchErrFormat, original, modified, current), source, err) + } + case err != nil: + return nil, nil, cmdutil.AddSourceToErr(fmt.Sprintf("getting instance of versioned object for %v:", p.mapping.GroupVersionKind), source, err) + case err == nil: + // Compute a three way strategic merge patch to send to server. + patchType = types.StrategicMergePatchType + + // Try to use openapi first if the openapi spec is available and can successfully calculate the patch. + // Otherwise, fall back to baked-in types. + if p.openapiSchema != nil { + if schema = p.openapiSchema.LookupResource(p.mapping.GroupVersionKind); schema != nil { + lookupPatchMeta = strategicpatch.PatchMetaFromOpenAPI{Schema: schema} + if openapiPatch, err := strategicpatch.CreateThreeWayMergePatch(original, modified, current, lookupPatchMeta, p.overwrite); err != nil { + fmt.Fprintf(errOut, "warning: error calculating patch from openapi spec: %v\n", err) + } else { + patchType = types.StrategicMergePatchType + patch = openapiPatch + } } } - } - if patch == nil { - // Create the versioned struct from the type defined in the restmapping - // (which is the API version we'll be submitting the patch to) - versionedObject, err := scheme.Scheme.New(p.mapping.GroupVersionKind) - switch { - case runtime.IsNotRegisteredError(err): - // fall back to generic JSON merge patch - patchType = types.MergePatchType - preconditions := []mergepatch.PreconditionFunc{mergepatch.RequireKeyUnchanged("apiVersion"), - mergepatch.RequireKeyUnchanged("kind"), mergepatch.RequireMetadataKeyUnchanged("name")} - patch, err = jsonmergepatch.CreateThreeWayJSONMergePatch(original, modified, current, preconditions...) - if err != nil { - if mergepatch.IsPreconditionFailed(err) { - return nil, nil, fmt.Errorf("%s", "At least one of apiVersion, kind and name was changed") - } - return nil, nil, cmdutil.AddSourceToErr(fmt.Sprintf(createPatchErrFormat, original, modified, current), source, err) - } - case err != nil: - return nil, nil, cmdutil.AddSourceToErr(fmt.Sprintf("getting instance of versioned object for %v:", p.mapping.GroupVersionKind), source, err) - case err == nil: - // Compute a three way strategic merge patch to send to server. - patchType = types.StrategicMergePatchType + if patch == nil { lookupPatchMeta, err = strategicpatch.NewPatchMetaFromStruct(versionedObject) if err != nil { return nil, nil, cmdutil.AddSourceToErr(fmt.Sprintf(createPatchErrFormat, original, modified, current), source, err) diff --git a/staging/src/k8s.io/apiserver/Godeps/Godeps.json b/staging/src/k8s.io/apiserver/Godeps/Godeps.json index de78fc380a0..ac7aef5679c 100644 --- a/staging/src/k8s.io/apiserver/Godeps/Godeps.json +++ b/staging/src/k8s.io/apiserver/Godeps/Godeps.json @@ -408,31 +408,31 @@ }, { "ImportPath": "github.com/gophercloud/gophercloud", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/utils", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/pagination", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gregjones/httpcache", diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/audit.go b/staging/src/k8s.io/apiserver/pkg/server/options/audit.go index 833e91e5307..e43ebb12bc9 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/audit.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/audit.go @@ -77,12 +77,17 @@ type AuditWebhookOptions struct { // // Defaults to asynchronous batch events. Mode string + // Configuration for batching webhook. Only used in batch mode. + BatchConfig pluginwebhook.BatchBackendConfig } func NewAuditOptions() *AuditOptions { return &AuditOptions{ - WebhookOptions: AuditWebhookOptions{Mode: pluginwebhook.ModeBatch}, - LogOptions: AuditLogOptions{Format: pluginlog.FormatJson}, + WebhookOptions: AuditWebhookOptions{ + Mode: pluginwebhook.ModeBatch, + BatchConfig: pluginwebhook.NewDefaultBatchBackendConfig(), + }, + LogOptions: AuditLogOptions{Format: pluginlog.FormatJson}, } } @@ -102,7 +107,7 @@ func (o *AuditOptions) Validate() []error { allErrors = append(allErrors, fmt.Errorf("feature '%s' must be enabled to set option --audit-webhook-config-file", features.AdvancedAuditing)) } } else { - // check webhook mode + // Check webhook mode validMode := false for _, m := range pluginwebhook.AllowedModes { if m == o.WebhookOptions.Mode { @@ -114,7 +119,21 @@ func (o *AuditOptions) Validate() []error { allErrors = append(allErrors, fmt.Errorf("invalid audit webhook mode %s, allowed modes are %q", o.WebhookOptions.Mode, strings.Join(pluginwebhook.AllowedModes, ","))) } - // check log format + // Check webhook batch configuration + if o.WebhookOptions.BatchConfig.BufferSize <= 0 { + allErrors = append(allErrors, fmt.Errorf("invalid audit batch webhook buffer size %v, must be a positive number", o.WebhookOptions.BatchConfig.BufferSize)) + } + if o.WebhookOptions.BatchConfig.MaxBatchSize <= 0 { + allErrors = append(allErrors, fmt.Errorf("invalid audit batch webhook max batch size %v, must be a positive number", o.WebhookOptions.BatchConfig.MaxBatchSize)) + } + if o.WebhookOptions.BatchConfig.ThrottleQPS <= 0 { + allErrors = append(allErrors, fmt.Errorf("invalid audit batch webhook throttle QPS %v, must be a positive number", o.WebhookOptions.BatchConfig.ThrottleQPS)) + } + if o.WebhookOptions.BatchConfig.ThrottleBurst <= 0 { + allErrors = append(allErrors, fmt.Errorf("invalid audit batch webhook throttle burst %v, must be a positive number", o.WebhookOptions.BatchConfig.ThrottleBurst)) + } + + // Check log format validFormat := false for _, f := range pluginlog.AllowedFormats { if f == o.LogOptions.Format { @@ -249,6 +268,24 @@ func (o *AuditWebhookOptions) AddFlags(fs *pflag.FlagSet) { "Strategy for sending audit events. Blocking indicates sending events should block"+ " server responses. Batch causes the webhook to buffer and send events"+ " asynchronously. Known modes are "+strings.Join(pluginwebhook.AllowedModes, ",")+".") + fs.IntVar(&o.BatchConfig.BufferSize, "audit-webhook-batch-buffer-size", + o.BatchConfig.BufferSize, "The size of the buffer to store events before "+ + "batching and sending to the webhook. Only used in batch mode.") + fs.IntVar(&o.BatchConfig.MaxBatchSize, "audit-webhook-batch-max-size", + o.BatchConfig.MaxBatchSize, "The maximum size of a batch sent to the webhook. "+ + "Only used in batch mode.") + fs.DurationVar(&o.BatchConfig.MaxBatchWait, "audit-webhook-batch-max-wait", + o.BatchConfig.MaxBatchWait, "The amount of time to wait before force sending the "+ + "batch that hadn't reached the max size. Only used in batch mode.") + fs.Float32Var(&o.BatchConfig.ThrottleQPS, "audit-webhook-batch-throttle-qps", + o.BatchConfig.ThrottleQPS, "Maximum average number of requests per second. "+ + "Only used in batch mode.") + fs.IntVar(&o.BatchConfig.ThrottleBurst, "audit-webhook-batch-throttle-burst", + o.BatchConfig.ThrottleBurst, "Maximum number of requests sent at the same "+ + "moment if ThrottleQPS was not utilized before. Only used in batch mode.") + fs.DurationVar(&o.BatchConfig.InitialBackoff, "audit-webhook-batch-initial-backoff", + o.BatchConfig.InitialBackoff, "The amount of time to wait before retrying the "+ + "first failed requests. Only used in batch mode.") } func (o *AuditWebhookOptions) applyTo(c *server.Config) error { @@ -256,7 +293,7 @@ func (o *AuditWebhookOptions) applyTo(c *server.Config) error { return nil } - webhook, err := pluginwebhook.NewBackend(o.ConfigFile, o.Mode, auditv1beta1.SchemeGroupVersion) + webhook, err := pluginwebhook.NewBackend(o.ConfigFile, o.Mode, auditv1beta1.SchemeGroupVersion, o.BatchConfig) if err != nil { return fmt.Errorf("initializing audit webhook: %v", err) } diff --git a/staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/webhook.go b/staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/webhook.go index 41d8c0ed92a..7f390ac57fb 100644 --- a/staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/webhook.go +++ b/staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/webhook.go @@ -57,9 +57,6 @@ var AllowedModes = []string{ const ( // Default configuration values for ModeBatch. - // - // TODO(ericchiang): Make these value configurable. Maybe through a - // kubeconfig extension? defaultBatchBufferSize = 10000 // Buffer up to 10000 events before starting discarding. defaultBatchMaxSize = 400 // Only send up to 400 events at a time. defaultBatchMaxWait = 30 * time.Second // Send events at least twice a minute. @@ -72,13 +69,49 @@ const ( // The plugin name reported in error metrics. const pluginName = "webhook" +// BatchBackendConfig represents batching webhook audit backend configuration. +type BatchBackendConfig struct { + // BufferSize defines a size of the buffering queue. + BufferSize int + // MaxBatchSize defines maximum size of a batch. + MaxBatchSize int + // MaxBatchWait defines maximum amount of time to wait for MaxBatchSize + // events to be accumulated in the buffer before forcibly sending what's + // being accumulated. + MaxBatchWait time.Duration + + // ThrottleQPS defines the allowed rate of batches per second sent to the webhook. + ThrottleQPS float32 + // ThrottleBurst defines the maximum rate of batches per second sent to the webhook in case + // the capacity defined by ThrottleQPS was not utilized. + ThrottleBurst int + + // InitialBackoff defines the amount of time to wait before retrying the requests + // to the webhook for the first time. + InitialBackoff time.Duration +} + +// NewDefaultBatchBackendConfig returns new BatchBackendConfig objects populated by default values. +func NewDefaultBatchBackendConfig() BatchBackendConfig { + return BatchBackendConfig{ + BufferSize: defaultBatchBufferSize, + MaxBatchSize: defaultBatchMaxSize, + MaxBatchWait: defaultBatchMaxWait, + + ThrottleQPS: defaultBatchThrottleQPS, + ThrottleBurst: defaultBatchThrottleBurst, + + InitialBackoff: defaultInitialBackoff, + } +} + // NewBackend returns an audit backend that sends events over HTTP to an external service. // The mode indicates the caching behavior of the webhook. Either blocking (ModeBlocking) // or buffered with batch POSTs (ModeBatch). -func NewBackend(kubeConfigFile string, mode string, groupVersion schema.GroupVersion) (audit.Backend, error) { +func NewBackend(kubeConfigFile string, mode string, groupVersion schema.GroupVersion, config BatchBackendConfig) (audit.Backend, error) { switch mode { case ModeBatch: - return newBatchWebhook(kubeConfigFile, groupVersion) + return newBatchWebhook(kubeConfigFile, groupVersion, config) case ModeBlocking: return newBlockingWebhook(kubeConfigFile, groupVersion) default: @@ -105,13 +138,13 @@ func init() { install.Install(groupFactoryRegistry, registry, audit.Scheme) } -func loadWebhook(configFile string, groupVersion schema.GroupVersion) (*webhook.GenericWebhook, error) { +func loadWebhook(configFile string, groupVersion schema.GroupVersion, initialBackoff time.Duration) (*webhook.GenericWebhook, error) { return webhook.NewGenericWebhook(registry, audit.Codecs, configFile, - []schema.GroupVersion{groupVersion}, defaultInitialBackoff) + []schema.GroupVersion{groupVersion}, initialBackoff) } func newBlockingWebhook(configFile string, groupVersion schema.GroupVersion) (*blockingBackend, error) { - w, err := loadWebhook(configFile, groupVersion) + w, err := loadWebhook(configFile, groupVersion, defaultInitialBackoff) if err != nil { return nil, err } @@ -146,19 +179,19 @@ func (b *blockingBackend) processEvents(ev ...*auditinternal.Event) error { return b.w.RestClient.Post().Body(&list).Do().Error() } -func newBatchWebhook(configFile string, groupVersion schema.GroupVersion) (*batchBackend, error) { - w, err := loadWebhook(configFile, groupVersion) +func newBatchWebhook(configFile string, groupVersion schema.GroupVersion, config BatchBackendConfig) (*batchBackend, error) { + w, err := loadWebhook(configFile, groupVersion, config.InitialBackoff) if err != nil { return nil, err } return &batchBackend{ w: w, - buffer: make(chan *auditinternal.Event, defaultBatchBufferSize), - maxBatchSize: defaultBatchMaxSize, - maxBatchWait: defaultBatchMaxWait, + buffer: make(chan *auditinternal.Event, config.BufferSize), + maxBatchSize: config.MaxBatchSize, + maxBatchWait: config.MaxBatchWait, shutdownCh: make(chan struct{}), - throttle: flowcontrol.NewTokenBucketRateLimiter(defaultBatchThrottleQPS, defaultBatchThrottleBurst), + throttle: flowcontrol.NewTokenBucketRateLimiter(config.ThrottleQPS, config.ThrottleBurst), }, nil } diff --git a/staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/webhook_test.go b/staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/webhook_test.go index 1b7f3df24ed..62c09fb3557 100644 --- a/staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/webhook_test.go +++ b/staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/webhook_test.go @@ -116,7 +116,7 @@ func newWebhook(t *testing.T, endpoint string, mode string, groupVersion schema. // NOTE(ericchiang): Do we need to use a proper serializer? require.NoError(t, stdjson.NewEncoder(f).Encode(config), "writing kubeconfig") - backend, err := NewBackend(f.Name(), mode, groupVersion) + backend, err := NewBackend(f.Name(), mode, groupVersion, NewDefaultBatchBackendConfig()) require.NoError(t, err, "initializing backend") return backend diff --git a/staging/src/k8s.io/client-go/Godeps/Godeps.json b/staging/src/k8s.io/client-go/Godeps/Godeps.json index 8b56b71a90b..aeef01ca2ca 100644 --- a/staging/src/k8s.io/client-go/Godeps/Godeps.json +++ b/staging/src/k8s.io/client-go/Godeps/Godeps.json @@ -172,31 +172,31 @@ }, { "ImportPath": "github.com/gophercloud/gophercloud", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/utils", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gophercloud/gophercloud/pagination", - "Rev": "db5f840b1d1a595280d643defc09ce277996959e" + "Rev": "8183543f90d1aef267a5ecc209f2e0715b355acb" }, { "ImportPath": "github.com/gregjones/httpcache", diff --git a/test/e2e/apps/network_partition.go b/test/e2e/apps/network_partition.go index 4c1360a45a0..4cabc2b46b1 100644 --- a/test/e2e/apps/network_partition.go +++ b/test/e2e/apps/network_partition.go @@ -116,6 +116,9 @@ var _ = SIGDescribe("Network Partition [Disruptive] [Slow]", func() { systemPods, err := framework.GetPodsInNamespace(c, ns, ignoreLabels) Expect(err).NotTo(HaveOccurred()) systemPodsNo = int32(len(systemPods)) + + // TODO(foxish): Re-enable testing on gce after kubernetes#56787 is fixed. + framework.SkipUnlessProviderIs("gke", "aws") if strings.Index(framework.TestContext.CloudConfig.NodeInstanceGroup, ",") >= 0 { framework.Failf("Test dose not support cluster setup with more than one MIG: %s", framework.TestContext.CloudConfig.NodeInstanceGroup) } else { @@ -126,7 +129,6 @@ var _ = SIGDescribe("Network Partition [Disruptive] [Slow]", func() { framework.KubeDescribe("Pods", func() { Context("should return to running and ready state after network partition is healed", func() { BeforeEach(func() { - framework.SkipUnlessProviderIs("gce", "gke", "aws") framework.SkipUnlessNodeCountIsAtLeast(2) }) @@ -347,7 +349,8 @@ var _ = SIGDescribe("Network Partition [Disruptive] [Slow]", func() { headlessSvcName := "test" BeforeEach(func() { - framework.SkipUnlessProviderIs("gce", "gke") + // TODO(foxish): Re-enable testing on gce after kubernetes#56787 is fixed. + framework.SkipUnlessProviderIs("gke") By("creating service " + headlessSvcName + " in namespace " + f.Namespace.Name) headlessService := framework.CreateServiceSpec(headlessSvcName, "", true, labels) _, err := f.ClientSet.CoreV1().Services(f.Namespace.Name).Create(headlessService) @@ -461,7 +464,6 @@ var _ = SIGDescribe("Network Partition [Disruptive] [Slow]", func() { framework.KubeDescribe("Pods", func() { Context("should be evicted from unready Node", func() { BeforeEach(func() { - framework.SkipUnlessProviderIs("gce", "gke", "aws") framework.SkipUnlessNodeCountIsAtLeast(2) }) diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/BUILD b/vendor/github.com/gophercloud/gophercloud/openstack/BUILD index 65166006a88..c42cd71dccc 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/BUILD +++ b/vendor/github.com/gophercloud/gophercloud/openstack/BUILD @@ -45,6 +45,7 @@ filegroup( "//vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/trusts:all-srcs", "//vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens:all-srcs", "//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions:all-srcs", + "//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks:all-srcs", "//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports:all-srcs", "//vendor/github.com/gophercloud/gophercloud/openstack/utils:all-srcs", ], diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/results.go index 47d58ccfb36..fb5c335b8ea 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/results.go @@ -65,7 +65,7 @@ type Flavor struct { VCPUs int `json:"vcpus"` // IsPublic indicates whether the flavor is public. - IsPublic bool `json:"is_public"` + IsPublic bool `json:"os-flavor-access:is_public"` } func (r *Flavor) UnmarshalJSON(b []byte) error { diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/requests.go index c445f0ede0e..626eb63e910 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/requests.go @@ -515,7 +515,7 @@ func (opts ResizeOpts) ToServerResizeMap() (map[string]interface{}, error) { // Note that this implies rebuilding it. // // Unfortunately, one cannot pass rebuild parameters to the resize function. -// When the resize completes, the server will be in RESIZE_VERIFY state. +// When the resize completes, the server will be in VERIFY_RESIZE state. // While in this state, you can explore the use of the new server's // configuration. If you like it, call ConfirmResize() to commit the resize // permanently. Otherwise, call RevertResize() to restore the old configuration. diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/BUILD b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/BUILD index 20fdc809dd9..019623118c0 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/BUILD +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/BUILD @@ -23,6 +23,7 @@ filegroup( name = "all-srcs", srcs = [ ":package-srcs", + "//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/listeners:all-srcs", diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external/BUILD b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external/BUILD new file mode 100644 index 00000000000..a29152f1e95 --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external/BUILD @@ -0,0 +1,27 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "requests.go", + "results.go", + ], + 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"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external/doc.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external/doc.go new file mode 100644 index 00000000000..b8261684e70 --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external/doc.go @@ -0,0 +1,46 @@ +/* +Package external provides information and interaction with the external +extension for the OpenStack Networking service. + +Example to List Networks with External Information + + type NetworkWithExternalExt struct { + networks.Network + external.NetworkExternalExt + } + + var allNetworks []NetworkWithExternalExt + + allPages, err := networks.List(networkClient, nil).AllPages() + if err != nil { + panic(err) + } + + err = networks.ExtractNetworksInto(allPages, &allNetworks) + if err != nil { + panic(err) + } + + for _, network := range allNetworks { + fmt.Println("%+v\n", network) + } + +Example to Create a Network with External Information + + iTrue := true + networkCreateOpts := networks.CreateOpts{ + Name: "private", + AdminStateUp: &iTrue, + } + + createOpts := external.CreateOptsExt{ + networkCreateOpts, + &iTrue, + } + + network, err := networks.Create(networkClient, createOpts).Extract() + if err != nil { + panic(err) + } +*/ +package external diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external/requests.go new file mode 100644 index 00000000000..f28e574612c --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external/requests.go @@ -0,0 +1,56 @@ +package external + +import ( + "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" +) + +// 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. +type CreateOptsExt struct { + networks.CreateOptsBuilder + External *bool `json:"router:external,omitempty"` +} + +// ToNetworkCreateMap adds the router:external options to the base network +// creation options. +func (opts CreateOptsExt) ToNetworkCreateMap() (map[string]interface{}, error) { + base, err := opts.CreateOptsBuilder.ToNetworkCreateMap() + if err != nil { + return nil, err + } + + if opts.External == nil { + return base, nil + } + + networkMap := base["network"].(map[string]interface{}) + networkMap["router:external"] = opts.External + + return base, nil +} + +// UpdateOptsExt is the structure used when updating existing external network +// resources. It embeds networks.UpdateOpts and so inherits all of its required +// and optional fields, with the addition of the External field. +type UpdateOptsExt struct { + networks.UpdateOptsBuilder + External *bool `json:"router:external,omitempty"` +} + +// ToNetworkUpdateMap casts an UpdateOpts struct to a map. +func (opts UpdateOptsExt) ToNetworkUpdateMap() (map[string]interface{}, error) { + base, err := opts.UpdateOptsBuilder.ToNetworkUpdateMap() + if err != nil { + return nil, err + } + + if opts.External == nil { + return base, nil + } + + networkMap := base["network"].(map[string]interface{}) + networkMap["router:external"] = opts.External + + return base, nil +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external/results.go new file mode 100644 index 00000000000..7cbbffdcf8a --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external/results.go @@ -0,0 +1,8 @@ +package external + +// NetworkExternalExt represents a decorated form of a Network with based on the +// "external-net" extension. +type NetworkExternalExt struct { + // Specifies whether the network is an external network or not. + External bool `json:"router:external"` +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/BUILD b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/BUILD new file mode 100644 index 00000000000..15bf4dc9ed9 --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/BUILD @@ -0,0 +1,31 @@ +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", + ], + importpath = "github.com/gophercloud/gophercloud/openstack/networking/v2/networks", + 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"], +) diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/doc.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/doc.go new file mode 100644 index 00000000000..e768b71f820 --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/doc.go @@ -0,0 +1,65 @@ +/* +Package networks contains functionality for working with Neutron network +resources. A network is an isolated virtual layer-2 broadcast domain that is +typically reserved for the tenant who created it (unless you configure the +network to be shared). Tenants can create multiple networks until the +thresholds per-tenant quota is reached. + +In the v2.0 Networking API, the network is the main entity. Ports and subnets +are always associated with a network. + +Example to List Networks + + listOpts := networks.ListOpts{ + TenantID: "a99e9b4e620e4db09a2dfb6e42a01e66", + } + + allPages, err := networks.List(networkClient, listOpts).AllPages() + if err != nil { + panic(err) + } + + allNetworks, err := networks.ExtractNetworks(allPages) + if err != nil { + panic(err) + } + + for _, network := range allNetworks { + fmt.Printf("%+v", network) + } + +Example to Create a Network + + iTrue := true + createOpts := networks.CreateOpts{ + Name: "network_1", + AdminStateUp: &iTrue, + } + + network, err := networks.Create(networkClient, createOpts).Extract() + if err != nil { + panic(err) + } + +Example to Update a Network + + networkID := "484cda0e-106f-4f4b-bb3f-d413710bbe78" + + updateOpts := networks.UpdateOpts{ + Name: "new_name", + } + + network, err := networks.Update(networkClient, networkID, updateOpts).Extract() + if err != nil { + panic(err) + } + +Example to Delete a Network + + networkID := "484cda0e-106f-4f4b-bb3f-d413710bbe78" + err := networks.Delete(networkClient, networkID).ExtractErr() + if err != nil { + panic(err) + } +*/ +package networks diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/requests.go new file mode 100644 index 00000000000..5b61b247192 --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/requests.go @@ -0,0 +1,165 @@ +package networks + +import ( + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/pagination" +) + +// ListOptsBuilder allows extensions to add additional parameters to the +// List request. +type ListOptsBuilder interface { + ToNetworkListQuery() (string, error) +} + +// ListOpts allows the filtering and sorting of paginated collections through +// the API. Filtering is achieved by passing in struct field values that map to +// the network attributes you want to see returned. SortKey allows you to 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 { + Status string `q:"status"` + Name string `q:"name"` + AdminStateUp *bool `q:"admin_state_up"` + TenantID string `q:"tenant_id"` + Shared *bool `q:"shared"` + ID string `q:"id"` + Marker string `q:"marker"` + Limit int `q:"limit"` + SortKey string `q:"sort_key"` + SortDir string `q:"sort_dir"` +} + +// ToNetworkListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToNetworkListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + return q.String(), err +} + +// List returns a Pager which allows you to iterate over a collection of +// networks. It accepts a ListOpts struct, which allows you to filter and sort +// the returned collection for greater efficiency. +func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { + url := listURL(c) + if opts != nil { + query, err := opts.ToNetworkListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page { + return NetworkPage{pagination.LinkedPageBase{PageResult: r}} + }) +} + +// Get retrieves a specific network based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) (r GetResult) { + _, r.Err = c.Get(getURL(c, id), &r.Body, nil) + return +} + +// CreateOptsBuilder allows extensions to add additional parameters to the +// Create request. +type CreateOptsBuilder interface { + ToNetworkCreateMap() (map[string]interface{}, error) +} + +// CreateOpts represents options used to create a network. +type CreateOpts struct { + AdminStateUp *bool `json:"admin_state_up,omitempty"` + Name string `json:"name,omitempty"` + Shared *bool `json:"shared,omitempty"` + TenantID string `json:"tenant_id,omitempty"` +} + +// ToNetworkCreateMap builds a request body from CreateOpts. +func (opts CreateOpts) ToNetworkCreateMap() (map[string]interface{}, error) { + return gophercloud.BuildRequestBody(opts, "network") +} + +// Create accepts a CreateOpts struct and creates a new network using the values +// provided. This operation does not actually require a request body, i.e. the +// CreateOpts struct argument can be empty. +// +// The tenant ID that is contained in the URI is the tenant that creates the +// network. An admin user, however, has the option of specifying another tenant +// ID in the CreateOpts struct. +func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) { + b, err := opts.ToNetworkCreateMap() + if err != nil { + r.Err = err + return + } + _, r.Err = c.Post(createURL(c), b, &r.Body, nil) + return +} + +// UpdateOptsBuilder allows extensions to add additional parameters to the +// Update request. +type UpdateOptsBuilder interface { + ToNetworkUpdateMap() (map[string]interface{}, error) +} + +// 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"` +} + +// ToNetworkUpdateMap builds a request body from UpdateOpts. +func (opts UpdateOpts) ToNetworkUpdateMap() (map[string]interface{}, error) { + return gophercloud.BuildRequestBody(opts, "network") +} + +// Update accepts a UpdateOpts struct and updates an existing network using the +// values provided. For more information, see the Create function. +func Update(c *gophercloud.ServiceClient, networkID string, opts UpdateOptsBuilder) (r UpdateResult) { + b, err := opts.ToNetworkUpdateMap() + if err != nil { + r.Err = err + return + } + _, r.Err = c.Put(updateURL(c, networkID), b, &r.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200, 201}, + }) + return +} + +// Delete accepts a unique ID and deletes the network associated with it. +func Delete(c *gophercloud.ServiceClient, networkID string) (r DeleteResult) { + _, r.Err = c.Delete(deleteURL(c, networkID), nil) + return +} + +// IDFromName is a convenience function that returns a network's ID, given +// its name. +func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) { + count := 0 + id := "" + pages, err := List(client, nil).AllPages() + if err != nil { + return "", err + } + + all, err := ExtractNetworks(pages) + if err != nil { + return "", err + } + + for _, s := range all { + if s.Name == name { + count++ + id = s.ID + } + } + + switch count { + case 0: + return "", gophercloud.ErrResourceNotFound{Name: name, ResourceType: "network"} + case 1: + return id, nil + default: + return "", gophercloud.ErrMultipleResourcesFound{Name: name, Count: count, ResourceType: "network"} + } +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/results.go new file mode 100644 index 00000000000..ffd0259f1d2 --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/results.go @@ -0,0 +1,111 @@ +package networks + +import ( + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/pagination" +) + +type commonResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a network resource. +func (r commonResult) Extract() (*Network, error) { + var s Network + err := r.ExtractInto(&s) + return &s, err +} + +func (r commonResult) ExtractInto(v interface{}) error { + return r.Result.ExtractIntoStructPtr(v, "network") +} + +// CreateResult represents the result of a create operation. Call its Extract +// method to interpret it as a Network. +type CreateResult struct { + commonResult +} + +// GetResult represents the result of a get operation. Call its Extract +// method to interpret it as a Network. +type GetResult struct { + commonResult +} + +// UpdateResult represents the result of an update operation. Call its Extract +// method to interpret it as a Network. +type UpdateResult 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 +} + +// Network represents, well, a network. +type Network struct { + // UUID for the network + ID string `json:"id"` + + // Human-readable name for the network. Might not be unique. + Name string `json:"name"` + + // The administrative state of network. If false (down), the network does not + // forward packets. + AdminStateUp bool `json:"admin_state_up"` + + // Indicates whether network is currently operational. Possible values include + // `ACTIVE', `DOWN', `BUILD', or `ERROR'. Plug-ins might define additional + // values. + Status string `json:"status"` + + // Subnets associated with this network. + Subnets []string `json:"subnets"` + + // Owner of network. + TenantID string `json:"tenant_id"` + + // Specifies whether the network resource can be accessed by any tenant. + Shared bool `json:"shared"` +} + +// NetworkPage is the page returned by a pager when traversing over a +// collection of networks. +type NetworkPage struct { + pagination.LinkedPageBase +} + +// NextPageURL is invoked when a paginated collection of networks 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 NetworkPage) NextPageURL() (string, error) { + var s struct { + Links []gophercloud.Link `json:"networks_links"` + } + err := r.ExtractInto(&s) + if err != nil { + return "", err + } + return gophercloud.ExtractNextURL(s.Links) +} + +// IsEmpty checks whether a NetworkPage struct is empty. +func (r NetworkPage) IsEmpty() (bool, error) { + is, err := ExtractNetworks(r) + return len(is) == 0, err +} + +// ExtractNetworks accepts a Page struct, specifically a NetworkPage struct, +// and extracts the elements into a slice of Network structs. In other words, +// a generic collection is mapped into a relevant slice. +func ExtractNetworks(r pagination.Page) ([]Network, error) { + var s []Network + err := ExtractNetworksInto(r, &s) + return s, err +} + +func ExtractNetworksInto(r pagination.Page, v interface{}) error { + return r.(NetworkPage).Result.ExtractIntoSlicePtr(v, "networks") +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/urls.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/urls.go new file mode 100644 index 00000000000..4a8fb1dc7d3 --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/urls.go @@ -0,0 +1,31 @@ +package networks + +import "github.com/gophercloud/gophercloud" + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("networks", id) +} + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("networks") +} + +func getURL(c *gophercloud.ServiceClient, id string) string { + return resourceURL(c, id) +} + +func listURL(c *gophercloud.ServiceClient) string { + return rootURL(c) +} + +func createURL(c *gophercloud.ServiceClient) string { + return rootURL(c) +} + +func updateURL(c *gophercloud.ServiceClient, id string) string { + return resourceURL(c, id) +} + +func deleteURL(c *gophercloud.ServiceClient, id string) string { + return resourceURL(c, id) +} diff --git a/vendor/github.com/gophercloud/gophercloud/params.go b/vendor/github.com/gophercloud/gophercloud/params.go index 6afc8f8b721..687af3dc0ce 100644 --- a/vendor/github.com/gophercloud/gophercloud/params.go +++ b/vendor/github.com/gophercloud/gophercloud/params.go @@ -347,12 +347,21 @@ func BuildQueryString(opts interface{}) (*url.URL, error) { params.Add(tags[0], v.Index(i).String()) } } + case reflect.Map: + if v.Type().Key().Kind() == reflect.String && v.Type().Elem().Kind() == reflect.String { + var s []string + for _, k := range v.MapKeys() { + value := v.MapIndex(k).String() + s = append(s, fmt.Sprintf("'%s':'%s'", k.String(), value)) + } + params.Add(tags[0], fmt.Sprintf("{%s}", strings.Join(s, ", "))) + } } } else { // Otherwise, the field is not set. if len(tags) == 2 && tags[1] == "required" { // And the field is required. Return an error. - return nil, fmt.Errorf("Required query parameter [%s] not set.", f.Name) + return &url.URL{}, fmt.Errorf("Required query parameter [%s] not set.", f.Name) } } }