././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0389223 python-octaviaclient-3.7.0/0000775000175000017500000000000000000000000015710 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/.coveragerc0000664000175000017500000000014700000000000020033 0ustar00zuulzuul00000000000000[run] branch = True source = octaviaclient omit = octaviaclient/tests/* [report] ignore_errors = True ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/.mailmap0000664000175000017500000000013100000000000017324 0ustar00zuulzuul00000000000000# Format is: # # ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/.pylintrc0000664000175000017500000000500300000000000017553 0ustar00zuulzuul00000000000000# The format of this file isn't really documented; just use --generate-rcfile [MASTER] # Add to the black list. It should be a base name, not a # path. You may set this option multiple times. ignore=.git,tests [MESSAGES CONTROL] # NOTE: The options which do not need to be suppressed can be removed. disable= # "F" Fatal errors that prevent further processing # "I" Informational noise c-extension-no-member, locally-disabled, # "E" Error for important programming issues (likely bugs) import-error, not-callable, no-member, # "W" Warnings for stylistic problems or minor programming issues abstract-method, anomalous-backslash-in-string, arguments-differ, attribute-defined-outside-init, broad-except, fixme, global-statement, pointless-string-statement, protected-access, redefined-builtin, redefined-outer-name, signature-differs, unidiomatic-typecheck, unused-argument, unused-variable, useless-super-delegation, # "C" Coding convention violations invalid-name, line-too-long, missing-docstring, consider-using-f-string, # "R" Refactor recommendations duplicate-code, too-few-public-methods, too-many-ancestors, too-many-arguments, too-many-branches, too-many-instance-attributes, too-many-lines, too-many-locals, too-many-public-methods, too-many-return-statements, too-many-statements, multiple-statements, duplicate-except, keyword-arg-before-vararg, useless-object-inheritance [BASIC] # Variable names can be 1 to 31 characters long, with lowercase and underscores variable-rgx=[a-z_][a-z0-9_]{0,30}$ # Argument names can be 2 to 31 characters long, with lowercase and underscores argument-rgx=[a-z_][a-z0-9_]{1,30}$ # Method names should be at least 3 characters long # and be lowercased with underscores method-rgx=([a-z_][a-z0-9_]{2,}|setUp|tearDown)$ # Module names matching module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ # Don't require docstrings on tests. no-docstring-rgx=((__.*__)|([tT]est.*)|setUp|tearDown)$ [FORMAT] # Maximum number of characters on a single line. max-line-length=79 [VARIABLES] # List of additional names supposed to be defined in builtins. Remember that # you should avoid to define new builtins when possible. additional-builtins= [CLASSES] [IMPORTS] # Deprecated modules which should not be used, separated by a comma deprecated-modules= [TYPECHECK] # List of module names for which member attributes should not be checked ignored-modules=six.moves,_MovedItems [REPORTS] # Tells whether to display a full report or only the messages reports=no ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/.stestr.conf0000664000175000017500000000010700000000000020157 0ustar00zuulzuul00000000000000[DEFAULT] test_path=${OS_TEST_PATH:-./octaviaclient/tests/} top_dir=./ ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220677.0 python-octaviaclient-3.7.0/AUTHORS0000664000175000017500000000427700000000000016772 0ustar00zuulzuul00000000000000Adam Harwell Andreas Jaeger Andrey Kurilin Ankur Gupta Ann Kamyshnikova Artem Goncharov Bar Elharar Bar RH Ben Nemec Bernhard M. Wiedemann Brian Haley Carlos Goncalves Corey Bryant Doug Hellmann Elancheran Subramanian Eric Fried Ghanshyam Mann Gregory Thiemonge Guoqiang Ding Jude Cross Kiran_totad Lingxian Kong M V P Nitesh Maciej Józefczyk Marcin Wilk Michael Johnson Michał Dulko Nguyen Hai Nguyen Hai Truong Nir Magnezi Noah Mickus Omer OpenStack Release Bot Sam Morrison ShangXiao Stephen Finucane Takashi Kajinami Takashi Kajinami Thomas Bechtold Tom Weininger Tony Breeds Yang JianFeng YuehuiLei Zane Bitter ZhaoBo ZhongShengping cao.yuan huangshan jacky06 lidong malei pengyuesheng qingszhao sapd sudhir_agarwal sunjia wangqi wu.shiming yangjianfeng yanpuqing zhangboye ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/CONTRIBUTING.rst0000664000175000017500000000124500000000000020353 0ustar00zuulzuul00000000000000If you would like to contribute to the development of OpenStack, you must follow the steps in this page: https://docs.openstack.org/infra/manual/developers.html If you already have a good understanding of how the system works and your OpenStack accounts are set up, you can skip to the development workflow section of this documentation to learn how changes to OpenStack should be submitted for review via the Gerrit tool: https://docs.openstack.org/infra/manual/developers.html#development-workflow Pull requests submitted through GitHub will be ignored. Bugs should be filed on OpenStack Storyboard, not GitHub: https://storyboard.openstack.org/#!/project/911 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220677.0 python-octaviaclient-3.7.0/ChangeLog0000664000175000017500000002235300000000000017467 0ustar00zuulzuul00000000000000CHANGES ======= 3.7.0 ----- * Added the vip\_vnic\_type load balancer field * reno: Update master for unmaintained/yoga * Bump hacking * Update python classifier in setup.cfg 3.6.0 ----- * Set default value for HSTS options to None * Update master for stable/2023.2 3.5.0 ----- * Fix validation of HSTS attributes * Fix inconsistency in validation error message for HSTS * Add extra validation for HSTS related arguments * Add support for HTTP Strict Transport Security * Update master for stable/2023.1 3.4.0 ----- * Remove munch dependency 3.3.0 ----- * Add munch explicitly to requirements * Fixing jobs with tox4 * Add missing flavor set --description option * Fix new pylint warnings * Add \*.orig to .gitignore * Switch to 2023.1 Python3 unit tests and generic template name * Fix pool protocols 3.2.0 ----- * Update master for stable/zed 3.1.0 ----- 3.0.0 ----- * Drop lower-constraints.txt and its testing * Update python testing as per zed cycle testing runtime * Bump tox minversion to 3.18.0 * Remove DELETED from the provisioning status list * Allow creating/showing LBs with Additional VIPs * Update master for stable/yoga 2.5.0 ----- * Add support for PROMETHEUS listeners * Clarify the client code is not python bindings * Ignore new pylint checker * Add Python3 yoga unit tests * Update master for stable/xena * Fix inconsistent parameter name in azp 2.4.0 ----- * Fix some typos * Improve the client performance on large clouds * Support pagination for 'list' API calls * setup.cfg: Replace dashes with underscores * Use py3 as the default runtime for tox * Add Python3 xena unit tests * Update master for stable/wallaby 2.3.0 ----- * Remove Babel * Improve error messages in list/show calls * Remove install unnecessary packages * Add ALPN support for pools * Fix lower-constraints job * remove unicode from code * Add tag support for Octavia resources * Add support for PROXYV2 protocol * Add Python3 wallaby unit tests * Update master for stable/victoria 2.2.0 ----- * Add SCTP support * Fix the lower-constraints job for focal * Add amphora delete command * Fix hacking min version to 3.0.1 * Add TLS versions and ciphers unsets * Add ALPN support for listeners * Fix new pylint errors 2.1.0 ----- * Show operating\_status in listing LB output * Switch to newer openstackdocstheme and reno versions * Add the ability to specify TLS protocols for a pool * Add l7policy and l7rule to octavia quota * Add Python3 victoria unit tests * Remove mocking of functools.partial * Add the ability to specify TLS protocols for a listener * Remove Babel requirement * Update master for stable/ussuri 2.0.1 ----- * Add the ability to specify the cipher list for a listener * Add the ability to specify the cipher list for a pool * Cleanup py27 support * Update hacking for Python3 * Fix doc8 check * Align python-octaviaclient to octavia coding style * Remove the dependency on the "mock" package * Fix Octavia client for API endpoint 503 * Add --long to amphora-list to show more columns * Fix long CLI error messages 2.0.0 ----- * Add support for availability zone [profiles] * Add amphora stats show API and CLI * Fix API breakage due to new exceptions module * Add "--wait" functionality * Do not get all resources if ID is passed * Stop testing python 2 1.11.0 ------ * Add librsvg2-bin/-tools to bindep.txt * List l7poclies by listener * Drop netifaces from requirements.txt * Update master for stable/train 1.10.0 ------ * Add support for SOURCE\_IP\_PORT algorithm * Wrap several show api calls with correct\_return\_codes * Add support to VIP access control list * Generate PDF documentation * Fix a bad unit test for amphora list * Bump the openstackdocstheme extension to 1.20 * Blacklist sphinx 2.1.0 (autodoc bug) * Add Python 3 Train unit tests * Update tox.ini for new upper constraints strategy 1.9.0 ----- * Adds "unset" action to the quota command * Adds "unset" action to the l7rule command * Adds "unset" action to the l7policy command * Adds "unset" action to the flavor command * Adds "unset" action to the healthmonitor command * Adds "unset" action to the member command * Adds "unset" action to the pool command * Cleanup requirements.txt * Replace git.openstack.org URLs with opendev.org URLs * OpenDev Migration Patch * Remove python3.5 jobs for Train * Adds "unset" action to the listener command * Adds "unset" action to the loadbalancer command * Make sure we always requests JSON responses * Update master for stable/stein 1.8.0 ----- * Add new options to HealthMonitor CLI * Add a new option '--redirect-http-code' into L7Policy CLI * Add enable\_tls option into Pool CLI * Add 2 new options to Pool for support backend certificates validation * Add 'tls\_container\_ref' option into Pool for backend re-encrption * Adds loadbalancer amphora configure to OSC * Add 4 l7rule types into Octavia CLI * Add client\_crl\_container\_ref for Listener API in CLI * Add 'client\_authentication' in Listener on client * Add 'client\_ca\_tls\_container\_ref' in Listener on client side * Update json module to jsonutils * Add load balancer flavor support to the OSC client * add python 3.7 unit test job * Make the documentation reproducible * Add some commands for octavia flavor and flavor\_profile * Add provider command support * Add --provider to load balancer create * Fix coverage and set a minimum 1.7.0 ----- * Fixed some typos * Add failover an amphora client support * Add compute\_flavor field to amphora * Support REDIRECT\_PREFIX for openstack client * Change openstack-dev to openstack-discuss * Add Python 3.6 classifier to setup.cfg * Add python 3.6 unit test job * Use templates for cover and lower-constraints * add python 3.6 unit test job * switch documentation job to new PTI * import zuul job settings from project-config * Update reno for stable/rocky 1.6.0 ----- * LB support UDP - Client part * Support backup members * Add some filter options to load balancer list command * Fix missing docs command mapping for status show * fix tox python3 overrides 1.5.0 ----- * Add timeout options to listener resource * Add loadbalancer status show client api and osc * update cmd2 dependency to handle py3 only versions * Update python-octaviaclient tox for stestr * Fix for docs build in tox.ini * Update the outdated links * fix a typo: s/extention/extension * Minor changes in docs * Updated from global requirements * Add release notes link to README * add lower-constraints job * Updated from global requirements * Updated from global requirements * Updated from global requirements * Add image\_id and timestamps to amphora * Update http links in docs * Updated from global requirements * fix error url * Update docs config for storyboard bugs * Updates the command mapping to include LB stats * Updated from global requirements * Update reno for stable/queens 1.4.0 ----- * Update and add listener stats release notes * Updated from global requirements * Remove direct dependency on testtools * Updated from global requirements * Improve unit testing scalability * Code cleanup * Update new documentation PTI jobs * Updated from global requirements * Updated from global requirements * Allow case-insensitive entries when selecting from choices * Add VIP QoS Policy client support * Add listener stats client api and osc * Fix release notes theme 1.3.0 ----- * Complement Octavia client with a set of features * Extend loadbalancer\_create valid VIP parameters combinations * Add Quota client API and OSC support * Add loadbalancer stats client api and osc * Updated from global requirements * Avoid tox\_install.sh for constraints support * Remove .testrepository/times.dbm in tox.ini * Updated from global requirements * Updated from global requirements * Fix missing TLS handling in listener create * Updated from global requirements * Improve error reporting for the octavia plugin * Updated from global requirements * Updated from global requirements * Move to auto-generated CLI reference * Remove positional from requirements * Lowercase vip\_Address in return * Remove reqs from test-req that exist in req * Updated from global requirements * Update reno for stable/pike * Update python-octaviaclient docs for migration * Updated from global requirements * Updated from global requirements * Replaces uuid.uuid4 with uuidutils.generate\_uuid() 1.1.0 ----- * Remove rogue calls to str.upper in l7rules * Replace six.iteritems() with .items() * Updated from global requirements * Add TLS-HELLO option for HealthMonitors * Remove old pep8 ignores that are no longer necessary * Updated from global requirements 1.0.0 ----- * Add check O346 to disallow backslash line continuation * Fix command to include PROXY and update metavars * Update help text for all commands * Add healthmonitor commands to client * Add l7rule commands to client * Add l7policy commands to client * Add member commands to client * Updated from global requirements * Add hacking checks * Add pool commands to client * Add Listener commands to client * Add loadbalancer commands to client * Updated from global requirements * Add install information to readme.rst * Version name correction to allow installing * Optimize the link address 0.1.0 ----- * Initialize plugin for OSC * Update Docs for more information and dummy commands * Add mapping documentation between legacy Neutron CLI and Octavia * Initial setup of the python-octaviaclient repo * Added .gitreview ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/HACKING.rst0000664000175000017500000000024200000000000017504 0ustar00zuulzuul00000000000000python-octaviaclient Style Commandments ======================================= Read the OpenStack Style Commandments https://docs.openstack.org/hacking/latest/ ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/LICENSE0000664000175000017500000002363700000000000016730 0ustar00zuulzuul00000000000000 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. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0389223 python-octaviaclient-3.7.0/PKG-INFO0000664000175000017500000000600500000000000017006 0ustar00zuulzuul00000000000000Metadata-Version: 1.2 Name: python-octaviaclient Version: 3.7.0 Summary: Octavia client for OpenStack Load Balancing Home-page: https://docs.openstack.org/python-octaviaclient/latest/ Author: OpenStack Author-email: openstack-discuss@lists.openstack.org License: UNKNOWN Description: Team and repository tags ======================== .. image:: https://governance.openstack.org/tc/badges/python-octaviaclient.svg :target: https://governance.openstack.org/tc/reference/tags/index.html .. Change things from this point on python-octaviaclient ==================== Octavia client for OpenStack Load Balancing This is an OpenStack Client (OSC) plugin for Octavia, an OpenStack Load Balancing project. For more information about Octavia see: https://docs.openstack.org/octavia/latest/ For more information about the OpenStack Client see: https://docs.openstack.org/python-openstackclient/latest/ * Free software: Apache license * Documentation: https://docs.openstack.org/python-octaviaclient/latest/ * Source: https://opendev.org/openstack/python-octaviaclient * Release notes: https://docs.openstack.org/releasenotes/python-octaviaclient/ * Bugs: https://storyboard.openstack.org/#!/project/911 Getting Started =============== .. note:: This is an OpenStack Client plugin. The ``python-openstackclient`` project should be installed to use this plugin. .. note:: This project is only intended to be used for the OpenStack Client CLI. The `openstacksdk `_ should be used for python bindings. Octavia client can be installed from PyPI using pip .. code-block:: bash pip install python-octaviaclient If you want to make changes to the Octavia client for testing and contribution, make any changes and then run .. code-block:: bash python setup.py develop or .. code-block:: bash pip install -e . Platform: UNKNOWN Classifier: Environment :: OpenStack Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: 3 :: Only Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Requires-Python: >=3.8 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/README.rst0000664000175000017500000000311700000000000017401 0ustar00zuulzuul00000000000000Team and repository tags ======================== .. image:: https://governance.openstack.org/tc/badges/python-octaviaclient.svg :target: https://governance.openstack.org/tc/reference/tags/index.html .. Change things from this point on python-octaviaclient ==================== Octavia client for OpenStack Load Balancing This is an OpenStack Client (OSC) plugin for Octavia, an OpenStack Load Balancing project. For more information about Octavia see: https://docs.openstack.org/octavia/latest/ For more information about the OpenStack Client see: https://docs.openstack.org/python-openstackclient/latest/ * Free software: Apache license * Documentation: https://docs.openstack.org/python-octaviaclient/latest/ * Source: https://opendev.org/openstack/python-octaviaclient * Release notes: https://docs.openstack.org/releasenotes/python-octaviaclient/ * Bugs: https://storyboard.openstack.org/#!/project/911 Getting Started =============== .. note:: This is an OpenStack Client plugin. The ``python-openstackclient`` project should be installed to use this plugin. .. note:: This project is only intended to be used for the OpenStack Client CLI. The `openstacksdk `_ should be used for python bindings. Octavia client can be installed from PyPI using pip .. code-block:: bash pip install python-octaviaclient If you want to make changes to the Octavia client for testing and contribution, make any changes and then run .. code-block:: bash python setup.py develop or .. code-block:: bash pip install -e . ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/bindep.txt0000664000175000017500000000046400000000000017716 0ustar00zuulzuul00000000000000# This is a cross-platform list tracking distribution packages needed for install and tests; # see https://docs.openstack.org/infra/bindep/ for additional information. # libsrvg2 is needed for sphinxcontrib-svg2pdfconverter in docs builds. librsvg2-tools [doc platform:rpm] librsvg2-bin [doc platform:dpkg] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0229225 python-octaviaclient-3.7.0/doc/0000775000175000017500000000000000000000000016455 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/doc/requirements.txt0000664000175000017500000000056700000000000021751 0ustar00zuulzuul00000000000000# The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. sphinx>=2.0.0,!=2.1.0 # BSD openstackdocstheme>=2.2.1 # Apache-2.0 # releasenotes reno>=3.1.0 # Apache-2.0 # PDF Docs sphinxcontrib-svg2pdfconverter>=0.1.0 # BSD ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0229225 python-octaviaclient-3.7.0/doc/source/0000775000175000017500000000000000000000000017755 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0229225 python-octaviaclient-3.7.0/doc/source/cli/0000775000175000017500000000000000000000000020524 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/doc/source/cli/index.rst0000664000175000017500000000512000000000000022363 0ustar00zuulzuul00000000000000Using Octavia CLI extensions to OpenStack Client ================================================ List of released CLI commands available in openstack client. These commands can be referenced by doing ``openstack help loadbalancer``. ============ loadbalancer ============ .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer create .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer delete .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer list .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer set .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer unset .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer show .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer stats show .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer status show .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer failover ======== listener ======== .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer listener * ==== pool ==== .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer pool * ====== member ====== .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer member * ============= healthmonitor ============= .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer healthmonitor * ======== l7policy ======== .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer l7policy * ====== l7rule ====== .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer l7rule * ===== quota ===== .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer quota * ======= amphora ======= .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer amphora * ======== provider ======== .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer provider * ====== flavor ====== .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer flavor * ============= flavorprofile ============= .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer flavorprofile * ================ availabilityzone ================ .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer availabilityzone * ======================= availabilityzoneprofile ======================= .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer availabilityzoneprofile * ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/doc/source/conf.py0000775000175000017500000001021300000000000021254 0ustar00zuulzuul00000000000000# -*- coding: utf-8 -*- # 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. import datetime import os import sys sys.path.insert(0, os.path.abspath('../..')) # -- General configuration ---------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ 'sphinx.ext.autodoc', 'openstackdocstheme', 'cliff.sphinxext', 'sphinxcontrib.rsvgconverter' ] # autodoc generation is a bit aggressive and a nuisance when doing heavy # text edit cycles. # execute "export SPHINX_DEBUG=1" in your terminal to disable # The suffix of source filenames. source_suffix = '.rst' # The master toctree document. master_doc = 'index' # General information about the project. copyright = '2016-2019, OpenStack Foundation' # If true, '()' will be appended to :func: etc. cross-reference text. add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). add_module_names = True # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'native' # openstackdocstheme options openstackdocs_repo_name = 'openstack/python-octaviaclient' openstackdocs_pdf_link = True openstackdocs_use_storyboard = True autoprogram_cliff_application = 'openstack' # -- Options for HTML output -------------------------------------------------- # The theme to use for HTML and HTML Help pages. Major themes that come with # Sphinx are currently 'default' and 'sphinxdoc'. # html_theme_path = ["."] # html_theme = '_theme' # html_static_path = ['static'] html_theme = 'openstackdocs' html_theme_options = { 'show_other_versions': True } # Output file base name for HTML help builder. htmlhelp_basename = 'python-octaviaclientdoc' # -- Options for LaTeX output ------------------------------------------------- # Fix Unicode character for sphinx_feature_classification # Sphinx default latex engine (pdflatex) doesn't know much unicode latex_preamble = r""" \usepackage{newunicodechar} \newunicodechar{✖}{\sffamily X} \setcounter{tocdepth}{2} \authoraddress{\textcopyright %s OpenStack Foundation} """ % datetime.datetime.now().year latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # 'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). # 'pointsize': '10pt', # Additional stuff for the LaTeX preamble. # openany: Skip blank pages in generated PDFs 'extraclassoptions': 'openany,oneside', 'makeindex': '', 'printindex': '', 'preamble': latex_preamble } # Disable usage of xindy https://bugzilla.redhat.com/show_bug.cgi?id=1643664 # Some distros are missing xindy latex_use_xindy = False # Fix missing apostrophe smartquotes_excludes = {'builders': ['latex']} # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass # [howto/manual]). latex_documents = [( 'index', 'doc-python-octaviaclient.tex', 'Octavia Python Client Documentation', 'OpenStack Octavia Team', 'manual' )] # The name of an image file (relative to this directory) to place at the top of # the title page. # latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. # latex_use_parts = False # If true, show page references after internal links. # latex_show_pagerefs = False # If true, show URL addresses after external links. # latex_show_urls = False # Documents to append as an appendix to all manuals. # latex_appendices = [] # If false, no module index is generated. latex_domain_indices = False ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0229225 python-octaviaclient-3.7.0/doc/source/contributor/0000775000175000017500000000000000000000000022327 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/doc/source/contributor/index.rst0000664000175000017500000000011600000000000024166 0ustar00zuulzuul00000000000000============ Contributing ============ .. include:: ../../../CONTRIBUTING.rst ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/doc/source/index.rst0000664000175000017500000000163600000000000021624 0ustar00zuulzuul00000000000000.. python-octaviaclient documentation master file, created by sphinx-quickstart on Tue Jul 9 22:26:36 2013. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. Python Octavia Client ===================== .. only:: html The Python Octavia Client (python-octaviaclient) is a command-line client for the OpenStack Load Balancing service. .. note:: This project is only intended to be used for the OpenStack Client CLI. The `openstacksdk `_ should be used for python bindings. Getting Started --------------- .. toctree:: :maxdepth: 2 Project Overview install/index contributor/index Usage ----- .. toctree:: :maxdepth: 2 cli/index reference/index .. only:: html Indices and tables ------------------ * :ref:`genindex` * :ref:`search` ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0229225 python-octaviaclient-3.7.0/doc/source/install/0000775000175000017500000000000000000000000021423 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/doc/source/install/index.rst0000664000175000017500000000074100000000000023266 0ustar00zuulzuul00000000000000============ Installation ============ This is an OpenStack Client plugin for the load-balancer (Octavia) project. Install the load-balancer (Octavia) plugin:: $ pip install python-octaviaclient Or, if you have virtualenvwrapper installed:: $ mkvirtualenv python-octaviaclient $ pip install python-octaviaclient .. note:: If python-openstackclient is not already installed it will be installed as part of the requirements for the Octavia client plugin. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/doc/source/readme.rst0000664000175000017500000000012200000000000021737 0ustar00zuulzuul00000000000000================ Project Overview ================ .. include:: ../../README.rst ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0229225 python-octaviaclient-3.7.0/doc/source/reference/0000775000175000017500000000000000000000000021713 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0229225 python-octaviaclient-3.7.0/doc/source/reference/data/0000775000175000017500000000000000000000000022624 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/doc/source/reference/data/lbaas.csv0000664000175000017500000000626100000000000024430 0ustar00zuulzuul00000000000000lbaas-healthmonitor-create,loadbalancer healthmonitor create,LBaaS v2 Create a healthmonitor. lbaas-healthmonitor-delete,loadbalancer healthmonitor delete,LBaaS v2 Delete a given healthmonitor. lbaas-healthmonitor-list,loadbalancer healthmonitor list,LBaaS v2 List healthmonitors that belong to a given tenant. lbaas-healthmonitor-show,loadbalancer healthmonitor show,LBaaS v2 Show information of a given healthmonitor. lbaas-healthmonitor-update,loadbalancer healthmonitor set,LBaaS v2 Update a given healthmonitor. lbaas-l7policy-create,loadbalancer l7policy create,LBaaS v2 Create L7 policy. lbaas-l7policy-delete,loadbalancer l7policy delete,LBaaS v2 Delete a given L7 policy. lbaas-l7policy-list,loadbalancer l7policy list,LBaaS v2 List L7 policies that belong to a given listener. lbaas-l7policy-show,loadbalancer l7policy show,LBaaS v2 Show information of a given L7 policy. lbaas-l7policy-update,loadbalancer l7policy set,LBaaS v2 Update a given L7 policy. lbaas-l7rule-create,loadbalancer l7rule create,LBaaS v2 Create L7 rule. lbaas-l7rule-delete,loadbalancer l7rule delete,LBaaS v2 Delete a given L7 rule. lbaas-l7rule-list,loadbalancer l7rule list,LBaaS v2 List L7 rules that belong to a given L7 policy. lbaas-l7rule-show,loadbalancer l7rule show,LBaaS v2 Show information of a given rule. lbaas-l7rule-update,loadbalancer l7rule set,LBaaS v2 Update a given L7 rule. lbaas-listener-create,loadbalancer listener create,LBaaS v2 Create a listener. lbaas-listener-delete,loadbalancer listener delete,LBaaS v2 Delete a given listener. lbaas-listener-list,loadbalancer listener list,LBaaS v2 List listeners that belong to a given tenant. lbaas-listener-show,loadbalancer listener show,LBaaS v2 Show information of a given listener. lbaas-listener-update,loadbalancer listener set,LBaaS v2 Update a given listener. lbaas-loadbalancer-create,loadbalancer create,LBaaS v2 Create a loadbalancer. lbaas-loadbalancer-delete,loadbalancer delete,LBaaS v2 Delete a given loadbalancer. lbaas-loadbalancer-list,loadbalancer list,LBaaS v2 List loadbalancers that belong to a given tenant. lbaas-loadbalancer-list-on-agent,,List the loadbalancers on a loadbalancer v2 agent. lbaas-loadbalancer-show,loadbalancer show,LBaaS v2 Show information of a given loadbalancer. lbaas-loadbalancer-stats,loadbalancer stats show,Retrieve stats for a given loadbalancer. lbaas-loadbalancer-status,loadbalancer status show,Retrieve status for a given loadbalancer. lbaas-loadbalancer-update,loadbalancer set,LBaaS v2 Update a given loadbalancer. lbaas-member-create,loadbalancer member create,LBaaS v2 Create a member. lbaas-member-delete,loadbalancer member delete,LBaaS v2 Delete a given member. lbaas-member-list,loadbalancer member list,LBaaS v2 List members that belong to a given pool. lbaas-member-show,loadbalancer member show,LBaaS v2 Show information of a given member. lbaas-member-update,loadbalancer member set,LBaaS v2 Update a given member. lbaas-pool-create,loadbalancer pool create,LBaaS v2 Create a pool. lbaas-pool-delete,loadbalancer pool delete,LBaaS v2 Delete a given pool. lbaas-pool-list,loadbalancer pool list,LBaaS v2 List pools that belong to a given tenant. lbaas-pool-show,loadbalancer pool show,LBaaS v2 Show information of a given pool. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/doc/source/reference/index.rst0000664000175000017500000000122100000000000023550 0ustar00zuulzuul00000000000000Python Octavia Client Reference =============================== The following is a mapping between legacy Neutron CLIs and the Octavia plugin into OSC. Think of it as a magic decoder ring if you were using the legacy CLIs and want to transition to OpenStack CLI. Command options are only shown when necessary. Mapping Guide - LBaaS v2 CLI ---------------------------- .. csv-table:: :header: "Neutron CLI", "OSC Equivalent", "Description" :widths: 30, 30, 40 :file: data/lbaas.csv .. note:: As commands get introduced they will populate the table. If no OSC Equivalent commands are listed, the command has not been implemented yet. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0229225 python-octaviaclient-3.7.0/octaviaclient/0000775000175000017500000000000000000000000020535 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/__init__.py0000664000175000017500000000123700000000000022651 0ustar00zuulzuul00000000000000# -*- coding: utf-8 -*- # 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. import pbr.version __version__ = pbr.version.VersionInfo('python-octaviaclient').version_string() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0229225 python-octaviaclient-3.7.0/octaviaclient/api/0000775000175000017500000000000000000000000021306 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/api/__init__.py0000664000175000017500000000000000000000000023405 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/api/constants.py0000664000175000017500000000750400000000000023702 0ustar00zuulzuul00000000000000# 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. # LOADBALANCER_RESOURCES = 'loadbalancers' LISTENER_RESOURCES = 'listeners' POOL_RESOURCES = 'pools' MEMBER_RESOURCES = 'members' HEALTH_MONITOR_RESOURCES = 'healthmonitors' L7POLICY_RESOURCES = 'l7policies' L7RULE_RESOURCES = 'rules' QUOTA_RESOURCES = 'quotas' AMPHORA_RESOURCES = 'amphorae' PROVIDER_RESOURCES = 'providers' PROVIDER_FLAVOR_CAPABILITY_RESOURCES = 'flavor_capabilities' PROVIDER_AVAILABILITY_ZONE_CAPABILITY_RESOURCES = ( 'availability_zone_capabilities') FLAVOR_RESOURCES = 'flavors' FLAVORPROFILE_RESOURCES = 'flavorprofiles' AVAILABILITYZONE_RESOURCES = 'availability_zones' AVAILABILITYZONEPROFILE_RESOURCES = 'availability_zone_profiles' BASE_LBAAS_ENDPOINT = '/lbaas' BASE_OCTAVIA_ENDPOINT = '/octavia' BASE_LOADBALANCER_URL = BASE_LBAAS_ENDPOINT + '/' + LOADBALANCER_RESOURCES BASE_SINGLE_LB_URL = BASE_LOADBALANCER_URL + '/{uuid}' BASE_LB_STATS_URL = BASE_SINGLE_LB_URL + '/stats' BASE_LOADBALANCER_STATUS_URL = BASE_SINGLE_LB_URL + '/status' BASE_LOADBALANCER_FAILOVER_URL = BASE_SINGLE_LB_URL + '/failover' BASE_LISTENER_URL = BASE_LBAAS_ENDPOINT + '/' + LISTENER_RESOURCES BASE_SINGLE_LISTENER_URL = BASE_LISTENER_URL + '/{uuid}' BASE_LISTENER_STATS_URL = BASE_SINGLE_LISTENER_URL + '/stats' BASE_POOL_URL = BASE_LBAAS_ENDPOINT + '/' + POOL_RESOURCES BASE_SINGLE_POOL_URL = BASE_POOL_URL + '/{pool_id}' BASE_MEMBER_URL = BASE_SINGLE_POOL_URL + '/' + MEMBER_RESOURCES BASE_SINGLE_MEMBER_URL = BASE_MEMBER_URL + '/{member_id}' BASE_HEALTH_MONITOR_URL = BASE_LBAAS_ENDPOINT + '/' + HEALTH_MONITOR_RESOURCES BASE_SINGLE_HEALTH_MONITOR_URL = BASE_HEALTH_MONITOR_URL + '/{uuid}' BASE_L7POLICY_URL = BASE_LBAAS_ENDPOINT + '/' + L7POLICY_RESOURCES BASE_SINGLE_L7POLICY_URL = BASE_L7POLICY_URL + '/{policy_uuid}' BASE_L7RULE_URL = BASE_SINGLE_L7POLICY_URL + '/' + L7RULE_RESOURCES BASE_SINGLE_L7RULE_URL = BASE_L7RULE_URL + '/{rule_uuid}' BASE_QUOTA_URL = BASE_LBAAS_ENDPOINT + '/' + QUOTA_RESOURCES BASE_SINGLE_QUOTA_URL = BASE_QUOTA_URL + '/{uuid}' BASE_QUOTA_DEFAULT_URL = BASE_QUOTA_URL + '/defaults' BASE_AMPHORA_URL = BASE_OCTAVIA_ENDPOINT + "/" + AMPHORA_RESOURCES BASE_SINGLE_AMPHORA_URL = BASE_AMPHORA_URL + "/{uuid}" BASE_AMPHORA_CONFIGURE_URL = BASE_SINGLE_AMPHORA_URL + '/config' BASE_AMPHORA_FAILOVER_URL = BASE_SINGLE_AMPHORA_URL + '/failover' BASE_AMPHORA_STATS_URL = BASE_SINGLE_AMPHORA_URL + '/stats' BASE_PROVIDER_URL = BASE_LBAAS_ENDPOINT + "/" + PROVIDER_RESOURCES BASE_PROVIDER_FLAVOR_CAPABILITY_URL = ( BASE_PROVIDER_URL + "/{provider}/" + PROVIDER_FLAVOR_CAPABILITY_RESOURCES) BASE_PROVIDER_AVAILABILITY_ZONE_CAPABILITY_URL = ( BASE_PROVIDER_URL + "/{provider}/" + PROVIDER_AVAILABILITY_ZONE_CAPABILITY_RESOURCES ) BASE_FLAVOR_URL = BASE_LBAAS_ENDPOINT + "/" + FLAVOR_RESOURCES BASE_SINGLE_FLAVOR_URL = BASE_FLAVOR_URL + "/{uuid}" BASE_FLAVORPROFILE_URL = BASE_LBAAS_ENDPOINT + "/" + FLAVORPROFILE_RESOURCES BASE_SINGLE_FLAVORPROFILE_URL = BASE_FLAVORPROFILE_URL + "/{uuid}" BASE_AVAILABILITYZONE_URL = BASE_LBAAS_ENDPOINT + "/availabilityzones" BASE_SINGLE_AVAILABILITYZONE_URL = BASE_AVAILABILITYZONE_URL + "/{name}" BASE_AVAILABILITYZONEPROFILE_URL = (BASE_LBAAS_ENDPOINT + "/availabilityzoneprofiles") BASE_SINGLE_AVAILABILITYZONEPROFILE_URL = (BASE_AVAILABILITYZONEPROFILE_URL + "/{uuid}") ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/api/exceptions.py0000664000175000017500000000213700000000000024044 0ustar00zuulzuul00000000000000# 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. # class OctaviaClientException(Exception): """The base exception class for all exceptions this library raises.""" def __init__(self, code, message=None, request_id=None): self.code = code self.message = message or self.__class__.message super().__init__(self.message) self.request_id = request_id def __str__(self): return "%s (HTTP %s) (Request-ID: %s)" % (self.message, self.code, self.request_id) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0229225 python-octaviaclient-3.7.0/octaviaclient/api/v2/0000775000175000017500000000000000000000000021635 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/api/v2/__init__.py0000664000175000017500000000000000000000000023734 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/api/v2/octavia.py0000664000175000017500000010760700000000000023650 0ustar00zuulzuul00000000000000# 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. # """Octavia API Library""" import functools import urllib.parse as urlparse from osc_lib.api import api from osc_lib import exceptions as osc_exc from octaviaclient.api import constants as const from octaviaclient.api import exceptions OctaviaClientException = exceptions.OctaviaClientException def correct_return_codes(func): _status_dict = {400: 'Bad Request', 401: 'Unauthorized', 403: 'Forbidden', 404: 'Not found', 409: 'Conflict', 413: 'Over Limit', 501: 'Not Implemented', 503: 'Service Unavailable'} def wrapper(*args, **kwargs): try: response = func(*args, **kwargs) except Exception as e: code = None message = 'Unknown Error' request_id = "n/a" if hasattr(e, 'request_id'): request_id = e.request_id if hasattr(e, 'response'): code = e.response.status_code try: message = e.response.json().get( 'faultstring', _status_dict.get(code, message)) except Exception: message = _status_dict.get(code, message) elif (isinstance(e, osc_exc.ClientException) and e.code != e.http_status): # cover https://review.opendev.org/675328 case code = e.http_status message = e.code else: raise raise OctaviaClientException( code=code, message=message, request_id=request_id) from e return response return wrapper class OctaviaAPI(api.BaseAPI): """Octavia API""" _endpoint_suffix = '/v2.0' # Make sure we are always requesting JSON responses JSON_HEADER = {'Accept': 'application/json'} def __init__(self, endpoint=None, **kwargs): super().__init__(endpoint=endpoint, **kwargs) self.endpoint = self.endpoint.rstrip('/') self._build_url() self._create = functools.partial(self.create, headers=self.JSON_HEADER) self._delete = functools.partial(self.delete, headers=self.JSON_HEADER) self._find = functools.partial(self.find, headers=self.JSON_HEADER) def _list(self, path, **params): get_all = params.pop('get_all', False) if not get_all: return self.list(path, **params, headers=self.JSON_HEADER) # Enable pagination for 'resources' resource_key = params.pop('resources') res = [] while True: response = self.list(path, **params, headers=self.JSON_HEADER) res.extend(response[resource_key]) links = response.get("{}_links".format(resource_key), []) for link in links: if link.get('rel') == 'next': query_str = urlparse.urlparse(link['href']).query params = urlparse.parse_qs(query_str) break else: break return {resource_key: res} def _build_url(self): if not self.endpoint.endswith(self._endpoint_suffix): self.endpoint += self._endpoint_suffix @correct_return_codes def load_balancer_list(self, **params): """List all load balancers :param params: Parameters to filter on :return: List of load balancers """ url = const.BASE_LOADBALANCER_URL response = self._list(url, get_all=True, resources=const.LOADBALANCER_RESOURCES, **params) return response @correct_return_codes def load_balancer_show(self, lb_id): """Show a load balancer :param string lb_id: ID of the load balancer to show :return: A dict of the specified load balancer's settings """ response = self._find(path=const.BASE_LOADBALANCER_URL, value=lb_id) return response @correct_return_codes def load_balancer_create(self, **params): """Create a load balancer :param params: Paramaters to create the load balancer with (expects json=) :return: A dict of the created load balancer's settings """ url = const.BASE_LOADBALANCER_URL response = self._create(url, **params) return response @correct_return_codes def load_balancer_delete(self, lb_id, **params): """Delete a load balancer :param string lb_id: The ID of the load balancer to delete :param params: A dict of url parameters :return: Response Code from the API """ url = const.BASE_SINGLE_LB_URL.format(uuid=lb_id) response = self._delete(url, params=params) return response @correct_return_codes def load_balancer_set(self, lb_id, **params): """Update a load balancer's settings :param string lb_id: The ID of the load balancer to update :param params: A dict of arguments to update a loadbalancer :return: Response Code from API """ url = const.BASE_SINGLE_LB_URL.format(uuid=lb_id) response = self._create(url, method='PUT', **params) return response @correct_return_codes def load_balancer_stats_show(self, lb_id, **kwargs): """Shows the current statistics for a load balancer. :param string lb_id: ID of the load balancer :return: A dict of the specified load balancer's statistics """ url = const.BASE_LB_STATS_URL.format(uuid=lb_id) response = self._list(url, **kwargs) return response @correct_return_codes def load_balancer_status_show(self, lb_id, **kwargs): """Display load balancer status tree in json format. :param string lb_id: ID of the load balancer :return: A dict of the specified load balancer's status """ url = const.BASE_LOADBALANCER_STATUS_URL.format(uuid=lb_id) response = self._list(url, **kwargs) return response @correct_return_codes def load_balancer_failover(self, lb_id): """Trigger load balancer failover :param string lb_id: ID of the load balancer to failover :return: Response Code from the API """ url = const.BASE_LOADBALANCER_FAILOVER_URL.format(uuid=lb_id) response = self._create(url, method='PUT') return response @correct_return_codes def listener_list(self, **kwargs): """List all listeners :param kwargs: Parameters to filter on :return: List of listeners """ url = const.BASE_LISTENER_URL response = self._list(url, get_all=True, resources=const.LISTENER_RESOURCES, **kwargs) return response @correct_return_codes def listener_show(self, listener_id): """Show a listener :param string listener_id: ID of the listener to show :return: A dict of the specified listener's settings """ response = self._find(path=const.BASE_LISTENER_URL, value=listener_id) return response @correct_return_codes def listener_create(self, **kwargs): """Create a listener :param kwargs: Parameters to create a listener with (expects json=) :return: A dict of the created listener's settings """ url = const.BASE_LISTENER_URL response = self._create(url, **kwargs) return response @correct_return_codes def listener_delete(self, listener_id): """Delete a listener :param stirng listener_id: ID of of listener to delete :return: Response Code from the API """ url = const.BASE_SINGLE_LISTENER_URL.format(uuid=listener_id) response = self._delete(url) return response @correct_return_codes def listener_set(self, listener_id, **kwargs): """Update a listener's settings :param string listener_id: ID of the listener to update :param kwargs: A dict of arguments to update a listener :return: Response Code from the API """ url = const.BASE_SINGLE_LISTENER_URL.format(uuid=listener_id) response = self._create(url, method='PUT', **kwargs) return response @correct_return_codes def listener_stats_show(self, listener_id, **kwargs): """Shows the current statistics for a listener :param string listener_id: ID of the listener :return: A dict of the specified listener's statistics """ url = const.BASE_LISTENER_STATS_URL.format(uuid=listener_id) response = self._list(url, **kwargs) return response @correct_return_codes def pool_list(self, **kwargs): """List all pools :param kwargs: Parameters to filter on :return: List of pools """ url = const.BASE_POOL_URL response = self._list(url, get_all=True, resources=const.POOL_RESOURCES, **kwargs) return response @correct_return_codes def pool_create(self, **kwargs): """Create a pool :param kwargs: Parameters to create a pool with (expects json=) :return: A dict of the created pool's settings """ url = const.BASE_POOL_URL response = self._create(url, **kwargs) return response @correct_return_codes def pool_delete(self, pool_id): """Delete a pool :param string pool_id: ID of of pool to delete :return: Response Code from the API """ url = const.BASE_SINGLE_POOL_URL.format(pool_id=pool_id) response = self._delete(url) return response @correct_return_codes def pool_show(self, pool_id): """Show a pool's settings :param string pool_id: ID of the pool to show :return: Dict of the specified pool's settings """ response = self._find(path=const.BASE_POOL_URL, value=pool_id) return response @correct_return_codes def pool_set(self, pool_id, **kwargs): """Update a pool's settings :param pool_id: ID of the pool to update :param kwargs: A dict of arguments to update a pool :return: Response Code from the API """ url = const.BASE_SINGLE_POOL_URL.format(pool_id=pool_id) response = self._create(url, method='PUT', **kwargs) return response @correct_return_codes def member_list(self, pool_id, **kwargs): """Lists the member from a given pool id :param pool_id: ID of the pool :param kwargs: A dict of filter arguments :return: Response list members """ url = const.BASE_MEMBER_URL.format(pool_id=pool_id) response = self._list(url, get_all=True, resources=const.MEMBER_RESOURCES, **kwargs) return response @correct_return_codes def member_show(self, pool_id, member_id): """Showing a member details of a pool :param pool_id: ID of pool the member is added :param member_id: ID of the member :param kwargs: A dict of arguments :return: Response of member """ url = const.BASE_MEMBER_URL.format(pool_id=pool_id) response = self._find(path=url, value=member_id) return response @correct_return_codes def member_create(self, pool_id, **kwargs): """Creating a member for the given pool id :param pool_id: ID of pool to which member is added :param kwargs: A Dict of arguments :return: A member details on successful creation """ url = const.BASE_MEMBER_URL.format(pool_id=pool_id) response = self._create(url, **kwargs) return response @correct_return_codes def member_delete(self, pool_id, member_id): """Removing a member from a pool and mark that member as deleted :param pool_id: ID of the pool :param member_id: ID of the member to be deleted :return: Response code from the API """ url = const.BASE_SINGLE_MEMBER_URL.format(pool_id=pool_id, member_id=member_id) response = self._delete(url) return response @correct_return_codes def member_set(self, pool_id, member_id, **kwargs): """Updating a member settings :param pool_id: ID of the pool :param member_id: ID of the member to be updated :param kwargs: A dict of the values of member to be updated :return: Response code from the API """ url = const.BASE_SINGLE_MEMBER_URL.format(pool_id=pool_id, member_id=member_id) response = self._create(url, method='PUT', **kwargs) return response @correct_return_codes def l7policy_list(self, **kwargs): """List all l7policies :param kwargs: Parameters to filter on :return: List of l7policies """ url = const.BASE_L7POLICY_URL response = self._list(url, get_all=True, resources=const.L7POLICY_RESOURCES, **kwargs) return response @correct_return_codes def l7policy_create(self, **kwargs): """Create a l7policy :param kwargs: Parameters to create a l7policy with (expects json=) :return: A dict of the created l7policy's settings """ url = const.BASE_L7POLICY_URL response = self._create(url, **kwargs) return response @correct_return_codes def l7policy_delete(self, l7policy_id): """Delete a l7policy :param string l7policy_id: ID of of l7policy to delete :return: Response Code from the API """ url = const.BASE_SINGLE_L7POLICY_URL.format(policy_uuid=l7policy_id) response = self._delete(url) return response @correct_return_codes def l7policy_show(self, l7policy_id): """Show a l7policy's settings :param string l7policy_id: ID of the l7policy to show :return: Dict of the specified l7policy's settings """ response = self._find(path=const.BASE_L7POLICY_URL, value=l7policy_id) return response @correct_return_codes def l7policy_set(self, l7policy_id, **kwargs): """Update a l7policy's settings :param l7policy_id: ID of the l7policy to update :param kwargs: A dict of arguments to update a l7policy :return: Response Code from the API """ url = const.BASE_SINGLE_L7POLICY_URL.format(policy_uuid=l7policy_id) response = self._create(url, method='PUT', **kwargs) return response @correct_return_codes def l7rule_list(self, l7policy_id, **kwargs): """List all l7rules for a l7policy :param kwargs: Parameters to filter on :return: List of l7rules """ url = const.BASE_L7RULE_URL.format(policy_uuid=l7policy_id) response = self._list(url, get_all=True, resources=const.L7RULE_RESOURCES, **kwargs) return response @correct_return_codes def l7rule_create(self, l7policy_id, **kwargs): """Create a l7rule :param string l7policy_id: The l7policy to create the l7rule for :param kwargs: Parameters to create a l7rule with (expects json=) :return: A dict of the created l7rule's settings """ url = const.BASE_L7RULE_URL.format(policy_uuid=l7policy_id) response = self._create(url, **kwargs) return response @correct_return_codes def l7rule_delete(self, l7rule_id, l7policy_id): """Delete a l7rule :param string l7rule_id: ID of of l7rule to delete :param string l7policy_id: ID of the l7policy for this l7rule :return: Response Code from the API """ url = const.BASE_SINGLE_L7RULE_URL.format(rule_uuid=l7rule_id, policy_uuid=l7policy_id) response = self._delete(url) return response @correct_return_codes def l7rule_show(self, l7rule_id, l7policy_id): """Show a l7rule's settings :param string l7rule_id: ID of the l7rule to show :param string l7policy_id: ID of the l7policy for this l7rule :return: Dict of the specified l7rule's settings """ url = const.BASE_L7RULE_URL.format(policy_uuid=l7policy_id) response = self._find(path=url, value=l7rule_id) return response @correct_return_codes def l7rule_set(self, l7rule_id, l7policy_id, **kwargs): """Update a l7rule's settings :param l7rule_id: ID of the l7rule to update :param string l7policy_id: ID of the l7policy for this l7rule :param kwargs: A dict of arguments to update a l7rule :return: Response Code from the API """ url = const.BASE_SINGLE_L7RULE_URL.format(rule_uuid=l7rule_id, policy_uuid=l7policy_id) response = self._create(url, method='PUT', **kwargs) return response @correct_return_codes def health_monitor_list(self, **kwargs): """List all health monitors :param kwargs: Parameters to filter on :return: A dict containing a list of health monitors """ url = const.BASE_HEALTH_MONITOR_URL response = self._list(url, get_all=True, resources=const.HEALTH_MONITOR_RESOURCES, **kwargs) return response @correct_return_codes def health_monitor_create(self, **kwargs): """Create a health monitor :param kwargs: Parameters to create a health monitor with (expects json=) :return: A dict of the created health monitor's settings """ url = const.BASE_HEALTH_MONITOR_URL response = self._create(url, **kwargs) return response @correct_return_codes def health_monitor_delete(self, health_monitor_id): """Delete a health_monitor :param string health_monitor_id: ID of of health monitor to delete :return: Response Code from the API """ url = const.BASE_SINGLE_HEALTH_MONITOR_URL.format( uuid=health_monitor_id) response = self._delete(url) return response @correct_return_codes def health_monitor_show(self, health_monitor_id): """Show a health monitor's settings :param string health_monitor_id: ID of the health monitor to show :return: Dict of the specified health monitor's settings """ url = const.BASE_HEALTH_MONITOR_URL response = self._find(path=url, value=health_monitor_id) return response @correct_return_codes def health_monitor_set(self, health_monitor_id, **kwargs): """Update a health monitor's settings :param health_monitor_id: ID of the health monitor to update :param kwargs: A dict of arguments to update a health monitor :return: Response Code from the API """ url = const.BASE_SINGLE_HEALTH_MONITOR_URL.format( uuid=health_monitor_id) response = self._create(url, method='PUT', **kwargs) return response @correct_return_codes def quota_list(self, **params): """List all quotas :param params: Parameters to filter on (not implemented) :return: A ``dict`` representing a list of quotas for the project """ url = const.BASE_QUOTA_URL response = self._list(url, get_all=True, resources=const.QUOTA_RESOURCES, **params) return response @correct_return_codes def quota_show(self, project_id): """Show a quota :param string project_id: ID of the project to show :return: A ``dict`` representing the quota for the project """ response = self._find(path=const.BASE_QUOTA_URL, value=project_id) return response @correct_return_codes def quota_reset(self, project_id): """Reset a quota :param string project_id: The ID of the project to reset quotas :return: ``None`` """ url = const.BASE_SINGLE_QUOTA_URL.format(uuid=project_id) response = self._delete(url) return response @correct_return_codes def quota_set(self, project_id, **params): """Update a quota's settings :param string project_id: The ID of the project to update :param params: A ``dict`` of arguments to update project quota :return: A ``dict`` representing the updated quota """ url = const.BASE_SINGLE_QUOTA_URL.format(uuid=project_id) response = self._create(url, method='PUT', **params) return response @correct_return_codes def quota_defaults_show(self): """Show quota defaults :return: A ``dict`` representing a list of quota defaults """ url = const.BASE_QUOTA_DEFAULT_URL response = self._list(url) return response @correct_return_codes def amphora_show(self, amphora_id): """Show an amphora :param string amphora_id: ID of the amphora to show :return: A ``dict`` of the specified amphora's attributes """ url = const.BASE_AMPHORA_URL response = self._find(path=url, value=amphora_id) return response @correct_return_codes def amphora_list(self, **kwargs): """List all amphorae :param kwargs: Parameters to filter on :return: A ``dict`` containing a list of amphorae """ url = const.BASE_AMPHORA_URL response = self._list(path=url, get_all=True, resources=const.AMPHORA_RESOURCES, **kwargs) return response @correct_return_codes def amphora_configure(self, amphora_id): """Update the amphora agent configuration :param string amphora_id: ID of the amphora to configure :return: Response Code from the API """ url = const.BASE_AMPHORA_CONFIGURE_URL.format(uuid=amphora_id) response = self._create(url, method='PUT') return response @correct_return_codes def amphora_delete(self, amphora_id): """Delete an amphora :param string amphora_id: The ID of the amphora to delete :return: Response Code from the API """ url = const.BASE_SINGLE_AMPHORA_URL.format(uuid=amphora_id) response = self._delete(url) return response @correct_return_codes def amphora_failover(self, amphora_id): """Force failover an amphorae :param string amphora_id: ID of the amphora to failover :return: Response Code from the API """ url = const.BASE_AMPHORA_FAILOVER_URL.format(uuid=amphora_id) response = self._create(url, method='PUT') return response @correct_return_codes def amphora_stats_show(self, amphora_id, **kwargs): """Show the current statistics for an amphora :param string amphora_id: ID of the amphora to show :return: A ``list`` of ``dict`` of the specified amphora's statistics """ url = const.BASE_AMPHORA_STATS_URL.format(uuid=amphora_id) response = self._list(path=url, **kwargs) return response @correct_return_codes def provider_list(self): """List all providers :return: A ``dict`` containing a list of provider """ url = const.BASE_PROVIDER_URL response = self._list(path=url, get_all=True, resources=const.PROVIDER_RESOURCES) return response @correct_return_codes def provider_flavor_capability_list(self, provider): """Show the flavor capabilities of the specified provider. :param string provider: The name of the provider to show :return: A ``dict`` containing the capabilities of the provider """ url = const.BASE_PROVIDER_FLAVOR_CAPABILITY_URL.format( provider=provider) resources = const.PROVIDER_FLAVOR_CAPABILITY_RESOURCES response = self._list(url, get_all=True, resources=resources) return response @correct_return_codes def provider_availability_zone_capability_list(self, provider): """Show the availability zone capabilities of the specified provider. :param string provider: The name of the provider to show :return: A ``dict`` containing the capabilities of the provider """ url = const.BASE_PROVIDER_AVAILABILITY_ZONE_CAPABILITY_URL.format( provider=provider) resources = const.PROVIDER_AVAILABILITY_ZONE_CAPABILITY_RESOURCES response = self._list(url, get_all=True, resources=resources) return response @correct_return_codes def flavor_list(self, **kwargs): """List all flavors :param kwargs: Parameters to filter on :return: A ``dict`` containing a list of flavor """ url = const.BASE_FLAVOR_URL response = self._list(path=url, get_all=True, resources=const.FLAVOR_RESOURCES, **kwargs) return response @correct_return_codes def flavor_delete(self, flavor_id): """Delete a flavor :param string flavor_id: ID of the flavor to delete :return: Response Code from the API """ url = const.BASE_SINGLE_FLAVOR_URL.format(uuid=flavor_id) response = self._delete(url) return response @correct_return_codes def flavor_create(self, **kwargs): """Create a flavor :param kwargs: Parameters to create a flavor with (expects json=) :return: A dict of the created flavor's settings """ url = const.BASE_FLAVOR_URL response = self._create(url, **kwargs) return response @correct_return_codes def flavor_set(self, flavor_id, **kwargs): """Update a flavor's settings :param string flavor_id: ID of the flavor to update :param kwargs: A dict of arguments to update a flavor :return: Response Code from the API """ url = const.BASE_SINGLE_FLAVOR_URL.format(uuid=flavor_id) response = self._create(url, method='PUT', **kwargs) return response @correct_return_codes def flavor_show(self, flavor_id): """Show a flavor :param string flavor_id: ID of the flavor to show :return: A dict of the specified flavor's settings """ response = self._find(path=const.BASE_FLAVOR_URL, value=flavor_id) return response @correct_return_codes def flavorprofile_create(self, **kwargs): """Create a flavor profile :param kwargs: Parameters to create a flavor profile with (expects json=) :return: A dict of the created flavor profile's settings """ url = const.BASE_FLAVORPROFILE_URL response = self._create(url, **kwargs) return response @correct_return_codes def flavorprofile_list(self, **kwargs): """List all flavor profiles :param kwargs: Parameters to filter on :return: List of flavor profile """ url = const.BASE_FLAVORPROFILE_URL response = self._list(url, get_all=True, resources=const.FLAVORPROFILE_RESOURCES, **kwargs) return response @correct_return_codes def flavorprofile_show(self, flavorprofile_id): """Show a flavor profile :param string flavorprofile_id: ID of the flavor profile to show :return: A dict of the specified flavor profile's settings """ response = self._find(path=const.BASE_FLAVORPROFILE_URL, value=flavorprofile_id) return response @correct_return_codes def flavorprofile_set(self, flavorprofile_id, **kwargs): """Update a flavor profile's settings :param string flavorprofile_id: ID of the flavor profile to update :kwargs: A dict of arguments to update the flavor profile :return: Response Code from the API """ url = const.BASE_SINGLE_FLAVORPROFILE_URL.format(uuid=flavorprofile_id) response = self._create(url, method='PUT', **kwargs) return response @correct_return_codes def flavorprofile_delete(self, flavorprofile_id): """Delete a flavor profile :param string flavorprofile_id: ID of the flavor profile to delete :return: Response Code from the API """ url = const.BASE_SINGLE_FLAVORPROFILE_URL.format(uuid=flavorprofile_id) response = self._delete(url) return response @correct_return_codes def availabilityzone_list(self, **kwargs): """List all availabilityzones :param kwargs: Parameters to filter on :return: A ``dict`` containing a list of availabilityzone """ url = const.BASE_AVAILABILITYZONE_URL response = self._list(path=url, get_all=True, resources=const.AVAILABILITYZONE_RESOURCES, **kwargs) return response @correct_return_codes def availabilityzone_delete(self, availabilityzone_name): """Delete a availabilityzone :param string availabilityzone_name: Name of the availabilityzone to delete :return: Response Code from the API """ url = const.BASE_SINGLE_AVAILABILITYZONE_URL.format( name=availabilityzone_name) response = self._delete(url) return response @correct_return_codes def availabilityzone_create(self, **kwargs): """Create a availabilityzone :param kwargs: Parameters to create a availabilityzone with (expects json=) :return: A dict of the created availabilityzone's settings """ url = const.BASE_AVAILABILITYZONE_URL response = self._create(url, **kwargs) return response @correct_return_codes def availabilityzone_set(self, availabilityzone_name, **kwargs): """Update a availabilityzone's settings :param string availabilityzone_name: Name of the availabilityzone to update :param kwargs: A dict of arguments to update a availabilityzone :return: Response Code from the API """ url = const.BASE_SINGLE_AVAILABILITYZONE_URL.format( name=availabilityzone_name) response = self._create(url, method='PUT', **kwargs) return response @correct_return_codes def availabilityzone_show(self, availabilityzone_name): """Show a availabilityzone :param string availabilityzone_name: Name of the availabilityzone to show :return: A dict of the specified availabilityzone's settings """ response = self._find(path=const.BASE_AVAILABILITYZONE_URL, value=availabilityzone_name) return response @correct_return_codes def availabilityzoneprofile_create(self, **kwargs): """Create a availabilityzone profile :param kwargs: Parameters to create a availabilityzone profile with (expects json=) :return: A dict of the created availabilityzone profile's settings """ url = const.BASE_AVAILABILITYZONEPROFILE_URL response = self._create(url, **kwargs) return response @correct_return_codes def availabilityzoneprofile_list(self, **kwargs): """List all availabilityzone profiles :param kwargs: Parameters to filter on :return: List of availabilityzone profile """ url = const.BASE_AVAILABILITYZONEPROFILE_URL resources = const.AVAILABILITYZONEPROFILE_RESOURCES response = self._list(url, get_all=True, resources=resources, **kwargs) return response @correct_return_codes def availabilityzoneprofile_show(self, availabilityzoneprofile_id): """Show a availabilityzone profile :param string availabilityzoneprofile_id: ID of the availabilityzone profile to show :return: A dict of the specified availabilityzone profile's settings """ response = self._find(path=const.BASE_AVAILABILITYZONEPROFILE_URL, value=availabilityzoneprofile_id) return response @correct_return_codes def availabilityzoneprofile_set(self, availabilityzoneprofile_id, **kwargs): """Update a availabilityzone profile's settings :param string availabilityzoneprofile_id: ID of the availabilityzone profile to update :kwargs: A dict of arguments to update the availabilityzone profile :return: Response Code from the API """ url = const.BASE_SINGLE_AVAILABILITYZONEPROFILE_URL.format( uuid=availabilityzoneprofile_id) response = self._create(url, method='PUT', **kwargs) return response @correct_return_codes def availabilityzoneprofile_delete(self, availabilityzoneprofile_id): """Delete a availabilityzone profile :param string availabilityzoneprofile_id: ID of the availabilityzone profile to delete :return: Response Code from the API """ url = const.BASE_SINGLE_AVAILABILITYZONEPROFILE_URL.format( uuid=availabilityzoneprofile_id) response = self._delete(url) return response ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0229225 python-octaviaclient-3.7.0/octaviaclient/hacking/0000775000175000017500000000000000000000000022141 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/hacking/__init__.py0000664000175000017500000000000000000000000024240 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/hacking/checks.py0000664000175000017500000002103000000000000023747 0ustar00zuulzuul00000000000000# Copyright (c) 2014 OpenStack Foundation. # # 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. """ Guidelines for writing new hacking checks - Use only for octaviaclient specific tests. OpenStack general tests should be submitted to the common 'hacking' module. - Pick numbers in the range O3xx. Find the current test with the highest allocated number and then pick the next value. - Keep the test method code in the source file ordered based on the O3xx value. - List the new rule in the top level HACKING.rst file - Add test cases for each new rule to octaviaclient/tests/unit/test_hacking.py """ import re from hacking import core _all_log_levels = {'critical', 'error', 'exception', 'info', 'warning'} _all_hints = {'_LC', '_LE', '_LI', '_', '_LW'} _log_translation_hint = re.compile( r".*LOG\.(%(levels)s)\(\s*(%(hints)s)\(" % { 'levels': '|'.join(_all_log_levels), 'hints': '|'.join(_all_hints), }) assert_trueinst_re = re.compile( r"(.)*assertTrue\(isinstance\((\w|\.|\'|\"|\[|\])+, " r"(\w|\.|\'|\"|\[|\])+\)\)") assert_equal_in_end_with_true_or_false_re = re.compile( r"assertEqual\((\w|[][.'\"])+ in (\w|[][.'\", ])+, (True|False)\)") assert_equal_in_start_with_true_or_false_re = re.compile( r"assertEqual\((True|False), (\w|[][.'\"])+ in (\w|[][.'\", ])+\)") assert_equal_with_true_re = re.compile( r"assertEqual\(True,") assert_equal_with_false_re = re.compile( r"assertEqual\(False,") mutable_default_args = re.compile(r"^\s*def .+\((.+=\{\}|.+=\[\])") assert_equal_end_with_none_re = re.compile(r"(.)*assertEqual\(.+, None\)") assert_equal_start_with_none_re = re.compile(r".*assertEqual\(None, .+\)") assert_not_equal_end_with_none_re = re.compile( r"(.)*assertNotEqual\(.+, None\)") assert_not_equal_start_with_none_re = re.compile( r"(.)*assertNotEqual\(None, .+\)") assert_no_xrange_re = re.compile( r"\s*xrange\s*\(") def _translation_checks_not_enforced(filename): # Do not do these validations on tests return any(pat in filename for pat in ["/tests/", "rally-jobs/plugins/"]) @core.flake8ext def assert_true_instance(logical_line): """Check for assertTrue(isinstance(a, b)) sentences O316 """ if assert_trueinst_re.match(logical_line): yield (0, "O316: assertTrue(isinstance(a, b)) sentences not allowed") @core.flake8ext def assert_equal_or_not_none(logical_line): """Check for assertEqual(A, None) or assertEqual(None, A) sentences, assertNotEqual(A, None) or assertNotEqual(None, A) sentences O318 """ msg = ("O318: assertEqual/assertNotEqual(A, None) or " "assertEqual/assertNotEqual(None, A) sentences not allowed") res = (assert_equal_start_with_none_re.match(logical_line) or assert_equal_end_with_none_re.match(logical_line) or assert_not_equal_start_with_none_re.match(logical_line) or assert_not_equal_end_with_none_re.match(logical_line)) if res: yield (0, msg) @core.flake8ext def assert_equal_true_or_false(logical_line): """Check for assertEqual(True, A) or assertEqual(False, A) sentences O323 """ res = (assert_equal_with_true_re.search(logical_line) or assert_equal_with_false_re.search(logical_line)) if res: yield (0, "O323: assertEqual(True, A) or assertEqual(False, A) " "sentences not allowed") @core.flake8ext def no_mutable_default_args(logical_line): msg = "O324: Method's default argument shouldn't be mutable!" if mutable_default_args.match(logical_line): yield (0, msg) @core.flake8ext def assert_equal_in(logical_line): """Check for assertEqual(A in B, True), assertEqual(True, A in B), assertEqual(A in B, False) or assertEqual(False, A in B) sentences O338 """ res = (assert_equal_in_start_with_true_or_false_re.search(logical_line) or assert_equal_in_end_with_true_or_false_re.search(logical_line)) if res: yield (0, "O338: Use assertIn/NotIn(A, B) rather than " "assertEqual(A in B, True/False) when checking collection " "contents.") @core.flake8ext def no_log_warn(logical_line): """Disallow 'LOG.warn(' O339 """ if logical_line.startswith('LOG.warn('): yield (0, "O339:Use LOG.warning() rather than LOG.warn()") @core.flake8ext def no_xrange(logical_line): """Disallow 'xrange()' O340 """ if assert_no_xrange_re.match(logical_line): yield (0, "O340: Do not use xrange().") @core.flake8ext def no_translate_logs(logical_line, filename): """O341 - Don't translate logs. Check for 'LOG.*(_(' and 'LOG.*(_Lx(' Translators don't provide translations for log messages, and operators asked not to translate them. * This check assumes that 'LOG' is a logger. :param logical_line: The logical line to check. :param filename: The file name where the logical line exists. :returns: None if the logical line passes the check, otherwise a tuple is yielded that contains the offending index in logical line and a message describe the check validation failure. """ if _translation_checks_not_enforced(filename): return msg = "O341: Log messages should not be translated!" match = _log_translation_hint.match(logical_line) if match: yield (logical_line.index(match.group()), msg) @core.flake8ext def check_raised_localized_exceptions(logical_line, filename): """O342 - Untranslated exception message. :param logical_line: The logical line to check. :param filename: The file name where the logical line exists. :returns: None if the logical line passes the check, otherwise a tuple is yielded that contains the offending index in logical line and a message describe the check validation failure. """ if _translation_checks_not_enforced(filename): return logical_line = logical_line.strip() raised_search = re.compile( r"raise (?:\w*)\((.*)\)").match(logical_line) if raised_search: exception_msg = raised_search.groups()[0] if exception_msg.startswith("\"") or exception_msg.startswith("\'"): msg = "O342: Untranslated exception message." yield (logical_line.index(exception_msg), msg) @core.flake8ext def check_no_basestring(logical_line): """O343 - basestring is not Python3-compatible. :param logical_line: The logical line to check. :returns: None if the logical line passes the check, otherwise a tuple is yielded that contains the offending index in logical line and a message describe the check validation failure. """ if re.search(r"\bbasestring\b", logical_line): msg = ("O343: basestring is not Python3-compatible, use " "six.string_types instead.") yield (0, msg) @core.flake8ext def check_no_eventlet_imports(logical_line): """O345 - Usage of Python eventlet module not allowed. :param logical_line: The logical line to check. :returns: None if the logical line passes the check, otherwise a tuple is yielded that contains the offending index in logical line and a message describe the check validation failure. """ if re.match(r'(import|from)\s+[(]?eventlet', logical_line): msg = 'O345 Usage of Python eventlet module not allowed' yield logical_line.index('eventlet'), msg @core.flake8ext def check_line_continuation_no_backslash(logical_line, tokens): """O346 - Don't use backslashes for line continuation. :param logical_line: The logical line to check. Not actually used. :param tokens: List of tokens to check. :returns: None if the tokens don't contain any issues, otherwise a tuple is yielded that contains the offending index in the logical line and a message describe the check validation failure. """ backslash = None for token_type, text, start, end, orig_line in tokens: m = re.match(r'.*(\\)\n', orig_line) if m: backslash = (start[0], m.start(1)) break if backslash is not None: msg = 'O346 Backslash line continuations not allowed' yield backslash, msg ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0229225 python-octaviaclient-3.7.0/octaviaclient/osc/0000775000175000017500000000000000000000000021321 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/osc/__init__.py0000664000175000017500000000000000000000000023420 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/osc/plugin.py0000664000175000017500000000417300000000000023176 0ustar00zuulzuul00000000000000# 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. """OpenStackClient plugin for Load Balancer service.""" import logging from osc_lib import utils from octaviaclient.api.v2 import octavia LOG = logging.getLogger(__name__) DEFAULT_LOADBALANCER_API_VERSION = '2.0' API_VERSION_OPTION = 'os_loadbalancer_api_version' API_NAME = 'load_balancer' LOAD_BALANCER_API_TYPE = 'loadbalancer' LOAD_BALANCER_API_VERSIONS = { '2.0': 'octaviaclient.api.v2.octavia.OctaviaAPI', } def make_client(instance): """Returns a load balancer service client""" endpoint = instance.get_endpoint_for_service_type( 'load-balancer', region_name=instance.region_name, interface=instance.interface, ) client = octavia.OctaviaAPI( session=instance.session, service_type='load-balancer', endpoint=endpoint, ) return client def build_option_parser(parser): """Hook to add global options Called from openstackclient.shell.OpenStackShell.__init__() after the builtin parser has been initialized. This is where a plugin can add global options such as an API version. :param argparse.ArgumentParser parser: The parser object that has been initialized by OpenStackShell. """ parser.add_argument( '--os-loadbalancer-api-version', metavar='', default=utils.env( 'OS_LOADBALANCER_API_VERSION', default=DEFAULT_LOADBALANCER_API_VERSION), help='OSC Plugin API version, default=' + DEFAULT_LOADBALANCER_API_VERSION + ' (Env: OS_LOADBALANCER_API_VERSION)') return parser ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0269225 python-octaviaclient-3.7.0/octaviaclient/osc/v2/0000775000175000017500000000000000000000000021650 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/osc/v2/__init__.py0000664000175000017500000000000000000000000023747 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/osc/v2/amphora.py0000664000175000017500000002064400000000000023657 0ustar00zuulzuul00000000000000# 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. # """Amphora action implementation""" from cliff import lister from osc_lib.command import command from osc_lib import utils from octaviaclient.osc.v2 import constants as const from octaviaclient.osc.v2 import utils as v2_utils class ListAmphora(lister.Lister): """List amphorae""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( '--loadbalancer', metavar='', dest='loadbalancer', help="Filter by load balancer (name or ID).", ) parser.add_argument( '--compute-id', metavar='', help="Filter by compute ID.", ) role_choices = {'MASTER', 'BACKUP', 'STANDALONE'} parser.add_argument( '--role', metavar='{' + ','.join(sorted(role_choices)) + '}', choices=role_choices, type=lambda s: s.upper(), # case insensitive help="Filter by role." ) status_choices = { 'ALLOCATED', 'BOOTING', 'DELETED', 'ERROR', 'PENDING_CREATE', 'PENDING_DELETE', 'READY', } parser.add_argument( '--status', '--provisioning-status', dest='status', metavar='{' + ','.join(sorted(status_choices)) + '}', choices=status_choices, type=lambda s: s.upper(), # case insensitive help="Filter by amphora provisioning status." ) parser.add_argument( '--long', action='store_true', help='Show additional fields.', ) return parser def take_action(self, parsed_args): columns = const.AMPHORA_COLUMNS if parsed_args.long: columns = const.AMPHORA_COLUMNS_LONG attrs = v2_utils.get_amphora_attrs(self.app.client_manager, parsed_args) data = self.app.client_manager.load_balancer.amphora_list(**attrs) formatters = { 'amphorae': v2_utils.format_list, } return ( columns, (utils.get_dict_properties( amp, columns, formatters=formatters) for amp in data['amphorae']), ) class ShowAmphora(command.ShowOne): """Show the details of a single amphora""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'amphora_id', metavar='', help='UUID of the amphora.', ) return parser def take_action(self, parsed_args): data = self.app.client_manager.load_balancer.amphora_show( amphora_id=parsed_args.amphora_id, ) rows = const.AMPHORA_ROWS formatters = { 'loadbalancers': v2_utils.format_list, 'amphorae': v2_utils.format_list, } return (rows, utils.get_dict_properties(data, rows, formatters=formatters)) class ConfigureAmphora(command.Command): """Update the amphora agent configuration""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'amphora_id', metavar='', help='UUID of the amphora to configure.', ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) return parser def take_action(self, parsed_args): attrs = v2_utils.get_amphora_attrs(self.app.client_manager, parsed_args) amp_id = attrs.pop('amphora_id') self.app.client_manager.load_balancer.amphora_configure( amphora_id=amp_id) if parsed_args.wait: amphora = self.app.client_manager.load_balancer.amphora_show( amp_id) lb_id = amphora.get('loadbalancer_id') # TODO(rm_work): No status change if the amp isn't linked to an LB? if lb_id: v2_utils.wait_for_active( status_f=(self.app.client_manager.load_balancer. load_balancer_show), res_id=lb_id ) class FailoverAmphora(command.Command): """Force failover an amphora""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'amphora_id', metavar='', help='UUID of the amphora.', ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) return parser def take_action(self, parsed_args): attrs = v2_utils.get_amphora_attrs(self.app.client_manager, parsed_args) amp_id = attrs.pop('amphora_id') amphora = self.app.client_manager.load_balancer.amphora_show(amp_id) self.app.client_manager.load_balancer.amphora_failover( amphora_id=amp_id) if parsed_args.wait: lb_id = amphora.get('loadbalancer_id') if lb_id: v2_utils.wait_for_active( status_f=(self.app.client_manager.load_balancer. load_balancer_show), res_id=lb_id ) else: v2_utils.wait_for_delete( status_f=(self.app.client_manager.load_balancer. amphora_show), res_id=amp_id ) class ShowAmphoraStats(command.ShowOne): """Shows the current statistics for an amphora.""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( '--listener', metavar='', help='Filter by listener (name or ID).', ) parser.add_argument( 'amphora_id', metavar='', help='UUID of the amphora.' ) return parser def take_action(self, parsed_args): rows = const.LOAD_BALANCER_STATS_ROWS listener_id = None if parsed_args.listener is not None: attrs = v2_utils.get_listener_attrs( self.app.client_manager, parsed_args) listener_id = attrs.pop('listener_id') data = self.app.client_manager.load_balancer.amphora_stats_show( amphora_id=parsed_args.amphora_id ) total_stats = { key: 0 for key in rows } for stats in data['amphora_stats']: if listener_id is None or listener_id == stats['listener_id']: for key in stats: if key in rows: total_stats[key] += stats[key] return (rows, (utils.get_dict_properties( total_stats, rows, formatters={}))) class DeleteAmphora(command.Command): """Delete a amphora""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'amphora_id', metavar='', help='UUID of the amphora to delete.', ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) return parser def take_action(self, parsed_args): self.app.client_manager.load_balancer.amphora_delete( amphora_id=parsed_args.amphora_id) if parsed_args.wait: v2_utils.wait_for_delete( status_f=self.app.client_manager.load_balancer.amphora_show, res_id=parsed_args.amphora_id, status_field=const.STATUS ) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/osc/v2/availabilityzone.py0000664000175000017500000002027200000000000025573 0ustar00zuulzuul00000000000000# Copyright (c) 2018 China Telecom Corporation # Copyright 2019 Red Hat, Inc. All rights reserved. # # All Rights Reserved. # # 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. """Availabilityzone action implementation""" from cliff import lister from osc_lib.command import command from osc_lib import utils from octaviaclient.osc.v2 import constants as const from octaviaclient.osc.v2 import utils as v2_utils class CreateAvailabilityzone(command.ShowOne): """Create an octavia availability zone""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( '--name', metavar='', required=True, help="New availability zone name." ) parser.add_argument( '--availabilityzoneprofile', metavar='', required=True, help="Availability zone profile to add the AZ to (name or ID)." ) parser.add_argument( '--description', metavar='', help="Set the availability zone description." ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=None, help="Enable the availability zone." ) admin_group.add_argument( '--disable', action='store_true', default=None, help="Disable the availability zone." ) return parser def take_action(self, parsed_args): rows = const.AVAILABILITYZONE_ROWS attrs = v2_utils.get_availabilityzone_attrs(self.app.client_manager, parsed_args) body = {"availability_zone": attrs} data = self.app.client_manager.load_balancer.availabilityzone_create( json=body) formatters = {'availability_zone_profiles': v2_utils.format_list} return (rows, (utils.get_dict_properties( data['availability_zone'], rows, formatters=formatters))) class DeleteAvailabilityzone(command.Command): """Delete an availability zone""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'availabilityzone', metavar='', help="Name of the availability zone to delete." ) return parser def take_action(self, parsed_args): attrs = v2_utils.get_availabilityzone_attrs(self.app.client_manager, parsed_args) availabilityzone_name = attrs.pop('availabilityzone_name') self.app.client_manager.load_balancer.availabilityzone_delete( availabilityzone_name=availabilityzone_name) class ListAvailabilityzone(lister.Lister): """List availability zones""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( '--name', metavar='', help="List availability zones according to their name." ) parser.add_argument( '--availabilityzoneprofile', metavar='', help="List availability zones according to their AZ profile.", ) admin_state_group = parser.add_mutually_exclusive_group() admin_state_group.add_argument( '--enable', action='store_true', default=None, help="List enabled availability zones." ) admin_state_group.add_argument( '--disable', action='store_true', default=None, help="List disabled availability zones." ) return parser def take_action(self, parsed_args): columns = const.AVAILABILITYZONE_COLUMNS attrs = v2_utils.get_availabilityzone_attrs(self.app.client_manager, parsed_args) data = self.app.client_manager.load_balancer.availabilityzone_list( **attrs) formatters = {'availabilityzoneprofiles': v2_utils.format_list} return (columns, (utils.get_dict_properties(s, columns, formatters=formatters) for s in data['availability_zones'])) class ShowAvailabilityzone(command.ShowOne): """Show the details for a single availability zone""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'availabilityzone', metavar='', help="Name of the availability zone." ) return parser def take_action(self, parsed_args): rows = const.AVAILABILITYZONE_ROWS attrs = v2_utils.get_availabilityzone_attrs(self.app.client_manager, parsed_args) availabilityzone_name = attrs.pop('availabilityzone_name') data = self.app.client_manager.load_balancer.availabilityzone_show( availabilityzone_name=availabilityzone_name ) formatters = {'availabilityzoneprofiles': v2_utils.format_list} return (rows, (utils.get_dict_properties( data, rows, formatters=formatters))) class SetAvailabilityzone(command.Command): """Update an availability zone""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'availabilityzone', metavar='', help='Name of the availability zone to update.' ) parser.add_argument( '--description', metavar='', help="Set the description of the availability zone." ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=None, help="Enable the availability zone." ) admin_group.add_argument( '--disable', action='store_true', default=None, help="Disable the availability zone." ) return parser def take_action(self, parsed_args): attrs = v2_utils.get_availabilityzone_attrs(self.app.client_manager, parsed_args) availabilityzone_name = attrs.pop('availabilityzone_name') body = {'availability_zone': attrs} self.app.client_manager.load_balancer.availabilityzone_set( availabilityzone_name, json=body) class UnsetAvailabilityzone(command.Command): """Clear availability zone settings""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'availabilityzone', metavar='', help="Name of the availability zone to update." ) parser.add_argument( '--description', action='store_true', help="Clear the availability zone description." ) return parser def take_action(self, parsed_args): unset_args = v2_utils.get_unsets(parsed_args) if not unset_args: return availabilityzone_id = v2_utils.get_resource_id( self.app.client_manager.load_balancer.availabilityzone_list, 'availability_zones', parsed_args.availabilityzone) body = {'availability_zone': unset_args} self.app.client_manager.load_balancer.availabilityzone_set( availabilityzone_id, json=body) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/osc/v2/availabilityzoneprofile.py0000664000175000017500000001454300000000000027160 0ustar00zuulzuul00000000000000# Copyright (c) 2018 China Telecom Corporation # All Rights Reserved. # # 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. """Availabilityzone profile action implementation""" from cliff import lister from osc_lib.command import command from osc_lib import utils from octaviaclient.osc.v2 import constants as const from octaviaclient.osc.v2 import utils as v2_utils class CreateAvailabilityzoneProfile(command.ShowOne): """Create an octavia availability zone profile""" def get_parser(self, prog_name): parser = super().get_parser( prog_name) parser.add_argument( '--name', metavar='', required=True, help="New octavia availability zone profile name." ) parser.add_argument( '--provider', metavar='', required=True, help="Provider name for the availability zone profile." ) parser.add_argument( '--availability-zone-data', metavar='', required=True, help="The JSON string containing the availability zone metadata." ) return parser def take_action(self, parsed_args): rows = const.AVAILABILITYZONEPROFILE_ROWS attrs = v2_utils.get_availabilityzoneprofile_attrs( self.app.client_manager, parsed_args) body = {"availability_zone_profile": attrs} client_manager = self.app.client_manager data = client_manager.load_balancer.availabilityzoneprofile_create( json=body) return (rows, (utils.get_dict_properties( data['availability_zone_profile'], rows, formatters={}))) class DeleteAvailabilityzoneProfile(command.Command): """Delete an availability zone profile""" def get_parser(self, prog_name): parser = super().get_parser( prog_name) parser.add_argument( 'availabilityzoneprofile', metavar='', help="Availability zone profile to delete (name or ID)." ) return parser def take_action(self, parsed_args): attrs = v2_utils.get_availabilityzoneprofile_attrs( self.app.client_manager, parsed_args) availabilityzoneprofile_id = attrs.pop('availability_zone_profile_id') self.app.client_manager.load_balancer.availabilityzoneprofile_delete( availabilityzoneprofile_id=availabilityzoneprofile_id) class ListAvailabilityzoneProfile(lister.Lister): """List availability zone profiles""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( '--name', metavar='', help="List availability zone profiles by profile name." ) parser.add_argument( '--provider', metavar='', help="List availability zone profiles according to their " "provider.", ) return parser def take_action(self, parsed_args): columns = const.AVAILABILITYZONEPROFILE_COLUMNS attrs = v2_utils.get_availabilityzoneprofile_attrs( self.app.client_manager, parsed_args) client_manager = self.app.client_manager data = client_manager.load_balancer.availabilityzoneprofile_list( **attrs) return (columns, (utils.get_dict_properties(s, columns, formatters={}) for s in data['availability_zone_profiles'])) class ShowAvailabilityzoneProfile(command.ShowOne): """Show the details of a single availability zone profile""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'availabilityzoneprofile', metavar='', help="Name or UUID of the availability zone profile to show." ) return parser def take_action(self, parsed_args): rows = const.AVAILABILITYZONEPROFILE_ROWS attrs = v2_utils.get_availabilityzoneprofile_attrs( self.app.client_manager, parsed_args) availabilityzoneprofile_id = attrs.pop('availability_zone_profile_id') client_manager = self.app.client_manager data = client_manager.load_balancer.availabilityzoneprofile_show( availabilityzoneprofile_id=availabilityzoneprofile_id ) return (rows, (utils.get_dict_properties( data, rows, formatters={}))) class SetAvailabilityzoneProfile(command.Command): """Update an availability zone profile""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'availabilityzoneprofile', metavar='', help='Name or UUID of the availability zone profile to update.' ) parser.add_argument( '--name', metavar='', help="Set the name of the availability zone profile." ) parser.add_argument( '--provider', metavar='', help="Set the provider of the availability zone profile." ) parser.add_argument( '--availability-zone-data', metavar='', help="Set the availability zone data of the profile." ) return parser def take_action(self, parsed_args): attrs = v2_utils.get_availabilityzoneprofile_attrs( self.app.client_manager, parsed_args) availabilityzoneprofile_id = attrs.pop('availability_zone_profile_id') body = {'availability_zone_profile': attrs} self.app.client_manager.load_balancer.availabilityzoneprofile_set( availabilityzoneprofile_id, json=body) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/osc/v2/constants.py0000664000175000017500000001506700000000000024247 0ustar00zuulzuul00000000000000# Copyright 2017 GoDaddy # 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. # LOAD_BALANCER_ROWS = ( 'admin_state_up', 'availability_zone', 'created_at', 'description', 'flavor_id', 'id', 'listeners', 'name', 'operating_status', 'pools', 'project_id', 'provider', 'provisioning_status', 'updated_at', 'vip_address', 'vip_network_id', 'vip_port_id', 'vip_qos_policy_id', 'vip_subnet_id', 'vip_vnic_type', 'tags', 'additional_vips', ) LOAD_BALANCER_COLUMNS = ( 'id', 'name', 'project_id', 'vip_address', 'provisioning_status', 'operating_status', 'provider') LOAD_BALANCER_STATS_ROWS = ( 'active_connections', 'bytes_in', 'bytes_out', 'request_errors', 'total_connections') LISTENER_ROWS = ( 'admin_state_up', 'connection_limit', 'created_at', 'default_pool_id', 'default_tls_container_ref', 'description', 'id', 'insert_headers', 'l7policies', 'loadbalancers', 'name', 'operating_status', 'project_id', 'protocol', 'protocol_port', 'provisioning_status', 'sni_container_refs', 'timeout_client_data', 'timeout_member_connect', 'timeout_member_data', 'timeout_tcp_inspect', 'updated_at', 'client_ca_tls_container_ref', 'client_authentication', 'client_crl_container_ref', 'allowed_cidrs', 'tls_ciphers', 'tls_versions', 'alpn_protocols', 'tags', 'hsts_max_age', 'hsts_include_subdomains', 'hsts_preload', ) LISTENER_COLUMNS = ( 'id', 'default_pool_id', 'name', 'project_id', 'protocol', 'protocol_port', 'admin_state_up') POOL_ROWS = ( 'admin_state_up', 'created_at', 'description', 'healthmonitor_id', 'id', 'lb_algorithm', 'listeners', 'loadbalancers', 'members', 'name', 'operating_status', 'project_id', 'protocol', 'provisioning_status', 'session_persistence', 'updated_at', 'tls_container_ref', 'ca_tls_container_ref', 'crl_container_ref', 'tls_enabled', 'tls_ciphers', 'tls_versions', 'tags', 'alpn_protocols') POOL_COLUMNS = ( 'id', 'name', 'project_id', 'provisioning_status', 'protocol', 'lb_algorithm', 'admin_state_up') MEMBER_ROWS = ( 'address', 'admin_state_up', 'created_at', 'id', 'name', 'operating_status', 'project_id', 'protocol_port', 'provisioning_status', 'subnet_id', 'updated_at', 'weight', 'monitor_port', 'monitor_address', 'backup', 'tags') MEMBER_COLUMNS = ( 'id', 'name', 'project_id', 'provisioning_status', 'address', 'protocol_port', 'operating_status', 'weight') L7POLICY_ROWS = ( 'listener_id', 'description', 'admin_state_up', 'rules', 'project_id', 'created_at', 'provisioning_status', 'updated_at', 'redirect_pool_id', 'redirect_url', 'redirect_prefix', 'action', 'position', 'id', 'operating_status', 'name', 'redirect_http_code', 'tags') L7POLICY_COLUMNS = ( 'id', 'name', 'project_id', 'provisioning_status', 'action', 'position', 'admin_state_up') L7RULE_ROWS = ( 'created_at', 'compare_type', 'provisioning_status', 'invert', 'admin_state_up', 'updated_at', 'value', 'key', 'project_id', 'type', 'id', 'operating_status', 'tags') L7RULE_COLUMNS = ( 'id', 'project_id', 'provisioning_status', 'compare_type', 'type', 'key', 'value', 'invert', 'admin_state_up') MONITOR_ROWS = ( 'project_id', 'name', 'admin_state_up', 'pools', 'created_at', 'provisioning_status', 'updated_at', 'delay', 'expected_codes', 'max_retries', 'http_method', 'timeout', 'max_retries_down', 'url_path', 'type', 'id', 'operating_status', 'http_version', 'domain_name', 'tags') MONITOR_COLUMNS = ( 'id', 'name', 'project_id', 'type', 'admin_state_up', ) QUOTA_ROWS = ( 'load_balancer', 'listener', 'pool', 'health_monitor', 'member', 'l7policy', 'l7rule', ) QUOTA_COLUMNS = ( 'project_id', 'load_balancer', 'listener', 'pool', 'health_monitor', 'member', 'l7policy', 'l7rule', ) AMPHORA_ROWS = ( 'id', 'loadbalancer_id', 'compute_id', 'lb_network_ip', 'vrrp_ip', 'ha_ip', 'vrrp_port_id', 'ha_port_id', 'cert_expiration', 'cert_busy', 'role', 'status', 'vrrp_interface', 'vrrp_id', 'vrrp_priority', 'cached_zone', 'created_at', 'updated_at', 'image_id', 'compute_flavor', ) AMPHORA_COLUMNS = ( 'id', 'loadbalancer_id', 'status', 'role', 'lb_network_ip', 'ha_ip', ) AMPHORA_COLUMNS_LONG = ( 'id', 'loadbalancer_id', 'status', 'role', 'lb_network_ip', 'ha_ip', 'compute_id', 'cached_zone', 'image_id', ) PROVIDER_COLUMNS = ( 'name', 'description', ) PROVIDER_CAPABILITY_COLUMNS = ( 'type', 'name', 'description', ) FLAVOR_ROWS = ( 'id', 'name', 'flavor_profile_id', 'enabled', 'description', ) FLAVOR_COLUMNS = ( 'id', 'name', 'flavor_profile_id', 'enabled', ) FLAVORPROFILE_ROWS = ( 'id', 'name', 'provider_name', 'flavor_data' ) FLAVORPROFILE_COLUMNS = ( 'id', 'name', 'provider_name', ) AVAILABILITYZONE_ROWS = ( 'name', 'availability_zone_profile_id', 'enabled', 'description', ) AVAILABILITYZONE_COLUMNS = ( 'name', 'availability_zone_profile_id', 'enabled', ) AVAILABILITYZONEPROFILE_ROWS = ( 'id', 'name', 'provider_name', 'availability_zone_data' ) AVAILABILITYZONEPROFILE_COLUMNS = ( 'id', 'name', 'provider_name', ) PROVISIONING_STATUS = 'provisioning_status' STATUS = 'status' # TCP/UDP port min/max MIN_PORT_NUMBER = 1 MAX_PORT_NUMBER = 65535 # Member weight min/max MIN_WEIGHT = 0 MAX_WEIGHT = 256 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/osc/v2/flavor.py0000664000175000017500000001747200000000000023526 0ustar00zuulzuul00000000000000# Copyright (c) 2018 China Telecom Corporation # Copyright 2019 Red Hat, Inc. All rights reserved. # # All Rights Reserved. # # 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. """Flavor action implementation""" from cliff import lister from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from oslo_utils import uuidutils from octaviaclient.osc.v2 import constants as const from octaviaclient.osc.v2 import utils as v2_utils class CreateFlavor(command.ShowOne): """Create a octavia flavor""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( '--name', metavar='', required=True, help="New flavor name." ) parser.add_argument( '--flavorprofile', metavar='', required=True, help="Flavor profile to add the flavor to (name or ID)." ) parser.add_argument( '--description', metavar='', help="Set flavor description." ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=None, help="Enable flavor." ) admin_group.add_argument( '--disable', action='store_true', default=None, help="Disable flavor." ) return parser def take_action(self, parsed_args): rows = const.FLAVOR_ROWS attrs = v2_utils.get_flavor_attrs(self.app.client_manager, parsed_args) body = {"flavor": attrs} data = self.app.client_manager.load_balancer.flavor_create( json=body) formatters = {'flavorprofiles': v2_utils.format_list} return (rows, (utils.get_dict_properties( data['flavor'], rows, formatters=formatters))) class DeleteFlavor(command.Command): """Delete a flavor""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'flavor', metavar='', help="Flavor to delete (name or ID)." ) return parser def take_action(self, parsed_args): attrs = v2_utils.get_flavor_attrs(self.app.client_manager, parsed_args) flavor_id = attrs.pop('flavor_id') self.app.client_manager.load_balancer.flavor_delete( flavor_id=flavor_id) class ListFlavor(lister.Lister): """List flavor""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( '--name', metavar='', help="List flavors according to their name." ) parser.add_argument( '--flavorprofile', metavar='', help="List flavors according to their flavor profile.", ) admin_state_group = parser.add_mutually_exclusive_group() admin_state_group.add_argument( '--enable', action='store_true', default=None, help="List enabled flavors." ) admin_state_group.add_argument( '--disable', action='store_true', default=None, help="List disabled flavors." ) return parser def take_action(self, parsed_args): columns = const.FLAVOR_COLUMNS attrs = v2_utils.get_flavor_attrs(self.app.client_manager, parsed_args) data = self.app.client_manager.load_balancer.flavor_list( **attrs) formatters = {'flavorprofiles': v2_utils.format_list} return (columns, (utils.get_dict_properties(s, columns, formatters=formatters) for s in data['flavors'])) class ShowFlavor(command.ShowOne): """Show the details for a single flavor""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'flavor', metavar='', help="Name or UUID of the flavor." ) return parser def take_action(self, parsed_args): rows = const.FLAVOR_ROWS data = None if uuidutils.is_uuid_like(parsed_args.flavor): try: data = self.app.client_manager.load_balancer.flavor_show( flavor_id=parsed_args.flavor) except exceptions.NotFound: pass if data is None: attrs = v2_utils.get_flavor_attrs(self.app.client_manager, parsed_args) flavor_id = attrs.pop('flavor_id') data = self.app.client_manager.load_balancer.flavor_show( flavor_id=flavor_id ) formatters = {'flavorprofiles': v2_utils.format_list} return (rows, (utils.get_dict_properties( data, rows, formatters=formatters))) class SetFlavor(command.Command): """Update a flavor""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'flavor', metavar='', help='Name or UUID of the flavor to update.' ) parser.add_argument( '--name', metavar='', help="Set the name of the flavor." ) parser.add_argument( '--description', metavar='', help="Set flavor description." ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=None, help="Enable flavor." ) admin_group.add_argument( '--disable', action='store_true', default=None, help="Disable flavor." ) return parser def take_action(self, parsed_args): attrs = v2_utils.get_flavor_attrs(self.app.client_manager, parsed_args) flavor_id = attrs.pop('flavor_id') body = {'flavor': attrs} self.app.client_manager.load_balancer.flavor_set( flavor_id, json=body) class UnsetFlavor(command.Command): """Clear flavor settings""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'flavor', metavar='', help="Flavor to update (name or ID)." ) parser.add_argument( '--description', action='store_true', help="Clear the flavor description." ) return parser def take_action(self, parsed_args): unset_args = v2_utils.get_unsets(parsed_args) if not unset_args: return flavor_id = v2_utils.get_resource_id( self.app.client_manager.load_balancer.flavor_list, 'flavors', parsed_args.flavor) body = {'flavor': unset_args} self.app.client_manager.load_balancer.flavor_set( flavor_id, json=body) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/osc/v2/flavorprofile.py0000664000175000017500000001430100000000000025073 0ustar00zuulzuul00000000000000# Copyright (c) 2018 China Telecom Corporation # All Rights Reserved. # # 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. """Flavor profile action implementation""" from cliff import lister from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from oslo_utils import uuidutils from octaviaclient.osc.v2 import constants as const from octaviaclient.osc.v2 import utils as v2_utils class CreateFlavorProfile(command.ShowOne): """Create a octavia flavor profile""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( '--name', metavar='', required=True, help="New octavia flavor profile name." ) parser.add_argument( '--provider', metavar='', required=True, help="Provider name for the flavor profile." ) parser.add_argument( '--flavor-data', metavar='', required=True, help="The JSON string containing the flavor metadata." ) return parser def take_action(self, parsed_args): rows = const.FLAVORPROFILE_ROWS attrs = v2_utils.get_flavorprofile_attrs(self.app.client_manager, parsed_args) body = {"flavorprofile": attrs} data = self.app.client_manager.load_balancer.flavorprofile_create( json=body) return (rows, (utils.get_dict_properties( data['flavorprofile'], rows, formatters={}))) class DeleteFlavorProfile(command.Command): """Delete a flavor profile""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'flavorprofile', metavar='', help="Flavor profiles to delete (name or ID)." ) return parser def take_action(self, parsed_args): attrs = v2_utils.get_flavorprofile_attrs(self.app.client_manager, parsed_args) flavorprofile_id = attrs.pop('flavorprofile_id') self.app.client_manager.load_balancer.flavorprofile_delete( flavorprofile_id=flavorprofile_id) class ListFlavorProfile(lister.Lister): """List flavor profile""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( '--name', metavar='', help="List flavor profiles by flavor profile name." ) parser.add_argument( '--provider', metavar='', help="List flavor profiles according to their provider.", ) return parser def take_action(self, parsed_args): columns = const.FLAVORPROFILE_COLUMNS attrs = v2_utils.get_flavorprofile_attrs(self.app.client_manager, parsed_args) data = self.app.client_manager.load_balancer.flavorprofile_list( **attrs) return (columns, (utils.get_dict_properties(s, columns, formatters={}) for s in data['flavorprofiles'])) class ShowFlavorProfile(command.ShowOne): """Show the details for a single flavor profile""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'flavorprofile', metavar='', help="Name or UUID of the flavor profile to show." ) return parser def take_action(self, parsed_args): rows = const.FLAVORPROFILE_ROWS data = None if uuidutils.is_uuid_like(parsed_args.flavorprofile): try: data = ( self.app.client_manager.load_balancer.flavorprofile_show( flavorprofile_id=parsed_args.flavorprofile)) except exceptions.NotFound: pass if data is None: attrs = v2_utils.get_flavorprofile_attrs(self.app.client_manager, parsed_args) flavorprofile_id = attrs.pop('flavorprofile_id') data = self.app.client_manager.load_balancer.flavorprofile_show( flavorprofile_id=flavorprofile_id ) return (rows, (utils.get_dict_properties( data, rows, formatters={}))) class SetFlavorProfile(command.Command): """Update a flavor profile""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'flavorprofile', metavar='', help='Name or UUID of the flavor profile to update.' ) parser.add_argument( '--name', metavar='', help="Set the name of the flavor profile." ) parser.add_argument( '--provider', metavar='', help="Set the provider of the flavor profile." ) parser.add_argument( '--flavor-data', metavar='', help="Set the flavor data of the flavor profile." ) return parser def take_action(self, parsed_args): attrs = v2_utils.get_flavorprofile_attrs(self.app.client_manager, parsed_args) flavorprofile_id = attrs.pop('flavorprofile_id') body = {'flavorprofile': attrs} self.app.client_manager.load_balancer.flavorprofile_set( flavorprofile_id, json=body) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/osc/v2/health_monitor.py0000664000175000017500000003776300000000000025256 0ustar00zuulzuul00000000000000# Copyright 2017 GoDaddy # Copyright 2019 Red Hat, Inc. All rights reserved. # # 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. # """Health Monitor action implementation""" from cliff import lister from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from osc_lib.utils import tags as _tag from oslo_utils import uuidutils from octaviaclient.osc.v2 import constants as const from octaviaclient.osc.v2 import utils as v2_utils HTTP_METHODS = ['GET', 'POST', 'DELETE', 'PUT', 'HEAD', 'OPTIONS', 'PATCH', 'CONNECT', 'TRACE'] HTTP_VERSIONS = [1.0, 1.1] TYPE_CHOICES = ['PING', 'HTTP', 'TCP', 'HTTPS', 'TLS-HELLO', 'UDP-CONNECT', 'SCTP'] class CreateHealthMonitor(command.ShowOne): """Create a health monitor""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'pool', metavar='', help="Set the pool for the health monitor (name or ID)." ) parser.add_argument( '--name', metavar='', help="Set the health monitor name." ) parser.add_argument( '--delay', metavar='', required=True, help="Set the time in seconds, between sending probes to members." ) parser.add_argument( '--domain-name', metavar='', help=("Set the domain name, which be injected into the HTTP Host " "Header to the backend server for HTTP health check.") ) parser.add_argument( '--expected-codes', metavar='', help="Set the list of HTTP status codes expected in response from " "the member to declare it healthy." ) parser.add_argument( '--http-method', metavar='{' + ','.join(HTTP_METHODS) + '}', choices=HTTP_METHODS, type=lambda s: s.upper(), # case insensitive help="Set the HTTP method that the health monitor uses for " "requests." ) parser.add_argument( '--http-version', metavar='', choices=HTTP_VERSIONS, type=float, help="Set the HTTP version." ) parser.add_argument( '--timeout', metavar='', required=True, help="Set the maximum time, in seconds, that a monitor waits to " "connect before it times out. This value must be less than " "the delay value." ) parser.add_argument( '--max-retries', metavar='', type=int, choices=range(1, 10), required=True, help="The number of successful checks before changing the " "operating status of the member to ONLINE." ) parser.add_argument( '--url-path', metavar='', help="Set the HTTP URL path of the request sent by the monitor to " "test the health of a backend member." ) parser.add_argument( '--type', metavar='{' + ','.join(TYPE_CHOICES) + '}', required=True, choices=TYPE_CHOICES, type=lambda s: s.upper(), # case insensitive help="Set the health monitor type." ) parser.add_argument( '--max-retries-down', metavar='', type=int, choices=range(1, 10), help="Set the number of allowed check failures before changing " "the operating status of the member to ERROR." ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=True, help="Enable health monitor (default)." ) admin_group.add_argument( '--disable', action='store_true', default=None, help="Disable health monitor." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) _tag.add_tag_option_to_parser_for_create( parser, 'health monitor') return parser def take_action(self, parsed_args): rows = const.MONITOR_ROWS attrs = v2_utils.get_health_monitor_attrs(self.app.client_manager, parsed_args) body = {"healthmonitor": attrs} data = self.app.client_manager.load_balancer.health_monitor_create( json=body) if parsed_args.wait: pool = self.app.client_manager.load_balancer.pool_show( data['healthmonitor']['pools'][0]['id']) v2_utils.wait_for_active( status_f=(self.app.client_manager.load_balancer. load_balancer_show), res_id=pool['loadbalancers'][0]['id'] ) data = { 'healthmonitor': ( self.app.client_manager.load_balancer.health_monitor_show( data['healthmonitor']['id'])) } formatters = {'pools': v2_utils.format_list, 'tags': v2_utils.format_list_flat} return (rows, (utils.get_dict_properties(data['healthmonitor'], rows, formatters=formatters))) class DeleteHealthMonitor(command.Command): """Delete a health monitor""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'health_monitor', metavar='', help="Health monitor to delete (name or ID)." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) return parser def take_action(self, parsed_args): attrs = v2_utils.get_health_monitor_attrs(self.app.client_manager, parsed_args) health_monitor_id = attrs.pop('health_monitor_id') self.app.client_manager.load_balancer.health_monitor_delete( health_monitor_id=health_monitor_id) if parsed_args.wait: v2_utils.wait_for_delete( status_f=(self.app.client_manager.load_balancer. health_monitor_show), res_id=health_monitor_id ) class ListHealthMonitor(lister.Lister): """List health monitors""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) _tag.add_tag_filtering_option_to_parser(parser, 'health monitor') return parser def take_action(self, parsed_args): columns = const.MONITOR_COLUMNS attrs = v2_utils.get_health_monitor_attrs(self.app.client_manager, parsed_args) data = self.app.client_manager.load_balancer.health_monitor_list( **attrs) formatters = {'pools': v2_utils.format_list} return (columns, (utils.get_dict_properties(s, columns, formatters=formatters) for s in data['healthmonitors'])) class ShowHealthMonitor(command.ShowOne): """Show the details of a single health monitor""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'health_monitor', metavar='', help='Name or UUID of the health monitor.' ) return parser def take_action(self, parsed_args): rows = const.MONITOR_ROWS data = None if uuidutils.is_uuid_like(parsed_args.health_monitor): try: data = ( self.app.client_manager.load_balancer.health_monitor_show( health_monitor_id=parsed_args.health_monitor)) except exceptions.NotFound: pass if data is None: attrs = v2_utils.get_health_monitor_attrs(self.app.client_manager, parsed_args) health_monitor_id = attrs.pop('health_monitor_id') data = self.app.client_manager.load_balancer.health_monitor_show( health_monitor_id=health_monitor_id, ) formatters = {'pools': v2_utils.format_list, 'tags': v2_utils.format_list_flat} return (rows, (utils.get_dict_properties(data, rows, formatters=formatters))) class SetHealthMonitor(command.Command): """Update a health monitor""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'health_monitor', metavar='', help="Health monitor to update (name or ID)." ) parser.add_argument( '--name', metavar='', help="Set health monitor name." ) parser.add_argument( '--delay', metavar='', help="Set the time in seconds, between sending probes to members." ) parser.add_argument( '--domain-name', metavar='', help=("Set the domain name, which be injected into the HTTP Host " "Header to the backend server for HTTP health check.") ) parser.add_argument( '--expected-codes', metavar='', help="Set the list of HTTP status codes expected in response from " "the member to declare it healthy." ) parser.add_argument( '--http-method', metavar='{' + ','.join(HTTP_METHODS) + '}', choices=HTTP_METHODS, type=lambda s: s.upper(), # case insensitive help="Set the HTTP method that the health monitor uses for " "requests." ) parser.add_argument( '--http-version', metavar='', choices=HTTP_VERSIONS, type=float, help="Set the HTTP version." ) parser.add_argument( '--timeout', metavar='', help="Set the maximum time, in seconds, that a monitor waits to " "connect before it times out. This value must be less than " "the delay value." ) parser.add_argument( '--max-retries', metavar='', type=int, choices=range(1, 10), help="Set the number of successful checks before changing the " "operating status of the member to ONLINE." ) parser.add_argument( '--max-retries-down', metavar='', type=int, choices=range(1, 10), help="Set the number of allowed check failures before changing " "the operating status of the member to ERROR." ) parser.add_argument( '--url-path', metavar='', help="Set the HTTP URL path of the request sent by the monitor to " "test the health of a backend member." ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=None, help="Enable health monitor." ) admin_group.add_argument( '--disable', action='store_true', default=None, help="Disable health monitor." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) _tag.add_tag_option_to_parser_for_set(parser, 'health monitor') return parser def take_action(self, parsed_args): attrs = v2_utils.get_health_monitor_attrs(self.app.client_manager, parsed_args) hm_id = attrs.pop('health_monitor_id') v2_utils.set_tags_for_set( self.app.client_manager.load_balancer.health_monitor_show, hm_id, attrs, clear_tags=parsed_args.no_tag) body = {'healthmonitor': attrs} self.app.client_manager.load_balancer.health_monitor_set( hm_id, json=body) if parsed_args.wait: v2_utils.wait_for_active( status_f=(self.app.client_manager.load_balancer. health_monitor_show), res_id=hm_id ) class UnsetHealthMonitor(command.Command): """Clear health monitor settings""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'health_monitor', metavar='', help="Health monitor to update (name or ID)." ) parser.add_argument( '--domain-name', action='store_true', help="Clear the health monitor domain name." ) parser.add_argument( '--expected-codes', action='store_true', help="Reset the health monitor expected codes to the API default." ) parser.add_argument( '--http-method', action='store_true', help="Reset the health monitor HTTP method to the API default." ) parser.add_argument( '--http-version', action='store_true', help="Reset the health monitor HTTP version to the API default." ) parser.add_argument( '--max-retries-down', action='store_true', help="Reset the health monitor max retries down to the API " "default." ) parser.add_argument( '--name', action='store_true', help="Clear the health monitor name." ) parser.add_argument( '--url-path', action='store_true', help="Clear the health monitor URL path." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) _tag.add_tag_option_to_parser_for_unset(parser, 'health monitor') return parser def take_action(self, parsed_args): unset_args = v2_utils.get_unsets(parsed_args) if not unset_args and not parsed_args.all_tag: return hm_id = v2_utils.get_resource_id( self.app.client_manager.load_balancer.health_monitor_list, 'healthmonitors', parsed_args.health_monitor) v2_utils.set_tags_for_unset( self.app.client_manager.load_balancer.health_monitor_show, hm_id, unset_args, clear_tags=parsed_args.all_tag) body = {'healthmonitor': unset_args} self.app.client_manager.load_balancer.health_monitor_set( hm_id, json=body) if parsed_args.wait: v2_utils.wait_for_active( status_f=(self.app.client_manager.load_balancer. health_monitor_show), res_id=hm_id ) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/osc/v2/l7policy.py0000664000175000017500000003170400000000000023771 0ustar00zuulzuul00000000000000# Copyright 2017 GoDaddy # Copyright 2019 Red Hat, Inc. All rights reserved. # # 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. # """L7policy action implementation""" from cliff import lister from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from osc_lib.utils import tags as _tag from oslo_utils import uuidutils from octaviaclient.osc.v2 import constants as const from octaviaclient.osc.v2 import utils as v2_utils from octaviaclient.osc.v2 import validate ACTION_CHOICES = ['REDIRECT_TO_URL', 'REDIRECT_TO_POOL', 'REDIRECT_PREFIX', 'REJECT'] REDIRECT_CODE_CHOICES = [301, 302, 303, 307, 308] class CreateL7Policy(command.ShowOne): """Create a l7policy""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'listener', metavar='', help="Listener to add l7policy to (name or ID)." ) parser.add_argument( '--name', metavar='', help="Set the l7policy name." ) parser.add_argument( '--description', metavar='', help="Set l7policy description." ) parser.add_argument( '--action', metavar='{' + ','.join(ACTION_CHOICES) + '}', required=True, choices=ACTION_CHOICES, type=lambda s: s.upper(), # case insensitive help="Set the action of the policy." ) redirect_group = parser.add_mutually_exclusive_group() redirect_group.add_argument( '--redirect-pool', metavar='', help="Set the pool to redirect requests to (name or ID)." ) redirect_group.add_argument( '--redirect-url', metavar='', help="Set the URL to redirect requests to." ) redirect_group.add_argument( '--redirect-prefix', metavar='', help="Set the URL Prefix to redirect requests to." ) parser.add_argument( '--redirect-http-code', metavar='', choices=REDIRECT_CODE_CHOICES, type=int, help="Set the HTTP response code for REDIRECT_URL or " "REDIRECT_PREFIX action." ) parser.add_argument( '--position', metavar='', type=int, help="Sequence number of this L7 Policy." ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=True, help="Enable l7policy (default)." ) admin_group.add_argument( '--disable', action='store_true', default=None, help="Disable l7policy." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) _tag.add_tag_option_to_parser_for_create( parser, 'l7policy') return parser def take_action(self, parsed_args): rows = const.L7POLICY_ROWS attrs = v2_utils.get_l7policy_attrs(self.app.client_manager, parsed_args) validate.check_l7policy_attrs(attrs) body = {"l7policy": attrs} data = self.app.client_manager.load_balancer.l7policy_create( json=body) if parsed_args.wait: listener = self.app.client_manager.load_balancer.listener_show( data['l7policy']['listener_id']) v2_utils.wait_for_active( status_f=(self.app.client_manager.load_balancer. load_balancer_show), res_id=listener['loadbalancers'][0]['id'] ) data = { 'l7policy': ( self.app.client_manager.load_balancer.l7policy_show( data['l7policy']['id'])) } formatters = {'rules': v2_utils.format_list, 'tags': v2_utils.format_list_flat} return (rows, (utils.get_dict_properties( data['l7policy'], rows, formatters=formatters))) class DeleteL7Policy(command.Command): """Delete a l7policy""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'l7policy', metavar="", help="l7policy to delete (name or ID)." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) return parser def take_action(self, parsed_args): attrs = v2_utils.get_l7policy_attrs(self.app.client_manager, parsed_args) l7policy_id = attrs.pop('l7policy_id') self.app.client_manager.load_balancer.l7policy_delete( l7policy_id=l7policy_id) if parsed_args.wait: v2_utils.wait_for_delete( status_f=(self.app.client_manager.load_balancer. l7policy_show), res_id=l7policy_id ) class ListL7Policy(lister.Lister): """List l7policies""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( '--listener', help="List l7policies that applied to the given listener " "(name or ID)." ) _tag.add_tag_filtering_option_to_parser(parser, 'l7policy') return parser def take_action(self, parsed_args): columns = const.L7POLICY_COLUMNS attrs = v2_utils.get_l7policy_attrs(self.app.client_manager, parsed_args) data = self.app.client_manager.load_balancer.l7policy_list(**attrs) formatters = {'rules': v2_utils.format_list} return (columns, (utils.get_dict_properties( s, columns, formatters=formatters) for s in data['l7policies'])) class ShowL7Policy(command.ShowOne): """Show the details of a single l7policy""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'l7policy', metavar='', help='Name or UUID of the l7policy.' ) return parser def take_action(self, parsed_args): rows = const.L7POLICY_ROWS data = None if uuidutils.is_uuid_like(parsed_args.l7policy): try: data = self.app.client_manager.load_balancer.l7policy_show( l7policy_id=parsed_args.l7policy) except exceptions.NotFound: pass if data is None: attrs = v2_utils.get_l7policy_attrs(self.app.client_manager, parsed_args) l7policy_id = attrs.pop('l7policy_id') data = self.app.client_manager.load_balancer.l7policy_show( l7policy_id=l7policy_id, ) formatters = {'rules': v2_utils.format_list, 'tags': v2_utils.format_list_flat} return (rows, (utils.get_dict_properties( data, rows, formatters=formatters))) class SetL7Policy(command.Command): """Update a l7policy""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'l7policy', metavar='', help="L7policy to update (name or ID)." ) parser.add_argument( '--name', metavar='', help="Set l7policy name." ) parser.add_argument( '--description', metavar='', help="Set l7policy description." ) parser.add_argument( '--action', metavar='{' + ','.join(ACTION_CHOICES) + '}', choices=ACTION_CHOICES, type=lambda s: s.upper(), # case insensitive help="Set the action of the policy." ) redirect_group = parser.add_mutually_exclusive_group() redirect_group.add_argument( '--redirect-pool', metavar='', help="Set the pool to redirect requests to (name or ID)." ) redirect_group.add_argument( '--redirect-url', metavar='', help="Set the URL to redirect requests to." ) redirect_group.add_argument( '--redirect-prefix', metavar='', help="Set the URL Prefix to redirect requests to." ) parser.add_argument( '--redirect-http-code', metavar='', choices=REDIRECT_CODE_CHOICES, type=int, help="Set the HTTP response code for REDIRECT_URL or " "REDIRECT_PREFIX action." ) parser.add_argument( '--position', metavar='', type=int, help="Set sequence number of this L7 Policy." ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=None, help="Enable l7policy." ) admin_group.add_argument( '--disable', action='store_true', default=None, help="Disable l7policy." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) _tag.add_tag_option_to_parser_for_set(parser, 'l7policy') return parser def take_action(self, parsed_args): attrs = v2_utils.get_l7policy_attrs(self.app.client_manager, parsed_args) validate.check_l7policy_attrs(attrs) l7policy_id = attrs.pop('l7policy_id') v2_utils.set_tags_for_set( self.app.client_manager.load_balancer.l7policy_show, l7policy_id, attrs, clear_tags=parsed_args.no_tag) body = {'l7policy': attrs} self.app.client_manager.load_balancer.l7policy_set( l7policy_id, json=body) if parsed_args.wait: v2_utils.wait_for_active( status_f=(self.app.client_manager.load_balancer. l7policy_show), res_id=l7policy_id ) class UnsetL7Policy(command.Command): """Clear l7policy settings""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'l7policy', metavar='', help="L7policy to update (name or ID)." ) parser.add_argument( '--description', action='store_true', help="Clear the l7policy description." ) parser.add_argument( '--name', action='store_true', help="Clear the l7policy name." ) parser.add_argument( '--redirect-http-code', action='store_true', help="Clear the l7policy redirect HTTP code." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) _tag.add_tag_option_to_parser_for_unset(parser, 'l7policy') return parser def take_action(self, parsed_args): unset_args = v2_utils.get_unsets(parsed_args) if not unset_args and not parsed_args.all_tag: return policy_id = v2_utils.get_resource_id( self.app.client_manager.load_balancer.l7policy_list, 'l7policies', parsed_args.l7policy) v2_utils.set_tags_for_unset( self.app.client_manager.load_balancer.l7policy_show, policy_id, unset_args, clear_tags=parsed_args.all_tag) body = {'l7policy': unset_args} self.app.client_manager.load_balancer.l7policy_set( policy_id, json=body) if parsed_args.wait: v2_utils.wait_for_active( status_f=(self.app.client_manager.load_balancer. l7policy_show), res_id=policy_id ) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/osc/v2/l7rule.py0000664000175000017500000003104200000000000023434 0ustar00zuulzuul00000000000000# Copyright 2017 GoDaddy # Copyright 2019 Red Hat, Inc. All rights reserved. # # 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. # """L7rule action implementation""" import functools from cliff import lister from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from osc_lib.utils import tags as _tag from oslo_utils import uuidutils from octaviaclient.osc.v2 import constants as const from octaviaclient.osc.v2 import utils as v2_utils from octaviaclient.osc.v2 import validate COMPARE_TYPES = ['REGEX', 'EQUAL_TO', 'CONTAINS', 'ENDS_WITH', 'STARTS_WITH'] TYPES = ['FILE_TYPE', 'PATH', 'COOKIE', 'HOST_NAME', 'HEADER', 'SSL_CONN_HAS_CERT', 'SSL_VERIFY_RESULT', 'SSL_DN_FIELD'] class CreateL7Rule(command.ShowOne): """Create a l7rule""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'l7policy', metavar='', help="l7policy to add l7rule to (name or ID)." ) parser.add_argument( '--compare-type', metavar='{' + ','.join(COMPARE_TYPES) + '}', required=True, choices=COMPARE_TYPES, type=lambda s: s.upper(), # case insensitive help="Set the compare type for the l7rule." ) parser.add_argument( '--invert', action='store_true', default=None, help="Invert l7rule." ) parser.add_argument( '--value', metavar='', required=True, help="Set the rule value to match on." ) parser.add_argument( '--key', metavar='', help="Set the key for the l7rule's value to match on." ) parser.add_argument( '--type', metavar='{' + ','.join(TYPES) + '}', required=True, choices=TYPES, type=lambda s: s.upper(), # case insensitive help="Set the type for the l7rule." ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=True, help="Enable l7rule (default)." ) admin_group.add_argument( '--disable', action='store_true', default=None, help="Disable l7rule." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) _tag.add_tag_option_to_parser_for_create( parser, 'l7rule') return parser def take_action(self, parsed_args): rows = const.L7RULE_ROWS attrs = v2_utils.get_l7rule_attrs(self.app.client_manager, parsed_args) validate.check_l7rule_attrs(attrs) l7policy_id = attrs.pop('l7policy_id') body = {"rule": attrs} data = self.app.client_manager.load_balancer.l7rule_create( l7policy_id=l7policy_id, json=body ) if parsed_args.wait: l7policy = self.app.client_manager.load_balancer.l7policy_show( l7policy_id) listener = self.app.client_manager.load_balancer.listener_show( l7policy['listener_id']) v2_utils.wait_for_active( status_f=(self.app.client_manager.load_balancer. load_balancer_show), res_id=listener['loadbalancers'][0]['id'] ) data = { 'rule': ( self.app.client_manager.load_balancer.l7rule_show( l7policy_id, data['rule']['id'])) } formatters = {'tags': v2_utils.format_list_flat} return (rows, (utils.get_dict_properties( data['rule'], rows, formatters=formatters))) class DeleteL7Rule(command.Command): """Delete a l7rule""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'l7policy', metavar="", help="l7policy to delete rule from (name or ID)." ) parser.add_argument( 'l7rule', metavar="", help="l7rule to delete." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) return parser def take_action(self, parsed_args): attrs = v2_utils.get_l7rule_attrs(self.app.client_manager, parsed_args) self.app.client_manager.load_balancer.l7rule_delete( l7rule_id=attrs['l7rule_id'], l7policy_id=attrs['l7policy_id'] ) if parsed_args.wait: l7rule_show = functools.partial( self.app.client_manager.load_balancer.l7rule_show, attrs['l7rule_id'] ) v2_utils.wait_for_delete( status_f=l7rule_show, res_id=attrs['l7policy_id'] ) class ListL7Rule(lister.Lister): """List l7rules for l7policy""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'l7policy', metavar='', help='l7policy to list rules for (name or ID).' ) _tag.add_tag_filtering_option_to_parser(parser, 'l7rule') return parser def take_action(self, parsed_args): columns = const.L7RULE_COLUMNS attrs = v2_utils.get_l7rule_attrs(self.app.client_manager, parsed_args) data = self.app.client_manager.load_balancer.l7rule_list( **attrs ) return (columns, (utils.get_dict_properties( s, columns, formatters={}) for s in data['rules'])) class ShowL7Rule(command.ShowOne): """Show the details of a single l7rule""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'l7policy', metavar="", help="l7policy to show rule from (name or ID)." ) parser.add_argument( 'l7rule', metavar="", help="l7rule to show." ) return parser def take_action(self, parsed_args): rows = const.L7RULE_ROWS data = None if (uuidutils.is_uuid_like(parsed_args.l7policy) and uuidutils.is_uuid_like(parsed_args.l7rule)): try: data = self.app.client_manager.load_balancer.l7rule_show( l7rule_id=parsed_args.l7rule, l7policy_id=parsed_args.l7policy) except exceptions.NotFound: pass if data is None: attrs = v2_utils.get_l7rule_attrs(self.app.client_manager, parsed_args) data = self.app.client_manager.load_balancer.l7rule_show( l7rule_id=attrs['l7rule_id'], l7policy_id=attrs['l7policy_id'] ) formatters = {'tags': v2_utils.format_list_flat} return (rows, (utils.get_dict_properties( data, rows, formatters=formatters))) class SetL7Rule(command.Command): """Update a l7rule""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'l7policy', metavar='', help="L7policy to update l7rule on (name or ID)." ) parser.add_argument( 'l7rule', metavar='', help="l7rule to update." ) parser.add_argument( '--compare-type', metavar='{' + ','.join(COMPARE_TYPES) + '}', choices=COMPARE_TYPES, type=lambda s: s.upper(), # case insensitive help="Set the compare type for the l7rule." ) parser.add_argument( '--invert', action='store_true', default=None, help="Invert l7rule." ) parser.add_argument( '--value', metavar='', help="Set the rule value to match on." ) parser.add_argument( '--key', metavar='', help="Set the key for the l7rule's value to match on." ) parser.add_argument( '--type', metavar='{' + ','.join(TYPES) + '}', choices=TYPES, type=lambda s: s.upper(), # case insensitive help="Set the type for the l7rule." ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=None, help="Enable l7rule." ) admin_group.add_argument( '--disable', action='store_true', default=None, help="Disable l7rule." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) _tag.add_tag_option_to_parser_for_set(parser, 'l7rule') return parser def take_action(self, parsed_args): attrs = v2_utils.get_l7rule_attrs(self.app.client_manager, parsed_args) validate.check_l7rule_attrs(attrs) l7policy_id = attrs.pop('l7policy_id') l7rule_id = attrs.pop('l7rule_id') # l7rule_id is the first argument in l7rule_show l7rule_show = functools.partial( self.app.client_manager.load_balancer.l7rule_show, l7rule_id ) v2_utils.set_tags_for_set( l7rule_show, l7policy_id, attrs, clear_tags=parsed_args.no_tag) body = {'rule': attrs} self.app.client_manager.load_balancer.l7rule_set( l7rule_id=l7rule_id, l7policy_id=l7policy_id, json=body ) if parsed_args.wait: v2_utils.wait_for_active( status_f=l7rule_show, res_id=l7policy_id ) class UnsetL7Rule(command.Command): """Clear l7rule settings""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'l7policy', metavar='', help="L7policy to update (name or ID)." ) parser.add_argument( 'l7rule_id', metavar='', help="l7rule to update." ) parser.add_argument( '--invert', action='store_true', help="Reset the l7rule invert to the API default." ) parser.add_argument( '--key', action='store_true', help="Clear the l7rule key." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) _tag.add_tag_option_to_parser_for_unset(parser, 'l7rule') return parser def take_action(self, parsed_args): unset_args = v2_utils.get_unsets(parsed_args) if not unset_args and not parsed_args.all_tag: return policy_id = v2_utils.get_resource_id( self.app.client_manager.load_balancer.l7policy_list, 'l7policies', parsed_args.l7policy) l7rule_show = functools.partial( self.app.client_manager.load_balancer.l7rule_show, parsed_args.l7rule_id ) v2_utils.set_tags_for_unset( l7rule_show, policy_id, unset_args, clear_tags=parsed_args.all_tag) body = {'rule': unset_args} self.app.client_manager.load_balancer.l7rule_set( l7policy_id=policy_id, l7rule_id=parsed_args.l7rule_id, json=body) if parsed_args.wait: v2_utils.wait_for_active( status_f=l7rule_show, res_id=policy_id, ) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/osc/v2/listener.py0000664000175000017500000006612600000000000024062 0ustar00zuulzuul00000000000000# Copyright 2017 GoDaddy # 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. # """Listener action implementation""" import argparse from cliff import lister from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from osc_lib.utils import tags as _tag from oslo_utils import uuidutils from octaviaclient.osc.v2 import constants as const from octaviaclient.osc.v2 import utils as v2_utils from octaviaclient.osc.v2 import validate PROTOCOL_CHOICES = ['TCP', 'HTTP', 'HTTPS', 'TERMINATED_HTTPS', 'UDP', 'SCTP', 'PROMETHEUS'] CLIENT_AUTH_CHOICES = ['NONE', 'OPTIONAL', 'MANDATORY'] class CreateListener(command.ShowOne): """Create a listener""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'loadbalancer', metavar='', help="Load balancer for the listener (name or ID)." ) parser.add_argument( '--name', metavar='', help="Set the listener name." ) parser.add_argument( '--description', metavar='', help="Set the description of this listener." ) parser.add_argument( '--protocol', metavar='{' + ','.join(PROTOCOL_CHOICES) + '}', choices=PROTOCOL_CHOICES, type=lambda s: s.upper(), # case insensitive required=True, help="The protocol for the listener." ) parser.add_argument( '--connection-limit', type=int, metavar='', help="Set the maximum number of connections permitted for this " "listener." ) parser.add_argument( '--default-pool', metavar='', help="Set the name or ID of the pool used by the listener if no " "L7 policies match." ) parser.add_argument( '--default-tls-container-ref', metavar='', help="The URI to the key manager service secrets container " "containing the certificate and key for TERMINATED_TLS " "listeners." ) parser.add_argument( '--sni-container-refs', metavar='', nargs='*', help="A list of URIs to the key manager service secrets " "containers containing the certificates and keys for " "TERMINATED_TLS the listener using Server Name Indication." ) parser.add_argument( '--insert-headers', metavar='', help="A dictionary of optional headers to insert into the request " "before it is sent to the backend member." ) parser.add_argument( '--protocol-port', metavar='', required=True, type=int, help="Set the protocol port number for the listener." ) parser.add_argument( '--timeout-client-data', type=int, metavar='', help="Frontend client inactivity timeout in milliseconds. " "Default: 50000." ) parser.add_argument( '--timeout-member-connect', type=int, metavar='', help="Backend member connection timeout in milliseconds. " "Default: 5000." ) parser.add_argument( '--timeout-member-data', type=int, metavar='', help="Backend member inactivity timeout in milliseconds. " "Default: 50000." ) parser.add_argument( '--timeout-tcp-inspect', type=int, metavar='', help="Time, in milliseconds, to wait for additional TCP packets " "for content inspection. Default: 0." ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=True, help="Enable listener (default)." ) admin_group.add_argument( '--disable', action='store_true', default=None, help="Disable listener." ) parser.add_argument( '--client-ca-tls-container-ref', metavar='', help="The URI to the key manager service secrets container " "containing the CA certificate for TERMINATED_TLS listeners." ) parser.add_argument( '--client-authentication', metavar='{' + ','.join(CLIENT_AUTH_CHOICES) + '}', choices=CLIENT_AUTH_CHOICES, type=lambda s: s.upper(), # case insensitive help="The TLS client authentication verify options for " "TERMINATED_TLS listeners." ) parser.add_argument( '--client-crl-container-ref', metavar='', help="The URI to the key manager service secrets container " "containting the CA revocation list file for TERMINATED_TLS " "listeners." ) parser.add_argument( '--allowed-cidr', dest='allowed_cidrs', metavar='', nargs='?', action='append', help="CIDR to allow access to the listener (can be set multiple " "times)." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) parser.add_argument( '--tls-ciphers', metavar='', help="Set the TLS ciphers to be used " "by the listener in OpenSSL format." ) parser.add_argument( '--tls-version', dest='tls_versions', metavar='', nargs='?', action='append', help="Set the TLS protocol version to be used " "by the listener (can be set multiple times)." ) parser.add_argument( '--alpn-protocol', dest='alpn_protocols', metavar='', nargs='?', action='append', help="Set the ALPN protocol to be used " "by the listener (can be set multiple times)." ) parser.add_argument( '--hsts-max-age', dest='hsts_max_age', metavar='', type=int, help="The value of the max_age directive for the " "Strict-Transport-Security HTTP response header. " "Setting this enables HTTP Strict Transport " "Security (HSTS) for the TLS-terminated listener." ) parser.add_argument( '--hsts-include-subdomains', action='store_true', dest='hsts_include_subdomains', default=None, help="Define whether the includeSubDomains directive should be " "added to the Strict-Transport-Security HTTP response " "header." ) parser.add_argument( '--hsts-preload', action='store_true', dest='hsts_preload', default=None, help="Define whether the preload directive should be " "added to the Strict-Transport-Security HTTP response " "header." ) _tag.add_tag_option_to_parser_for_create( parser, 'listener') return parser def take_action(self, parsed_args): rows = const.LISTENER_ROWS attrs = v2_utils.get_listener_attrs(self.app.client_manager, parsed_args) validate.check_listener_attrs(attrs) body = {"listener": attrs} data = self.app.client_manager.load_balancer.listener_create( json=body) if parsed_args.wait: v2_utils.wait_for_active( status_f=(self.app.client_manager.load_balancer. load_balancer_show), res_id=data['listener']['loadbalancers'][0]['id'] ) data = { 'listener': ( self.app.client_manager.load_balancer.listener_show( data['listener']['id'])) } formatters = {'loadbalancers': v2_utils.format_list, 'pools': v2_utils.format_list, 'l7policies': v2_utils.format_list, 'insert_headers': v2_utils.format_hash, 'allowed_cidrs': v2_utils.format_list_flat, 'tags': v2_utils.format_list_flat} return (rows, (utils.get_dict_properties(data['listener'], rows, formatters=formatters))) class DeleteListener(command.Command): """Delete a listener""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'listener', metavar="", help="Listener to delete (name or ID)." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) return parser def take_action(self, parsed_args): attrs = v2_utils.get_listener_attrs(self.app.client_manager, parsed_args) listener_id = attrs.pop('listener_id') self.app.client_manager.load_balancer.listener_delete( listener_id=listener_id) if parsed_args.wait: v2_utils.wait_for_delete( status_f=self.app.client_manager.load_balancer.listener_show, res_id=listener_id ) class ListListener(lister.Lister): """List listeners""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( '--name', metavar='', help="List listeners by listener name." ) parser.add_argument( '--loadbalancer', metavar='', help="Filter by load balancer (name or ID).", ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=None, help="List enabled listeners." ) admin_group.add_argument( '--disable', action='store_true', default=None, help="List disabled listeners." ) parser.add_argument( '--project', metavar='', help="List listeners by project ID." ) _tag.add_tag_filtering_option_to_parser(parser, 'listener') return parser def take_action(self, parsed_args): columns = const.LISTENER_COLUMNS attrs = v2_utils.get_listener_attrs(self.app.client_manager, parsed_args) data = self.app.client_manager.load_balancer.listener_list(**attrs) formatters = {'loadbalancers': v2_utils.format_list} return (columns, (utils.get_dict_properties(s, columns, formatters=formatters) for s in data['listeners'])) class ShowListener(command.ShowOne): """Show the details of a single listener""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'listener', metavar='', help='Name or UUID of the listener.' ) return parser def take_action(self, parsed_args): rows = const.LISTENER_ROWS data = None if uuidutils.is_uuid_like(parsed_args.listener): try: data = self.app.client_manager.load_balancer.listener_show( listener_id=parsed_args.listener) except exceptions.NotFound: pass if data is None: attrs = v2_utils.get_listener_attrs(self.app.client_manager, parsed_args) listener_id = attrs.pop('listener_id') data = self.app.client_manager.load_balancer.listener_show( listener_id=listener_id, ) formatters = {'loadbalancers': v2_utils.format_list, 'pools': v2_utils.format_list, 'l7policies': v2_utils.format_list, 'insert_headers': v2_utils.format_hash, 'allowed_cidrs': v2_utils.format_list_flat, 'tags': v2_utils.format_list_flat} return rows, utils.get_dict_properties(data, rows, formatters=formatters) class SetListener(command.Command): """Update a listener""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'listener', metavar="", help="Listener to modify (name or ID)." ) parser.add_argument( '--name', metavar='', help="Set the listener name." ) parser.add_argument( '--description', metavar='', help="Set the description of this listener." ) parser.add_argument( '--connection-limit', metavar='', help="The maximum number of connections permitted for this " "listener. Default value is -1 which represents infinite " "connections." ) parser.add_argument( '--default-pool', metavar='', help="The ID of the pool used by the listener if no L7 policies " "match." ) parser.add_argument( '--default-tls-container-ref', metavar='', help="The URI to the key manager service secrets container " "containing the certificate and key for TERMINATED_TLS " "listeners." ) parser.add_argument( '--sni-container-refs', metavar='', nargs='*', help="A list of URIs to the key manager service secrets " "containers containing the certificates and keys for " "TERMINATED_TLS the listener using Server Name Indication." ) parser.add_argument( '--insert-headers', metavar='', help="A dictionary of optional headers to insert into the request " "before it is sent to the backend member." ) parser.add_argument( '--timeout-client-data', type=int, metavar='', help="Frontend client inactivity timeout in milliseconds. " "Default: 50000." ) parser.add_argument( '--timeout-member-connect', type=int, metavar='', help="Backend member connection timeout in milliseconds. " "Default: 5000." ) parser.add_argument( '--timeout-member-data', type=int, metavar='', help="Backend member inactivity timeout in milliseconds. " "Default: 50000." ) parser.add_argument( '--timeout-tcp-inspect', type=int, metavar='', help="Time, in milliseconds, to wait for additional TCP packets " "for content inspection. Default: 0." ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=None, help="Enable listener." ) admin_group.add_argument( '--disable', action='store_true', default=None, help="Disable listener." ) parser.add_argument( '--client-ca-tls-container-ref', metavar='', help="The URI to the key manager service secrets container " "containing the CA certificate for TERMINATED_TLS listeners." ) parser.add_argument( '--client-authentication', metavar='{' + ','.join(CLIENT_AUTH_CHOICES) + '}', choices=CLIENT_AUTH_CHOICES, type=lambda s: s.upper(), # case insensitive help="The TLS client authentication verify options for " "TERMINATED_TLS listeners." ) parser.add_argument( '--client-crl-container-ref', metavar='', help="The URI to the key manager service secrets container " "containting the CA revocation list file for TERMINATED_TLS " "listeners." ) parser.add_argument( '--allowed-cidr', dest='allowed_cidrs', metavar='', nargs='?', action='append', help="CIDR to allow access to the listener (can be set multiple " "times)." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) parser.add_argument( '--tls-ciphers', metavar='', help="Set the TLS ciphers to be used " "by the listener in OpenSSL format." ) parser.add_argument( '--tls-version', dest='tls_versions', metavar='', nargs='?', action='append', help="Set the TLS protocol version to be used " "by the listener (can be set multiple times)." ) parser.add_argument( '--alpn-protocol', dest='alpn_protocols', metavar='', nargs='?', action='append', help="Set the ALPN protocol to be used " "by the listener (can be set multiple times)." ) parser.add_argument( '--hsts-max-age', dest='hsts_max_age', metavar='', type=int, default=argparse.SUPPRESS, help="The value of the max_age directive for the " "Strict-Transport-Security HTTP response header. " "Setting this enables HTTP Strict Transport " "Security (HSTS) for the TLS-terminated listener." ) parser.add_argument( '--hsts-include-subdomains', action='store_true', default=argparse.SUPPRESS, dest='hsts_include_subdomains', help="Defines whether the includeSubDomains directive should be " "added to the Strict-Transport-Security HTTP response " "header." ) parser.add_argument( '--hsts-preload', action='store_true', default=argparse.SUPPRESS, dest='hsts_preload', help="Defines whether the preload directive should be " "added to the Strict-Transport-Security HTTP response " "header." ) _tag.add_tag_option_to_parser_for_set(parser, 'listener') return parser def take_action(self, parsed_args): attrs = v2_utils.get_listener_attrs(self.app.client_manager, parsed_args) listener_id = attrs.pop('listener_id') v2_utils.set_tags_for_set( self.app.client_manager.load_balancer.listener_show, listener_id, attrs, clear_tags=parsed_args.no_tag) body = {'listener': attrs} self.app.client_manager.load_balancer.listener_set( listener_id, json=body) if parsed_args.wait: v2_utils.wait_for_active( status_f=self.app.client_manager.load_balancer.listener_show, res_id=listener_id ) class UnsetListener(command.Command): """Clear listener settings""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'listener', metavar="", help="Listener to modify (name or ID)." ) parser.add_argument( '--name', action='store_true', help="Clear the listener name." ) parser.add_argument( '--description', action='store_true', help="Clear the description of this listener." ) parser.add_argument( '--connection-limit', action='store_true', help="Reset the connection limit to the API default." ) parser.add_argument( '--default-pool', dest='default_pool_id', action='store_true', help="Clear the default pool from the listener." ) parser.add_argument( '--default-tls-container-ref', action='store_true', help="Remove the default TLS container reference from the " "listener." ) parser.add_argument( '--sni-container-refs', action='store_true', help="Remove the TLS SNI container references from the listener." ) parser.add_argument( '--insert-headers', action='store_true', help="Clear the insert headers from the listener." ) parser.add_argument( '--timeout-client-data', action='store_true', help="Reset the client data timeout to the API default." ) parser.add_argument( '--timeout-member-connect', action='store_true', help="Reset the member connect timeout to the API default." ) parser.add_argument( '--timeout-member-data', action='store_true', help="Reset the member data timeout to the API default." ) parser.add_argument( '--timeout-tcp-inspect', action='store_true', help="Reset the TCP inspection timeout to the API default." ) parser.add_argument( '--client-ca-tls-container-ref', action='store_true', help="Clear the client CA TLS container reference from the " "listener." ) parser.add_argument( '--client-authentication', action='store_true', help="Reset the client authentication setting to the API default." ) parser.add_argument( '--client-crl-container-ref', action='store_true', help="Clear the client CRL container reference from the listener." ) parser.add_argument( '--allowed-cidrs', action='store_true', help="Clear all allowed CIDRs from the listener." ) parser.add_argument( '--tls-versions', action='store_true', help='Clear all TLS versions from the listener.', ) parser.add_argument( '--tls-ciphers', action='store_true', help='Clear all TLS ciphers from the listener.', ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) parser.add_argument( '--alpn-protocols', action='store_true', help="Clear all ALPN protocols from the listener." ) parser.add_argument( '--hsts-max-age', dest='hsts_max_age', action='store_true', help="Disables HTTP Strict Transport " "Security (HSTS) for the TLS-terminated listener." ) parser.add_argument( '--hsts-include-subdomains', action='store_true', dest='hsts_include_subdomains', help="Removes the includeSubDomains directive from the " "Strict-Transport-Security HTTP response header." ) parser.add_argument( '--hsts-preload', action='store_true', dest='hsts_preload', help="Removes the preload directive from the " "Strict-Transport-Security HTTP response header." ) _tag.add_tag_option_to_parser_for_unset(parser, 'listener') return parser def take_action(self, parsed_args): unset_args = v2_utils.get_unsets(parsed_args) if not unset_args and not parsed_args.all_tag: return listener_id = v2_utils.get_resource_id( self.app.client_manager.load_balancer.listener_list, 'listeners', parsed_args.listener) v2_utils.set_tags_for_unset( self.app.client_manager.load_balancer.listener_show, listener_id, unset_args, clear_tags=parsed_args.all_tag) body = {'listener': unset_args} self.app.client_manager.load_balancer.listener_set( listener_id, json=body) if parsed_args.wait: v2_utils.wait_for_active( status_f=self.app.client_manager.load_balancer.listener_show, res_id=listener_id ) class ShowListenerStats(command.ShowOne): """Shows the current statistics for a listener.""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'listener', metavar='', help='Name or UUID of the listener.' ) return parser def take_action(self, parsed_args): rows = const.LOAD_BALANCER_STATS_ROWS attrs = v2_utils.get_listener_attrs(self.app.client_manager, parsed_args) listener_id = attrs.pop('listener_id') data = self.app.client_manager.load_balancer.listener_stats_show( listener_id=listener_id, ) return (rows, (utils.get_dict_properties( data['stats'], rows, formatters={}))) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/osc/v2/load_balancer.py0000664000175000017500000004564500000000000025006 0ustar00zuulzuul00000000000000# 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. # """Load Balancer action implementation""" from cliff import lister from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from osc_lib.utils import tags as _tag from oslo_serialization import jsonutils from oslo_utils import uuidutils from octaviaclient.osc.v2 import constants as const from octaviaclient.osc.v2 import utils as v2_utils PROVISIONING_STATUS = ['ACTIVE', 'ERROR', 'PENDING_CREATE', 'PENDING_UPDATE', 'PENDING_DELETE'] OPERATING_STATUS = ['ONLINE', 'DRAINING', 'OFFLINE', 'DEGRADED', 'ERROR', 'NO_MONITOR'] class CreateLoadBalancer(command.ShowOne): """Create a load balancer""" @staticmethod def _check_attrs(attrs): verify_args = ['vip_subnet_id', 'vip_network_id', 'vip_port_id'] if not any(i in attrs for i in verify_args): msg = ("Missing required argument: Requires one of " "--vip-subnet-id, --vip-network-id or --vip-port-id") raise exceptions.CommandError(msg) if all(i in attrs for i in ('vip_network_id', 'vip_port_id')): msg = ("Argument error: --vip-port-id can not be used with " "--vip-network-id") raise exceptions.CommandError(msg) def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( '--name', metavar='', help="New load balancer name." ) parser.add_argument( '--description', metavar='', help="Set load balancer description." ) parser.add_argument( '--vip-address', metavar='', help="Set the VIP IP Address." ) vip_group = parser.add_argument_group( "VIP Network", description="At least one of the following arguments is required." ) vip_group.add_argument( '--vip-port-id', metavar='', help="Set Port for the load balancer (name or ID)." ) vip_group.add_argument( '--vip-subnet-id', metavar='', help="Set subnet for the load balancer (name or ID)." ) vip_group.add_argument( '--vip-network-id', metavar='', help="Set network for the load balancer (name or ID)." ) parser.add_argument( '--vip-qos-policy-id', metavar='', help="Set QoS policy ID for VIP port. Unset with 'None'.", ) parser.add_argument( '--additional-vip', metavar='subnet-id=[,ip-address=]', action='append', help="Expose an additional VIP on the load balancer. This " "parameter can be provided more than once." ) parser.add_argument( '--project', metavar='', help="Project for the load balancer (name or ID)." ) parser.add_argument( '--provider', metavar='', help="Provider name for the load balancer." ) parser.add_argument( '--availability-zone', metavar='', default=None, help="Availability zone for the load balancer." ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=True, help="Enable load balancer (default)." ) admin_group.add_argument( '--disable', action='store_true', default=None, help="Disable load balancer." ) parser.add_argument( '--flavor', metavar='', help="The name or ID of the flavor for the load balancer." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) _tag.add_tag_option_to_parser_for_create( parser, 'load balancer') return parser def take_action(self, parsed_args): rows = const.LOAD_BALANCER_ROWS attrs = v2_utils.get_loadbalancer_attrs(self.app.client_manager, parsed_args) self._check_attrs(attrs) body = {'loadbalancer': attrs} data = self.app.client_manager.load_balancer.load_balancer_create( json=body) if parsed_args.wait: v2_utils.wait_for_active( status_f=(self.app.client_manager.load_balancer. load_balancer_show), res_id=data['loadbalancer']['id'] ) data = { 'loadbalancer': ( self.app.client_manager.load_balancer.load_balancer_show( data['loadbalancer']['id'])) } # Handle older API versions that did not have the vip_vnic_type if not data['loadbalancer'].get('vip_vnic_type', False): data['loadbalancer']['vip_vnic_type'] = 'normal' formatters = { 'listeners': v2_utils.format_list, 'pools': v2_utils.format_list, 'l7policies': v2_utils.format_list, 'tags': v2_utils.format_list_flat } return (rows, (utils.get_dict_properties( data['loadbalancer'], rows, formatters=formatters))) class DeleteLoadBalancer(command.Command): """Delete a load balancer""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'loadbalancer', metavar='', help="Load balancers to delete (name or ID)." ) parser.add_argument( '--cascade', action='store_true', default=None, help="Cascade the delete to all child elements of the load " "balancer." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) return parser def take_action(self, parsed_args): attrs = v2_utils.get_loadbalancer_attrs(self.app.client_manager, parsed_args) lb_id = attrs.pop('loadbalancer_id') self.app.client_manager.load_balancer.load_balancer_delete( lb_id=lb_id, **attrs) if parsed_args.wait: v2_utils.wait_for_delete( status_f=(self.app.client_manager.load_balancer. load_balancer_show), res_id=lb_id ) class FailoverLoadBalancer(command.Command): """Trigger load balancer failover""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'loadbalancer', metavar='', help="Name or UUID of the load balancer." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) return parser def take_action(self, parsed_args): attrs = v2_utils.get_loadbalancer_attrs(self.app.client_manager, parsed_args) lb_id = attrs.pop('loadbalancer_id') self.app.client_manager.load_balancer.load_balancer_failover( lb_id=lb_id) if parsed_args.wait: v2_utils.wait_for_active( status_f=(self.app.client_manager.load_balancer. load_balancer_show), res_id=lb_id ) class ListLoadBalancer(lister.Lister): """List load balancers""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( '--name', metavar='', help="List load balancers according to their name." ) admin_state_group = parser.add_mutually_exclusive_group() admin_state_group.add_argument( '--enable', action='store_true', default=None, help="List enabled load balancers." ) admin_state_group.add_argument( '--disable', action='store_true', default=None, help="List disabled load balancers." ) parser.add_argument( '--project', metavar='', help="List load balancers according to their project (name or ID)." ) parser.add_argument( '--vip-network-id', metavar='', help="List load balancers according to their VIP network " "(name or ID)." ) parser.add_argument( '--vip-subnet-id', metavar='', help="List load balancers according to their VIP subnet " "(name or ID)." ) parser.add_argument( '--vip-qos-policy-id', metavar='', help="List load balancers according to their VIP Qos policy " "(name or ID)." ) parser.add_argument( '--vip-port-id', metavar='', help="List load balancers according to their VIP port " "(name or ID)." ) parser.add_argument( '--provisioning-status', metavar='{' + ','.join(PROVISIONING_STATUS) + '}', choices=PROVISIONING_STATUS, type=lambda s: s.upper(), help="List load balancers according to their provisioning status." ) parser.add_argument( '--operating-status', metavar='{' + ','.join(OPERATING_STATUS) + '}', choices=OPERATING_STATUS, type=lambda s: s.upper(), help="List load balancers according to their operating status." ) parser.add_argument( '--provider', metavar='', help="List load balancers according to their provider." ) parser.add_argument( '--flavor', metavar='', help="List load balancers according to their flavor." ) parser.add_argument( '--availability-zone', metavar='', help="List load balancers according to their availability zone." ) _tag.add_tag_filtering_option_to_parser(parser, 'load balancer') return parser def take_action(self, parsed_args): columns = const.LOAD_BALANCER_COLUMNS attrs = v2_utils.get_loadbalancer_attrs(self.app.client_manager, parsed_args) data = self.app.client_manager.load_balancer.load_balancer_list( **attrs) return (columns, (utils.get_dict_properties( s, columns, formatters={}, ) for s in data['loadbalancers'])) class ShowLoadBalancer(command.ShowOne): """Show the details for a single load balancer""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'loadbalancer', metavar='', help="Name or UUID of the load balancer." ) return parser def take_action(self, parsed_args): rows = const.LOAD_BALANCER_ROWS data = None if uuidutils.is_uuid_like(parsed_args.loadbalancer): try: data = ( self.app.client_manager.load_balancer.load_balancer_show( lb_id=parsed_args.loadbalancer)) except exceptions.NotFound: pass if data is None: attrs = v2_utils.get_loadbalancer_attrs( self.app.client_manager, parsed_args) lb_id = attrs.pop('loadbalancer_id') data = self.app.client_manager.load_balancer.load_balancer_show( lb_id=lb_id) # Handle older API versions that did not have the vip_vnic_type if not data.get('vip_vnic_type', False): data['vip_vnic_type'] = 'normal' formatters = { 'listeners': v2_utils.format_list, 'pools': v2_utils.format_list, 'l7policies': v2_utils.format_list, 'tags': v2_utils.format_list_flat } return (rows, (utils.get_dict_properties( data, rows, formatters=formatters))) class SetLoadBalancer(command.Command): """Update a load balancer""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'loadbalancer', metavar='', help='Name or UUID of the load balancer to update.' ) parser.add_argument( '--name', metavar='', help="Set load balancer name." ) parser.add_argument( '--description', metavar='', help="Set load balancer description." ) parser.add_argument( '--vip-qos-policy-id', metavar='', help="Set QoS policy ID for VIP port. Unset with 'None'.", ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=None, help="Enable load balancer." ) admin_group.add_argument( '--disable', action='store_true', default=None, help="Disable load balancer." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) _tag.add_tag_option_to_parser_for_set(parser, 'load balancer') return parser def take_action(self, parsed_args): attrs = v2_utils.get_loadbalancer_attrs(self.app.client_manager, parsed_args) lb_id = attrs.pop('loadbalancer_id') v2_utils.set_tags_for_set( self.app.client_manager.load_balancer.load_balancer_show, lb_id, attrs, clear_tags=parsed_args.no_tag) body = {'loadbalancer': attrs} self.app.client_manager.load_balancer.load_balancer_set( lb_id, json=body) if parsed_args.wait: v2_utils.wait_for_active( status_f=(self.app.client_manager.load_balancer. load_balancer_show), res_id=lb_id ) class UnsetLoadBalancer(command.Command): """Clear load balancer settings""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'loadbalancer', metavar='', help='Name or UUID of the load balancer to update.' ) parser.add_argument( '--name', action='store_true', help="Clear the load balancer name." ) parser.add_argument( '--description', action='store_true', help="Clear the load balancer description." ) parser.add_argument( '--vip-qos-policy-id', action='store_true', help="Clear the load balancer QoS policy.", ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) _tag.add_tag_option_to_parser_for_unset(parser, 'load balancer') return parser def take_action(self, parsed_args): unset_args = v2_utils.get_unsets(parsed_args) if not unset_args and not parsed_args.all_tag: return lb_id = v2_utils.get_resource_id( self.app.client_manager.load_balancer.load_balancer_list, 'loadbalancers', parsed_args.loadbalancer) v2_utils.set_tags_for_unset( self.app.client_manager.load_balancer.load_balancer_show, lb_id, unset_args, clear_tags=parsed_args.all_tag) body = {'loadbalancer': unset_args} self.app.client_manager.load_balancer.load_balancer_set( lb_id, json=body) if parsed_args.wait: v2_utils.wait_for_active( status_f=(self.app.client_manager.load_balancer. load_balancer_show), res_id=lb_id ) class ShowLoadBalancerStats(command.ShowOne): """Shows the current statistics for a load balancer""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'loadbalancer', metavar='', help="Name or UUID of the load balancer." ) return parser def take_action(self, parsed_args): rows = const.LOAD_BALANCER_STATS_ROWS attrs = v2_utils.get_loadbalancer_attrs(self.app.client_manager, parsed_args) lb_id = attrs.pop('loadbalancer_id') data = self.app.client_manager.load_balancer.load_balancer_stats_show( lb_id=lb_id ) return (rows, (utils.get_dict_properties( data['stats'], rows, formatters={}))) class ShowLoadBalancerStatus(command.Command): """Display load balancer status tree in json format""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'loadbalancer', metavar='', help="Name or UUID of the load balancer." ) return parser def take_action(self, parsed_args): attrs = v2_utils.get_loadbalancer_attrs(self.app.client_manager, parsed_args) lb_id = attrs.pop('loadbalancer_id') data = self.app.client_manager.load_balancer.load_balancer_status_show( lb_id=lb_id ) res = data.get('statuses', {}) print(jsonutils.dumps(res, indent=4)) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/osc/v2/member.py0000664000175000017500000003361400000000000023500 0ustar00zuulzuul00000000000000# Copyright 2019 Red Hat, Inc. All rights reserved. # # 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. # """Member action implementation""" import functools from cliff import lister from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from osc_lib.utils import tags as _tag from oslo_utils import uuidutils from octaviaclient.osc.v2 import constants as const from octaviaclient.osc.v2 import utils as v2_utils from octaviaclient.osc.v2 import validate class ListMember(lister.Lister): """List members in a pool""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'pool', metavar='', help="Pool name or ID to list the members of." ) _tag.add_tag_filtering_option_to_parser(parser, 'member') return parser def take_action(self, parsed_args): columns = const.MEMBER_COLUMNS attrs = v2_utils.get_member_attrs(self.app.client_manager, parsed_args) data = self.app.client_manager.load_balancer.member_list( **attrs) return (columns, (utils.get_dict_properties( s, columns, formatters={}, ) for s in data['members'])) class ShowMember(command.ShowOne): """Shows details of a single Member""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'pool', metavar='', help='Pool name or ID to show the members of.' ) parser.add_argument( 'member', metavar='', help="Name or ID of the member to show." ) return parser def take_action(self, parsed_args): rows = const.MEMBER_ROWS data = None if (uuidutils.is_uuid_like(parsed_args.pool) and uuidutils.is_uuid_like(parsed_args.member)): try: data = self.app.client_manager.load_balancer.member_show( pool_id=parsed_args.pool, member_id=parsed_args.member) except exceptions.NotFound: pass if data is None: attrs = v2_utils.get_member_attrs(self.app.client_manager, parsed_args) member_id = attrs.pop('member_id') pool_id = attrs.pop('pool_id') data = self.app.client_manager.load_balancer.member_show( pool_id=pool_id, member_id=member_id) formatters = {'tags': v2_utils.format_list_flat} return (rows, (utils.get_dict_properties( data, rows, formatters=formatters))) class CreateMember(command.ShowOne): """Creating a member in a pool""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'pool', metavar='', help="ID or name of the pool to create the member for." ) parser.add_argument( '--name', metavar='', help="Name of the member." ) backup = parser.add_mutually_exclusive_group() backup.add_argument( '--disable-backup', action='store_true', default=None, help="Disable member backup (default)." ) backup.add_argument( '--enable-backup', action='store_true', default=None, help="Enable member backup." ) parser.add_argument( '--weight', metavar='', type=int, help="The weight of a member determines the portion of requests " "or connections it services compared to the other members of " "the pool." ) parser.add_argument( '--address', metavar='', help="The IP address of the backend member server.", required=True ) parser.add_argument( '--subnet-id', metavar='', help="The subnet ID the member service is accessible from." ) parser.add_argument( '--protocol-port', metavar='', type=int, help="The protocol port number the backend member server is " "listening on.", required=True ) parser.add_argument( '--monitor-port', metavar='', type=int, help="An alternate protocol port used for health monitoring a " "backend member.", ) parser.add_argument( '--monitor-address', metavar='', help="An alternate IP address used for health monitoring a " "backend member." ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=None, help="Enable member (default)." ) admin_group.add_argument( '--disable', action='store_true', default=None, help="Disable member." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) _tag.add_tag_option_to_parser_for_create( parser, 'member') return parser def take_action(self, parsed_args): rows = const.MEMBER_ROWS attrs = v2_utils.get_member_attrs(self.app.client_manager, parsed_args) validate.check_member_attrs(attrs) pool_id = attrs.pop('pool_id') body = {"member": attrs} data = self.app.client_manager.load_balancer.member_create( pool_id=pool_id, json=body ) if parsed_args.wait: pool = self.app.client_manager.load_balancer.pool_show(pool_id) v2_utils.wait_for_active( status_f=(self.app.client_manager.load_balancer. load_balancer_show), res_id=pool['loadbalancers'][0]['id'] ) data = { 'member': ( self.app.client_manager.load_balancer.member_show( pool_id, data['member']['id'])) } formatters = {'tags': v2_utils.format_list_flat} return (rows, (utils.get_dict_properties( data['member'], rows, formatters=formatters))) class SetMember(command.Command): """Update a member""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'pool', metavar='', help="Pool that the member to update belongs to (name or ID)." ) parser.add_argument( 'member', metavar='', help="Name or ID of the member to update." ) parser.add_argument( '--name', metavar='', help="Set the name of the member." ) backup = parser.add_mutually_exclusive_group() backup.add_argument( '--disable-backup', action='store_true', default=None, help="Disable member backup (default)." ) backup.add_argument( '--enable-backup', action='store_true', default=None, help="Enable member backup." ) parser.add_argument( '--weight', metavar='', type=int, help="Set the weight of member in the pool." ) parser.add_argument( '--monitor-port', metavar='', type=int, help="An alternate protocol port used for health monitoring a " "backend member.", ) parser.add_argument( '--monitor-address', metavar='', help="An alternate IP address used for health monitoring a " "backend member." ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=None, help="Set the admin_state_up to True." ) admin_group.add_argument( '--disable', action='store_true', default=None, help="Set the admin_state_up to False.") parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) _tag.add_tag_option_to_parser_for_set(parser, 'member') return parser def take_action(self, parsed_args): attrs = v2_utils.get_member_attrs(self.app.client_manager, parsed_args) validate.check_member_attrs(attrs) pool_id = attrs.pop('pool_id') member_id = attrs.pop('member_id') member_show = functools.partial( self.app.client_manager.load_balancer.member_show, pool_id ) v2_utils.set_tags_for_set( member_show, member_id, attrs, clear_tags=parsed_args.no_tag) post_data = {"member": attrs} self.app.client_manager.load_balancer.member_set( pool_id=pool_id, member_id=member_id, json=post_data ) if parsed_args.wait: v2_utils.wait_for_active( status_f=member_show, res_id=member_id ) class DeleteMember(command.Command): """Delete a member from a pool """ def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'pool', metavar='', help="Pool name or ID to delete the member from." ) parser.add_argument( 'member', metavar='', help="Name or ID of the member to be deleted." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) return parser def take_action(self, parsed_args): attrs = v2_utils.get_member_attrs(self.app.client_manager, parsed_args) id = attrs.pop('member_id') pool_id = attrs.pop('pool_id') self.app.client_manager.load_balancer.member_delete( pool_id=pool_id, member_id=id ) if parsed_args.wait: member_show = functools.partial( self.app.client_manager.load_balancer.member_show, pool_id ) v2_utils.wait_for_delete( status_f=member_show, res_id=id ) class UnsetMember(command.Command): """Clear member settings""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'pool', metavar='', help="Pool that the member to update belongs to (name or ID)." ) parser.add_argument( 'member', metavar="", help="Member to modify (name or ID)." ) parser.add_argument( '--backup', action='store_true', help="Clear the backup member flag." ) parser.add_argument( '--monitor-address', action='store_true', help="Clear the member monitor address." ) parser.add_argument( '--monitor-port', action='store_true', help="Clear the member monitor port." ) parser.add_argument( '--name', action='store_true', help="Clear the member name." ) parser.add_argument( '--weight', action='store_true', help="Reset the member weight to the API default." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) _tag.add_tag_option_to_parser_for_unset(parser, 'member') return parser def take_action(self, parsed_args): unset_args = v2_utils.get_unsets(parsed_args) if not unset_args and not parsed_args.all_tag: return pool_id = v2_utils.get_resource_id( self.app.client_manager.load_balancer.pool_list, 'pools', parsed_args.pool) member_show = functools.partial( self.app.client_manager.load_balancer.member_show, pool_id ) member_dict = {'pool_id': pool_id, 'member_id': parsed_args.member} member_id = v2_utils.get_resource_id( self.app.client_manager.load_balancer.member_list, 'members', member_dict) v2_utils.set_tags_for_unset( member_show, member_id, unset_args, clear_tags=parsed_args.all_tag) body = {'member': unset_args} self.app.client_manager.load_balancer.member_set( pool_id=pool_id, member_id=member_id, json=body) if parsed_args.wait: v2_utils.wait_for_active( status_f=member_show, res_id=member_id ) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/osc/v2/pool.py0000664000175000017500000004246000000000000023201 0ustar00zuulzuul00000000000000# Copyright 2017 GoDaddy # Copyright 2019 Red Hat, Inc. All rights reserved. # 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. # """Pool action implementation""" from cliff import lister from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from osc_lib.utils import tags as _tag from oslo_utils import uuidutils from octaviaclient.osc.v2 import constants as const from octaviaclient.osc.v2 import utils as v2_utils PROTOCOL_CHOICES = ['TCP', 'HTTP', 'HTTPS', 'PROXY', 'PROXYV2', 'UDP', 'SCTP'] ALGORITHM_CHOICES = ['SOURCE_IP', 'ROUND_ROBIN', 'LEAST_CONNECTIONS', 'SOURCE_IP_PORT'] class CreatePool(command.ShowOne): """Create a pool""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( '--name', metavar='', help="Set pool name." ) parser.add_argument( '--description', metavar='', help="Set pool description." ) parser.add_argument( '--protocol', metavar='{' + ','.join(PROTOCOL_CHOICES) + '}', required=True, choices=PROTOCOL_CHOICES, type=lambda s: s.upper(), # case insensitive help="Set the pool protocol." ) parent_group = parser.add_mutually_exclusive_group(required=True) parent_group.add_argument( '--listener', metavar='', help="Listener to add the pool to (name or ID)." ) parent_group.add_argument( '--loadbalancer', metavar='', help="Load balancer to add the pool to (name or ID)." ) parser.add_argument( '--session-persistence', metavar='', help="Set the session persistence for the listener (key=value)." ) parser.add_argument( '--lb-algorithm', metavar='{' + ','.join(ALGORITHM_CHOICES) + '}', required=True, choices=ALGORITHM_CHOICES, type=lambda s: s.upper(), # case insensitive help="Load balancing algorithm to use." ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=True, help="Enable pool (default)." ) admin_group.add_argument( '--disable', action='store_true', default=None, help="Disable pool." ) parser.add_argument( '--tls-container-ref', metavar='', help="The reference to the key manager service secrets container " "containing the certificate and key for ``tls_enabled`` " "pools to re-encrpt the traffic to backend member servers." ) parser.add_argument( '--ca-tls-container-ref', metavar='', help="The reference to the key manager service secrets container " "containing the CA certificate for ``tls_enabled`` pools " "to check the backend member servers certificates." ) parser.add_argument( '--crl-container-ref', metavar='', help="The reference to the key manager service secrets container " "containting the CA revocation list file for ``tls_enabled`` " "pools to validate the backend member servers certificates." ) tls_enable = parser.add_mutually_exclusive_group() tls_enable.add_argument( '--enable-tls', action='store_true', default=None, help="Enable backend member re-encryption." ) tls_enable.add_argument( '--disable-tls', action='store_true', default=None, help="Disable backend member re-encryption." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) parser.add_argument( '--tls-ciphers', metavar='', help="Set the TLS ciphers to be used by the pool " "in OpenSSL cipher string format." ) parser.add_argument( '--tls-version', dest='tls_versions', metavar='', nargs='?', action='append', help="Set the TLS protocol version to be used " "by the pool (can be set multiple times)." ) parser.add_argument( '--alpn-protocol', dest='alpn_protocols', metavar='', nargs='?', action='append', help="Set the ALPN protocol to be used " "by the pool (can be set multiple times)." ) _tag.add_tag_option_to_parser_for_create( parser, 'pool') return parser def take_action(self, parsed_args): rows = const.POOL_ROWS attrs = v2_utils.get_pool_attrs(self.app.client_manager, parsed_args) body = {"pool": attrs} data = self.app.client_manager.load_balancer.pool_create( json=body) if parsed_args.wait: v2_utils.wait_for_active( status_f=(self.app.client_manager.load_balancer. load_balancer_show), res_id=data['pool']['loadbalancers'][0]['id'] ) data = { 'pool': ( self.app.client_manager.load_balancer.pool_show( data['pool']['id'])) } formatters = {'loadbalancers': v2_utils.format_list, 'members': v2_utils.format_list, 'listeners': v2_utils.format_list, 'session_persistence': v2_utils.format_hash, 'tags': v2_utils.format_list_flat} return (rows, (utils.get_dict_properties( data['pool'], rows, formatters=formatters, mixed_case_fields=['enable-tls']))) class DeletePool(command.Command): """Delete a pool""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'pool', metavar="", help="Pool to delete (name or ID)." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) return parser def take_action(self, parsed_args): attrs = v2_utils.get_pool_attrs(self.app.client_manager, parsed_args) pool_id = attrs.pop('pool_id') self.app.client_manager.load_balancer.pool_delete( pool_id=pool_id) if parsed_args.wait: v2_utils.wait_for_delete( status_f=self.app.client_manager.load_balancer.pool_show, res_id=pool_id ) class ListPool(lister.Lister): """List pools""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( '--loadbalancer', metavar='', help="Filter by load balancer (name or ID).", ) _tag.add_tag_filtering_option_to_parser(parser, 'pool') return parser def take_action(self, parsed_args): columns = const.POOL_COLUMNS attrs = v2_utils.get_pool_attrs(self.app.client_manager, parsed_args) data = self.app.client_manager.load_balancer.pool_list(**attrs) formatters = {'loadbalancers': v2_utils.format_list, 'members': v2_utils.format_list, 'listeners': v2_utils.format_list} return (columns, (utils.get_dict_properties( s, columns, formatters=formatters) for s in data['pools'])) class ShowPool(command.ShowOne): """Show the details of a single pool""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'pool', metavar='', help='Name or UUID of the pool.' ) return parser def take_action(self, parsed_args): rows = const.POOL_ROWS data = None if uuidutils.is_uuid_like(parsed_args.pool): try: data = self.app.client_manager.load_balancer.pool_show( pool_id=parsed_args.pool) except exceptions.NotFound: pass if data is None: attrs = v2_utils.get_pool_attrs(self.app.client_manager, parsed_args) pool_id = attrs.pop('pool_id') data = self.app.client_manager.load_balancer.pool_show( pool_id=pool_id, ) formatters = {'loadbalancers': v2_utils.format_list, 'members': v2_utils.format_list, 'listeners': v2_utils.format_list, 'session_persistence': v2_utils.format_hash, 'tags': v2_utils.format_list_flat} return (rows, (utils.get_dict_properties( data, rows, formatters=formatters, mixed_case_fields=['enable-tls']))) class SetPool(command.Command): """Update a pool""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'pool', metavar="", help="Pool to update (name or ID)." ) parser.add_argument( '--name', metavar='', help="Set the name of the pool." ) parser.add_argument( '--description', metavar='', help="Set the description of the pool." ) parser.add_argument( '--session-persistence', metavar='', help="Set the session persistence for the listener (key=value)." ) parser.add_argument( '--lb-algorithm', metavar='{' + ','.join(ALGORITHM_CHOICES) + '}', choices=ALGORITHM_CHOICES, type=lambda s: s.upper(), # case insensitive help="Set the load balancing algorithm to use." ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=None, help="Enable pool." ) admin_group.add_argument( '--disable', action='store_true', default=None, help="Disable pool." ) parser.add_argument( '--tls-container-ref', metavar='', help="The URI to the key manager service secrets container " "containing the certificate and key for TERMINATED_TLS " "pools to re-encrpt the traffic from TERMINATED_TLS " "listener to backend servers." ) parser.add_argument( '--ca-tls-container-ref', metavar='', help="The URI to the key manager service secrets container " "containing the CA certificate for TERMINATED_TLS listeners " "to check the backend servers certificates in ssl traffic." ) parser.add_argument( '--crl-container-ref', metavar='', help="The URI to the key manager service secrets container " "containting the CA revocation list file for TERMINATED_TLS " "listeners to valid the backend servers certificates in ssl " "traffic." ) tls_enable = parser.add_mutually_exclusive_group() tls_enable.add_argument( '--enable-tls', action='store_true', default=None, help="Enable backend associated members re-encryption." ) tls_enable.add_argument( '--disable-tls', action='store_true', default=None, help="disable backend associated members re-encryption." ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) parser.add_argument( '--tls-ciphers', metavar='', help="Set the TLS ciphers to be used by the pool " "in OpenSSL cipher string format." ) parser.add_argument( '--tls-version', dest='tls_versions', metavar='', nargs='?', action='append', help="Set the TLS protocol version to be used " "by the pool (can be set multiple times)." ) parser.add_argument( '--alpn-protocol', dest='alpn_protocols', metavar='', nargs='?', action='append', help="Set the ALPN protocol to be used " "by the pool (can be set multiple times)." ) _tag.add_tag_option_to_parser_for_set(parser, 'pool') return parser def take_action(self, parsed_args): attrs = v2_utils.get_pool_attrs(self.app.client_manager, parsed_args) pool_id = attrs.pop('pool_id') v2_utils.set_tags_for_set( self.app.client_manager.load_balancer.pool_show, pool_id, attrs, clear_tags=parsed_args.no_tag) body = {'pool': attrs} self.app.client_manager.load_balancer.pool_set( pool_id, json=body) if parsed_args.wait: v2_utils.wait_for_active( status_f=self.app.client_manager.load_balancer.pool_show, res_id=pool_id ) class UnsetPool(command.Command): """Clear pool settings""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'pool', metavar="", help="Pool to modify (name or ID)." ) parser.add_argument( '--name', action='store_true', help="Clear the pool name." ) parser.add_argument( '--description', action='store_true', help="Clear the description of this pool." ) parser.add_argument( '--ca-tls-container-ref', action='store_true', help="Clear the certificate authority certificate reference on " "this pool." ) parser.add_argument( '--crl-container-ref', action='store_true', help="Clear the certificate revocation list reference on " "this pool." ) parser.add_argument( '--session-persistence', action='store_true', help="Disables session persistence on the pool." ) parser.add_argument( '--tls-container-ref', action='store_true', help="Clear the certificate reference for this pool." ) parser.add_argument( '--tls-versions', action='store_true', help='Clear all TLS versions from the pool.', ) parser.add_argument( '--tls-ciphers', action='store_true', help='Clear all TLS ciphers from the pool.', ) parser.add_argument( '--wait', action='store_true', help='Wait for action to complete.', ) parser.add_argument( '--alpn-protocols', action='store_true', help="Clear all ALPN protocols from the pool." ) _tag.add_tag_option_to_parser_for_unset(parser, 'pool') return parser def take_action(self, parsed_args): unset_args = v2_utils.get_unsets(parsed_args) if not unset_args and not parsed_args.all_tag: return pool_id = v2_utils.get_resource_id( self.app.client_manager.load_balancer.pool_list, 'pools', parsed_args.pool) v2_utils.set_tags_for_unset( self.app.client_manager.load_balancer.pool_show, pool_id, unset_args, clear_tags=parsed_args.all_tag) body = {'pool': unset_args} self.app.client_manager.load_balancer.pool_set( pool_id, json=body) if parsed_args.wait: v2_utils.wait_for_active( status_f=self.app.client_manager.load_balancer.pool_show, res_id=pool_id ) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/osc/v2/provider.py0000664000175000017500000000644200000000000024062 0ustar00zuulzuul00000000000000# Copyright (c) 2018 China Telecom Corporation # All Rights Reserved. # # 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. """Octavia provider action implementation""" from cliff import lister from osc_lib import utils from octaviaclient.osc.v2 import constants as const from octaviaclient.osc.v2 import utils as v2_utils class ListProvider(lister.Lister): """List all providers""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) return parser def take_action(self, parsed_args): columns = const.PROVIDER_COLUMNS data = self.app.client_manager.load_balancer.provider_list() return (columns, (utils.get_dict_properties( s, columns, formatters={}, ) for s in data['providers'])) class ListProviderCapability(lister.Lister): """List specified provider driver's capabilities.""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'provider', metavar='', help="Name of the provider driver." ) type_group = parser.add_mutually_exclusive_group() type_group.add_argument( '--flavor', action='store_true', default=None, help="Get capabilities for flavor only." ) type_group.add_argument( '--availability-zone', action='store_true', default=None, help="Get capabilities for availability zone only." ) return parser def take_action(self, parsed_args): columns = const.PROVIDER_CAPABILITY_COLUMNS attrs = v2_utils.get_provider_attrs(parsed_args) provider = attrs.pop('provider_name') fetch_flavor = attrs.pop('flavor', False) fetch_az = attrs.pop('availability_zone', False) client = self.app.client_manager data = [] if not fetch_az: flavor_data = ( client.load_balancer. provider_flavor_capability_list(provider=provider)) for capability in flavor_data['flavor_capabilities']: capability['type'] = 'flavor' data.append(capability) if not fetch_flavor: az_data = ( client.load_balancer. provider_availability_zone_capability_list( provider=provider)) for capability in az_data['availability_zone_capabilities']: capability['type'] = 'availability_zone' data.append(capability) return (columns, (utils.get_dict_properties( s, columns, formatters={}, ) for s in data)) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/osc/v2/quota.py0000664000175000017500000002057500000000000023364 0ustar00zuulzuul00000000000000# Copyright 2019 Red Hat, Inc. All rights reserved. # # 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. # """Quota action implementation""" from cliff import lister from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from oslo_utils import uuidutils from octaviaclient.osc.v2 import constants as const from octaviaclient.osc.v2 import utils as v2_utils class ListQuota(lister.Lister): """List quotas""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( '--project', metavar='', help="Name or UUID of the project." ) return parser def take_action(self, parsed_args): columns = const.QUOTA_COLUMNS attrs = v2_utils.get_listener_attrs(self.app.client_manager, parsed_args) data = self.app.client_manager.load_balancer.quota_list(**attrs) formatters = {'quotas': v2_utils.format_list} return (columns, (utils.get_dict_properties(s, columns, formatters=formatters) for s in data['quotas'])) class ShowQuota(command.ShowOne): """Show the quota details for a project""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'project', metavar='', help="Name or UUID of the project." ) return parser def take_action(self, parsed_args): rows = const.QUOTA_ROWS data = None if uuidutils.is_uuid_like(parsed_args.project): try: data = self.app.client_manager.load_balancer.quota_show( project_id=parsed_args.project) except exceptions.NotFound: pass if data is None: attrs = v2_utils.get_quota_attrs(self.app.client_manager, parsed_args) project_id = attrs.pop('project_id') data = self.app.client_manager.load_balancer.quota_show( project_id=project_id ) return (rows, (utils.get_dict_properties(data, rows))) class ShowQuotaDefaults(command.ShowOne): """Show quota defaults""" def take_action(self, parsed_args): rows = const.QUOTA_ROWS data = self.app.client_manager.load_balancer.quota_defaults_show() return (rows, (utils.get_dict_properties(data['quota'], rows))) class SetQuota(command.ShowOne): """Update a quota""" @staticmethod def _check_attrs(attrs): args = ['health_monitor', 'listener', 'load_balancer', 'member', 'pool', 'l7policy', 'l7rule'] if not any(arg in attrs for arg in args): args = [arg.replace('_', '') for arg in args] msg = ('Missing required argument. Requires at least one of:%s' % ','.join((' --%s' % arg) for arg in args)) raise exceptions.CommandError(msg) def get_parser(self, prog_name): parser = super().get_parser(prog_name) quota_group = parser.add_argument_group( "Quota limits", description='At least one of the following arguments is required.' ) quota_group.add_argument( '--healthmonitor', dest='health_monitor', metavar='', help=('New value for the health monitor quota. Value -1 means ' 'unlimited.') ) quota_group.add_argument( '--listener', metavar='', help=('New value for the listener quota. Value -1 means ' 'unlimited.') ) quota_group.add_argument( '--loadbalancer', dest='load_balancer', metavar='', help=('New value for the load balancer quota limit. Value -1 ' 'means unlimited.') ) quota_group.add_argument( '--member', metavar='', help=('New value for the member quota limit. Value -1 means ' 'unlimited.') ) quota_group.add_argument( '--pool', metavar='', help=('New value for the pool quota limit. Value -1 means ' 'unlimited.') ) quota_group.add_argument( '--l7policy', metavar='', help=('New value for the l7policy quota limit. Value -1 means ' 'unlimited.') ) quota_group.add_argument( '--l7rule', metavar='', help=('New value for the l7rule quota limit. Value -1 means ' 'unlimited.') ) parser.add_argument( 'project', metavar='', help="Name or UUID of the project." ) return parser def take_action(self, parsed_args): rows = const.QUOTA_ROWS attrs = v2_utils.get_quota_attrs(self.app.client_manager, parsed_args) self._check_attrs(attrs) project_id = attrs.pop('project_id') body = {'quota': attrs} data = self.app.client_manager.load_balancer.quota_set(project_id, json=body) return (rows, (utils.get_dict_properties(data['quota'], rows))) class ResetQuota(command.Command): """Resets quotas to default quotas""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'project', metavar="", help="Project to reset quotas (name or ID)." ) return parser def take_action(self, parsed_args): attrs = v2_utils.get_quota_attrs(self.app.client_manager, parsed_args) project_id = attrs.pop('project_id') self.app.client_manager.load_balancer.quota_reset( project_id=project_id) class UnsetQuota(command.Command): """Clear quota settings""" def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'project', metavar='', help="Name or UUID of the project." ) parser.add_argument( '--loadbalancer', action='store_true', help="Reset the load balancer quota to the default." ) parser.add_argument( '--listener', action='store_true', help="Reset the listener quota to the default." ) parser.add_argument( '--pool', action='store_true', help="Reset the pool quota to the default." ) parser.add_argument( '--member', action='store_true', help="Reset the member quota to the default." ) parser.add_argument( '--healthmonitor', action='store_true', help="Reset the health monitor quota to the default." ) parser.add_argument( '--l7policy', action='store_true', help="Reset the l7policy quota to the default." ) parser.add_argument( '--l7rule', action='store_true', help="Reset the l7rule quota to the default." ) return parser def take_action(self, parsed_args): unset_args = v2_utils.get_unsets(parsed_args) if not unset_args: return project_id = v2_utils.get_resource_id( self.app.client_manager.identity, 'project', parsed_args.project) body = {'quota': unset_args} self.app.client_manager.load_balancer.quota_set( project_id, json=body) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/osc/v2/utils.py0000664000175000017500000006006300000000000023367 0ustar00zuulzuul00000000000000# Copyright 2017 GoDaddy # 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. import functools import ipaddress from openstackclient.identity import common as identity_common from osc_lib import exceptions as osc_exc from osc_lib import utils from oslo_utils import uuidutils from octaviaclient.api import exceptions from octaviaclient.osc.v2 import constants def _map_attrs(args, source_attr_map): res = {} for k, v in args.items(): if (v is None) or (k not in source_attr_map): continue source_val = source_attr_map[k] # Attributes with 2 values map directly to a callable if len(source_val) == 2: res[source_val[0]] = source_val[1](v) # Attributes with 3 values map directly to a resource elif len(source_val) == 3: if not isinstance(v, list): res[source_val[0]] = get_resource_id( source_val[2], source_val[1], v, ) else: res[source_val[0]] = [get_resource_id( source_val[2], source_val[1], x, ) for x in v] # Attributes with 4 values map to a resource with a parent elif len(source_val) == 4: parent = source_attr_map[source_val[2]] parent_id = get_resource_id( parent[2], parent[1], args[source_val[2]], ) child = source_val res[child[0]] = get_resource_id( child[3], child[1], {child[0]: str(v), parent[0]: str(parent_id)}, ) return res def _find_resource(list_funct, resource_name, root_tag, name, parent=None): """Search for a resource by name and ID. This function will search for a resource by both the name and ID, returning the resource once it finds a match. If no match is found, an exception will be raised. :param list_funct: The resource list method to call during searches. :param resource_name: The name of the resource type we are searching for. :param root_tag: The root tag of the resource returned from the API. :param name: The value we are searching for, a resource name or ID. :param parent: The parent resource ID, when required. :return: The resource found for the name or ID. :raises osc_exc.CommandError: If more than one match or none are found. """ if parent: parent_args = [parent] else: parent_args = [] # Optimize the API call order if we got a UUID-like name or not if uuidutils.is_uuid_like(name): # Try by ID first resource = list_funct(*parent_args, id=name)[root_tag] if len(resource) == 1: return resource[0] # Try by name next resource = list_funct(*parent_args, name=name)[root_tag] if len(resource) == 1: return resource[0] if len(resource) > 1: msg = ("{0} {1} found with name or ID of {2}. Please try " "again with UUID".format(len(resource), resource_name, name)) raise osc_exc.CommandError(msg) else: # Try by name first resource = list_funct(*parent_args, name=name)[root_tag] if len(resource) == 1: return resource[0] if len(resource) > 1: msg = ("{0} {1} found with name or ID of {2}. Please try " "again with UUID".format(len(resource), resource_name, name)) raise osc_exc.CommandError(msg) # Try by ID next resource = list_funct(*parent_args, id=name)[root_tag] if len(resource) == 1: return resource[0] # We didn't find what we were looking for, raise a consistent error. msg = "Unable to locate {0} in {1}".format(name, resource_name) raise osc_exc.CommandError(msg) def get_resource_id(resource, resource_name, name): """Converts a resource name into a UUID for consumption for the API :param callable resource: A client_manager callable :param resource_name: The resource key name for the dictonary returned :param name: The name of the resource to convert to UUID :return: The UUID of the found resource """ try: # Allow None as a value if resource_name in ('policies',): if name.lower() in ('none', 'null', 'void'): return None primary_key = 'id' # Availability-zones don't have an id value if resource_name == 'availability_zones': primary_key = 'name' # Projects can be non-uuid so we need to account for this if resource_name == 'project': if name != 'non-uuid': project_id = identity_common.find_project( resource, name ).id return project_id return 'non-uuid' if resource_name == 'members': member = _find_resource(resource, resource_name, 'members', name['member_id'], parent=name['pool_id']) return member.get('id') if resource_name == 'l7rules': l7rule = _find_resource(resource, resource_name, 'rules', name['l7rule_id'], parent=name['l7policy_id']) return l7rule.get('id') resource = _find_resource(resource, resource_name, resource_name, name) return resource.get(primary_key) except IndexError as e: msg = "Unable to locate {0} in {1}".format(name, resource_name) raise osc_exc.CommandError(msg) from e def add_tags_attr_map(attr_map): tags_attr_map = { 'tags': ('tags', list), 'any_tags': ('tags-any', list), 'not_tags': ('not-tags', list), 'not_any_tags': ('not-tags-any', list), } attr_map.update(tags_attr_map) def validate_vip_dict(vip_dict, client_manager): # We have validation in two places -- _map_attrs checks sub-resources, and # later _check_attrs does further api-specific validation. We need both for # additional vips, so we may as well just do both here while we're at it. if 'subnet_id' not in vip_dict: raise osc_exc.CommandError( 'Additional VIPs must include a subnet-id.') subnet_id = get_resource_id(client_manager.neutronclient.list_subnets, 'subnets', vip_dict['subnet_id']) vip_dict['subnet_id'] = subnet_id if 'ip_address' in vip_dict: try: ipaddress.ip_address(vip_dict['ip_address']) except ValueError as e: raise osc_exc.CommandError(str(e)) def handle_additional_vips(vips, client_manager): additional_vips = [] for vip in vips: vip_dict = {} parts = vip.split(',') for part in parts: k, v = part.split('=') vip_dict[k.replace('-', '_')] = v validate_vip_dict(vip_dict, client_manager) additional_vips.append(vip_dict) return additional_vips def get_loadbalancer_attrs(client_manager, parsed_args): attr_map = { 'name': ('name', str), 'description': ('description', str), 'protocol': ('protocol', str), 'loadbalancer': ( 'loadbalancer_id', 'loadbalancers', client_manager.load_balancer.load_balancer_list ), 'connection_limit': ('connection_limit', str), 'protocol_port': ('protocol_port', int), 'project': ( 'project_id', 'project', client_manager.identity ), 'vip_address': ('vip_address', str), 'vip_port_id': ( 'vip_port_id', 'ports', client_manager.neutronclient.list_ports ), 'vip_subnet_id': ( 'vip_subnet_id', 'subnets', client_manager.neutronclient.list_subnets ), 'vip_network_id': ( 'vip_network_id', 'networks', client_manager.neutronclient.list_networks ), 'vip_qos_policy_id': ( 'vip_qos_policy_id', 'policies', client_manager.neutronclient.list_qos_policies, ), 'vip_vnic_type': ('vip_vnic_type', str), 'enable': ('admin_state_up', lambda x: True), 'disable': ('admin_state_up', lambda x: False), 'cascade': ('cascade', lambda x: True), 'provisioning_status': ('provisioning_status', str), 'operating_status': ('operating_status', str), 'provider': ('provider', str), 'flavor': ( 'flavor_id', 'flavors', client_manager.load_balancer.flavor_list ), 'availability_zone': ('availability_zone', str), 'additional_vip': ( 'additional_vips', functools.partial( handle_additional_vips, client_manager=client_manager) ), } add_tags_attr_map(attr_map) _attrs = vars(parsed_args) attrs = _map_attrs(_attrs, attr_map) return attrs def get_listener_attrs(client_manager, parsed_args): attr_map = { 'name': ('name', str), 'description': ('description', str), 'protocol': ('protocol', str), 'listener': ( 'listener_id', 'listeners', client_manager.load_balancer.listener_list ), 'loadbalancer': ( 'loadbalancer_id', 'loadbalancers', client_manager.load_balancer.load_balancer_list ), 'connection_limit': ('connection_limit', str), 'protocol_port': ('protocol_port', int), 'default_pool': ( 'default_pool_id', 'pools', client_manager.load_balancer.pool_list ), 'project': ( 'project_id', 'project', client_manager.identity ), 'enable': ('admin_state_up', lambda x: True), 'disable': ('admin_state_up', lambda x: False), 'insert_headers': ('insert_headers', _format_kv), 'default_tls_container_ref': ('default_tls_container_ref', str), 'sni_container_refs': ('sni_container_refs', list), 'timeout_client_data': ('timeout_client_data', int), 'timeout_member_connect': ('timeout_member_connect', int), 'timeout_member_data': ('timeout_member_data', int), 'timeout_tcp_inspect': ('timeout_tcp_inspect', int), 'client_ca_tls_container_ref': ('client_ca_tls_container_ref', _format_str_if_need_treat_unset), 'client_authentication': ('client_authentication', str), 'client_crl_container_ref': ('client_crl_container_ref', _format_str_if_need_treat_unset), 'allowed_cidrs': ('allowed_cidrs', list), 'tls_ciphers': ('tls_ciphers', str), 'tls_versions': ('tls_versions', list), 'alpn_protocols': ('alpn_protocols', list), 'hsts_max_age': ('hsts_max_age', int), 'hsts_include_subdomains': ('hsts_include_subdomains', bool), 'hsts_preload': ('hsts_preload', bool), } add_tags_attr_map(attr_map) _attrs = vars(parsed_args) attrs = _map_attrs(_attrs, attr_map) return attrs def get_pool_attrs(client_manager, parsed_args): attr_map = { 'name': ('name', str), 'description': ('description', str), 'protocol': ('protocol', str), 'pool': ( 'pool_id', 'pools', client_manager.load_balancer.pool_list ), 'loadbalancer': ( 'loadbalancer_id', 'loadbalancers', client_manager.load_balancer.load_balancer_list ), 'lb_algorithm': ('lb_algorithm', str), 'listener': ( 'listener_id', 'listeners', client_manager.load_balancer.listener_list ), 'project': ( 'project_id', 'project', client_manager.identity ), 'session_persistence': ('session_persistence', _format_kv), 'enable': ('admin_state_up', lambda x: True), 'disable': ('admin_state_up', lambda x: False), 'tls_container_ref': ('tls_container_ref', _format_str_if_need_treat_unset), 'ca_tls_container_ref': ('ca_tls_container_ref', _format_str_if_need_treat_unset), 'crl_container_ref': ('crl_container_ref', _format_str_if_need_treat_unset), 'enable_tls': ('tls_enabled', lambda x: True), 'disable_tls': ('tls_enabled', lambda x: False), 'tls_ciphers': ('tls_ciphers', str), 'tls_versions': ('tls_versions', list), 'alpn_protocols': ('alpn_protocols', list), } add_tags_attr_map(attr_map) _attrs = vars(parsed_args) attrs = _map_attrs(_attrs, attr_map) return attrs def get_member_attrs(client_manager, parsed_args): attr_map = { 'name': ('name', str), 'address': ('address', str), 'protocol_port': ('protocol_port', int), 'project_id': ( 'project_id', 'project', client_manager.identity ), 'pool': ( 'pool_id', 'pools', client_manager.load_balancer.pool_list ), 'member': ( 'member_id', 'members', 'pool', client_manager.load_balancer.member_list ), 'enable_backup': ('backup', lambda x: True), 'disable_backup': ('backup', lambda x: False), 'weight': ('weight', int), 'subnet_id': ( 'subnet_id', 'subnets', client_manager.neutronclient.list_subnets ), 'monitor_port': ('monitor_port', int), 'monitor_address': ('monitor_address', str), 'enable': ('admin_state_up', lambda x: True), 'disable': ('admin_state_up', lambda x: False), } add_tags_attr_map(attr_map) _attrs = vars(parsed_args) attrs = _map_attrs(_attrs, attr_map) return attrs def get_l7policy_attrs(client_manager, parsed_args): attr_map = { 'name': ('name', str), 'description': ('description', str), 'redirect_url': ('redirect_url', str), 'redirect_http_code': ('redirect_http_code', int), 'redirect_prefix': ('redirect_prefix', str), 'l7policy': ( 'l7policy_id', 'l7policies', client_manager.load_balancer.l7policy_list ), 'redirect_pool': ( 'redirect_pool_id', 'pools', client_manager.load_balancer.pool_list ), 'listener': ( 'listener_id', 'listeners', client_manager.load_balancer.listener_list ), 'action': ('action', str), 'project': ( 'project_id', 'projects', client_manager.identity ), 'position': ('position', int), 'enable': ('admin_state_up', lambda x: True), 'disable': ('admin_state_up', lambda x: False) } add_tags_attr_map(attr_map) _attrs = vars(parsed_args) attrs = _map_attrs(_attrs, attr_map) return attrs def get_l7rule_attrs(client_manager, parsed_args): attr_map = { 'action': ('action', str), 'project': ( 'project_id', 'project', client_manager.identity ), 'invert': ('invert', lambda x: True), 'l7rule': ( 'l7rule_id', 'l7rules', 'l7policy', # parent attr client_manager.load_balancer.l7rule_list ), 'l7policy': ( 'l7policy_id', 'l7policies', client_manager.load_balancer.l7policy_list ), 'value': ('value', str), 'key': ('key', str), 'type': ('type', str), 'compare_type': ('compare_type', str), 'enable': ('admin_state_up', lambda x: True), 'disable': ('admin_state_up', lambda x: False) } add_tags_attr_map(attr_map) _attrs = vars(parsed_args) attrs = _map_attrs(_attrs, attr_map) return attrs def get_health_monitor_attrs(client_manager, parsed_args): attr_map = { 'health_monitor': ( 'health_monitor_id', 'healthmonitors', client_manager.load_balancer.health_monitor_list ), 'project': ( 'project_id', 'project', client_manager.identity ), 'name': ('name', str), 'pool': ( 'pool_id', 'pools', client_manager.load_balancer.pool_list ), 'delay': ('delay', int), 'expected_codes': ('expected_codes', str), 'max_retries': ('max_retries', int), 'http_method': ('http_method', str), 'type': ('type', str), 'timeout': ('timeout', int), 'max_retries_down': ('max_retries_down', int), 'url_path': ('url_path', str), 'enable': ('admin_state_up', lambda x: True), 'disable': ('admin_state_up', lambda x: False), 'http_version': ('http_version', float), 'domain_name': ('domain_name', str) } add_tags_attr_map(attr_map) _attrs = vars(parsed_args) attrs = _map_attrs(_attrs, attr_map) return attrs def get_quota_attrs(client_manager, parsed_args): attr_map = { 'health_monitor': ('health_monitor', int), 'listener': ('listener', int), 'load_balancer': ('load_balancer', int), 'member': ('member', int), 'pool': ('pool', int), 'l7policy': ('l7policy', int), 'l7rule': ('l7rule', int), 'project': ( 'project_id', 'project', client_manager.identity ), } _attrs = vars(parsed_args) attrs = _map_attrs(_attrs, attr_map) return attrs def get_amphora_attrs(client_manager, parsed_args): attr_map = { 'amphora_id': ( 'amphora_id', 'amphorae', client_manager.load_balancer.amphora_list, ), 'loadbalancer': ( 'loadbalancer_id', 'loadbalancers', client_manager.load_balancer.load_balancer_list, ), 'compute_id': ('compute_id', str), 'role': ('role', str), 'status': ('status', str), } return _map_attrs(vars(parsed_args), attr_map) def get_provider_attrs(parsed_args): attr_map = { 'provider': ('provider_name', str), 'description': ('description', str), 'flavor': ('flavor', bool), 'availability_zone': ('availability_zone', bool), } return _map_attrs(vars(parsed_args), attr_map) def get_flavor_attrs(client_manager, parsed_args): attr_map = { 'name': ('name', str), 'flavor': ( 'flavor_id', 'flavors', client_manager.load_balancer.flavor_list, ), 'flavorprofile': ( 'flavor_profile_id', 'flavorprofiles', client_manager.load_balancer.flavorprofile_list, ), 'enable': ('enabled', lambda x: True), 'disable': ('enabled', lambda x: False), 'description': ('description', str), } _attrs = vars(parsed_args) attrs = _map_attrs(_attrs, attr_map) return attrs def get_flavorprofile_attrs(client_manager, parsed_args): attr_map = { 'name': ('name', str), 'flavorprofile': ( 'flavorprofile_id', 'flavorprofiles', client_manager.load_balancer.flavorprofile_list, ), 'provider': ('provider_name', str), 'flavor_data': ('flavor_data', str), } _attrs = vars(parsed_args) attrs = _map_attrs(_attrs, attr_map) return attrs def get_availabilityzone_attrs(client_manager, parsed_args): attr_map = { 'name': ('name', str), 'availabilityzone': ( 'availabilityzone_name', 'availability_zones', client_manager.load_balancer.availabilityzone_list, ), 'availabilityzoneprofile': ( 'availability_zone_profile_id', 'availability_zone_profiles', client_manager.load_balancer.availabilityzoneprofile_list, ), 'enable': ('enabled', lambda x: True), 'disable': ('enabled', lambda x: False), 'description': ('description', str), } _attrs = vars(parsed_args) attrs = _map_attrs(_attrs, attr_map) return attrs def get_availabilityzoneprofile_attrs(client_manager, parsed_args): attr_map = { 'name': ('name', str), 'availabilityzoneprofile': ( 'availability_zone_profile_id', 'availability_zone_profiles', client_manager.load_balancer.availabilityzoneprofile_list, ), 'provider': ('provider_name', str), 'availability_zone_data': ('availability_zone_data', str), } _attrs = vars(parsed_args) attrs = _map_attrs(_attrs, attr_map) return attrs def format_list(data): return '\n'.join(i['id'] for i in data) def format_list_flat(data): return '\n'.join(i for i in data) def format_hash(data): if data: return '\n'.join('{}={}'.format(k, v) for k, v in data.items()) return None def _format_kv(data): formatted_kv = {} values = data.split(',') for value in values: k, v = value.split('=') formatted_kv[k] = v return formatted_kv def _format_str_if_need_treat_unset(data): if data.lower() in ('none', 'null', 'void'): return None return str(data) def get_unsets(parsed_args): unsets = {} for arg, value in vars(parsed_args).items(): if value and arg == 'tags': unsets[arg] = value elif value is True and arg not in ('wait', 'all_tag'): unsets[arg] = None return unsets class _Munch(dict): __getattr__ = dict.get def wait_for_active(status_f, res_id): success = utils.wait_for_status( status_f=lambda x: _Munch(status_f(x)), res_id=res_id, status_field=constants.PROVISIONING_STATUS, sleep_time=3 ) if not success: raise exceptions.OctaviaClientException( code="n/a", message="The resource did not successfully reach ACTIVE status.") def wait_for_delete(status_f, res_id, status_field=constants.PROVISIONING_STATUS): class Getter(object): @staticmethod def get(id): return _Munch(status_f(id)) try: success = utils.wait_for_delete( manager=Getter, res_id=res_id, status_field=status_field, sleep_time=3 ) if not success: raise exceptions.OctaviaClientException( code="n/a", message="The resource could not be successfully deleted.") except exceptions.OctaviaClientException as e: if e.code != 404: raise def set_tags_for_set(resource_get, resource_id, attrs, clear_tags=False): if attrs.get('tags'): resource = resource_get(resource_id) tags = set([] if clear_tags else resource['tags']) tags |= set(attrs['tags']) attrs['tags'] = list(tags) elif clear_tags: attrs['tags'] = [] def set_tags_for_unset(resource_get, resource_id, attrs, clear_tags=False): if clear_tags: attrs['tags'] = [] elif attrs.get('tags'): resource = resource_get(resource_id) tags = set(resource['tags']) tags -= set(attrs['tags']) attrs['tags'] = list(tags) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/osc/v2/validate.py0000664000175000017500000000677000000000000024025 0ustar00zuulzuul00000000000000# 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. # from osc_lib import exceptions from octaviaclient.osc.v2 import constants def check_l7policy_attrs(attrs): msg = None if 'action' not in attrs: return if attrs['action'] == 'REDIRECT_TO_POOL': if 'redirect_pool_id' not in attrs: msg = 'Missing argument: --redirect-pool' elif attrs['action'] == 'REDIRECT_TO_URL': if 'redirect_url' not in attrs: msg = 'Missing argument: --redirect-url' elif attrs['action'] == 'REDIRECT_PREFIX': if 'redirect_prefix' not in attrs: msg = 'Missing argument: --redirect-prefix' if msg is not None: raise exceptions.CommandError(msg) def check_l7rule_attrs(attrs): if 'type' in attrs: if attrs['type'] in ('COOKIE', 'HEADER'): if 'key' not in attrs: msg = ( "Missing argument: --type {type_name} requires " "--key ".format(type_name=attrs['type'])) raise exceptions.CommandError(msg) # Handling these range validations here instead of "choices" as "choices" will # output every possible option in the error message. def _validate_TCP_UDP_SCTP_port_range(port_number, parameter_name): if (port_number < constants.MIN_PORT_NUMBER or port_number > constants.MAX_PORT_NUMBER): msg = ("Invalid input for field/attribute '{name}', Value: " "'{port}'. Value must be between {pmin} and {pmax}.".format( name=parameter_name, port=port_number, pmin=constants.MIN_PORT_NUMBER, pmax=constants.MAX_PORT_NUMBER)) raise exceptions.InvalidValue(msg) def check_listener_attrs(attrs): if 'protocol_port' in attrs: _validate_TCP_UDP_SCTP_port_range(attrs['protocol_port'], 'protocol-port') extra_hsts_opts_set = attrs.get('hsts_preload') or attrs.get( 'hsts_include_subdomains') if extra_hsts_opts_set and 'hsts_max_age' not in attrs: raise exceptions.InvalidValue( "Argument hsts_max_age is required when using hsts_preload or " "hsts_include_subdomains arguments.") def check_member_attrs(attrs): if 'protocol_port' in attrs: _validate_TCP_UDP_SCTP_port_range(attrs['protocol_port'], 'protocol-port') if 'member_port' in attrs: _validate_TCP_UDP_SCTP_port_range(attrs['member_port'], 'member-port') if 'weight' in attrs: if (attrs['weight'] < constants.MIN_WEIGHT or attrs['weight'] > constants.MAX_WEIGHT): msg = ("Invalid input for field/attribute 'weight', Value: " "'{weight}'. Value must be between {wmin} and " "{wmax}.".format(weight=attrs['weight'], wmin=constants.MIN_WEIGHT, wmax=constants.MAX_WEIGHT)) raise exceptions.InvalidValue(msg) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0269225 python-octaviaclient-3.7.0/octaviaclient/tests/0000775000175000017500000000000000000000000021677 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/__init__.py0000664000175000017500000000000000000000000023776 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/fakes.py0000664000175000017500000001546600000000000023356 0ustar00zuulzuul00000000000000# Copyright 2013 Nebula 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. # import copy import sys from unittest import mock from oslo_serialization import jsonutils from keystoneauth1 import fixture import requests AUTH_TOKEN = "foobar" AUTH_URL = "http://0.0.0.0" USERNAME = "itchy" PASSWORD = "scratchy" PROJECT_NAME = "poochie" REGION_NAME = "richie" INTERFACE = "catchy" VERSION = "3" TEST_RESPONSE_DICT = fixture.V2Token(token_id=AUTH_TOKEN, user_name=USERNAME) _s = TEST_RESPONSE_DICT.add_service('identity', name='keystone') _s.add_endpoint(AUTH_URL + ':5000/v2.0') _s = TEST_RESPONSE_DICT.add_service('network', name='neutron') _s.add_endpoint(AUTH_URL + ':9696') _s = TEST_RESPONSE_DICT.add_service('compute', name='nova') _s.add_endpoint(AUTH_URL + ':8774/v2.1') _s = TEST_RESPONSE_DICT.add_service('image', name='glance') _s.add_endpoint(AUTH_URL + ':9292') _s = TEST_RESPONSE_DICT.add_service('object', name='swift') _s.add_endpoint(AUTH_URL + ':8080/v1') TEST_RESPONSE_DICT_V3 = fixture.V3Token(user_name=USERNAME) TEST_RESPONSE_DICT_V3.set_project_scope() TEST_VERSIONS = fixture.DiscoveryList(href=AUTH_URL) def to_unicode_dict(catalog_dict): """Converts dict to unicode dict """ if isinstance(catalog_dict, dict): return {to_unicode_dict(key): to_unicode_dict(value) for key, value in catalog_dict.items()} elif isinstance(catalog_dict, list): return [to_unicode_dict(element) for element in catalog_dict] elif isinstance(catalog_dict, str): return catalog_dict + u"" else: return catalog_dict class FakeStdout(object): def __init__(self): self.content = [] def write(self, text): self.content.append(text) def make_string(self): result = '' for line in self.content: result = result + line return result class FakeLog(object): def __init__(self): self.messages = {} def debug(self, msg): self.messages['debug'] = msg def info(self, msg): self.messages['info'] = msg def warning(self, msg): self.messages['warning'] = msg def error(self, msg): self.messages['error'] = msg def critical(self, msg): self.messages['critical'] = msg class FakeApp(object): def __init__(self, _stdout, _log): self.stdout = _stdout self.client_manager = None self.stdin = sys.stdin self.stdout = _stdout or sys.stdout self.stderr = sys.stderr self.log = _log class FakeOptions(object): def __init__(self, **kwargs): self.os_beta_command = False class FakeClient(object): def __init__(self, **kwargs): self.endpoint = kwargs['endpoint'] self.token = kwargs['token'] class FakeClientManager(object): _api_version = { 'image': '2', } def __init__(self): self.compute = None self.identity = None self.image = None self.object_store = None self.volume = None self.network = None self.session = None self.auth_ref = None self.auth_plugin_name = None self.network_endpoint_enabled = True self.neutronclient = mock.MagicMock() def get_configuration(self): return { 'auth': { 'username': USERNAME, 'password': PASSWORD, 'token': AUTH_TOKEN, }, 'region': REGION_NAME, 'identity_api_version': VERSION, } def is_network_endpoint_enabled(self): return self.network_endpoint_enabled class FakeModule(object): def __init__(self, name, version): self.name = name self.__version__ = version # Workaround for openstacksdk case self.version = mock.Mock() self.version.__version__ = version class FakeResource(object): def __init__(self, manager=None, info=None, loaded=False, methods=None): """Set attributes and methods for a resource. :param manager: The resource manager :param Dictionary info: A dictionary with all attributes :param bool loaded: True if the resource is loaded in memory :param Dictionary methods: A dictionary with all methods """ info = info or {} methods = methods or {} self.__name__ = type(self).__name__ self.manager = manager self._info = info self._add_details(info) self._add_methods(methods) self._loaded = loaded def _add_details(self, info): for (k, v) in info.items(): setattr(self, k, v) def _add_methods(self, methods): """Fake methods with MagicMock objects. For each <@key, @value> pairs in methods, add an callable MagicMock object named @key as an attribute, and set the mock's return_value to @value. When users access the attribute with (), @value will be returned, which looks like a function call. """ for (name, ret) in methods.items(): method = mock.Mock(return_value=ret) setattr(self, name, method) def __repr__(self): reprkeys = sorted(k for k in self.__dict__ if k[0] != '_' and k != 'manager') info = ", ".join("%s=%s" % (k, getattr(self, k)) for k in reprkeys) return "<%s %s>" % (self.__class__.__name__, info) def keys(self): return list(self._info) def to_dict(self): return copy.deepcopy(self._info) @property def info(self): return self._info def __getitem__(self, item): return self._info.get(item) def get(self, item, default=None): return self._info.get(item, default) class FakeResponse(requests.Response): def __init__(self, headers=None, status_code=200, data=None, encoding=None): super().__init__() headers = headers or {} self.status_code = status_code self.headers.update(headers) self._content = jsonutils.dumps(data) if not isinstance(self._content, bytes): self._content = self._content.encode() class FakeModel(dict): def __getattr__(self, key): try: return self[key] except KeyError: raise AttributeError(key) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0269225 python-octaviaclient-3.7.0/octaviaclient/tests/functional/0000775000175000017500000000000000000000000024041 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/functional/__init__.py0000664000175000017500000000000000000000000026140 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/functional/base.py0000664000175000017500000001051200000000000025324 0ustar00zuulzuul00000000000000# 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. import os import re import shlex import subprocess from osc_lib.tests import utils from tempest.lib.cli import output_parser from tempest.lib import exceptions COMMON_DIR = os.path.dirname(os.path.abspath(__file__)) FUNCTIONAL_DIR = os.path.normpath(os.path.join(COMMON_DIR, '..')) ROOT_DIR = os.path.normpath(os.path.join(FUNCTIONAL_DIR, '..')) EXAMPLE_DIR = os.path.join(ROOT_DIR, 'examples') def execute(cmd, fail_ok=False, merge_stderr=False): """Executes specified command for the given action.""" cmdlist = shlex.split(cmd) result = '' result_err = '' stdout = subprocess.PIPE stderr = subprocess.STDOUT if merge_stderr else subprocess.PIPE proc = subprocess.Popen(cmdlist, stdout=stdout, stderr=stderr) result, result_err = proc.communicate() result = result.decode('utf-8') if not fail_ok and proc.returncode != 0: raise exceptions.CommandFailed(proc.returncode, cmd, result, result_err) return result class TestCase(utils.TestCase): delimiter_line = re.compile(r'^\+\-[\+\-]+\-\+$') @classmethod def openstack(cls, cmd, fail_ok=False): """Executes openstackclient command for the given action.""" return execute('openstack ' + cmd, fail_ok=fail_ok) @classmethod def get_openstack_configuration_value(cls, configuration): opts = cls.get_opts([configuration]) return cls.openstack('configuration show ' + opts) @classmethod def get_openstack_extension_names(cls): opts = cls.get_opts(['Name']) return cls.openstack('extension list ' + opts) @classmethod def get_opts(cls, fields, output_format='value'): return ' -f {0} {1}'.format(output_format, ' '.join(['-c ' + it for it in fields])) @classmethod def assertOutput(cls, expected, actual): if expected != actual: raise Exception(expected + ' != ' + actual) @classmethod def assertInOutput(cls, expected, actual): if expected not in actual: raise Exception(expected + ' not in ' + actual) @classmethod def assertsOutputNotNone(cls, observed): if observed is None: raise Exception('No output observed') def assert_table_structure(self, items, field_names): """Verify that all items have keys listed in field_names.""" for item in items: for field in field_names: self.assertIn(field, item) def assert_show_fields(self, show_output, field_names): """Verify that all items have keys listed in field_names.""" # field_names = ['name', 'description'] # show_output = [{'name': 'fc2b98d8faed4126b9e371eda045ade2'}, # {'description': 'description-821397086'}] # this next line creates a flattened list of all 'keys' (like 'name', # and 'description' out of the output all_headers = [item for sublist in show_output for item in sublist] for field_name in field_names: self.assertIn(field_name, all_headers) def parse_show_as_object(self, raw_output): """Return a dict with values parsed from cli output.""" items = self.parse_show(raw_output) o = {} for item in items: o.update(item) return o def parse_show(self, raw_output): """Return list of dicts with item values parsed from cli output.""" items = [] table_ = output_parser.table(raw_output) for row in table_['values']: item = {} item[row[0]] = row[1] items.append(item) return items def parse_listing(self, raw_output): """Return list of dicts with basic item parsed from cli output.""" return output_parser.listing(raw_output) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0269225 python-octaviaclient-3.7.0/octaviaclient/tests/functional/osc/0000775000175000017500000000000000000000000024625 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/functional/osc/__init__.py0000664000175000017500000000000000000000000026724 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0269225 python-octaviaclient-3.7.0/octaviaclient/tests/functional/osc/v2/0000775000175000017500000000000000000000000025154 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/functional/osc/v2/__init__.py0000664000175000017500000000000000000000000027253 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0269225 python-octaviaclient-3.7.0/octaviaclient/tests/unit/0000775000175000017500000000000000000000000022656 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/unit/__init__.py0000664000175000017500000000000000000000000024755 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0269225 python-octaviaclient-3.7.0/octaviaclient/tests/unit/api/0000775000175000017500000000000000000000000023427 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/unit/api/__init__.py0000664000175000017500000000000000000000000025526 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/unit/api/test_octavia.py0000664000175000017500000014665300000000000026505 0ustar00zuulzuul00000000000000# 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. # """Load Balancer v2 API Library Tests""" from keystoneauth1 import session from oslo_utils import uuidutils from requests_mock.contrib import fixture from osc_lib.tests import utils from octaviaclient.api import exceptions from octaviaclient.api.v2 import octavia FAKE_ACCOUNT = 'q12we34r' FAKE_AUTH = '11223344556677889900' FAKE_URL = 'http://example.com/v2.0/' FAKE_LBAAS_URL = FAKE_URL + 'lbaas/' FAKE_OCTAVIA_URL = FAKE_URL + 'octavia/' FAKE_LB = uuidutils.generate_uuid() FAKE_LI = uuidutils.generate_uuid() FAKE_PO = uuidutils.generate_uuid() FAKE_ME = uuidutils.generate_uuid() FAKE_L7PO = uuidutils.generate_uuid() FAKE_L7RU = uuidutils.generate_uuid() FAKE_HM = uuidutils.generate_uuid() FAKE_PRJ = uuidutils.generate_uuid() FAKE_AMP = uuidutils.generate_uuid() FAKE_PROVIDER = 'fake_provider' FAKE_FV = uuidutils.generate_uuid() FAKE_FVPF = uuidutils.generate_uuid() FAKE_AZ = 'fake_az' FAKE_AZPF = uuidutils.generate_uuid() LIST_LB_RESP = { 'loadbalancers': [{'name': 'lb1'}, {'name': 'lb2'}] } LIST_LI_RESP = { 'listeners': [{'name': 'lb1'}, {'name': 'lb2'}] } LIST_PO_RESP = { 'pools': [{'name': 'po1'}, {'name': 'po2'}] } LIST_ME_RESP = { 'members': [{'name': 'mem1'}, {'name': 'mem2'}] } LIST_L7PO_RESP = { 'l7policies': [{'name': 'l71'}, {'name': 'l72'}] } LIST_L7RU_RESP = { 'rules': [{'id': uuidutils.generate_uuid()}, {'id': uuidutils.generate_uuid()}] } LIST_HM_RESP = { 'healthmonitors': [{'id': uuidutils.generate_uuid()}, {'id': uuidutils.generate_uuid()}] } LIST_QT_RESP = { 'quotas': [{'health_monitor': -1}, {'listener': -1}, {'load_balancer': 5}, {'member': 10}, {'pool': 20}, {'project': uuidutils.generate_uuid()}] } LIST_AMP_RESP = { 'amphorae': [{'id': uuidutils.generate_uuid()}, {'id': uuidutils.generate_uuid()}] } LIST_PROVIDER_RESP = { 'providers': [{'name': 'provider1', 'description': 'description of provider1'}, {'name': 'provider2', 'description': 'description of provider2'}] } LIST_FV_RESP = { 'flavors': [{'name': 'fv1'}, {'name': 'fv2'}] } LIST_FVPF_RESP = { 'flavorprofiles': [{'name': 'fvpf1'}, {'name': 'fvpf2'}] } LIST_AZ_RESP = { 'availability_zones': [{'name': 'az1'}, {'name': 'az2'}] } LIST_AZPF_RESP = { 'availability_zone_profiles': [{'name': 'azpf1'}, {'name': 'azpf2'}] } POLICY_ERROR_STRING = ( "Policy does not allow this request to be performed.") LIST_POLICY_ERR_RESP = { 'faultcode': "Client", 'faultstring': POLICY_ERROR_STRING, 'debuginfo': None } SINGLE_LB_RESP = {'loadbalancer': {'id': FAKE_LB, 'name': 'lb1'}} SINGLE_LB_UPDATE = {"loadbalancer": {"admin_state_up": False}} SINGLE_LB_STATS_RESP = {'bytes_in': '0'} SINGLE_LB_STATUS_RESP = {'statuses': {'operating_status': 'ONLINE', 'provisioning_status': 'ACTIVE'}} SINGLE_LI_RESP = {'listener': {'id': FAKE_LI, 'name': 'li1'}} SINGLE_LI_UPDATE = {"listener": {"admin_state_up": False}} SINGLE_PO_RESP = {'pool': {'id': FAKE_PO, 'name': 'li1'}} SINGLE_PO_UPDATE = {'pool': {'admin_state_up': False}} SINGLE_L7PO_RESP = {'l7policy': {'id': FAKE_L7PO, 'name': 'l71'}} SINGLE_L7PO_UPDATE = {'l7policy': {'admin_state_up': False}} SINGLE_ME_RESP = {'member': {'id': FAKE_ME, 'name': 'mem1'}} SINGLE_ME_UPDATE = {"member": {"admin_state_up": False}} SINGLE_L7RU_RESP = {'rule': {'id': FAKE_L7RU}} SINGLE_L7RU_UPDATE = {'rule': {'admin_state_up': False}} SINGLE_HM_RESP = {'healthmonitor': {'id': FAKE_ME}} SINGLE_HM_UPDATE = {'healthmonitor': {'admin_state_up': False}} SINGLE_QT_RESP = {'quota': {'pool': -1}} SINGLE_QT_UPDATE = {'quota': {'pool': -1}} SINGLB_AMP_RESP = {'amphora': {'id': FAKE_AMP}} SINGLE_AMP_STATS_RESP = {'bytes_in': '0'} SINGLE_PROVIDER_CAPABILITY_RESP = { 'flavor_capabilities': [{'some_capability': 'Capabilicy description'}] } SINGLE_FV_RESP = {'flavor': {'id': FAKE_FV, 'name': 'fv1'}} SINGLE_FV_UPDATE = {'flavor': {'enabled': False}} SINGLE_FVPF_RESP = {'flavorprofile': {'id': FAKE_FVPF, 'name': 'fvpf1'}} SINGLE_FVPF_UPDATE = {'flavorprofile': {'provider_name': 'fake_provider'}} SINGLE_AZ_RESP = {'availability_zone': {'name': FAKE_AZ}} SINGLE_AZ_UPDATE = {'availability_zone': {'enabled': False}} SINGLE_AZPF_RESP = {'availability_zone_profile': {'id': FAKE_AZPF, 'name': 'azpf1'}} SINGLE_AZPF_UPDATE = {'availability_zone_profile': { 'provider_name': 'fake_provider'}} class TestAPI(utils.TestCase): def test_client_exception(self): self.assertIs(octavia.OctaviaClientException, exceptions.OctaviaClientException) class TestOctaviaClient(utils.TestCase): def setUp(self): super().setUp() sess = session.Session() self.api = octavia.OctaviaAPI(session=sess, endpoint=FAKE_URL) self.requests_mock = self.useFixture(fixture.Fixture()) class TestLoadBalancer(TestOctaviaClient): _error_message = ("Validation failure: Test message.") def test_list_load_balancer_no_options(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'loadbalancers', json=LIST_LB_RESP, status_code=200, ) ret = self.api.load_balancer_list() self.assertEqual(LIST_LB_RESP, ret) def test_list_load_balancer_not_allowed(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'loadbalancers', json=LIST_POLICY_ERR_RESP, status_code=403, ) ret = self.assertRaises( octavia.OctaviaClientException, self.api.load_balancer_list) self.assertEqual(POLICY_ERROR_STRING, ret.message) def test_show_load_balancer(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'loadbalancers/' + FAKE_LB, json=SINGLE_LB_RESP, status_code=200 ) ret = self.api.load_balancer_show(FAKE_LB) self.assertEqual(SINGLE_LB_RESP['loadbalancer'], ret) def test_create_load_balancer(self): self.requests_mock.register_uri( 'POST', FAKE_LBAAS_URL + 'loadbalancers', json=SINGLE_LB_RESP, status_code=200 ) ret = self.api.load_balancer_create(json=SINGLE_LB_RESP) self.assertEqual(SINGLE_LB_RESP, ret) def test_create_load_balancer_error(self): self.requests_mock.register_uri( 'POST', FAKE_LBAAS_URL + 'loadbalancers', text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.load_balancer_create, json=SINGLE_LB_RESP) def test_create_load_balancer_503_error(self): self.requests_mock.register_uri( 'POST', FAKE_LBAAS_URL + 'loadbalancers', status_code=503 ) self.assertRaisesRegex(exceptions.OctaviaClientException, 'Service Unavailable', self.api.load_balancer_create, json=SINGLE_LB_RESP) def test_set_load_balancer(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'loadbalancers/' + FAKE_LB, json=SINGLE_LB_UPDATE, status_code=200 ) ret = self.api.load_balancer_set(FAKE_LB, json=SINGLE_LB_UPDATE) self.assertEqual(SINGLE_LB_UPDATE, ret) def test_set_load_balancer_error(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'loadbalancers/' + FAKE_LB, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.load_balancer_set, FAKE_LB, json=SINGLE_LB_UPDATE) def test_failover_load_balancer(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'loadbalancers/' + FAKE_LB + '/failover', status_code=202, ) ret = self.api.load_balancer_failover(FAKE_LB) self.assertEqual(202, ret.status_code) def test_failover_load_balancer_error(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'loadbalancers/' + FAKE_LB + '/failover', text='{"faultstring": "%s"}' % self._error_message, status_code=409, ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.load_balancer_failover, FAKE_LB) def test_delete_load_balancer(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'loadbalancers/' + FAKE_LB, status_code=200 ) ret = self.api.load_balancer_delete(FAKE_LB) self.assertEqual(200, ret.status_code) def test_delete_load_balancer_error(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'loadbalancers/' + FAKE_LB, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.load_balancer_delete, FAKE_LB) def test_stats_show_load_balancer(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'loadbalancers/' + FAKE_LB + '/stats', json=SINGLE_LB_STATS_RESP, status_code=200, ) ret = self.api.load_balancer_stats_show(FAKE_LB) self.assertEqual(SINGLE_LB_STATS_RESP, ret) def test_status_show_load_balancer(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'loadbalancers/' + FAKE_LB + '/status', json=SINGLE_LB_STATUS_RESP, status_code=200, ) ret = self.api.load_balancer_status_show(FAKE_LB) self.assertEqual(SINGLE_LB_STATUS_RESP, ret) def test_list_listeners_no_options(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'listeners', json=LIST_LI_RESP, status_code=200, ) ret = self.api.listener_list() self.assertEqual(LIST_LI_RESP, ret) def test_list_listener_not_allowed(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'listeners', json=LIST_POLICY_ERR_RESP, status_code=403, ) ret = self.assertRaises( octavia.OctaviaClientException, self.api.listener_list) self.assertEqual(POLICY_ERROR_STRING, ret.message) def test_show_listener(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'listeners/' + FAKE_LI, json=SINGLE_LI_RESP, status_code=200 ) ret = self.api.listener_show(FAKE_LI) self.assertEqual(SINGLE_LI_RESP['listener'], ret) def test_create_listener(self): self.requests_mock.register_uri( 'POST', FAKE_LBAAS_URL + 'listeners', json=SINGLE_LI_RESP, status_code=200 ) ret = self.api.listener_create(json=SINGLE_LI_RESP) self.assertEqual(SINGLE_LI_RESP, ret) def test_create_listener_error(self): self.requests_mock.register_uri( 'POST', FAKE_LBAAS_URL + 'listeners', text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.listener_create, json=SINGLE_LI_RESP) def test_set_listeners(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'listeners/' + FAKE_LI, json=SINGLE_LI_UPDATE, status_code=200 ) ret = self.api.listener_set(FAKE_LI, json=SINGLE_LI_UPDATE) self.assertEqual(SINGLE_LI_UPDATE, ret) def test_set_listeners_error(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'listeners/' + FAKE_LI, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.listener_set, FAKE_LI, json=SINGLE_LI_UPDATE) def test_delete_listener(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'listeners/' + FAKE_LI, status_code=200 ) ret = self.api.listener_delete(FAKE_LI) self.assertEqual(200, ret.status_code) def test_delete_listener_error(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'listeners/' + FAKE_LI, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.listener_delete, FAKE_LI) def test_stats_show_listener(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'listeners/' + FAKE_LI + '/stats', json=SINGLE_LB_STATS_RESP, status_code=200, ) ret = self.api.listener_stats_show(FAKE_LI) self.assertEqual(SINGLE_LB_STATS_RESP, ret) def test_list_pool_no_options(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'pools', json=LIST_PO_RESP, status_code=200, ) ret = self.api.pool_list() self.assertEqual(LIST_PO_RESP, ret) def test_list_pool_not_allowed(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'pools', json=LIST_POLICY_ERR_RESP, status_code=403, ) ret = self.assertRaises( octavia.OctaviaClientException, self.api.pool_list) self.assertEqual(POLICY_ERROR_STRING, ret.message) def test_show_pool(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'pools/' + FAKE_PO, json=SINGLE_PO_RESP, status_code=200 ) ret = self.api.pool_show(FAKE_PO) self.assertEqual(SINGLE_PO_RESP['pool'], ret) def test_create_pool(self): self.requests_mock.register_uri( 'POST', FAKE_LBAAS_URL + 'pools', json=SINGLE_PO_RESP, status_code=200 ) ret = self.api.pool_create(json=SINGLE_PO_RESP) self.assertEqual(SINGLE_PO_RESP, ret) def test_create_pool_error(self): self.requests_mock.register_uri( 'POST', FAKE_LBAAS_URL + 'pools', text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.pool_create, json=SINGLE_PO_RESP) def test_set_pool(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'pools/' + FAKE_PO, json=SINGLE_PO_UPDATE, status_code=200 ) ret = self.api.pool_set(FAKE_PO, json=SINGLE_PO_UPDATE) self.assertEqual(SINGLE_PO_UPDATE, ret) def test_set_pool_error(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'pools/' + FAKE_PO, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.pool_set, FAKE_PO, json=SINGLE_PO_UPDATE) def test_delete_pool(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'pools/' + FAKE_PO, status_code=200 ) ret = self.api.pool_delete(FAKE_PO) self.assertEqual(200, ret.status_code) def test_delete_pool_error(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'pools/' + FAKE_PO, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.pool_delete, FAKE_PO) def test_list_member_no_options(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'pools/' + FAKE_PO + '/members', json=LIST_ME_RESP, status_code=200, ) ret = self.api.member_list(FAKE_PO) self.assertEqual(LIST_ME_RESP, ret) def test_list_member_not_allowed(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'pools/' + FAKE_PO + '/members', json=LIST_POLICY_ERR_RESP, status_code=403, ) ret = self.assertRaises( octavia.OctaviaClientException, self.api.member_list, FAKE_PO) self.assertEqual(POLICY_ERROR_STRING, ret.message) def test_show_member(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'pools/' + FAKE_PO + '/members/' + FAKE_ME, json=SINGLE_ME_RESP, status_code=200 ) ret = self.api.member_show(pool_id=FAKE_PO, member_id=FAKE_ME) self.assertEqual(SINGLE_ME_RESP['member'], ret) def test_create_member(self): self.requests_mock.register_uri( 'POST', FAKE_LBAAS_URL + 'pools/' + FAKE_PO + '/members', json=SINGLE_ME_RESP, status_code=200 ) ret = self.api.member_create(json=SINGLE_ME_RESP, pool_id=FAKE_PO) self.assertEqual(SINGLE_ME_RESP, ret) def test_create_member_error(self): self.requests_mock.register_uri( 'POST', FAKE_LBAAS_URL + 'pools/' + FAKE_PO + '/members', text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.member_create, json=SINGLE_ME_RESP, pool_id=FAKE_PO) def test_set_member(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'pools/' + FAKE_PO + '/members/' + FAKE_ME, json=SINGLE_ME_UPDATE, status_code=200 ) ret = self.api.member_set(pool_id=FAKE_PO, member_id=FAKE_ME, json=SINGLE_ME_UPDATE) self.assertEqual(SINGLE_ME_UPDATE, ret) def test_set_member_error(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'pools/' + FAKE_PO + '/members/' + FAKE_ME, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.member_set, pool_id=FAKE_PO, member_id=FAKE_ME, json=SINGLE_ME_UPDATE) def test_delete_member(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'pools/' + FAKE_PO + '/members/' + FAKE_ME, status_code=200 ) ret = self.api.member_delete(pool_id=FAKE_PO, member_id=FAKE_ME) self.assertEqual(200, ret.status_code) def test_delete_member_error(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'pools/' + FAKE_PO + '/members/' + FAKE_ME, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.member_delete, pool_id=FAKE_PO, member_id=FAKE_ME) def test_list_l7policy_no_options(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'l7policies', json=LIST_L7PO_RESP, status_code=200, ) ret = self.api.l7policy_list() self.assertEqual(LIST_L7PO_RESP, ret) def test_list_l7policy_not_allowed(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'l7policies', json=LIST_POLICY_ERR_RESP, status_code=403, ) ret = self.assertRaises( octavia.OctaviaClientException, self.api.l7policy_list) self.assertEqual(POLICY_ERROR_STRING, ret.message) def test_show_l7policy(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO, json=SINGLE_L7PO_RESP, status_code=200 ) ret = self.api.l7policy_show(FAKE_L7PO) self.assertEqual(SINGLE_L7PO_RESP['l7policy'], ret) def test_create_l7policy(self): self.requests_mock.register_uri( 'POST', FAKE_LBAAS_URL + 'l7policies', json=SINGLE_L7PO_RESP, status_code=200 ) ret = self.api.l7policy_create(json=SINGLE_L7PO_RESP) self.assertEqual(SINGLE_L7PO_RESP, ret) def test_create_l7policy_error(self): self.requests_mock.register_uri( 'POST', FAKE_LBAAS_URL + 'l7policies', text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.l7policy_create, json=SINGLE_L7PO_RESP) def test_set_l7policy(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO, json=SINGLE_L7PO_UPDATE, status_code=200 ) ret = self.api.l7policy_set(FAKE_L7PO, json=SINGLE_L7PO_UPDATE) self.assertEqual(SINGLE_L7PO_UPDATE, ret) def test_set_l7policy_error(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.l7policy_set, FAKE_L7PO, json=SINGLE_L7PO_UPDATE) def test_delete_l7policy(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO, status_code=200 ) ret = self.api.l7policy_delete(FAKE_L7PO) self.assertEqual(200, ret.status_code) def test_delete_l7policy_error(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.l7policy_delete, FAKE_L7PO) def test_list_l7rule_no_options(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO + '/rules', json=LIST_L7RU_RESP, status_code=200, ) ret = self.api.l7rule_list(FAKE_L7PO) self.assertEqual(LIST_L7RU_RESP, ret) def test_list_l7rule_not_allowed(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO + '/rules', json=LIST_POLICY_ERR_RESP, status_code=403, ) ret = self.assertRaises( octavia.OctaviaClientException, self.api.l7rule_list, FAKE_L7PO) self.assertEqual(POLICY_ERROR_STRING, ret.message) def test_show_l7rule(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO + '/rules/' + FAKE_L7RU, json=SINGLE_L7RU_RESP, status_code=200 ) ret = self.api.l7rule_show(FAKE_L7RU, FAKE_L7PO) self.assertEqual(SINGLE_L7RU_RESP['rule'], ret) def test_create_l7rule(self): self.requests_mock.register_uri( 'POST', FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO + '/rules', json=SINGLE_L7RU_RESP, status_code=200 ) ret = self.api.l7rule_create(FAKE_L7PO, json=SINGLE_L7RU_RESP) self.assertEqual(SINGLE_L7RU_RESP, ret) def test_create_l7rule_error(self): self.requests_mock.register_uri( 'POST', FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO + '/rules', text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.l7rule_create, FAKE_L7PO, json=SINGLE_L7RU_RESP) def test_set_l7rule(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO + '/rules/' + FAKE_L7RU, json=SINGLE_L7RU_UPDATE, status_code=200 ) ret = self.api.l7rule_set( l7rule_id=FAKE_L7RU, l7policy_id=FAKE_L7PO, json=SINGLE_L7RU_UPDATE ) self.assertEqual(SINGLE_L7RU_UPDATE, ret) def test_set_l7rule_error(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO + '/rules/' + FAKE_L7RU, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.l7rule_set, l7rule_id=FAKE_L7RU, l7policy_id=FAKE_L7PO, json=SINGLE_L7RU_UPDATE) def test_delete_l7rule(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO + '/rules/' + FAKE_L7RU, status_code=200 ) ret = self.api.l7rule_delete( l7rule_id=FAKE_L7RU, l7policy_id=FAKE_L7PO ) self.assertEqual(200, ret.status_code) def test_delete_l7rule_error(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO + '/rules/' + FAKE_L7RU, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.l7rule_delete, l7rule_id=FAKE_L7RU, l7policy_id=FAKE_L7PO) def test_list_health_monitor_no_options(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'healthmonitors', json=LIST_HM_RESP, status_code=200, ) ret = self.api.health_monitor_list() self.assertEqual(LIST_HM_RESP, ret) def test_list_health_monitor_not_allowed(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'healthmonitors', json=LIST_POLICY_ERR_RESP, status_code=403, ) ret = self.assertRaises( octavia.OctaviaClientException, self.api.health_monitor_list) self.assertEqual(POLICY_ERROR_STRING, ret.message) def test_show_health_monitor(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'healthmonitors/' + FAKE_HM, json=SINGLE_HM_RESP, status_code=200 ) ret = self.api.health_monitor_show(FAKE_HM) self.assertEqual(SINGLE_HM_RESP['healthmonitor'], ret) def test_create_health_monitor(self): self.requests_mock.register_uri( 'POST', FAKE_LBAAS_URL + 'healthmonitors', json=SINGLE_HM_RESP, status_code=200 ) ret = self.api.health_monitor_create(json=SINGLE_HM_RESP) self.assertEqual(SINGLE_HM_RESP, ret) def test_create_health_monitor_error(self): self.requests_mock.register_uri( 'POST', FAKE_LBAAS_URL + 'healthmonitors', text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.health_monitor_create, json=SINGLE_HM_RESP) def test_set_health_monitor(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'healthmonitors/' + FAKE_HM, json=SINGLE_HM_UPDATE, status_code=200 ) ret = self.api.health_monitor_set(FAKE_HM, json=SINGLE_HM_UPDATE) self.assertEqual(SINGLE_HM_UPDATE, ret) def test_set_health_monitor_error(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'healthmonitors/' + FAKE_HM, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.health_monitor_set, FAKE_HM, json=SINGLE_HM_UPDATE) def test_delete_health_monitor(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'healthmonitors/' + FAKE_HM, status_code=200 ) ret = self.api.health_monitor_delete(FAKE_HM) self.assertEqual(200, ret.status_code) def test_delete_health_monitor_error(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'healthmonitors/' + FAKE_HM, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.health_monitor_delete, FAKE_HM) def test_list_quota_no_options(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'quotas', json=LIST_QT_RESP, status_code=200, ) ret = self.api.quota_list() self.assertEqual(LIST_QT_RESP, ret) def test_list_quota_not_allowed(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'quotas', json=LIST_POLICY_ERR_RESP, status_code=403, ) ret = self.assertRaises( octavia.OctaviaClientException, self.api.quota_list) self.assertEqual(POLICY_ERROR_STRING, ret.message) def test_show_quota(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'quotas/' + FAKE_PRJ, json=SINGLE_QT_RESP, status_code=200 ) ret = self.api.quota_show(FAKE_PRJ) self.assertEqual(SINGLE_QT_RESP['quota'], ret) def test_set_quota(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'quotas/' + FAKE_PRJ, json=SINGLE_QT_UPDATE, status_code=200 ) ret = self.api.quota_set(FAKE_PRJ, json=SINGLE_QT_UPDATE) self.assertEqual(SINGLE_QT_UPDATE, ret) def test_set_quota_error(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'quotas/' + FAKE_PRJ, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.quota_set, FAKE_PRJ, json=SINGLE_QT_UPDATE) def test_reset_quota(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'quotas/' + FAKE_PRJ, status_code=200 ) ret = self.api.quota_reset(FAKE_PRJ) self.assertEqual(200, ret.status_code) def test_reset_quota_error(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'quotas/' + FAKE_PRJ, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.quota_reset, FAKE_PRJ) def test_list_amphora_no_options(self): self.requests_mock.register_uri( 'GET', FAKE_OCTAVIA_URL + 'amphorae?', json=LIST_AMP_RESP, status_code=200, ) ret = self.api.amphora_list() self.assertEqual(LIST_AMP_RESP, ret) def test_list_amphora_not_allowed(self): self.requests_mock.register_uri( 'GET', FAKE_OCTAVIA_URL + 'amphorae', json=LIST_POLICY_ERR_RESP, status_code=403, ) ret = self.assertRaises( octavia.OctaviaClientException, self.api.amphora_list) self.assertEqual(POLICY_ERROR_STRING, ret.message) def test_show_amphora(self): self.requests_mock.register_uri( 'GET', FAKE_OCTAVIA_URL + 'amphorae/' + FAKE_AMP, json=SINGLB_AMP_RESP, status_code=200 ) ret = self.api.amphora_show(FAKE_AMP) self.assertEqual(SINGLB_AMP_RESP['amphora'], ret) def test_configure_amphora(self): self.requests_mock.register_uri( 'PUT', FAKE_OCTAVIA_URL + 'amphorae/' + FAKE_AMP + '/config', status_code=202, ) ret = self.api.amphora_configure(FAKE_AMP) self.assertEqual(202, ret.status_code) def test_configure_amphora_error(self): self.requests_mock.register_uri( 'PUT', FAKE_OCTAVIA_URL + 'amphorae/' + FAKE_AMP + '/config', text='{"faultstring": "%s"}' % self._error_message, status_code=409, ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.amphora_configure, FAKE_AMP) def test_delete_amphora(self): self.requests_mock.register_uri( 'DELETE', FAKE_OCTAVIA_URL + 'amphorae/' + FAKE_AMP, status_code=200 ) ret = self.api.amphora_delete(FAKE_AMP) self.assertEqual(200, ret.status_code) def test_stats_show_amphora(self): self.requests_mock.register_uri( 'GET', FAKE_OCTAVIA_URL + 'amphorae/' + FAKE_AMP + '/stats', json=SINGLE_AMP_STATS_RESP, status_code=200 ) ret = self.api.amphora_stats_show(FAKE_AMP) self.assertEqual(SINGLE_AMP_STATS_RESP, ret) def test_failover_amphora(self): self.requests_mock.register_uri( 'PUT', FAKE_OCTAVIA_URL + 'amphorae/' + FAKE_AMP + '/failover', status_code=202, ) ret = self.api.amphora_failover(FAKE_AMP) self.assertEqual(202, ret.status_code) def test_failover_amphora_error(self): self.requests_mock.register_uri( 'PUT', FAKE_OCTAVIA_URL + 'amphorae/' + FAKE_AMP + '/failover', text='{"faultstring": "%s"}' % self._error_message, status_code=409, ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.amphora_failover, FAKE_AMP) def test_list_provider(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'providers', json=LIST_PROVIDER_RESP, status_code=200, ) ret = self.api.provider_list() self.assertEqual(LIST_PROVIDER_RESP, ret) def test_show_provider_capability(self): self.requests_mock.register_uri( 'GET', (FAKE_LBAAS_URL + 'providers/' + FAKE_PROVIDER + '/flavor_capabilities'), json=SINGLE_PROVIDER_CAPABILITY_RESP, status_code=200 ) ret = self.api.provider_flavor_capability_list(FAKE_PROVIDER) self.assertEqual( SINGLE_PROVIDER_CAPABILITY_RESP, ret) def test_list_flavor_no_options(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'flavors', json=LIST_FV_RESP, status_code=200, ) ret = self.api.flavor_list() self.assertEqual(LIST_FV_RESP, ret) def test_show_flavor(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'flavors/' + FAKE_FV, json=SINGLE_FV_RESP, status_code=200 ) ret = self.api.flavor_show(FAKE_FV) self.assertEqual(SINGLE_FV_RESP['flavor'], ret) def test_create_flavor(self): self.requests_mock.register_uri( 'POST', FAKE_LBAAS_URL + 'flavors', json=SINGLE_FV_RESP, status_code=200 ) ret = self.api.flavor_create(json=SINGLE_FV_RESP) self.assertEqual(SINGLE_FV_RESP, ret) def test_create_flavor_error(self): self.requests_mock.register_uri( 'POST', FAKE_LBAAS_URL + 'flavors', text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.flavor_create, json=SINGLE_FV_RESP) def test_set_flavor(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'flavors/' + FAKE_FV, json=SINGLE_FV_UPDATE, status_code=200 ) ret = self.api.flavor_set(FAKE_FV, json=SINGLE_FV_UPDATE) self.assertEqual(SINGLE_FV_UPDATE, ret) def test_set_flavor_error(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'flavors/' + FAKE_FV, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.flavor_set, FAKE_FV, json=SINGLE_FV_UPDATE) def test_delete_flavor(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'flavors/' + FAKE_FV, status_code=200 ) ret = self.api.flavor_delete(FAKE_FV) self.assertEqual(200, ret.status_code) def test_delete_flavor_error(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'flavors/' + FAKE_FV, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.flavor_delete, FAKE_FV) def test_list_flavorprofiles_no_options(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'flavorprofiles', json=LIST_FVPF_RESP, status_code=200, ) ret = self.api.flavorprofile_list() self.assertEqual(LIST_FVPF_RESP, ret) def test_show_flavorprofile(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'flavorprofiles/' + FAKE_FVPF, json=SINGLE_FVPF_RESP, status_code=200 ) ret = self.api.flavorprofile_show(FAKE_FVPF) self.assertEqual(SINGLE_FVPF_RESP['flavorprofile'], ret) def test_create_flavorprofile(self): self.requests_mock.register_uri( 'POST', FAKE_LBAAS_URL + 'flavorprofiles', json=SINGLE_FVPF_RESP, status_code=200 ) ret = self.api.flavorprofile_create(json=SINGLE_FVPF_RESP) self.assertEqual(SINGLE_FVPF_RESP, ret) def test_create_flavorprofile_error(self): self.requests_mock.register_uri( 'POST', FAKE_LBAAS_URL + 'flavorprofiles', text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.flavorprofile_create, json=SINGLE_FVPF_RESP) def test_set_flavorprofiles(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'flavorprofiles/' + FAKE_FVPF, json=SINGLE_FVPF_UPDATE, status_code=200 ) ret = self.api.flavorprofile_set(FAKE_FVPF, json=SINGLE_FVPF_UPDATE) self.assertEqual(SINGLE_FVPF_UPDATE, ret) def test_set_flavorprofiles_error(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'flavorprofiles/' + FAKE_FVPF, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.flavorprofile_set, FAKE_FVPF, json=SINGLE_FVPF_UPDATE) def test_delete_flavorprofile(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'flavorprofiles/' + FAKE_FVPF, status_code=200 ) ret = self.api.flavorprofile_delete(FAKE_FVPF) self.assertEqual(200, ret.status_code) def test_delete_flavorprofile_error(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'flavorprofiles/' + FAKE_FVPF, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.flavorprofile_delete, FAKE_FVPF) def test_list_availabilityzone_no_options(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'availabilityzones', json=LIST_AZ_RESP, status_code=200, ) ret = self.api.availabilityzone_list() self.assertEqual(LIST_AZ_RESP, ret) def test_show_availabilityzone(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'availabilityzones/' + FAKE_AZ, json=SINGLE_AZ_RESP, status_code=200 ) ret = self.api.availabilityzone_show(FAKE_AZ) self.assertEqual(SINGLE_AZ_RESP['availability_zone'], ret) def test_create_availabilityzone(self): self.requests_mock.register_uri( 'POST', FAKE_LBAAS_URL + 'availabilityzones', json=SINGLE_AZ_RESP, status_code=200 ) ret = self.api.availabilityzone_create(json=SINGLE_AZ_RESP) self.assertEqual(SINGLE_AZ_RESP, ret) def test_create_availabilityzone_error(self): self.requests_mock.register_uri( 'POST', FAKE_LBAAS_URL + 'availabilityzones', text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.availabilityzone_create, json=SINGLE_AZ_RESP) def test_set_availabilityzone(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'availabilityzones/' + FAKE_AZ, json=SINGLE_AZ_UPDATE, status_code=200 ) ret = self.api.availabilityzone_set(FAKE_AZ, json=SINGLE_AZ_UPDATE) self.assertEqual(SINGLE_AZ_UPDATE, ret) def test_set_availabilityzone_error(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'availabilityzones/' + FAKE_AZ, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.availabilityzone_set, FAKE_AZ, json=SINGLE_AZ_UPDATE) def test_delete_availabilityzone(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'availabilityzones/' + FAKE_AZ, status_code=200 ) ret = self.api.availabilityzone_delete(FAKE_AZ) self.assertEqual(200, ret.status_code) def test_delete_availabilityzone_error(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'availabilityzones/' + FAKE_AZ, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.availabilityzone_delete, FAKE_AZ) def test_list_availabilityzoneprofiles_no_options(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'availabilityzoneprofiles', json=LIST_AZPF_RESP, status_code=200, ) ret = self.api.availabilityzoneprofile_list() self.assertEqual(LIST_AZPF_RESP, ret) def test_show_availabilityzoneprofile(self): self.requests_mock.register_uri( 'GET', FAKE_LBAAS_URL + 'availabilityzoneprofiles/' + FAKE_AZPF, json=SINGLE_AZPF_RESP, status_code=200 ) ret = self.api.availabilityzoneprofile_show(FAKE_AZPF) self.assertEqual(SINGLE_AZPF_RESP['availability_zone_profile'], ret) def test_create_availabilityzoneprofile(self): self.requests_mock.register_uri( 'POST', FAKE_LBAAS_URL + 'availabilityzoneprofiles', json=SINGLE_AZPF_RESP, status_code=200 ) ret = self.api.availabilityzoneprofile_create(json=SINGLE_AZPF_RESP) self.assertEqual(SINGLE_AZPF_RESP, ret) def test_create_availabilityzoneprofile_error(self): self.requests_mock.register_uri( 'POST', FAKE_LBAAS_URL + 'availabilityzoneprofiles', text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.availabilityzoneprofile_create, json=SINGLE_AZPF_RESP) def test_set_availabilityzoneprofiles(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'availabilityzoneprofiles/' + FAKE_AZPF, json=SINGLE_AZPF_UPDATE, status_code=200 ) ret = self.api.availabilityzoneprofile_set(FAKE_AZPF, json=SINGLE_AZPF_UPDATE) self.assertEqual(SINGLE_AZPF_UPDATE, ret) def test_set_availabilityzoneprofiles_error(self): self.requests_mock.register_uri( 'PUT', FAKE_LBAAS_URL + 'availabilityzoneprofiles/' + FAKE_AZPF, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.availabilityzoneprofile_set, FAKE_AZPF, json=SINGLE_AZPF_UPDATE) def test_delete_availabilityzoneprofile(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'availabilityzoneprofiles/' + FAKE_AZPF, status_code=200 ) ret = self.api.availabilityzoneprofile_delete(FAKE_AZPF) self.assertEqual(200, ret.status_code) def test_delete_availabilityzoneprofile_error(self): self.requests_mock.register_uri( 'DELETE', FAKE_LBAAS_URL + 'availabilityzoneprofiles/' + FAKE_AZPF, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) self.assertRaisesRegex(exceptions.OctaviaClientException, self._error_message, self.api.availabilityzoneprofile_delete, FAKE_AZPF) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0269225 python-octaviaclient-3.7.0/octaviaclient/tests/unit/osc/0000775000175000017500000000000000000000000023442 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/unit/osc/__init__.py0000664000175000017500000000000000000000000025541 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0309224 python-octaviaclient-3.7.0/octaviaclient/tests/unit/osc/v2/0000775000175000017500000000000000000000000023771 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/unit/osc/v2/__init__.py0000664000175000017500000000000000000000000026070 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/unit/osc/v2/constants.py0000664000175000017500000001637000000000000026366 0ustar00zuulzuul00000000000000# 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. # from oslo_utils import uuidutils AMPHORA_ATTRS = { "id": uuidutils.generate_uuid(dashed=True), "loadbalancer_id": uuidutils.generate_uuid(dashed=True), "compute_id": uuidutils.generate_uuid(dashed=True), "lb_network_ip": "192.168.1.3", "vrrp_ip": "192.168.1.6", "ha_ip": "192.168.1.10", "vrrp_port_id": uuidutils.generate_uuid(dashed=True), "ha_port_id": uuidutils.generate_uuid(dashed=True), "cert_expiration": "2019-09-19 00:34:51", "cert_busy": 0, "role": "BACKUP", "status": "ALLOCATED", "vrrp_interface": "eth1", "vrrp_id": 1, "vrrp_priority": 200, "cached_zone": "zone2", "image_id": uuidutils.generate_uuid(dashed=True), } HM_ATTRS = { "project_id": uuidutils.generate_uuid(dashed=True), "name": "hm-name-" + uuidutils.generate_uuid(dashed=True), "admin_state_up": True, "pools": [ { "id": uuidutils.generate_uuid(dashed=True) } ], "created_at": "2017-05-10T06:11:10", "provisioning_status": "PENDING_CREATE", "delay": 10, "expected_codes": "200", "max_retries": 2, "http_method": "GET", "timeout": 10, "max_retries_down": 3, "url_path": "/some/custom/path", "type": "HTTP", "id": uuidutils.generate_uuid(dashed=True), "http_version": 1.1, "domain_name": "testlab.com" } LISTENER_ATTRS = { "id": uuidutils.generate_uuid(), "name": "li-name-" + uuidutils.generate_uuid(dashed=True), "project_id": uuidutils.generate_uuid(dashed=True), "protocol": "HTTP", "protocol_port": 80, "provisioning_status": "ACTIVE", "default_pool_id": None, "loadbalancers": None, "connection_limit": 10, "admin_state_up": True, "default_tls_container_ref": uuidutils.generate_uuid(dashed=True), "sni_container_refs": [uuidutils.generate_uuid(dashed=True), uuidutils.generate_uuid(dashed=True)], "timeout_client_data": 50000, "timeout_member_connect": 5000, "timeout_member_data": 50000, "timeout_tcp_inspect": 0, 'client_ca_tls_container_ref': uuidutils.generate_uuid(dashed=True), 'client_authentication': "OPTIONAL", 'client_crl_container_ref': uuidutils.generate_uuid(dashed=True), "allowed_cidrs": ['192.0.2.0/24', '198.51.100.0/24'], 'tls_ciphers': "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256", 'tls_versions': ['TLSv1.1', 'TLSv1.2'], 'alpn_protocols': ['h2', 'http/1.1'], "tags": ["foo", "bar"], 'hsts_max_age': 15_000_000, 'hsts_include_subdomains': True, 'hsts_preload': True, } LOADBALANCER_ATTRS = { "id": uuidutils.generate_uuid(), "name": "lb-name-" + uuidutils.generate_uuid(dashed=True), "project_id": uuidutils.generate_uuid(dashed=True), "vip_address": "192.0.2.124", "vip_network_id": uuidutils.generate_uuid(dashed=True), "vip_subnet_id": uuidutils.generate_uuid(dashed=True), "vip_qos_policy_id": uuidutils.generate_uuid(dashed=True), "provisioning_status": "ACTIVE", "operating_status": "ONLINE", "provider": "octavia", "flavor_id": uuidutils.generate_uuid(dashed=True), "additional_vips": [{ "subnet_id": uuidutils.generate_uuid(dashed=True), "ip_address": "192.0.2.156" }, { "subnet_id": uuidutils.generate_uuid(dashed=True), "ip_address": "192.0.2.179" }], "tags": ["foo", "bar"] } L7POLICY_ATTRS = { "listener_id": uuidutils.generate_uuid(), "description": "fake desc", "admin_state_up": True, "rules": [{"id": uuidutils.generate_uuid()}], "provisioning_status": "active", "redirect_pool_id": uuidutils.generate_uuid(), "action": "POOL_REDIRECT", "position": 1, "project_id": uuidutils.generate_uuid(), "id": uuidutils.generate_uuid(), "name": "l7po-name-" + uuidutils.generate_uuid(dashed=True), } L7RULE_ATTRS = { "created_at": "2017-05-04T18:46:35", "compare_type": "ENDS_WITH", "provisioning_status": "ACTIVE", "invert": False, "admin_state_up": True, "value": ".example.com", "key": None, "project_id": uuidutils.generate_uuid(), "type": "HOST_NAME", "id": uuidutils.generate_uuid(), "operating_status": "ONLINE", } MEMBER_ATTRS = { "project_id": uuidutils.generate_uuid(dashed=True), "name": "test-member", "backup": False, "weight": 1, "admin_state_up": True, "subnet_id": uuidutils.generate_uuid(dashed=True), "tenant_id": uuidutils.generate_uuid(dashed=True), "provisioning_status": "ACTIVE", "address": "192.0.2.122", "protocol_port": 80, "id": uuidutils.generate_uuid(dashed=True), "operating_status": "NO_MONITOR", "pool_id": uuidutils.generate_uuid(dashed=True), } POOL_ATTRS = { "admin_state_up": True, "description": "fake desc", "id": uuidutils.generate_uuid(), "lb_algorithm": "ROUND_ROBIN", "listeners": [{"id": uuidutils.generate_uuid()}], "loadbalancers": [{"id": uuidutils.generate_uuid()}], "members": [{"id": uuidutils.generate_uuid()}], "name": "po-name-" + uuidutils.generate_uuid(dashed=True), "project_id": uuidutils.generate_uuid(dashed=True), "protocol": "HTTP", "provisioning_status": "ACTIVE", "tls_container_ref": uuidutils.generate_uuid(), "ca_tls_container_ref": uuidutils.generate_uuid(), "crl_container_ref": uuidutils.generate_uuid(), "tls_enabled": True, "tls_ciphers": "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256", "tls_versions": ['TLSv1.1', 'TLSv1.2'], "tags": ["foo", "bar"], "alpn_protocols": ['h2', 'http/1.1'] } QUOTA_ATTRS = { "health_monitor": -1, "listener": None, "load_balancer": 5, "member": 50, "pool": None, "l7policy": 20, "l7rule": 30, "project_id": uuidutils.generate_uuid(dashed=True), } PROVIDER_ATTRS = { "name": "provider1", "description": "Description of provider1." } CAPABILITY_ATTRS = { "name": "some_capability", "description": "Description of capability." } FLAVOR_ATTRS = { "id": uuidutils.generate_uuid(), "name": "fv-name-" + uuidutils.generate_uuid(dashed=True), "flavor_profile_id": None, "enabled": True, } FLAVORPROFILE_ATTRS = { "id": uuidutils.generate_uuid(), "name": "fvpf-name-" + uuidutils.generate_uuid(dashed=True), "provider_name": "mock_provider", "flavor_data": '{"mock_key": "mock_value"}', } AVAILABILITY_ZONE_ATTRS = { "name": "az-name-" + uuidutils.generate_uuid(dashed=True), "availability_zone_profile_id": None, "enabled": True, "description": "Description of AZ", } AVAILABILITY_ZONE_PROFILE_ATTRS = { "id": uuidutils.generate_uuid(), "name": "azpf-name-" + uuidutils.generate_uuid(dashed=True), "provider_name": "mock_provider", "availabilityzone_data": '{"mock_key": "mock_value"}', } ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/unit/osc/v2/fakes.py0000664000175000017500000000337300000000000025442 0ustar00zuulzuul00000000000000# 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. # import copy from unittest import mock from osc_lib.tests import utils from octaviaclient.tests import fakes from octaviaclient.tests.unit.osc.v2 import constants class FakeOctaviaClient(object): def __init__(self, **kwargs): self.load_balancers = mock.Mock() self.load_balancers.resource_class = fakes.FakeResource(None, {}) self.auth_token = kwargs['token'] self.management_url = kwargs['endpoint'] class TestOctaviaClient(utils.TestCommand): def setUp(self): super().setUp() self.app.client_manager.load_balancer = FakeOctaviaClient( endpoint=fakes.AUTH_URL, token=fakes.AUTH_TOKEN, ) def createFakeResource(name, attrs=None): """Creates a single fake resource object. :param name: resource_name :param attrs: ``dict`` of customized resource attributes :returns: A FakeResource object """ attrs = attrs or {} # Set to default resource_info = getattr(constants, "{}_attrs".format(name).upper()) assert resource_info is not None, "{} is not found".format(name) resource_info.update(attrs) return fakes.FakeResource( info=copy.deepcopy(resource_info), loaded=True, ) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/unit/osc/v2/test_amphora.py0000664000175000017500000002676200000000000027046 0ustar00zuulzuul00000000000000# 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. # import copy from unittest import mock import osc_lib.tests.utils as osc_test_utils from oslo_utils import uuidutils from octaviaclient.osc.v2 import amphora from octaviaclient.osc.v2 import constants from octaviaclient.tests.unit.osc.v2 import constants as attr_consts from octaviaclient.tests.unit.osc.v2 import fakes class TestAmphora(fakes.TestOctaviaClient): def setUp(self): super().setUp() self._amp = fakes.createFakeResource('amphora') self.amp_info = copy.deepcopy(attr_consts.AMPHORA_ATTRS) self.columns = copy.deepcopy(constants.AMPHORA_COLUMNS) self.columns_long = copy.deepcopy(constants.AMPHORA_COLUMNS_LONG) self.rows = copy.deepcopy(constants.AMPHORA_ROWS) info_list = {'amphorae': [ {k: v for k, v in attr_consts.AMPHORA_ATTRS.items() if ( k in self.columns_long)}, ]} self.api_mock = mock.Mock() self.api_mock.amphora_list.return_value = info_list self.api_mock.amphora_show.return_value = info_list['amphorae'][0] lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock class TestAmphoraList(TestAmphora): def setUp(self): super().setUp() self.data_list = (tuple( attr_consts.AMPHORA_ATTRS[k] for k in self.columns),) self.data_list_long = (tuple( attr_consts.AMPHORA_ATTRS[k] for k in self.columns_long),) self.cmd = amphora.ListAmphora(self.app, None) def test_amphora_list_no_options(self): arglist = [] verify_list = [] parsed_args = self.check_parser(self.cmd, arglist, verify_list) columns, data = self.cmd.take_action(parsed_args) self.api_mock.amphora_list.assert_called_with() self.assertEqual(self.columns, columns) self.assertEqual(self.data_list, tuple(data)) def test_amphora_list_long(self): arglist = ['--long'] verify_list = [] parsed_args = self.check_parser(self.cmd, arglist, verify_list) columns, data = self.cmd.take_action(parsed_args) self.api_mock.amphora_list.assert_called_with() self.assertEqual(self.columns_long, columns) self.assertEqual(self.data_list_long, tuple(data)) @mock.patch('octaviaclient.osc.v2.utils.get_amphora_attrs') def test_amphora_list_with_loadbalancer(self, mock_client): mock_client.return_value = { 'loadbalancer_id': self._amp.loadbalancer_id, 'compute_id': self._amp.compute_id, 'role': self._amp.role, 'status': self._amp.status, } arglist = [ '--loadbalancer', self._amp.loadbalancer_id, '--compute-id', self._amp.compute_id, '--role', 'Master', '--status', 'allocAted', ] verify_list = [ ('loadbalancer', self._amp.loadbalancer_id), ('compute_id', self._amp.compute_id), ('role', 'MASTER'), ('status', 'ALLOCATED'), ] parsed_args = self.check_parser(self.cmd, arglist, verify_list) columns, data = self.cmd.take_action(parsed_args) self.assertEqual(self.columns, columns) self.assertEqual(self.data_list, tuple(data)) class TestAmphoraShow(TestAmphora): def setUp(self): super().setUp() self.cmd = amphora.ShowAmphora(self.app, None) def test_amphora_show_no_args(self): self.assertRaises( osc_test_utils.ParserException, self.check_parser, self.cmd, [], [], ) @mock.patch('octaviaclient.osc.v2.utils.get_amphora_attrs') def test_amphora_show(self, mock_client): mock_client.return_value = {'amphora_id': self._amp.id} arglist = [self._amp.id] verify_list = [('amphora_id', self._amp.id)] parsed_args = self.check_parser(self.cmd, arglist, verify_list) rows, data = self.cmd.take_action(parsed_args) self.assertEqual(self.rows, rows) self.api_mock.amphora_show.assert_called_with(amphora_id=self._amp.id) class TestAmphoraConfigure(TestAmphora): def setUp(self): super().setUp() self.cmd = amphora.ConfigureAmphora(self.app, None) def test_amphora_configure(self): arglist = [self._amp.id] verify_list = [('amphora_id', self._amp.id)] parsed_args = self.check_parser(self.cmd, arglist, verify_list) self.cmd.take_action(parsed_args) self.api_mock.amphora_configure.assert_called_with( amphora_id=self._amp.id) @mock.patch('osc_lib.utils.wait_for_status') def test_amphora_configure_linked_wait(self, mock_wait): arglist = [self._amp.id, '--wait'] verify_list = [('amphora_id', self._amp.id)] parsed_args = self.check_parser(self.cmd, arglist, verify_list) self.cmd.take_action(parsed_args) self.api_mock.amphora_configure.assert_called_with( amphora_id=self._amp.id) mock_wait.assert_called_once_with( status_f=mock.ANY, res_id=self._amp.loadbalancer_id, sleep_time=mock.ANY, status_field='provisioning_status') @mock.patch('osc_lib.utils.wait_for_status') def test_amphora_configure_unlinked_wait(self, mock_wait): self.api_mock.amphora_show.return_value.pop('loadbalancer_id') arglist = [self._amp.id, '--wait'] verify_list = [('amphora_id', self._amp.id)] parsed_args = self.check_parser(self.cmd, arglist, verify_list) self.cmd.take_action(parsed_args) self.api_mock.amphora_configure.assert_called_with( amphora_id=self._amp.id) # TODO(rm_work): No wait expected if the amp isn't linked to an LB? mock_wait.assert_not_called() class TestAmphoraFailover(TestAmphora): def setUp(self): super().setUp() self.cmd = amphora.FailoverAmphora(self.app, None) def test_amphora_failover(self): arglist = [self._amp.id] verify_list = [('amphora_id', self._amp.id)] parsed_args = self.check_parser(self.cmd, arglist, verify_list) self.cmd.take_action(parsed_args) self.api_mock.amphora_failover.assert_called_with( amphora_id=self._amp.id) @mock.patch('osc_lib.utils.wait_for_status') @mock.patch('osc_lib.utils.wait_for_delete') def test_amphora_failover_linked_wait(self, mock_wait_delete, mock_wait_active): arglist = [self._amp.id, '--wait'] verify_list = [ ('amphora_id', self._amp.id), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verify_list) self.cmd.take_action(parsed_args) self.api_mock.amphora_failover.assert_called_with( amphora_id=self._amp.id) mock_wait_active.assert_called_once_with( status_f=mock.ANY, res_id=self._amp.loadbalancer_id, sleep_time=mock.ANY, status_field='provisioning_status') mock_wait_delete.assert_not_called() @mock.patch('osc_lib.utils.wait_for_status') @mock.patch('osc_lib.utils.wait_for_delete') def test_amphora_failover_unlinked_wait(self, mock_wait_delete, mock_wait_active): self.api_mock.amphora_show.return_value.pop('loadbalancer_id') arglist = [self._amp.id, '--wait'] verify_list = [ ('amphora_id', self._amp.id), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verify_list) self.cmd.take_action(parsed_args) self.api_mock.amphora_failover.assert_called_with( amphora_id=self._amp.id) mock_wait_active.assert_not_called() mock_wait_delete.assert_called_once_with( manager=mock.ANY, res_id=self._amp.id, sleep_time=mock.ANY, status_field='provisioning_status') class TestAmphoraStatsShow(TestAmphora): def setUp(self): super().setUp() # map fake listener_id to fake bytes_in counter self.stats = { uuidutils.generate_uuid(): 12, uuidutils.generate_uuid(): 34, } amphora_stats_info = [ {'listener_id': k, 'bytes_in': self.stats[k]} for k in self.stats] self.api_mock.amphora_stats_show.return_value = { 'amphora_stats': amphora_stats_info} lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = amphora.ShowAmphoraStats(self.app, None) def test_amphora_stats_show(self): arglist = [self._amp.id] verifylist = [ ('amphora_id', self._amp.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.amphora_stats_show.assert_called_with( amphora_id=self._amp.id) column_idx = columns.index('bytes_in') total_bytes_in = sum(self.stats.values()) self.assertEqual(data[column_idx], total_bytes_in) @mock.patch('octaviaclient.osc.v2.utils.get_listener_attrs') def test_amphora_stats_show_with_listener_id(self, mock_get_listener_attrs): listener_id = list(self.stats)[0] arglist = ['--listener', listener_id, self._amp.id] verifylist = [ ('amphora_id', self._amp.id), ] mock_get_listener_attrs.return_value = { 'listener_id': listener_id } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.amphora_stats_show.assert_called_with( amphora_id=self._amp.id) column_idx = columns.index('bytes_in') bytes_in = self.stats[listener_id] self.assertEqual(data[column_idx], bytes_in) class TestAmphoraDelete(TestAmphora): def setUp(self): super(TestAmphoraDelete, self).setUp() self.cmd = amphora.DeleteAmphora(self.app, None) def test_amphora_delete(self): arglist = [self._amp.id] verifylist = [ ('amphora_id', self._amp.id) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.amphora_delete.assert_called_with( amphora_id=self._amp.id) @mock.patch('osc_lib.utils.wait_for_delete') def test_amphora_delete_wait(self, mock_wait): arglist = [self._amp.id, '--wait'] verifylist = [ ('amphora_id', self._amp.id), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.amphora_delete.assert_called_with( amphora_id=self._amp.id) mock_wait.assert_called_once_with( manager=mock.ANY, res_id=self._amp.id, sleep_time=mock.ANY, status_field='status') ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/unit/osc/v2/test_availabilityzone.py0000664000175000017500000002163000000000000030752 0ustar00zuulzuul00000000000000# # All Rights Reserved. # # 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. import copy from unittest import mock from osc_lib import exceptions from octaviaclient.osc.v2 import availabilityzone from octaviaclient.osc.v2 import constants from octaviaclient.tests.unit.osc.v2 import constants as attr_consts from octaviaclient.tests.unit.osc.v2 import fakes class TestAvailabilityzone(fakes.TestOctaviaClient): def setUp(self): super().setUp() self._availabilityzone = fakes.createFakeResource('availability_zone') self.availabilityzone_info = copy.deepcopy( attr_consts.AVAILABILITY_ZONE_ATTRS) self.columns = copy.deepcopy(constants.AVAILABILITYZONE_COLUMNS) self.api_mock = mock.Mock() self.api_mock.availabilityzone_list.return_value = copy.deepcopy( {'availability_zones': [attr_consts.AVAILABILITY_ZONE_ATTRS]}) lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock class TestAvailabilityzoneList(TestAvailabilityzone): def setUp(self): super().setUp() self.datalist = (tuple( attr_consts.AVAILABILITY_ZONE_ATTRS[k] for k in self.columns),) self.cmd = availabilityzone.ListAvailabilityzone(self.app, None) def test_availabilityzone_list_no_options(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.availabilityzone_list.assert_called_with() self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_availabilityzone_list_with_options(self): arglist = ['--name', 'availabilityzone1'] verifylist = [('name', 'availabilityzone1')] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.availabilityzone_list.assert_called_with( name='availabilityzone1') self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) class TestAvailabilityzoneDelete(TestAvailabilityzone): def setUp(self): super().setUp() self.cmd = availabilityzone.DeleteAvailabilityzone(self.app, None) def test_availabilityzone_delete(self): arglist = [self._availabilityzone.name] verifylist = [ ('availabilityzone', self._availabilityzone.name) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.availabilityzone_delete.assert_called_with( availabilityzone_name=self._availabilityzone.name) def test_availabilityzone_delete_failure(self): arglist = ['unknown_availabilityzone'] verifylist = [ ('availabilityzone', 'unknown_availabilityzone') ] self.api_mock.availabilityzone_list.return_value = { 'availability_zones': []} parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertNotCalled(self.api_mock.availabilityzone_delete) class TestAvailabilityzoneCreate(TestAvailabilityzone): def setUp(self): super().setUp() self.api_mock.availabilityzone_create.return_value = { 'availability_zone': self.availabilityzone_info} lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = availabilityzone.CreateAvailabilityzone(self.app, None) @mock.patch('octaviaclient.osc.v2.utils.get_availabilityzone_attrs') def test_availabilityzone_create(self, mock_client): mock_client.return_value = self.availabilityzone_info arglist = ['--name', self._availabilityzone.name, '--availabilityzoneprofile', 'mock_azpf_id', '--description', 'description for availabilityzone'] verifylist = [ ('availabilityzoneprofile', 'mock_azpf_id'), ('name', self._availabilityzone.name), ('description', 'description for availabilityzone') ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.availabilityzone_create.assert_called_with( json={'availability_zone': self.availabilityzone_info}) class TestAvailabilityzoneShow(TestAvailabilityzone): def setUp(self): super().setUp() mock_show = self.api_mock.availabilityzone_show mock_show.return_value = self.availabilityzone_info lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = availabilityzone.ShowAvailabilityzone(self.app, None) def test_availabilityzone_show(self): arglist = [self._availabilityzone.name] verifylist = [ ('availabilityzone', self._availabilityzone.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.availabilityzone_show.assert_called_with( availabilityzone_name=self._availabilityzone.name) class TestAvailabilityzoneSet(TestAvailabilityzone): def setUp(self): super().setUp() self.cmd = availabilityzone.SetAvailabilityzone(self.app, None) def test_availabilityzone_set(self): arglist = [self._availabilityzone.name, '--description', 'new_desc'] verifylist = [ ('availabilityzone', self._availabilityzone.name), ('description', 'new_desc'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.availabilityzone_set.assert_called_with( self._availabilityzone.name, json={ 'availability_zone': { 'description': 'new_desc' }}) class TestAvailabilityzoneUnset(TestAvailabilityzone): PARAMETERS = ('description',) def setUp(self): super().setUp() self.cmd = availabilityzone.UnsetAvailabilityzone(self.app, None) def test_hm_unset_description(self): self._test_availabilityzone_unset_param('description') def _test_availabilityzone_unset_param(self, param): self.api_mock.availabilityzone_set.reset_mock() arg_param = param.replace('_', '-') if '_' in param else param arglist = [self._availabilityzone.name, '--%s' % arg_param] ref_body = {'availability_zone': {param: None}} verifylist = [ ('availabilityzone', self._availabilityzone.name), ] for ref_param in self.PARAMETERS: verifylist.append((ref_param, param == ref_param)) print(verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.availabilityzone_set.assert_called_once_with( self._availabilityzone.name, json=ref_body) def test_availabilityzone_unset_all(self): self.api_mock.availabilityzone_set.reset_mock() ref_body = {'availability_zone': {x: None for x in self.PARAMETERS}} arglist = [self._availabilityzone.name] for ref_param in self.PARAMETERS: arg_param = (ref_param.replace('_', '-') if '_' in ref_param else ref_param) arglist.append('--%s' % arg_param) verifylist = list(zip(self.PARAMETERS, [True] * len(self.PARAMETERS))) verifylist = [('availabilityzone', self._availabilityzone.name)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.availabilityzone_set.assert_called_once_with( self._availabilityzone.name, json=ref_body) def test_availabilityzone_unset_none(self): self.api_mock.availabilityzone_set.reset_mock() arglist = [self._availabilityzone.name] verifylist = list(zip(self.PARAMETERS, [False] * len(self.PARAMETERS))) verifylist = [('availabilityzone', self._availabilityzone.name)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.availabilityzone_set.assert_not_called() ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/unit/osc/v2/test_availabilityzoneprofile.py0000664000175000017500000001743300000000000032341 0ustar00zuulzuul00000000000000# # All Rights Reserved. # # 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. import copy from unittest import mock from osc_lib import exceptions from octaviaclient.osc.v2 import availabilityzoneprofile from octaviaclient.osc.v2 import constants from octaviaclient.tests.unit.osc.v2 import constants as attr_consts from octaviaclient.tests.unit.osc.v2 import fakes class TestAvailabilityzoneProfile(fakes.TestOctaviaClient): def setUp(self): super().setUp() self._availabilityzoneprofile = fakes.createFakeResource( 'availability_zone_profile') self.availabilityzoneprofile_info = copy.deepcopy( attr_consts.AVAILABILITY_ZONE_PROFILE_ATTRS) self.columns = copy.deepcopy(constants.AVAILABILITYZONEPROFILE_COLUMNS) self.api_mock = mock.Mock() mock_list = self.api_mock.availabilityzoneprofile_list mock_list.return_value = copy.deepcopy({'availability_zone_profiles': [ attr_consts.AVAILABILITY_ZONE_PROFILE_ATTRS]}) lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock class TestAvailabilityzoneProfileList(TestAvailabilityzoneProfile): def setUp(self): super().setUp() self.datalist = (tuple( attr_consts.AVAILABILITY_ZONE_PROFILE_ATTRS[k] for k in self.columns),) self.cmd = availabilityzoneprofile.ListAvailabilityzoneProfile( self.app, None) def test_availabilityzoneprofile_list_no_options(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.availabilityzoneprofile_list.assert_called_with() self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_availabilityzoneprofile_list_with_options(self): arglist = ['--name', 'availabilityzoneprofile1'] verifylist = [('name', 'availabilityzoneprofile1')] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.availabilityzoneprofile_list.assert_called_with( name='availabilityzoneprofile1') self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) class TestAvailabilityzoneProfileDelete(TestAvailabilityzoneProfile): def setUp(self): super().setUp() self.cmd = availabilityzoneprofile.DeleteAvailabilityzoneProfile( self.app, None) def test_availabilityzoneprofile_delete(self): arglist = [self._availabilityzoneprofile.id] verifylist = [ ('availabilityzoneprofile', self._availabilityzoneprofile.id) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.availabilityzoneprofile_delete.assert_called_with( availabilityzoneprofile_id=self._availabilityzoneprofile.id) def test_availabilityzoneprofile_delete_failure(self): arglist = ['unknown_availabilityzoneprofile'] verifylist = [ ('availabilityzoneprofile', 'unknown_availabilityzoneprofile') ] self.api_mock.availabilityzoneprofile_list.return_value = { 'availability_zone_profiles': []} parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertNotCalled(self.api_mock.availabilityzoneprofile_delete) class TestAvailabilityzoneProfileCreate(TestAvailabilityzoneProfile): def setUp(self): super().setUp() self.api_mock.availabilityzoneprofile_create.return_value = { 'availability_zone_profile': self.availabilityzoneprofile_info} lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = availabilityzoneprofile.CreateAvailabilityzoneProfile( self.app, None) @mock.patch('octaviaclient.osc.v2.utils.get_availabilityzoneprofile_attrs') def test_availabilityzoneprofile_create(self, mock_client): mock_client.return_value = self.availabilityzoneprofile_info arglist = ['--name', self._availabilityzoneprofile.name, '--provider', 'mock_provider', '--availability-zone-data', '{"mock_key": "mock_value"}'] verifylist = [ ('provider', 'mock_provider'), ('name', self._availabilityzoneprofile.name), ('availability_zone_data', '{"mock_key": "mock_value"}') ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.availabilityzoneprofile_create.assert_called_with( json={ 'availability_zone_profile': self.availabilityzoneprofile_info }) class TestAvailabilityzoneProfileShow(TestAvailabilityzoneProfile): def setUp(self): super().setUp() mock_show = self.api_mock.availabilityzoneprofile_show mock_show.return_value = self.availabilityzoneprofile_info lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = availabilityzoneprofile.ShowAvailabilityzoneProfile( self.app, None) def test_availabilityzoneprofile_show(self): arglist = [self._availabilityzoneprofile.id] verifylist = [ ('availabilityzoneprofile', self._availabilityzoneprofile.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.availabilityzoneprofile_show.assert_called_with( availabilityzoneprofile_id=self._availabilityzoneprofile.id) class TestAvailabilityzoneProfileSet(TestAvailabilityzoneProfile): def setUp(self): super().setUp() self.cmd = availabilityzoneprofile.SetAvailabilityzoneProfile( self.app, None) def test_availabilityzoneprofile_set(self): arglist = [self._availabilityzoneprofile.id, '--name', 'new_name'] verifylist = [ ('availabilityzoneprofile', self._availabilityzoneprofile.id), ('name', 'new_name'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.availabilityzoneprofile_set.assert_called_with( self._availabilityzoneprofile.id, json={ 'availability_zone_profile': { 'name': 'new_name' }}) arglist = [self._availabilityzoneprofile.id, '--availability-zone-data', '{"key1": "value1"}'] verifylist = [ ('availabilityzoneprofile', self._availabilityzoneprofile.id), ('availability_zone_data', '{"key1": "value1"}'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.availabilityzoneprofile_set.assert_called_with( self._availabilityzoneprofile.id, json={ 'availability_zone_profile': { 'availability_zone_data': '{"key1": "value1"}' }}) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/unit/osc/v2/test_flavor.py0000664000175000017500000001750700000000000026705 0ustar00zuulzuul00000000000000# Copyright (c) 2018 China Telecom Corporation # All Rights Reserved. # # 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. import copy from unittest import mock from osc_lib import exceptions from octaviaclient.osc.v2 import constants from octaviaclient.osc.v2 import flavor from octaviaclient.tests.unit.osc.v2 import constants as attr_consts from octaviaclient.tests.unit.osc.v2 import fakes class TestFlavor(fakes.TestOctaviaClient): def setUp(self): super().setUp() self._flavor = fakes.createFakeResource('flavor') self.flavor_info = copy.deepcopy(attr_consts.FLAVOR_ATTRS) self.columns = copy.deepcopy(constants.FLAVOR_COLUMNS) self.api_mock = mock.Mock() self.api_mock.flavor_list.return_value = copy.deepcopy( {'flavors': [attr_consts.FLAVOR_ATTRS]}) lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock class TestFlavorList(TestFlavor): def setUp(self): super().setUp() self.datalist = (tuple( attr_consts.FLAVOR_ATTRS[k] for k in self.columns),) self.cmd = flavor.ListFlavor(self.app, None) def test_flavor_list_no_options(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.flavor_list.assert_called_with() self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_flavor_list_with_options(self): arglist = ['--name', 'flavor1'] verifylist = [('name', 'flavor1')] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.flavor_list.assert_called_with(name='flavor1') self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) class TestFlavorDelete(TestFlavor): def setUp(self): super().setUp() self.cmd = flavor.DeleteFlavor(self.app, None) def test_flavor_delete(self): arglist = [self._flavor.id] verifylist = [ ('flavor', self._flavor.id) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.flavor_delete.assert_called_with( flavor_id=self._flavor.id) def test_flavor_delete_failure(self): arglist = ['unknown_flavor'] verifylist = [ ('flavor', 'unknown_flavor') ] self.api_mock.flavor_list.return_value = {'flavors': []} parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertNotCalled(self.api_mock.flavor_delete) class TestFlavorCreate(TestFlavor): def setUp(self): super().setUp() self.api_mock.flavor_create.return_value = { 'flavor': self.flavor_info} lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = flavor.CreateFlavor(self.app, None) @mock.patch('octaviaclient.osc.v2.utils.get_flavor_attrs') def test_flavor_create(self, mock_client): mock_client.return_value = self.flavor_info arglist = ['--name', self._flavor.name, '--flavorprofile', 'mock_fvpf_id', '--description', 'description for flavor'] verifylist = [ ('flavorprofile', 'mock_fvpf_id'), ('name', self._flavor.name), ('description', 'description for flavor') ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.flavor_create.assert_called_with( json={'flavor': self.flavor_info}) class TestFlavorShow(TestFlavor): def setUp(self): super().setUp() self.api_mock.flavor_show.return_value = self.flavor_info lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = flavor.ShowFlavor(self.app, None) def test_flavor_show(self): arglist = [self._flavor.id] verifylist = [ ('flavor', self._flavor.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.flavor_show.assert_called_with( flavor_id=self._flavor.id) class TestFlavorSet(TestFlavor): def setUp(self): super().setUp() self.cmd = flavor.SetFlavor(self.app, None) def test_flavor_set(self): arglist = [self._flavor.id, '--name', 'new_name', '--description', 'new_desc'] verifylist = [ ('flavor', self._flavor.id), ('name', 'new_name'), ('description', 'new_desc') ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.flavor_set.assert_called_with( self._flavor.id, json={ 'flavor': { 'name': 'new_name', 'description': 'new_desc' }}) class TestFlavorUnset(TestFlavor): PARAMETERS = ('description',) def setUp(self): super().setUp() self.cmd = flavor.UnsetFlavor(self.app, None) def test_hm_unset_description(self): self._test_flavor_unset_param('description') def _test_flavor_unset_param(self, param): self.api_mock.flavor_set.reset_mock() arg_param = param.replace('_', '-') if '_' in param else param arglist = [self._flavor.id, '--%s' % arg_param] ref_body = {'flavor': {param: None}} verifylist = [ ('flavor', self._flavor.id), ] for ref_param in self.PARAMETERS: verifylist.append((ref_param, param == ref_param)) print(verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.flavor_set.assert_called_once_with( self._flavor.id, json=ref_body) def test_flavor_unset_all(self): self.api_mock.flavor_set.reset_mock() ref_body = {'flavor': {x: None for x in self.PARAMETERS}} arglist = [self._flavor.id] for ref_param in self.PARAMETERS: arg_param = (ref_param.replace('_', '-') if '_' in ref_param else ref_param) arglist.append('--%s' % arg_param) verifylist = list(zip(self.PARAMETERS, [True] * len(self.PARAMETERS))) verifylist = [('flavor', self._flavor.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.flavor_set.assert_called_once_with( self._flavor.id, json=ref_body) def test_flavor_unset_none(self): self.api_mock.flavor_set.reset_mock() arglist = [self._flavor.id] verifylist = list(zip(self.PARAMETERS, [False] * len(self.PARAMETERS))) verifylist = [('flavor', self._flavor.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.flavor_set.assert_not_called() ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/unit/osc/v2/test_flavorprofile.py0000664000175000017500000001427600000000000030266 0ustar00zuulzuul00000000000000# Copyright (c) 2018 China Telecom Corporation # All Rights Reserved. # # 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. import copy from unittest import mock from osc_lib import exceptions from octaviaclient.osc.v2 import constants from octaviaclient.osc.v2 import flavorprofile from octaviaclient.tests.unit.osc.v2 import constants as attr_consts from octaviaclient.tests.unit.osc.v2 import fakes class TestFlavorProfile(fakes.TestOctaviaClient): def setUp(self): super().setUp() self._flavorprofile = fakes.createFakeResource('flavorprofile') self.flavorprofile_info = copy.deepcopy( attr_consts.FLAVORPROFILE_ATTRS) self.columns = copy.deepcopy(constants.FLAVORPROFILE_COLUMNS) self.api_mock = mock.Mock() self.api_mock.flavorprofile_list.return_value = copy.deepcopy( {'flavorprofiles': [attr_consts.FLAVORPROFILE_ATTRS]}) lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock class TestFlavorProfileList(TestFlavorProfile): def setUp(self): super().setUp() self.datalist = (tuple( attr_consts.FLAVORPROFILE_ATTRS[k] for k in self.columns),) self.cmd = flavorprofile.ListFlavorProfile(self.app, None) def test_flavorprofile_list_no_options(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.flavorprofile_list.assert_called_with() self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_flavorprofile_list_with_options(self): arglist = ['--name', 'flavorprofile1'] verifylist = [('name', 'flavorprofile1')] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.flavorprofile_list.assert_called_with( name='flavorprofile1') self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) class TestFlavorProfileDelete(TestFlavorProfile): def setUp(self): super().setUp() self.cmd = flavorprofile.DeleteFlavorProfile(self.app, None) def test_flavorprofile_delete(self): arglist = [self._flavorprofile.id] verifylist = [ ('flavorprofile', self._flavorprofile.id) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.flavorprofile_delete.assert_called_with( flavorprofile_id=self._flavorprofile.id) def test_flavorprofile_delete_failure(self): arglist = ['unknown_flavorprofile'] verifylist = [ ('flavorprofile', 'unknown_flavorprofile') ] self.api_mock.flavorprofile_list.return_value = { 'flavorprofiles': []} parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertNotCalled(self.api_mock.flavorprofile_delete) class TestFlavorProfileCreate(TestFlavorProfile): def setUp(self): super().setUp() self.api_mock.flavorprofile_create.return_value = { 'flavorprofile': self.flavorprofile_info} lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = flavorprofile.CreateFlavorProfile(self.app, None) @mock.patch('octaviaclient.osc.v2.utils.get_flavorprofile_attrs') def test_flavorprofile_create(self, mock_client): mock_client.return_value = self.flavorprofile_info arglist = ['--name', self._flavorprofile.name, '--provider', 'mock_provider', '--flavor-data', '{"mock_key": "mock_value"}'] verifylist = [ ('provider', 'mock_provider'), ('name', self._flavorprofile.name), ('flavor_data', '{"mock_key": "mock_value"}') ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.flavorprofile_create.assert_called_with( json={'flavorprofile': self.flavorprofile_info}) class TestFlavorProfileShow(TestFlavorProfile): def setUp(self): super().setUp() self.api_mock.flavorprofile_show.return_value = self.flavorprofile_info lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = flavorprofile.ShowFlavorProfile(self.app, None) def test_flavorprofile_show(self): arglist = [self._flavorprofile.id] verifylist = [ ('flavorprofile', self._flavorprofile.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.flavorprofile_show.assert_called_with( flavorprofile_id=self._flavorprofile.id) class TestFlavorProfileSet(TestFlavorProfile): def setUp(self): super().setUp() self.cmd = flavorprofile.SetFlavorProfile(self.app, None) def test_flavorprofile_set(self): arglist = [self._flavorprofile.id, '--name', 'new_name'] verifylist = [ ('flavorprofile', self._flavorprofile.id), ('name', 'new_name'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.flavorprofile_set.assert_called_with( self._flavorprofile.id, json={ 'flavorprofile': { 'name': 'new_name' }}) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/unit/osc/v2/test_health_monitor.py0000664000175000017500000004610100000000000030420 0ustar00zuulzuul00000000000000# Copyright 2019 Red Hat, Inc. All rights reserved. # # 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. # import copy from unittest import mock from osc_lib import exceptions from octaviaclient.osc.v2 import constants from octaviaclient.osc.v2 import health_monitor from octaviaclient.tests.unit.osc.v2 import constants as attr_consts from octaviaclient.tests.unit.osc.v2 import fakes class TestHealthMonitor(fakes.TestOctaviaClient): def setUp(self): super().setUp() self._hm = fakes.createFakeResource('hm') self.hm_info = copy.deepcopy(attr_consts.HM_ATTRS) self.columns = copy.deepcopy(constants.MONITOR_COLUMNS) info_list = {'healthmonitors': [ {k: v for k, v in attr_consts.HM_ATTRS.items() if ( k in self.columns)}, ]} self.api_mock = mock.Mock() self.api_mock.health_monitor_list.return_value = info_list lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock class TestHealthMonitorList(TestHealthMonitor): def setUp(self): super().setUp() self.datalist = (tuple(attr_consts.HM_ATTRS[k] for k in self.columns),) self.cmd = health_monitor.ListHealthMonitor(self.app, None) def test_health_monitor_list_no_options(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.health_monitor_list.assert_called_with() self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_health_monitor_list_with_tags(self): arglist = ['--tags', 'foo,bar'] verifylist = [('tags', ['foo', 'bar'])] expected_attrs = { 'tags': ['foo', 'bar'] } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.health_monitor_list.assert_called_with(**expected_attrs) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_health_monitor_list_with_any_tags(self): arglist = ['--any-tags', 'foo,bar'] verifylist = [('any_tags', ['foo', 'bar'])] expected_attrs = { 'tags-any': ['foo', 'bar'] } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.health_monitor_list.assert_called_with(**expected_attrs) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_health_monitor_list_with_not_tags(self): arglist = ['--not-tags', 'foo,bar'] verifylist = [('not_tags', ['foo', 'bar'])] expected_attrs = { 'not-tags': ['foo', 'bar'] } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.health_monitor_list.assert_called_with(**expected_attrs) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_health_monitor_list_with_not_any_tags(self): arglist = ['--not-any-tags', 'foo,bar'] verifylist = [('not_any_tags', ['foo', 'bar'])] expected_attrs = { 'not-tags-any': ['foo', 'bar'] } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.health_monitor_list.assert_called_with(**expected_attrs) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) class TestHealthMonitorDelete(TestHealthMonitor): def setUp(self): super().setUp() self.cmd = health_monitor.DeleteHealthMonitor(self.app, None) def test_health_monitor_delete(self): arglist = [self._hm.id] verifylist = [ ('health_monitor', self._hm.id) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.health_monitor_delete.assert_called_with( health_monitor_id=self._hm.id) @mock.patch('osc_lib.utils.wait_for_delete') def test_health_monitor_delete_wait(self, mock_wait): arglist = [self._hm.id, '--wait'] verifylist = [ ('health_monitor', self._hm.id), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.health_monitor_delete.assert_called_with( health_monitor_id=self._hm.id) mock_wait.assert_called_once_with( manager=mock.ANY, res_id=self._hm.id, sleep_time=mock.ANY, status_field='provisioning_status') def test_health_monitor_delete_failure(self): arglist = ['unknown_hm'] verifylist = [ ('health_monitor', 'unknown_hm') ] self.api_mock.health_monitor_list.return_value = { 'healthmonitors': []} parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertNotCalled(self.api_mock.health_monitor_delete) class TestHealthMonitorCreate(TestHealthMonitor): def setUp(self): super().setUp() self.api_mock = mock.Mock() self.api_mock.health_monitor_create.return_value = { 'healthmonitor': self.hm_info} lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = health_monitor.CreateHealthMonitor(self.app, None) @mock.patch('octaviaclient.osc.v2.utils.get_health_monitor_attrs') def test_health_monitor_create(self, mock_client): mock_client.return_value = self.hm_info arglist = ['mock_pool_id', '--name', self._hm.name, '--delay', str(self._hm.delay), '--timeout', str(self._hm.timeout), '--max-retries', str(self._hm.max_retries), '--type', self._hm.type.lower(), '--http-method', self._hm.http_method.lower(), '--http-version', str(self._hm.http_version), '--domain-name', self._hm.domain_name] verifylist = [ ('pool', 'mock_pool_id'), ('name', self._hm.name), ('delay', str(self._hm.delay)), ('timeout', str(self._hm.timeout)), ('max_retries', self._hm.max_retries), ('type', self._hm.type), ('http_method', self._hm.http_method), ('http_version', self._hm.http_version), ('domain_name', self._hm.domain_name) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.health_monitor_create.assert_called_with( json={'healthmonitor': self.hm_info}) @mock.patch('osc_lib.utils.wait_for_status') @mock.patch('octaviaclient.osc.v2.utils.get_health_monitor_attrs') def test_health_monitor_create_wait(self, mock_client, mock_wait): self.hm_info['pools'] = [{'id': 'mock_pool_id'}] mock_client.return_value = self.hm_info self.api_mock.pool_show.return_value = { 'loadbalancers': [{'id': 'mock_lb_id'}]} self.api_mock.health_monitor_show.return_value = self.hm_info arglist = ['mock_pool_id', '--name', self._hm.name, '--delay', str(self._hm.delay), '--timeout', str(self._hm.timeout), '--max-retries', str(self._hm.max_retries), '--type', self._hm.type.lower(), '--http-method', self._hm.http_method.lower(), '--http-version', str(self._hm.http_version), '--domain-name', self._hm.domain_name, '--wait'] verifylist = [ ('pool', 'mock_pool_id'), ('name', self._hm.name), ('delay', str(self._hm.delay)), ('timeout', str(self._hm.timeout)), ('max_retries', self._hm.max_retries), ('type', self._hm.type), ('http_method', self._hm.http_method), ('http_version', self._hm.http_version), ('domain_name', self._hm.domain_name), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.health_monitor_create.assert_called_with( json={'healthmonitor': self.hm_info}) mock_wait.assert_called_once_with( status_f=mock.ANY, res_id='mock_lb_id', sleep_time=mock.ANY, status_field='provisioning_status') @mock.patch('octaviaclient.osc.v2.utils.get_health_monitor_attrs') def test_health_monitor_create_with_tag(self, mock_attrs): mock_attrs.return_value = self.hm_info arglist = ['mock_pool_id', '--name', self._hm.name, '--delay', str(self._hm.delay), '--timeout', str(self._hm.timeout), '--max-retries', str(self._hm.max_retries), '--type', self._hm.type.lower(), '--tag', 'foo'] verifylist = [ ('pool', 'mock_pool_id'), ('name', self._hm.name), ('delay', str(self._hm.delay)), ('timeout', str(self._hm.timeout)), ('max_retries', self._hm.max_retries), ('type', self._hm.type), ('tags', ['foo']) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.health_monitor_create.assert_called_with( json={'healthmonitor': self.hm_info}) class TestHealthMonitorShow(TestHealthMonitor): def setUp(self): super().setUp() self.api_mock.health_monitor_show.return_value = { 'healthmonitor': self.hm_info, } lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = health_monitor.ShowHealthMonitor(self.app, None) def test_health_monitor_show(self): arglist = [self._hm.id] verifylist = [ ('health_monitor', self._hm.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.health_monitor_show.assert_called_with( health_monitor_id=self._hm.id) class TestHealthMonitorSet(TestHealthMonitor): def setUp(self): super().setUp() self.cmd = health_monitor.SetHealthMonitor(self.app, None) def test_health_monitor_set(self): arglist = [self._hm.id, '--name', 'new_name', '--http-version', str(self._hm.http_version), '--domain-name', self._hm.domain_name] verifylist = [ ('health_monitor', self._hm.id), ('name', 'new_name'), ('http_version', self._hm.http_version), ('domain_name', self._hm.domain_name) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.health_monitor_set.assert_called_with( self._hm.id, json={'healthmonitor': { 'name': 'new_name', 'http_version': self._hm.http_version, 'domain_name': self._hm.domain_name}}) @mock.patch('osc_lib.utils.wait_for_status') def test_health_monitor_set_wait(self, mock_wait): arglist = [self._hm.id, '--name', 'new_name', '--wait'] verifylist = [ ('health_monitor', self._hm.id), ('name', 'new_name'), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.health_monitor_set.assert_called_with( self._hm.id, json={'healthmonitor': {'name': 'new_name'}}) mock_wait.assert_called_once_with( status_f=mock.ANY, res_id=self._hm.id, sleep_time=mock.ANY, status_field='provisioning_status') def test_health_monitor_set_tag(self): self.api_mock.health_monitor_show.return_value = { 'tags': ['foo'] } arglist = [self._hm.id, '--tag', 'bar'] verifylist = [ ('health_monitor', self._hm.id), ('tags', ['bar']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.health_monitor_set.assert_called_once() kwargs = self.api_mock.health_monitor_set.mock_calls[0][2] tags = kwargs['json']['healthmonitor']['tags'] self.assertEqual(2, len(tags)) self.assertIn('foo', tags) self.assertIn('bar', tags) def test_health_monitor_set_tag_no_tag(self): self.api_mock.health_monitor_show.return_value = { 'tags': ['foo'] } arglist = [self._hm.id, '--tag', 'bar', '--no-tag'] verifylist = [ ('health_monitor', self._hm.id), ('tags', ['bar']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.health_monitor_set.assert_called_once_with( self._hm.id, json={"healthmonitor": {"tags": ['bar']}}) class TestHealthMonitorUnset(TestHealthMonitor): PARAMETERS = ('name', 'domain_name', 'expected_codes', 'http_method', 'http_version', 'max_retries_down', 'url_path') def setUp(self): super().setUp() self.cmd = health_monitor.UnsetHealthMonitor(self.app, None) def test_hm_unset_domain_name(self): self._test_hm_unset_param('domain_name') def test_hm_unset_expected_codes(self): self._test_hm_unset_param('expected_codes') def test_hm_unset_http_method(self): self._test_hm_unset_param('http_method') def test_hm_unset_http_version(self): self._test_hm_unset_param('http_version') def test_hm_unset_max_retries_down(self): self._test_hm_unset_param('max_retries_down') def test_hm_unset_name(self): self._test_hm_unset_param('name') def test_hm_unset_name_wait(self): self._test_hm_unset_param_wait('name') def test_hm_unset_url_path(self): self._test_hm_unset_param('url_path') def _test_hm_unset_param(self, param): self.api_mock.health_monitor_set.reset_mock() arg_param = param.replace('_', '-') if '_' in param else param arglist = [self._hm.id, '--%s' % arg_param] ref_body = {'healthmonitor': {param: None}} verifylist = [ ('health_monitor', self._hm.id), ] for ref_param in self.PARAMETERS: verifylist.append((ref_param, param == ref_param)) parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.health_monitor_set.assert_called_once_with( self._hm.id, json=ref_body) @mock.patch('osc_lib.utils.wait_for_status') def _test_hm_unset_param_wait(self, param, mock_wait): self.api_mock.health_monitor_set.reset_mock() arg_param = param.replace('_', '-') if '_' in param else param arglist = [self._hm.id, '--%s' % arg_param, '--wait'] ref_body = {'healthmonitor': {param: None}} verifylist = [ ('health_monitor', self._hm.id), ('wait', True), ] for ref_param in self.PARAMETERS: verifylist.append((ref_param, param == ref_param)) parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.health_monitor_set.assert_called_once_with( self._hm.id, json=ref_body) mock_wait.assert_called_once_with( status_f=mock.ANY, res_id=self._hm.id, sleep_time=mock.ANY, status_field='provisioning_status') def test_hm_unset_all(self): self.api_mock.health_monitor_set.reset_mock() ref_body = {'healthmonitor': {x: None for x in self.PARAMETERS}} arglist = [self._hm.id] for ref_param in self.PARAMETERS: arg_param = (ref_param.replace('_', '-') if '_' in ref_param else ref_param) arglist.append('--%s' % arg_param) verifylist = list(zip(self.PARAMETERS, [True] * len(self.PARAMETERS))) verifylist = [('health_monitor', self._hm.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.health_monitor_set.assert_called_once_with( self._hm.id, json=ref_body) def test_hm_unset_none(self): self.api_mock.health_monitor_set.reset_mock() arglist = [self._hm.id] verifylist = list(zip(self.PARAMETERS, [False] * len(self.PARAMETERS))) verifylist = [('health_monitor', self._hm.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.health_monitor_set.assert_not_called() def test_health_monitor_unset_tag(self): self.api_mock.health_monitor_set.reset_mock() self.api_mock.health_monitor_show.return_value = { 'tags': ['foo', 'bar'] } arglist = [self._hm.id, '--tag', 'foo'] verifylist = [ ('health_monitor', self._hm.id), ('tags', ['foo']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.health_monitor_set.assert_called_once_with( self._hm.id, json={"healthmonitor": {"tags": ['bar']}}) def test_health_monitor_unset_all_tag(self): self.api_mock.health_monitor_set.reset_mock() self.api_mock.health_monitor_show.return_value = { 'tags': ['foo', 'bar'] } arglist = [self._hm.id, '--all-tag'] verifylist = [ ('health_monitor', self._hm.id), ('all_tag', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.health_monitor_set.assert_called_once_with( self._hm.id, json={"healthmonitor": {"tags": []}}) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/unit/osc/v2/test_l7policy.py0000664000175000017500000004512700000000000027155 0ustar00zuulzuul00000000000000# Copyright 2019 Red Hat, Inc. All rights reserved. # # 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. # import copy from unittest import mock from osc_lib import exceptions from octaviaclient.osc.v2 import constants from octaviaclient.osc.v2 import l7policy from octaviaclient.tests.unit.osc.v2 import constants as attr_consts from octaviaclient.tests.unit.osc.v2 import fakes class TestL7Policy(fakes.TestOctaviaClient): def setUp(self): super().setUp() self._l7po = fakes.createFakeResource('l7policy') self.l7po_info = copy.deepcopy(attr_consts.L7POLICY_ATTRS) self.columns = copy.deepcopy(constants.L7POLICY_COLUMNS) self.api_mock = mock.Mock() self.api_mock.l7policy_list.return_value = copy.deepcopy( {'l7policies': [attr_consts.L7POLICY_ATTRS]}) lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock class TestL7PolicyList(TestL7Policy): def setUp(self): super().setUp() self.datalist = (tuple( attr_consts.L7POLICY_ATTRS[k] for k in self.columns),) self.cmd = l7policy.ListL7Policy(self.app, None) def test_l7policy_list_no_options(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.l7policy_list.assert_called_with() self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) @mock.patch('octaviaclient.osc.v2.utils.get_l7policy_attrs') def test_l7policy_list_by_listener(self, mock_l7policy_attrs): mock_l7policy_attrs.return_value = { 'listener_id': self._l7po.listener_id, } arglist = ['--listener', 'mock_li_id'] verifylist = [('listener', 'mock_li_id')] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.l7policy_list.assert_called_with( listener_id=self._l7po.listener_id ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_l7policy_list_with_tags(self): arglist = ['--tags', 'foo,bar'] verifylist = [('tags', ['foo', 'bar'])] expected_attrs = { 'tags': ['foo', 'bar'] } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.l7policy_list.assert_called_with(**expected_attrs) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_l7policy_list_with_any_tags(self): arglist = ['--any-tags', 'foo,bar'] verifylist = [('any_tags', ['foo', 'bar'])] expected_attrs = { 'tags-any': ['foo', 'bar'] } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.l7policy_list.assert_called_with(**expected_attrs) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_l7policy_list_with_not_tags(self): arglist = ['--not-tags', 'foo,bar'] verifylist = [('not_tags', ['foo', 'bar'])] expected_attrs = { 'not-tags': ['foo', 'bar'] } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.l7policy_list.assert_called_with(**expected_attrs) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_l7policy_list_with_not_any_tags(self): arglist = ['--not-any-tags', 'foo,bar'] verifylist = [('not_any_tags', ['foo', 'bar'])] expected_attrs = { 'not-tags-any': ['foo', 'bar'] } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.l7policy_list.assert_called_with(**expected_attrs) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) class TestL7PolicyDelete(TestL7Policy): def setUp(self): super().setUp() self.cmd = l7policy.DeleteL7Policy(self.app, None) def test_l7policy_delete(self): arglist = [self._l7po.id] verifylist = [ ('l7policy', self._l7po.id) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7policy_delete.assert_called_with( l7policy_id=self._l7po.id) @mock.patch('osc_lib.utils.wait_for_delete') def test_l7policy_delete_wait(self, mock_wait): arglist = [self._l7po.id, '--wait'] verifylist = [ ('l7policy', self._l7po.id), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7policy_delete.assert_called_with( l7policy_id=self._l7po.id) mock_wait.assert_called_once_with( manager=mock.ANY, res_id=self._l7po.id, sleep_time=mock.ANY, status_field='provisioning_status') def test_l7policy_delete_failure(self): arglist = ['unknown_policy'] verifylist = [ ('l7policy', 'unknown_policy') ] self.api_mock.l7policy_list.return_value = {'l7policies': []} parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertNotCalled(self.api_mock.l7policy_delete) class TestL7PolicyCreate(TestL7Policy): def setUp(self): super().setUp() self.api_mock.l7policy_create.return_value = { 'l7policy': self.l7po_info} lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = l7policy.CreateL7Policy(self.app, None) @mock.patch('octaviaclient.osc.v2.utils.get_l7policy_attrs') def test_l7policy_create(self, mock_attrs): mock_attrs.return_value = { 'listener_id': self._l7po.listener_id, 'name': self._l7po.name, 'action': 'REDIRECT_TO_POOL', 'redirect_pool_id': self._l7po.redirect_pool_id } arglist = ['mock_li_id', '--name', self._l7po.name, '--action', 'REDIRECT_TO_POOL'.lower(), '--redirect-pool', self._l7po.redirect_pool_id] verifylist = [ ('listener', 'mock_li_id'), ('name', self._l7po.name), ('action', 'REDIRECT_TO_POOL'), ('redirect_pool', self._l7po.redirect_pool_id) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7policy_create.assert_called_with( json={'l7policy': { 'listener_id': self._l7po.listener_id, 'name': self._l7po.name, 'action': 'REDIRECT_TO_POOL', 'redirect_pool_id': self._l7po.redirect_pool_id }}) @mock.patch('osc_lib.utils.wait_for_status') @mock.patch('octaviaclient.osc.v2.utils.get_l7policy_attrs') def test_l7policy_create_wait(self, mock_attrs, mock_wait): mock_attrs.return_value = { 'listener_id': self._l7po.listener_id, 'name': self._l7po.name, 'action': 'REDIRECT_TO_POOL', 'redirect_pool_id': self._l7po.redirect_pool_id } self.api_mock.listener_show.return_value = { 'loadbalancers': [{'id': 'mock_lb_id'}]} self.api_mock.l7policy_show.return_value = self.l7po_info arglist = ['mock_li_id', '--name', self._l7po.name, '--action', 'REDIRECT_TO_POOL'.lower(), '--redirect-pool', self._l7po.redirect_pool_id, '--wait'] verifylist = [ ('listener', 'mock_li_id'), ('name', self._l7po.name), ('action', 'REDIRECT_TO_POOL'), ('redirect_pool', self._l7po.redirect_pool_id), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7policy_create.assert_called_with( json={'l7policy': { 'listener_id': self._l7po.listener_id, 'name': self._l7po.name, 'action': 'REDIRECT_TO_POOL', 'redirect_pool_id': self._l7po.redirect_pool_id }}) mock_wait.assert_called_once_with( status_f=mock.ANY, res_id='mock_lb_id', sleep_time=mock.ANY, status_field='provisioning_status') @mock.patch('octaviaclient.osc.v2.utils.get_l7policy_attrs') def test_l7policy_create_with_tag(self, mock_attrs): mock_attrs.return_value = { 'listener_id': self._l7po.listener_id, 'name': self._l7po.name, 'action': 'REDIRECT_TO_POOL', 'redirect_pool_id': self._l7po.redirect_pool_id, 'tags': ['foo'] } arglist = ['mock_li_id', '--name', self._l7po.name, '--action', 'REDIRECT_TO_POOL'.lower(), '--redirect-pool', self._l7po.redirect_pool_id, '--tag', 'foo'] verifylist = [ ('listener', 'mock_li_id'), ('name', self._l7po.name), ('action', 'REDIRECT_TO_POOL'), ('redirect_pool', self._l7po.redirect_pool_id), ('tags', ['foo']) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7policy_create.assert_called_with( json={'l7policy': { 'listener_id': self._l7po.listener_id, 'name': self._l7po.name, 'action': 'REDIRECT_TO_POOL', 'redirect_pool_id': self._l7po.redirect_pool_id, 'tags': ['foo']}}) class TestL7PolicyShow(TestL7Policy): def setUp(self): super().setUp() self.api_mock.l7policy_list.return_value = [{'id': self._l7po.id}] self.api_mock.l7policy_show.return_value = self.l7po_info lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = l7policy.ShowL7Policy(self.app, None) @mock.patch('octaviaclient.osc.v2.utils.get_l7policy_attrs') def test_l7policy_show(self, mock_attrs): mock_attrs.return_value = {'l7policy_id': self._l7po.id} arglist = [self._l7po.id] verifylist = [ ('l7policy', self._l7po.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7policy_show.assert_called_with( l7policy_id=self._l7po.id) class TestL7PolicySet(TestL7Policy): def setUp(self): super().setUp() self.cmd = l7policy.SetL7Policy(self.app, None) def test_l7policy_set(self): arglist = [self._l7po.id, '--name', 'new_name'] verifylist = [ ('l7policy', self._l7po.id), ('name', 'new_name') ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7policy_set.assert_called_with( self._l7po.id, json={'l7policy': {'name': 'new_name'}}) @mock.patch('osc_lib.utils.wait_for_status') def test_l7policy_set_wait(self, mock_wait): arglist = [self._l7po.id, '--name', 'new_name', '--wait'] verifylist = [ ('l7policy', self._l7po.id), ('name', 'new_name'), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7policy_set.assert_called_with( self._l7po.id, json={'l7policy': {'name': 'new_name'}}) mock_wait.assert_called_once_with( status_f=mock.ANY, res_id=self._l7po.id, sleep_time=mock.ANY, status_field='provisioning_status') def test_l7policy_set_tag(self): self.api_mock.l7policy_show.return_value = { 'tags': ['foo'] } arglist = [self._l7po.id, '--tag', 'bar'] verifylist = [ ('l7policy', self._l7po.id), ('tags', ['bar']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7policy_set.assert_called_once() kwargs = self.api_mock.l7policy_set.mock_calls[0][2] tags = kwargs['json']['l7policy']['tags'] self.assertEqual(2, len(tags)) self.assertIn('foo', tags) self.assertIn('bar', tags) def test_l7policy_set_tag_no_tag(self): self.api_mock.l7policy_show.return_value = { 'tags': ['foo'] } arglist = [self._l7po.id, '--tag', 'bar', '--no-tag'] verifylist = [ ('l7policy', self._l7po.id), ('tags', ['bar']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7policy_set.assert_called_once_with( self._l7po.id, json={'l7policy': {'tags': ['bar']}} ) class TestL7PolicyUnset(TestL7Policy): PARAMETERS = ('name', 'description', 'redirect_http_code') def setUp(self): super().setUp() self.cmd = l7policy.UnsetL7Policy(self.app, None) def test_l7policy_unset_description(self): self._test_l7policy_unset_param('description') def test_l7policy_unset_name(self): self._test_l7policy_unset_param('name') def test_l7policy_unset_name_wait(self): self._test_l7policy_unset_param_wait('name') def test_l7policy_unset_redirect_http_code(self): self._test_l7policy_unset_param('redirect_http_code') def _test_l7policy_unset_param(self, param): self.api_mock.l7policy_set.reset_mock() arg_param = param.replace('_', '-') if '_' in param else param arglist = [self._l7po.id, '--%s' % arg_param] ref_body = {'l7policy': {param: None}} verifylist = [ ('l7policy', self._l7po.id), ] for ref_param in self.PARAMETERS: verifylist.append((ref_param, param == ref_param)) parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7policy_set.assert_called_once_with( self._l7po.id, json=ref_body) @mock.patch('osc_lib.utils.wait_for_status') def _test_l7policy_unset_param_wait(self, param, mock_wait): self.api_mock.l7policy_set.reset_mock() arg_param = param.replace('_', '-') if '_' in param else param arglist = [self._l7po.id, '--%s' % arg_param, '--wait'] ref_body = {'l7policy': {param: None}} verifylist = [ ('l7policy', self._l7po.id), ('wait', True), ] for ref_param in self.PARAMETERS: verifylist.append((ref_param, param == ref_param)) parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7policy_set.assert_called_once_with( self._l7po.id, json=ref_body) mock_wait.assert_called_once_with( status_f=mock.ANY, res_id=self._l7po.id, sleep_time=mock.ANY, status_field='provisioning_status') def test_l7policy_unset_all(self): self.api_mock.l7policy_set.reset_mock() ref_body = {'l7policy': {x: None for x in self.PARAMETERS}} arglist = [self._l7po.id] for ref_param in self.PARAMETERS: arg_param = (ref_param.replace('_', '-') if '_' in ref_param else ref_param) arglist.append('--%s' % arg_param) verifylist = list(zip(self.PARAMETERS, [True] * len(self.PARAMETERS))) verifylist = [('l7policy', self._l7po.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7policy_set.assert_called_once_with( self._l7po.id, json=ref_body) def test_l7policy_unset_none(self): self.api_mock.l7policy_set.reset_mock() arglist = [self._l7po.id] verifylist = list(zip(self.PARAMETERS, [False] * len(self.PARAMETERS))) verifylist = [('l7policy', self._l7po.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7policy_set.assert_not_called() def test_l7policy_unset_tag(self): self.api_mock.l7policy_set.reset_mock() self.api_mock.l7policy_show.return_value = { 'tags': ['foo', 'bar'] } arglist = [self._l7po.id, '--tag', 'foo'] verifylist = [ ('l7policy', self._l7po.id), ('tags', ['foo']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7policy_set.assert_called_once_with( self._l7po.id, json={'l7policy': {'tags': ['bar']}} ) def test_l7policy_unset_all_tag(self): self.api_mock.l7policy_set.reset_mock() self.api_mock.l7policy_show.return_value = { 'tags': ['foo', 'bar'] } arglist = [self._l7po.id, '--all-tag'] verifylist = [ ('l7policy', self._l7po.id), ('all_tag', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7policy_set.assert_called_once_with( self._l7po.id, json={'l7policy': {'tags': []}} ) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/unit/osc/v2/test_l7rule.py0000664000175000017500000005077200000000000026627 0ustar00zuulzuul00000000000000# Copyright 2019 Red Hat, Inc. All rights reserved. # # 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. # import copy from unittest import mock from octaviaclient.osc.v2 import constants from octaviaclient.osc.v2 import l7rule from octaviaclient.tests.unit.osc.v2 import constants as attr_consts from octaviaclient.tests.unit.osc.v2 import fakes class TestL7Rule(fakes.TestOctaviaClient): def setUp(self): super().setUp() self._l7ru = fakes.createFakeResource('l7rule') self.l7rule_info = copy.deepcopy(attr_consts.L7RULE_ATTRS) self.columns = copy.deepcopy(constants.L7RULE_COLUMNS) self._l7po = fakes.createFakeResource('l7policy') self.api_mock = mock.Mock() self.api_mock.l7rule_list.return_value = copy.deepcopy( {'rules': [attr_consts.L7RULE_ATTRS]}) self.api_mock.l7policy_list.return_value = copy.deepcopy( {'l7policies': [attr_consts.L7POLICY_ATTRS]}) lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock class TestL7RuleList(TestL7Rule): def setUp(self): super().setUp() self.datalist = (tuple( attr_consts.L7RULE_ATTRS[k] for k in self.columns),) self.cmd = l7rule.ListL7Rule(self.app, None) @mock.patch('octaviaclient.osc.v2.utils.get_l7rule_attrs') def test_l7rule_list_no_options(self, mock_attrs): mock_attrs.return_value = {'l7policy_id': self._l7po.id} arglist = [self._l7po.id] verifylist = [('l7policy', self._l7po.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.l7rule_list.assert_called_with(l7policy_id=self._l7po.id) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_l7rule_list_with_tags(self): arglist = [self._l7po.id, '--tags', 'foo,bar'] verifylist = [('l7policy', self._l7po.id), ('tags', ['foo', 'bar'])] expected_attrs = { 'l7policy_id': self._l7po.id, 'tags': ['foo', 'bar'] } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.l7rule_list.assert_called_with(**expected_attrs) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_l7rule_list_with_any_tags(self): arglist = [self._l7po.id, '--any-tags', 'foo,bar'] verifylist = [('l7policy', self._l7po.id), ('any_tags', ['foo', 'bar'])] expected_attrs = { 'l7policy_id': self._l7po.id, 'tags-any': ['foo', 'bar'] } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.l7rule_list.assert_called_with(**expected_attrs) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_l7rule_list_with_not_tags(self): arglist = [self._l7po.id, '--not-tags', 'foo,bar'] verifylist = [('l7policy', self._l7po.id), ('not_tags', ['foo', 'bar'])] expected_attrs = { 'l7policy_id': self._l7po.id, 'not-tags': ['foo', 'bar'] } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.l7rule_list.assert_called_with(**expected_attrs) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_l7rule_list_with_not_any_tags(self): arglist = [self._l7po.id, '--not-any-tags', 'foo,bar'] verifylist = [('l7policy', self._l7po.id), ('not_any_tags', ['foo', 'bar'])] expected_attrs = { 'l7policy_id': self._l7po.id, 'not-tags-any': ['foo', 'bar'] } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.l7rule_list.assert_called_with(**expected_attrs) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) class TestL7RuleDelete(TestL7Rule): def setUp(self): super().setUp() self.cmd = l7rule.DeleteL7Rule(self.app, None) @mock.patch('octaviaclient.osc.v2.utils.get_l7rule_attrs') def test_l7rule_delete(self, mock_attrs): mock_attrs.return_value = { 'l7policy_id': self._l7po.id, 'l7rule_id': self._l7ru.id, } arglist = [self._l7po.id, self._l7ru.id] verifylist = [ ('l7policy', self._l7po.id), ('l7rule', self._l7ru.id) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7rule_delete.assert_called_with( l7rule_id=self._l7ru.id, l7policy_id=self._l7po.id ) @mock.patch('osc_lib.utils.wait_for_delete') @mock.patch('octaviaclient.osc.v2.utils.get_l7rule_attrs') def test_l7rule_delete_wait(self, mock_attrs, mock_wait): mock_attrs.return_value = { 'l7policy_id': self._l7po.id, 'l7rule_id': self._l7ru.id, } arglist = [self._l7po.id, self._l7ru.id, '--wait'] verifylist = [ ('l7policy', self._l7po.id), ('l7rule', self._l7ru.id), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7rule_delete.assert_called_with( l7rule_id=self._l7ru.id, l7policy_id=self._l7po.id ) mock_wait.assert_called_once_with( manager=mock.ANY, res_id=self._l7po.id, sleep_time=mock.ANY, status_field='provisioning_status') class TestL7RuleCreate(TestL7Rule): def setUp(self): super().setUp() self.api_mock.l7rule_create.return_value = { 'rule': self.l7rule_info} lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = l7rule.CreateL7Rule(self.app, None) @mock.patch('octaviaclient.osc.v2.utils.get_l7rule_attrs') def test_l7rule_create(self, mock_attrs): mock_attrs.return_value = { 'l7policy_id': self._l7po.id, 'compare-type': 'ENDS_WITH', 'value': '.example.com', 'type': 'HOST_NAME' } arglist = [self._l7po.id, '--compare-type', 'ENDS_WITH', '--value', '.example.com', '--type', 'HOST_NAME'.lower()] verifylist = [ ('l7policy', self._l7po.id), ('compare_type', 'ENDS_WITH'), ('value', '.example.com'), ('type', 'HOST_NAME') ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7rule_create.assert_called_with( l7policy_id=self._l7po.id, json={'rule': { 'compare-type': 'ENDS_WITH', 'value': '.example.com', 'type': 'HOST_NAME'} }) @mock.patch('osc_lib.utils.wait_for_status') @mock.patch('octaviaclient.osc.v2.utils.get_l7rule_attrs') def test_l7rule_create_wait(self, mock_attrs, mock_wait): mock_attrs.return_value = { 'l7policy_id': self._l7po.id, 'compare-type': 'ENDS_WITH', 'value': '.example.com', 'type': 'HOST_NAME' } self.api_mock.l7policy_show.return_value = { 'listener_id': 'mock_listener_id'} self.api_mock.listener_show.return_value = { 'loadbalancers': [{'id': 'mock_lb_id'}]} self.api_mock.l7rule_show.return_value = self.l7rule_info arglist = [self._l7po.id, '--compare-type', 'ENDS_WITH', '--value', '.example.com', '--type', 'HOST_NAME'.lower(), '--wait'] verifylist = [ ('l7policy', self._l7po.id), ('compare_type', 'ENDS_WITH'), ('value', '.example.com'), ('type', 'HOST_NAME'), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7rule_create.assert_called_with( l7policy_id=self._l7po.id, json={'rule': { 'compare-type': 'ENDS_WITH', 'value': '.example.com', 'type': 'HOST_NAME'} }) mock_wait.assert_called_once_with( status_f=mock.ANY, res_id='mock_lb_id', sleep_time=mock.ANY, status_field='provisioning_status') @mock.patch('octaviaclient.osc.v2.utils.get_l7rule_attrs') def test_l7rule_create_with_tag(self, mock_attrs): mock_attrs.return_value = { 'l7policy_id': self._l7po.id, 'compare-type': 'ENDS_WITH', 'value': '.example.com', 'type': 'HOST_NAME', 'tags': ['foo'] } arglist = [self._l7po.id, '--compare-type', 'ENDS_WITH', '--value', '.example.com', '--type', 'HOST_NAME'.lower(), '--tag', 'foo'] verifylist = [ ('l7policy', self._l7po.id), ('compare_type', 'ENDS_WITH'), ('value', '.example.com'), ('type', 'HOST_NAME'), ('tags', ['foo']) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7rule_create.assert_called_with( l7policy_id=self._l7po.id, json={'rule': { 'compare-type': 'ENDS_WITH', 'value': '.example.com', 'type': 'HOST_NAME', 'tags': ['foo']} }) class TestL7RuleShow(TestL7Rule): def setUp(self): super().setUp() self.api_mock.l7rule_show.return_value = self.l7rule_info lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = l7rule.ShowL7Rule(self.app, None) def test_l7rule_show(self): arglist = [self._l7po.id, self._l7ru.id] verifylist = [ ('l7policy', self._l7po.id), ('l7rule', self._l7ru.id) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7rule_show.assert_called_with( l7rule_id=self._l7ru.id, l7policy_id=self._l7po.id ) class TestL7RuleSet(TestL7Rule): def setUp(self): super().setUp() self.cmd = l7rule.SetL7Rule(self.app, None) @mock.patch('octaviaclient.osc.v2.utils.get_l7rule_attrs') def test_l7rule_set(self, mock_attrs): mock_attrs.return_value = { 'admin_state_up': False, 'l7policy_id': self._l7po.id, 'l7rule_id': self._l7ru.id } arglist = [ self._l7po.id, self._l7ru.id, '--disable' ] verifylist = [ ('l7policy', self._l7po.id), ('l7rule', self._l7ru.id), ('disable', True) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7rule_set.assert_called_with( l7rule_id=self._l7ru.id, l7policy_id=self._l7po.id, json={'rule': {'admin_state_up': False}}) @mock.patch('osc_lib.utils.wait_for_status') @mock.patch('octaviaclient.osc.v2.utils.get_l7rule_attrs') def test_l7rule_set_wait(self, mock_attrs, mock_wait): mock_attrs.return_value = { 'admin_state_up': False, 'l7policy_id': self._l7po.id, 'l7rule_id': self._l7ru.id } arglist = [ self._l7po.id, self._l7ru.id, '--disable', '--wait', ] verifylist = [ ('l7policy', self._l7po.id), ('l7rule', self._l7ru.id), ('disable', True), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7rule_set.assert_called_with( l7rule_id=self._l7ru.id, l7policy_id=self._l7po.id, json={'rule': {'admin_state_up': False}}) mock_wait.assert_called_once_with( status_f=mock.ANY, res_id=self._l7po.id, sleep_time=mock.ANY, status_field='provisioning_status') @mock.patch('octaviaclient.osc.v2.utils.get_l7rule_attrs') def test_l7rule_set_tag(self, mock_attrs): self.api_mock.l7rule_show.return_value = { 'tags': ['foo'] } mock_attrs.return_value = { 'l7policy_id': self._l7po.id, 'l7rule_id': self._l7ru.id, 'tags': ['bar'] } arglist = [ self._l7po.id, self._l7ru.id, '--tag', 'bar' ] verifylist = [ ('l7policy', self._l7po.id), ('l7rule', self._l7ru.id), ('tags', ['bar']) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7rule_set.assert_called_once() kwargs = self.api_mock.l7rule_set.mock_calls[0][2] tags = kwargs['json']['rule']['tags'] self.assertEqual(2, len(tags)) self.assertIn('foo', tags) self.assertIn('bar', tags) @mock.patch('octaviaclient.osc.v2.utils.get_l7rule_attrs') def test_l7rule_set_tag_no_tag(self, mock_attrs): self.api_mock.l7rule_show.return_value = { 'tags': ['foo'] } mock_attrs.return_value = { 'l7policy_id': self._l7po.id, 'l7rule_id': self._l7ru.id, 'tags': ['bar'] } arglist = [ self._l7po.id, self._l7ru.id, '--tag', 'bar', '--no-tag' ] verifylist = [ ('l7policy', self._l7po.id), ('l7rule', self._l7ru.id), ('tags', ['bar']), ('no_tag', True) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7rule_set.assert_called_once_with( l7policy_id=self._l7po.id, l7rule_id=self._l7ru.id, json={'rule': {'tags': ['bar']}} ) class TestL7RuleUnset(TestL7Rule): PARAMETERS = ('invert', 'key') def setUp(self): super().setUp() self.cmd = l7rule.UnsetL7Rule(self.app, None) def test_l7rule_unset_invert(self): self._test_l7rule_unset_param('invert') def test_l7rule_unset_invert_wait(self): self._test_l7rule_unset_param_wait('invert') def test_l7rule_unset_key(self): self._test_l7rule_unset_param('key') def _test_l7rule_unset_param(self, param): self.api_mock.l7rule_set.reset_mock() arg_param = param.replace('_', '-') if '_' in param else param arglist = [self._l7po.id, self._l7ru.id, '--%s' % arg_param] ref_body = {'rule': {param: None}} verifylist = [ ('l7rule_id', self._l7ru.id), ] for ref_param in self.PARAMETERS: verifylist.append((ref_param, param == ref_param)) parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7rule_set.assert_called_once_with( l7policy_id=self._l7po.id, l7rule_id=self._l7ru.id, json=ref_body) @mock.patch('osc_lib.utils.wait_for_status') def _test_l7rule_unset_param_wait(self, param, mock_wait): self.api_mock.l7rule_set.reset_mock() arg_param = param.replace('_', '-') if '_' in param else param arglist = [self._l7po.id, self._l7ru.id, '--%s' % arg_param, '--wait'] ref_body = {'rule': {param: None}} verifylist = [ ('l7policy', self._l7po.id), ('l7rule_id', self._l7ru.id), ('wait', True), ] for ref_param in self.PARAMETERS: verifylist.append((ref_param, param == ref_param)) parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7rule_set.assert_called_once_with( l7policy_id=self._l7po.id, l7rule_id=self._l7ru.id, json=ref_body) mock_wait.assert_called_once_with( status_f=mock.ANY, res_id=self._l7po.id, sleep_time=mock.ANY, status_field='provisioning_status') def test_l7rule_unset_all(self): self.api_mock.l7rule_set.reset_mock() ref_body = {'rule': {x: None for x in self.PARAMETERS}} arglist = [self._l7po.id, self._l7ru.id] for ref_param in self.PARAMETERS: arg_param = (ref_param.replace('_', '-') if '_' in ref_param else ref_param) arglist.append('--%s' % arg_param) verifylist = list(zip(self.PARAMETERS, [True] * len(self.PARAMETERS))) verifylist = [('l7rule_id', self._l7ru.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7rule_set.assert_called_once_with( l7policy_id=self._l7po.id, l7rule_id=self._l7ru.id, json=ref_body) def test_l7rule_unset_none(self): self.api_mock.l7rule_set.reset_mock() arglist = [self._l7po.id, self._l7ru.id] verifylist = list(zip(self.PARAMETERS, [False] * len(self.PARAMETERS))) verifylist = [('l7rule_id', self._l7ru.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7rule_set.assert_not_called() @mock.patch('octaviaclient.osc.v2.utils.get_l7rule_attrs') def test_l7rule_unset_tag(self, mock_attrs): self.api_mock.l7rule_show.return_value = { 'tags': ['foo', 'bar'] } mock_attrs.return_value = { 'l7policy_id': self._l7po.id, 'l7rule_id': self._l7ru.id, 'tags': ['foo', 'bar'] } arglist = [ self._l7po.id, self._l7ru.id, '--tag', 'foo' ] verifylist = [ ('l7policy', self._l7po.id), ('l7rule_id', self._l7ru.id), ('tags', ['foo']) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7rule_set.assert_called_once_with( l7policy_id=self._l7po.id, l7rule_id=self._l7ru.id, json={'rule': {'tags': ['bar']}} ) @mock.patch('octaviaclient.osc.v2.utils.get_l7rule_attrs') def test_l7rule_unset_all_tags(self, mock_attrs): self.api_mock.l7rule_show.return_value = { 'tags': ['foo', 'bar'] } mock_attrs.return_value = { 'l7policy_id': self._l7po.id, 'l7rule_id': self._l7ru.id, 'tags': ['foo', 'bar'] } arglist = [ self._l7po.id, self._l7ru.id, '--all-tag' ] verifylist = [ ('l7policy', self._l7po.id), ('l7rule_id', self._l7ru.id), ('all_tag', True) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.l7rule_set.assert_called_once_with( l7policy_id=self._l7po.id, l7rule_id=self._l7ru.id, json={'rule': {'tags': []}} ) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/unit/osc/v2/test_listener.py0000664000175000017500000007033000000000000027232 0ustar00zuulzuul00000000000000# 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. # import copy from unittest import mock from osc_lib import exceptions from octaviaclient.osc.v2 import constants from octaviaclient.osc.v2 import listener from octaviaclient.tests.unit.osc.v2 import constants as attr_consts from octaviaclient.tests.unit.osc.v2 import fakes class TestListener(fakes.TestOctaviaClient): def setUp(self): super().setUp() self._listener = fakes.createFakeResource('listener') self.listener_info = copy.deepcopy(attr_consts.LISTENER_ATTRS) self.columns = copy.deepcopy(constants.LISTENER_COLUMNS) self.api_mock = mock.Mock() self.api_mock.listener_list.return_value = copy.deepcopy( {'listeners': [attr_consts.LISTENER_ATTRS]}) lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock class TestListenerList(TestListener): def setUp(self): super().setUp() self.datalist = (tuple( attr_consts.LISTENER_ATTRS[k] for k in self.columns),) self.cmd = listener.ListListener(self.app, None) def test_listener_list_no_options(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.listener_list.assert_called_with() self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_listener_list_with_options(self): arglist = ['--name', 'rainbarrel'] verifylist = [('name', 'rainbarrel')] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.listener_list.assert_called_with(name='rainbarrel') self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_listener_list_with_tags(self): arglist = ['--tags', 'foo,bar'] verifylist = [('tags', ['foo', 'bar'])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.listener_list.assert_called_with( tags=['foo', 'bar']) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_listener_list_with_any_tags(self): arglist = ['--any-tags', 'foo,bar'] verifylist = [('any_tags', ['foo', 'bar'])] expected_attrs = { "tags-any": ['foo', 'bar'] } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.listener_list.assert_called_with(**expected_attrs) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_listener_list_with_not_tags(self): arglist = ['--not-tags', 'foo,bar'] verifylist = [('not_tags', ['foo', 'bar'])] expected_attrs = { "not-tags": ['foo', 'bar'] } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.listener_list.assert_called_with(**expected_attrs) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_listener_list_with_not_any_tags(self): arglist = ['--not-any-tags', 'foo,bar'] verifylist = [('not_any_tags', ['foo', 'bar'])] expected_attrs = { "not-tags-any": ['foo', 'bar'] } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.listener_list.assert_called_with(**expected_attrs) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) class TestListenerDelete(TestListener): def setUp(self): super().setUp() self.cmd = listener.DeleteListener(self.app, None) def test_listener_delete(self): arglist = [self._listener.id] verifylist = [ ('listener', self._listener.id) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.listener_delete.assert_called_with( listener_id=self._listener.id) @mock.patch('osc_lib.utils.wait_for_delete') def test_listener_delete_wait(self, mock_wait): arglist = [self._listener.id, '--wait'] verifylist = [ ('listener', self._listener.id), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.listener_delete.assert_called_with( listener_id=self._listener.id) mock_wait.assert_called_once_with( manager=mock.ANY, res_id=self._listener.id, sleep_time=mock.ANY, status_field='provisioning_status') def test_listener_delete_failure(self): arglist = ['unknown_lb'] verifylist = [ ('listener', 'unknown_lb') ] self.api_mock.listener_list.return_value = {'listeners': []} parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertNotCalled(self.api_mock.listener_delete) class TestListenerCreate(TestListener): def setUp(self): super().setUp() self.api_mock.listener_create.return_value = { 'listener': self.listener_info} lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = listener.CreateListener(self.app, None) @mock.patch('octaviaclient.osc.v2.utils.get_listener_attrs') def test_listener_create(self, mock_client): mock_client.return_value = self.listener_info arglist = ['mock_lb_id', '--name', self._listener.name, '--protocol', 'HTTP', '--protocol-port', '80'] verifylist = [ ('loadbalancer', 'mock_lb_id'), ('name', self._listener.name), ('protocol', 'HTTP'), ('protocol_port', 80) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertIsNone(parsed_args.hsts_include_subdomains) self.assertIsNone(parsed_args.hsts_preload) self.assertIsNone(parsed_args.hsts_max_age) self.cmd.take_action(parsed_args) self.api_mock.listener_create.assert_called_with( json={'listener': self.listener_info}) @mock.patch('osc_lib.utils.wait_for_status') @mock.patch('octaviaclient.osc.v2.utils.get_listener_attrs') def test_listener_create_wait(self, mock_client, mock_wait): self.listener_info['loadbalancers'] = [{'id': 'mock_lb_id'}] mock_client.return_value = self.listener_info self.api_mock.listener_show.return_value = self.listener_info arglist = ['mock_lb_id', '--name', self._listener.name, '--protocol', 'HTTP', '--protocol-port', '80', '--wait'] verifylist = [ ('loadbalancer', 'mock_lb_id'), ('name', self._listener.name), ('protocol', 'HTTP'), ('protocol_port', 80), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.listener_create.assert_called_with( json={'listener': self.listener_info}) mock_wait.assert_called_once_with( status_f=mock.ANY, res_id=self.listener_info['loadbalancers'][0]['id'], sleep_time=mock.ANY, status_field='provisioning_status') @mock.patch('octaviaclient.osc.v2.utils.get_listener_attrs') def test_tls_listener_create(self, mock_client): mock_client.return_value = self.listener_info arglist = ['mock_lb_id', '--name', self._listener.name, '--protocol', 'TERMINATED_HTTPS'.lower(), '--protocol-port', '443', '--sni-container-refs', self._listener.sni_container_refs[0], self._listener.sni_container_refs[1], '--default-tls-container-ref', self._listener.default_tls_container_ref, '--client-ca-tls-container-ref', self._listener.client_ca_tls_container_ref, '--client-authentication', self._listener.client_authentication, '--client-crl-container-ref', self._listener.client_crl_container_ref, '--tls-ciphers', self._listener.tls_ciphers, '--tls-version', self._listener.tls_versions[0], '--tls-version', self._listener.tls_versions[1], '--alpn-protocol', self._listener.alpn_protocols[0], '--alpn-protocol', self._listener.alpn_protocols[1], '--hsts-max-age', '12000000', '--hsts-include-subdomains', '--hsts-preload', ] verifylist = [ ('loadbalancer', 'mock_lb_id'), ('name', self._listener.name), ('protocol', 'TERMINATED_HTTPS'), ('protocol_port', 443), ('sni_container_refs', self._listener.sni_container_refs), ('default_tls_container_ref', self._listener.default_tls_container_ref), ('client_ca_tls_container_ref', self._listener.client_ca_tls_container_ref), ('client_authentication', self._listener.client_authentication), ('client_crl_container_ref', self._listener.client_crl_container_ref), ('tls_ciphers', self._listener.tls_ciphers), ('tls_versions', self._listener.tls_versions), ('alpn_protocols', self._listener.alpn_protocols), ('hsts_max_age', 12_000_000), ('hsts_include_subdomains', True), ('hsts_preload', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.listener_create.assert_called_with( json={'listener': self.listener_info}) @mock.patch('octaviaclient.osc.v2.utils.get_listener_attrs') def test_listener_create_timeouts(self, mock_client): mock_client.return_value = self.listener_info arglist = ['mock_lb_id', '--name', self._listener.name, '--protocol', 'HTTP', '--protocol-port', '80', '--timeout-client-data', '123', '--timeout-member-connect', '234', '--timeout-member-data', '345', '--timeout-tcp-inspect', '456'] verifylist = [ ('loadbalancer', 'mock_lb_id'), ('name', self._listener.name), ('protocol', 'HTTP'), ('protocol_port', 80), ('timeout_client_data', 123), ('timeout_member_connect', 234), ('timeout_member_data', 345), ('timeout_tcp_inspect', 456), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.listener_create.assert_called_with( json={'listener': self.listener_info}) @mock.patch('octaviaclient.osc.v2.utils.get_listener_attrs') def test_listener_create_with_tag(self, mock_client): mock_client.return_value = self.listener_info arglist = ['mock_lb_id', '--name', self._listener.name, '--protocol', 'HTTP', '--protocol-port', '80', '--tag', 'foo'] verifylist = [ ('loadbalancer', 'mock_lb_id'), ('name', self._listener.name), ('protocol', 'HTTP'), ('protocol_port', 80), ('tags', ['foo']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.listener_create.assert_called_with( json={'listener': self.listener_info}) class TestListenerShow(TestListener): def setUp(self): super().setUp() self.api_mock.listener_show.return_value = self.listener_info lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = listener.ShowListener(self.app, None) def test_listener_show(self): arglist = [self._listener.id] verifylist = [ ('listener', self._listener.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.listener_show.assert_called_with( listener_id=self._listener.id) class TestListenerSet(TestListener): def setUp(self): super().setUp() self.cmd = listener.SetListener(self.app, None) def test_listener_set(self): arglist = [self._listener.id, '--name', 'new_name', '--sni-container-refs', self._listener.sni_container_refs[0], self._listener.sni_container_refs[1], '--default-tls-container-ref', self._listener.default_tls_container_ref, '--client-ca-tls-container-ref', self._listener.client_ca_tls_container_ref, '--client-authentication', self._listener.client_authentication, '--client-crl-container-ref', self._listener.client_crl_container_ref, '--allowed-cidr', self._listener.allowed_cidrs[0], '--allowed-cidr', self._listener.allowed_cidrs[1], '--tls-ciphers', self._listener.tls_ciphers, '--tls-version', self._listener.tls_versions[0], '--tls-version', self._listener.tls_versions[1], '--alpn-protocol', self._listener.alpn_protocols[0], '--alpn-protocol', self._listener.alpn_protocols[1], '--hsts-max-age', '15000000', '--hsts-include-subdomains', '--hsts-preload', ] verifylist = [ ('listener', self._listener.id), ('name', 'new_name'), ('sni_container_refs', self._listener.sni_container_refs), ('default_tls_container_ref', self._listener.default_tls_container_ref), ('client_ca_tls_container_ref', self._listener.client_ca_tls_container_ref), ('client_authentication', self._listener.client_authentication), ('client_crl_container_ref', self._listener.client_crl_container_ref), ('allowed_cidrs', self._listener.allowed_cidrs), ('tls_ciphers', self._listener.tls_ciphers), ('tls_versions', self._listener.tls_versions), ('alpn_protocols', self._listener.alpn_protocols), ('hsts_max_age', 15_000_000), ('hsts_include_subdomains', True), ('hsts_preload', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.listener_set.assert_called_with( self._listener.id, json={ 'listener': { 'name': 'new_name', 'sni_container_refs': self._listener.sni_container_refs, 'default_tls_container_ref': self._listener.default_tls_container_ref, 'client_ca_tls_container_ref': self._listener.client_ca_tls_container_ref, 'client_authentication': self._listener.client_authentication, 'client_crl_container_ref': self._listener.client_crl_container_ref, 'allowed_cidrs': self._listener.allowed_cidrs, 'tls_ciphers': self._listener.tls_ciphers, 'tls_versions': self._listener.tls_versions, 'alpn_protocols': self._listener.alpn_protocols, 'hsts_max_age': 15_000_000, 'hsts_include_subdomains': True, 'hsts_preload': True, } } ) def test_listener_set_suppressed(self): arglist = [self._listener.id, '--name', 'foo'] verifylist = [('name', 'foo')] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) # Suppressed arguments should not be included self.assertNotIn('hsts_preload', parsed_args) self.assertNotIn('hsts_include_subdomain', parsed_args) self.assertNotIn('hsts_max_age', parsed_args) self.api_mock.listener_set.assert_called_with( self._listener.id, json={ 'listener': { 'name': 'foo', } } ) @mock.patch('osc_lib.utils.wait_for_status') def test_listener_set_wait(self, mock_wait): arglist = [self._listener.id, '--name', 'new_name', '--wait'] verifylist = [ ('listener', self._listener.id), ('name', 'new_name'), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.listener_set.assert_called_with( self._listener.id, json={ 'listener': {'name': 'new_name'} } ) mock_wait.assert_called_once_with( status_f=mock.ANY, res_id=self._listener.id, sleep_time=mock.ANY, status_field='provisioning_status') def test_listener_set_tag(self): self.api_mock.listener_show.return_value = { 'tags': ['foo'] } arglist = [self._listener.id, '--tag', 'bar'] verifylist = [ ('listener', self._listener.id), ('tags', ['bar']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.listener_set.assert_called_once() kwargs = self.api_mock.listener_set.mock_calls[0][2] tags = kwargs['json']['listener']['tags'] self.assertEqual(2, len(tags)) self.assertIn('foo', tags) self.assertIn('bar', tags) def test_listener_set_tag_no_tag(self): self.api_mock.listener_show.return_value = { 'tags': ['foo'] } arglist = [self._listener.id, '--tag', 'bar', '--no-tag'] verifylist = [ ('listener', self._listener.id), ('tags', ['bar']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.listener_set.assert_called_once_with( self._listener.id, json={"listener": {"tags": ['bar']}} ) class TestListenerStatsShow(TestListener): def setUp(self): super().setUp() listener_stats_info = {'stats': {'bytes_in': '0'}} self.api_mock.listener_stats_show.return_value = { 'stats': listener_stats_info['stats']} lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = listener.ShowListenerStats(self.app, None) def test_listener_stats_show(self): arglist = [self._listener.id] verifylist = [ ('listener', self._listener.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.listener_stats_show.assert_called_with( listener_id=self._listener.id) class TestListenerUnset(TestListener): PARAMETERS = ('name', 'description', 'connection_limit', 'default_pool_id', 'default_tls_container_ref', 'sni_container_refs', 'insert_headers', 'timeout_client_data', 'timeout_member_connect', 'timeout_member_data', 'timeout_tcp_inspect', 'client_ca_tls_container_ref', 'client_authentication', 'client_crl_container_ref', 'allowed_cidrs', 'tls_versions', 'tls_ciphers') def setUp(self): super().setUp() self.cmd = listener.UnsetListener(self.app, None) def test_listener_unset_name(self): self._test_listener_unset_param('name') def test_listener_unset_name_wait(self): self._test_listener_unset_param_wait('name') def test_listener_unset_description(self): self._test_listener_unset_param('description') def test_listener_unset_connection_limit(self): self._test_listener_unset_param('connection_limit') def test_listener_unset_default_pool(self): self._test_listener_unset_param('default_pool') def test_listener_unset_default_tls_container_ref(self): self._test_listener_unset_param('default_tls_container_ref') def test_listener_unset_sni_container_refs(self): self._test_listener_unset_param('sni_container_refs') def test_listener_unset_insert_headers(self): self._test_listener_unset_param('insert_headers') def test_listener_unset_timeout_client_data(self): self._test_listener_unset_param('timeout_client_data') def test_listener_unset_timeout_member_connect(self): self._test_listener_unset_param('timeout_member_connect') def test_listener_unset_timeout_member_data(self): self._test_listener_unset_param('timeout_member_data') def test_listener_unset_timeout_tcp_inspect(self): self._test_listener_unset_param('timeout_tcp_inspect') def test_listener_unset_client_ca_tls_container_ref(self): self._test_listener_unset_param('client_ca_tls_container_ref') def test_listener_unset_client_authentication(self): self._test_listener_unset_param('client_authentication') def test_listener_unset_client_crl_container_ref(self): self._test_listener_unset_param('client_crl_container_ref') def test_listener_unset_allowed_cidrs(self): self._test_listener_unset_param('allowed_cidrs') def test_listener_unset_tls_versions(self): self._test_listener_unset_param('tls_versions') def test_listener_unset_tls_ciphers(self): self._test_listener_unset_param('tls_ciphers') def test_listener_unset_hsts_max_age(self): self._test_listener_unset_param('hsts_max_age') def test_listener_unset_hsts_include_subdomains(self): self._test_listener_unset_param('hsts_include_subdomains') def test_listener_unset_hsts_preload(self): self._test_listener_unset_param('hsts_preload') def _test_listener_unset_param(self, param): self.api_mock.listener_set.reset_mock() arg_param = param.replace('_', '-') if '_' in param else param arglist = [self._listener.id, '--%s' % arg_param] # Handle the special rename case of default_pool rename if param == 'default_pool': param = 'default_pool_id' ref_body = {'listener': {param: None}} verifylist = [ ('listener', self._listener.id), ] for ref_param in self.PARAMETERS: verifylist.append((ref_param, param == ref_param)) parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.listener_set.assert_called_once_with( self._listener.id, json=ref_body) @mock.patch('osc_lib.utils.wait_for_status') def _test_listener_unset_param_wait(self, param, mock_wait): self.api_mock.listener_set.reset_mock() arg_param = param.replace('_', '-') if '_' in param else param arglist = [self._listener.id, '--%s' % arg_param, '--wait'] # Handle the special rename case of default_pool rename if param == 'default_pool': param = 'default_pool_id' ref_body = {'listener': {param: None}} verifylist = [ ('listener', self._listener.id), ('wait', True), ] for ref_param in self.PARAMETERS: verifylist.append((ref_param, param == ref_param)) parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.listener_set.assert_called_once_with( self._listener.id, json=ref_body) mock_wait.assert_called_once_with( status_f=mock.ANY, res_id=self._listener.id, sleep_time=mock.ANY, status_field='provisioning_status') def test_listener_unset_all(self): self.api_mock.listener_set.reset_mock() ref_body = {'listener': {x: None for x in self.PARAMETERS}} arglist = [self._listener.id] for ref_param in self.PARAMETERS: # Handle the special rename case of default_pool rename if ref_param == 'default_pool_id': ref_param = 'default_pool' arg_param = (ref_param.replace('_', '-') if '_' in ref_param else ref_param) arglist.append('--%s' % arg_param) verifylist = list(zip(self.PARAMETERS, [True] * len(self.PARAMETERS))) verifylist = [('listener', self._listener.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.listener_set.assert_called_once_with( self._listener.id, json=ref_body) def test_listener_unset_none(self): self.api_mock.listener_set.reset_mock() arglist = [self._listener.id] verifylist = list(zip(self.PARAMETERS, [False] * len(self.PARAMETERS))) verifylist = [('listener', self._listener.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.listener_set.assert_not_called() def test_listener_unset_tag(self): self.api_mock.listener_set.reset_mock() self.api_mock.listener_show.return_value = { 'tags': ['foo', 'bar'] } arglist = [self._listener.id, '--tag', 'foo'] verifylist = [ ('listener', self._listener.id), ('tags', ['foo']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.listener_set.assert_called_once_with( self._listener.id, json={"listener": {"tags": ['bar']}} ) def test_listener_unset_all_tag(self): self.api_mock.listener_set.reset_mock() self.api_mock.listener_show.return_value = { 'tags': ['foo', 'bar'] } arglist = [self._listener.id, '--all-tag'] verifylist = [ ('listener', self._listener.id), ('all_tag', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.listener_set.assert_called_once_with( self._listener.id, json={"listener": {"tags": []}} ) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/unit/osc/v2/test_load_balancer.py0000664000175000017500000010056200000000000030154 0ustar00zuulzuul00000000000000# 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. import argparse import copy import itertools from unittest import mock from osc_lib import exceptions from oslo_utils import uuidutils from octaviaclient.osc.v2 import constants from octaviaclient.osc.v2 import load_balancer from octaviaclient.tests.unit.osc.v2 import constants as attr_consts from octaviaclient.tests.unit.osc.v2 import fakes class TestLoadBalancer(fakes.TestOctaviaClient): def setUp(self): super().setUp() self._lb = fakes.createFakeResource('loadbalancer') self.lb_info = copy.deepcopy(attr_consts.LOADBALANCER_ATTRS) self.columns = copy.deepcopy(constants.LOAD_BALANCER_COLUMNS) self.api_mock = mock.Mock() self.api_mock.load_balancer_list.return_value = copy.deepcopy( {'loadbalancers': [attr_consts.LOADBALANCER_ATTRS]}) lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock lb_client.neutronclient = mock.MagicMock() class TestLoadBalancerList(TestLoadBalancer): def setUp(self): super().setUp() self.datalist = (tuple( attr_consts.LOADBALANCER_ATTRS[k] for k in self.columns),) self.cmd = load_balancer.ListLoadBalancer(self.app, None) def test_load_balancer_list_no_options(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.load_balancer_list.assert_called_with() self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_load_balancer_list_with_name(self): arglist = ['--name', 'rainbarrel'] verifylist = [('name', 'rainbarrel')] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.load_balancer_list.assert_called_with(name='rainbarrel') self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_list_with_network(self, mock_client): mock_client.return_value = { 'vip_network_id': self._lb.vip_network_id, } arglist = [ '--vip-network-id', self._lb.vip_network_id, ] verify_list = [ ('vip_network_id', self._lb.vip_network_id), ] parsed_args = self.check_parser(self.cmd, arglist, verify_list) columns, data = self.cmd.take_action(parsed_args) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_list_with_subnet(self, mock_client): mock_client.return_value = { 'vip_subnet_id': self._lb.vip_subnet_id, } arglist = [ '--vip-subnet-id', self._lb.vip_subnet_id, ] verify_list = [ ('vip_subnet_id', self._lb.vip_subnet_id), ] parsed_args = self.check_parser(self.cmd, arglist, verify_list) columns, data = self.cmd.take_action(parsed_args) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_list_with_qos_policy(self, mock_client): mock_client.return_value = { 'vip_qos_policy_id': self._lb.vip_qos_policy_id, } arglist = [ '--vip-qos-policy-id', self._lb.vip_qos_policy_id, ] verify_list = [ ('vip_qos_policy_id', self._lb.vip_qos_policy_id), ] parsed_args = self.check_parser(self.cmd, arglist, verify_list) columns, data = self.cmd.take_action(parsed_args) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_list_with_provisioning_status(self, mock_client): mock_client.return_value = { 'provisioning_status': self._lb.provisioning_status, } arglist = [ '--provisioning-status', 'active', ] verify_list = [ ('provisioning_status', 'ACTIVE'), ] parsed_args = self.check_parser(self.cmd, arglist, verify_list) columns, data = self.cmd.take_action(parsed_args) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_list_with_operating_status(self, mock_client): mock_client.return_value = { 'operating_status': self._lb.operating_status, } arglist = [ '--operating-status', 'ONLiNE', ] verify_list = [ ('operating_status', 'ONLINE'), ] parsed_args = self.check_parser(self.cmd, arglist, verify_list) columns, data = self.cmd.take_action(parsed_args) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_list_with_provider(self, mock_client): mock_client.return_value = { 'provider': self._lb.provider, } arglist = [ '--provider', 'octavia', ] verify_list = [ ('provider', 'octavia'), ] parsed_args = self.check_parser(self.cmd, arglist, verify_list) columns, data = self.cmd.take_action(parsed_args) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_list_with_flavor(self, mock_client): mock_client.return_value = { 'flavor_id': self._lb.flavor_id, } arglist = [ '--flavor', self._lb.flavor_id, ] verify_list = [ ('flavor', self._lb.flavor_id), ] parsed_args = self.check_parser(self.cmd, arglist, verify_list) columns, data = self.cmd.take_action(parsed_args) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_list_with_tags(self, mock_client): mock_client.return_value = { 'tags': self._lb.tags, } arglist = [ '--tags', ",".join(self._lb.tags), ] verify_list = [ ('tags', self._lb.tags), ] parsed_args = self.check_parser(self.cmd, arglist, verify_list) columns, data = self.cmd.take_action(parsed_args) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_list_with_any_tags(self, mock_client): mock_client.return_value = { 'tags': self._lb.tags, } arglist = [ '--any-tags', ",".join(self._lb.tags), ] verify_list = [ ('any_tags', self._lb.tags), ] parsed_args = self.check_parser(self.cmd, arglist, verify_list) columns, data = self.cmd.take_action(parsed_args) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_list_with_not_tags(self, mock_client): mock_client.return_value = { 'tags': self._lb.tags[0], } arglist = [ '--any-tags', ",".join(self._lb.tags), ] verify_list = [ ('any_tags', self._lb.tags), ] parsed_args = self.check_parser(self.cmd, arglist, verify_list) columns, data = self.cmd.take_action(parsed_args) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_list_with_not_any_tags(self, mock_client): mock_client.return_value = { 'tags': self._lb.tags[0], } arglist = [ '--not-any-tags', ",".join(self._lb.tags), ] verify_list = [ ('not_any_tags', self._lb.tags), ] parsed_args = self.check_parser(self.cmd, arglist, verify_list) columns, data = self.cmd.take_action(parsed_args) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) class TestLoadBalancerDelete(TestLoadBalancer): def setUp(self): super().setUp() self.cmd = load_balancer.DeleteLoadBalancer(self.app, None) def test_load_balancer_delete(self): arglist = [self._lb.id] verifylist = [ ('loadbalancer', self._lb.id) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.load_balancer_delete.assert_called_with( lb_id=self._lb.id) @mock.patch('osc_lib.utils.wait_for_delete') def test_load_balancer_delete_wait(self, mock_wait): arglist = [self._lb.id, '--wait'] verifylist = [ ('loadbalancer', self._lb.id), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.load_balancer_delete.assert_called_with( lb_id=self._lb.id) mock_wait.assert_called_once_with( manager=mock.ANY, res_id=self.lb_info['id'], sleep_time=mock.ANY, status_field='provisioning_status') def test_load_balancer_delete_failure(self): arglist = ['unknown_lb'] verifylist = [ ('loadbalancer', 'unknown_lb') ] self.api_mock.load_balancer_list.return_value = { 'loadbalancers': []} parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertNotCalled(self.api_mock.load_balancer_delete) class TestLoadBalancerCreate(TestLoadBalancer): def setUp(self): super().setUp() self.api_mock.load_balancer_create.return_value = { 'loadbalancer': self.lb_info } lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = load_balancer.CreateLoadBalancer(self.app, None) @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_create(self, mock_client): mock_client.return_value = self.lb_info arglist = ['--name', self._lb.name, '--vip-network-id', self._lb.vip_network_id, '--project', self._lb.project_id, '--flavor', self._lb.flavor_id] verifylist = [ ('name', self._lb.name), ('vip_network_id', self._lb.vip_network_id), ('project', self._lb.project_id), ('flavor', self._lb.flavor_id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.load_balancer_create.assert_called_with( json={'loadbalancer': self.lb_info}) @mock.patch('osc_lib.utils.wait_for_status') @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_create_wait(self, mock_client, mock_wait): mock_client.return_value = self.lb_info self.api_mock.load_balancer_show.return_value = self.lb_info arglist = ['--name', self._lb.name, '--vip-network-id', self._lb.vip_network_id, '--project', self._lb.project_id, '--flavor', self._lb.flavor_id, '--wait'] verifylist = [ ('name', self._lb.name), ('vip_network_id', self._lb.vip_network_id), ('project', self._lb.project_id), ('flavor', self._lb.flavor_id), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.load_balancer_create.assert_called_with( json={'loadbalancer': self.lb_info}) mock_wait.assert_called_once_with( status_f=mock.ANY, res_id=self.lb_info['id'], sleep_time=mock.ANY, status_field='provisioning_status') @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_create_with_qos_policy(self, mock_client): qos_policy_id = 'qos_id' lb_info = copy.deepcopy(self.lb_info) lb_info.update({'vip_qos_policy_id': qos_policy_id}) mock_client.return_value = lb_info arglist = [ '--name', self._lb.name, '--vip-network-id', self._lb.vip_network_id, '--project', self._lb.project_id, '--vip-qos-policy-id', qos_policy_id, ] verifylist = [ ('name', self._lb.name), ('vip_network_id', self._lb.vip_network_id), ('project', self._lb.project_id), ('vip_qos_policy_id', qos_policy_id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.load_balancer_create.assert_called_with( json={'loadbalancer': lb_info}) @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_create_with_additional_vips(self, mock_client): mock_client.return_value = self.lb_info arglist = [ '--name', self._lb.name, '--vip-subnet-id', self._lb.vip_subnet_id, '--project', self._lb.project_id, '--additional-vip', 'subnet-id={},ip-address={}'.format( self._lb.additional_vips[0]['subnet_id'], self._lb.additional_vips[0]['ip_address']), '--additional-vip', 'subnet-id={},ip-address={}'.format( self._lb.additional_vips[1]['subnet_id'], self._lb.additional_vips[1]['ip_address']) ] verifylist = [ ('name', self._lb.name), ('vip_subnet_id', self._lb.vip_subnet_id), ('project', self._lb.project_id), ('additional_vip', [ 'subnet-id={},ip-address={}'.format( self._lb.additional_vips[0]['subnet_id'], self._lb.additional_vips[0]['ip_address']), 'subnet-id={},ip-address={}'.format( self._lb.additional_vips[1]['subnet_id'], self._lb.additional_vips[1]['ip_address'])]) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.load_balancer_create.assert_called_with( json={'loadbalancer': self.lb_info}) @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_create_with_provider(self, mock_client): provider = 'foobar' lb_info = copy.deepcopy(self.lb_info) lb_info.update({'provider': provider}) mock_client.return_value = lb_info arglist = [ '--name', self._lb.name, '--vip-network-id', self._lb.vip_network_id, '--project', self._lb.project_id, '--provider', provider, ] verifylist = [ ('name', self._lb.name), ('vip_network_id', self._lb.vip_network_id), ('project', self._lb.project_id), ('provider', provider), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.load_balancer_create.assert_called_with( json={'loadbalancer': lb_info}) @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_create_with_tags(self, mock_client): lb_info = copy.deepcopy(self.lb_info) lb_info.update({'tags': self._lb.tags}) mock_client.return_value = lb_info arglist = [ '--name', self._lb.name, '--vip-network-id', self._lb.vip_network_id, '--project', self._lb.project_id, '--tag', self._lb.tags[0], '--tag', self._lb.tags[1], ] verifylist = [ ('name', self._lb.name), ('vip_network_id', self._lb.vip_network_id), ('project', self._lb.project_id), ('tags', self._lb.tags), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.load_balancer_create.assert_called_with( json={'loadbalancer': lb_info}) @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_create_missing_args(self, mock_client): attrs_list = self.lb_info # init missing keys args = ("vip_subnet_id", "vip_network_id", "vip_port_id") for a in args: # init missing keys attrs_list[a] = '' # verify all valid combinations of args for n in range(len(args) + 1): for comb in itertools.combinations(args, n): # subtract comb's keys from attrs_list filtered_attrs = {k: v for k, v in attrs_list.items() if ( k not in comb)} # Add the 'wait' attribute, which isn't part of an LB directly filtered_attrs['wait'] = False mock_client.return_value = filtered_attrs parsed_args = argparse.Namespace(**filtered_attrs) if not any(k in filtered_attrs for k in args) or all( k in filtered_attrs for k in ("vip_network_id", "vip_port_id") ): self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args ) else: try: self.cmd.take_action(parsed_args) except exceptions.CommandError as e: self.fail("%s raised unexpectedly" % e) class TestLoadBalancerShow(TestLoadBalancer): def setUp(self): super().setUp() self.api_mock.load_balancer_show.return_value = { 'loadbalancer': self.lb_info} lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = load_balancer.ShowLoadBalancer(self.app, None) def test_load_balancer_show(self): arglist = [self._lb.id] verifylist = [ ('loadbalancer', self._lb.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.load_balancer_show.assert_called_with(lb_id=self._lb.id) class TestLoadBalancerSet(TestLoadBalancer): def setUp(self): super().setUp() lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = load_balancer.SetLoadBalancer(self.app, None) @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_set(self, mock_attrs): qos_policy_id = uuidutils.generate_uuid() mock_attrs.return_value = { 'loadbalancer_id': self._lb.id, 'name': 'new_name', 'vip_qos_policy_id': qos_policy_id, } arglist = [self._lb.id, '--name', 'new_name', '--vip-qos-policy-id', qos_policy_id] verifylist = [ ('loadbalancer', self._lb.id), ('name', 'new_name'), ('vip_qos_policy_id', qos_policy_id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.load_balancer_set.assert_called_with( self._lb.id, json={ 'loadbalancer': { 'name': 'new_name', 'vip_qos_policy_id': qos_policy_id, } }) @mock.patch('osc_lib.utils.wait_for_status') @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_set_wait(self, mock_attrs, mock_wait): qos_policy_id = uuidutils.generate_uuid() mock_attrs.return_value = { 'loadbalancer_id': self._lb.id, 'name': 'new_name', 'vip_qos_policy_id': qos_policy_id, } arglist = [self._lb.id, '--name', 'new_name', '--vip-qos-policy-id', qos_policy_id, '--wait'] verifylist = [ ('loadbalancer', self._lb.id), ('name', 'new_name'), ('vip_qos_policy_id', qos_policy_id), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.load_balancer_set.assert_called_with( self._lb.id, json={ 'loadbalancer': { 'name': 'new_name', 'vip_qos_policy_id': qos_policy_id, } }) mock_wait.assert_called_once_with( status_f=mock.ANY, res_id=self.lb_info['id'], sleep_time=mock.ANY, status_field='provisioning_status') @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_set_tag(self, mock_attrs): self.api_mock.load_balancer_show.return_value = { 'tags': ['foo'] } mock_attrs.return_value = { 'loadbalancer_id': self._lb.id, 'tags': ['bar'] } arglist = [self._lb.id, '--tag', 'bar'] verifylist = [ ('loadbalancer', self._lb.id), ('tags', ['bar']) ] try: parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) except Exception as e: self.fail("%s raised unexpectedly" % e) self.api_mock.load_balancer_set.assert_called_once() kwargs = self.api_mock.load_balancer_set.mock_calls[0][2] tags = kwargs['json']['loadbalancer']['tags'] self.assertEqual(2, len(tags)) self.assertIn('foo', tags) self.assertIn('bar', tags) @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_set_tag_no_tag(self, mock_attrs): self.api_mock.load_balancer_show.return_value = { 'tags': ['foo'] } mock_attrs.return_value = { 'loadbalancer_id': self._lb.id, 'tags': ['bar'] } arglist = [self._lb.id, '--tag', 'bar', '--no-tag'] verifylist = [ ('loadbalancer', self._lb.id), ('tags', ['bar']) ] try: parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) except Exception as e: self.fail("%s raised unexpectedly" % e) self.api_mock.load_balancer_set.assert_called_once_with( self._lb.id, json={'loadbalancer': {'tags': ['bar']}}) @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_remove_qos_policy(self, mock_attrs): mock_attrs.return_value = { 'loadbalancer_id': self._lb.id, 'vip_qos_policy_id': None, } arglist = [self._lb.id, '--vip-qos-policy-id', 'None'] verifylist = [ ('loadbalancer', self._lb.id), ('vip_qos_policy_id', 'None'), ] try: parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) except Exception as e: self.fail("%s raised unexpectedly" % e) class TestLoadBalancerStats(TestLoadBalancer): def setUp(self): super().setUp() lb_stats_info = {'stats': {'bytes_in': '0'}} self.api_mock.load_balancer_stats_show.return_value = { 'stats': lb_stats_info['stats']} lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = load_balancer.ShowLoadBalancerStats(self.app, None) def test_load_balancer_stats_show(self): arglist = [self._lb.id] verifylist = [ ('loadbalancer', self._lb.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.load_balancer_stats_show.assert_called_with( lb_id=self._lb.id) class TestLoadBalancerStatus(TestLoadBalancer): def setUp(self): super().setUp() expected_res = {'statuses': {'operating_status': 'ONLINE', 'provisioning_status': 'ACTIVE'}} self.api_mock.load_balancer_status_show.return_value = { 'statuses': expected_res['statuses'] } lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = load_balancer.ShowLoadBalancerStatus(self.app, None) def test_load_balancer_status_show(self): # lbaas-loadbalancer-status test_id. arglist = [self._lb.id] verifylist = [ ('loadbalancer', self._lb.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.load_balancer_status_show.assert_called_with( lb_id=self._lb.id) class TestLoadBalancerFailover(TestLoadBalancer): def setUp(self): super().setUp() self.cmd = load_balancer.FailoverLoadBalancer(self.app, None) def test_load_balancer_failover(self): arglist = [self._lb.id] verifylist = [ ('loadbalancer', self._lb.id) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.load_balancer_failover.assert_called_with( lb_id=self._lb.id) @mock.patch('osc_lib.utils.wait_for_status') def test_load_balancer_failover_wait(self, mock_wait): arglist = [self._lb.id, '--wait'] verifylist = [ ('loadbalancer', self._lb.id), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.load_balancer_failover.assert_called_with( lb_id=self._lb.id) mock_wait.assert_called_once_with( status_f=mock.ANY, res_id=self._lb.id, sleep_time=mock.ANY, status_field='provisioning_status') class TestLoadBalancerUnset(TestLoadBalancer): PARAMETERS = ('name', 'description', 'vip_qos_policy_id') def setUp(self): super().setUp() lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = load_balancer.UnsetLoadBalancer(self.app, None) def test_load_balancer_unset_name(self): self._test_load_balancer_unset_param('name') def test_load_balancer_unset_name_wait(self): self._test_load_balancer_unset_param_wait('name') def test_load_balancer_unset_description(self): self._test_load_balancer_unset_param('description') def test_load_balancer_unset_qos(self): self._test_load_balancer_unset_param('vip_qos_policy_id') def _test_load_balancer_unset_param(self, param): self.api_mock.load_balancer_set.reset_mock() ref_body = {'loadbalancer': {param: None}} arg_param = param.replace('_', '-') if '_' in param else param arglist = [self._lb.id, '--%s' % arg_param] verifylist = [ ('loadbalancer', self._lb.id), ] for ref_param in self.PARAMETERS: verifylist.append((ref_param, param == ref_param)) parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.load_balancer_set.assert_called_once_with( self._lb.id, json=ref_body) @mock.patch('osc_lib.utils.wait_for_status') def _test_load_balancer_unset_param_wait(self, param, mock_wait): self.api_mock.load_balancer_set.reset_mock() ref_body = {'loadbalancer': {param: None}} arg_param = param.replace('_', '-') if '_' in param else param arglist = [self._lb.id, '--%s' % arg_param, '--wait'] verifylist = [ ('loadbalancer', self._lb.id), ('wait', True), ] for ref_param in self.PARAMETERS: verifylist.append((ref_param, param == ref_param)) parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.load_balancer_set.assert_called_once_with( self._lb.id, json=ref_body) mock_wait.assert_called_once_with( status_f=mock.ANY, res_id=self.lb_info['id'], sleep_time=mock.ANY, status_field='provisioning_status') def test_load_balancer_unset_all(self): self.api_mock.load_balancer_set.reset_mock() ref_body = {'loadbalancer': {x: None for x in self.PARAMETERS}} arglist = [self._lb.id] for ref_param in self.PARAMETERS: arg_param = (ref_param.replace('_', '-') if '_' in ref_param else ref_param) arglist.append('--%s' % arg_param) verifylist = list(zip(self.PARAMETERS, [True] * len(self.PARAMETERS))) verifylist = [('loadbalancer', self._lb.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.load_balancer_set.assert_called_once_with( self._lb.id, json=ref_body) def test_load_balancer_unset_none(self): self.api_mock.load_balancer_set.reset_mock() arglist = [self._lb.id] verifylist = list(zip(self.PARAMETERS, [False] * len(self.PARAMETERS))) verifylist = [('loadbalancer', self._lb.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.load_balancer_set.assert_not_called() def test_load_balancer_unset_tag(self): self.api_mock.load_balancer_show.return_value = { 'tags': ['foo', 'bar'] } arglist = [self._lb.id, '--tag', 'foo'] verifylist = [ ('loadbalancer', self._lb.id), ('tags', ['foo']) ] try: parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) except Exception as e: self.fail("%s raised unexpectedly" % e) self.api_mock.load_balancer_set.assert_called_once_with( self._lb.id, json={'loadbalancer': {'tags': ['bar']}}) def test_load_balancer_unset_all_tag(self): self.api_mock.load_balancer_show.return_value = { 'tags': ['foo', 'bar'] } arglist = [self._lb.id, '--all-tag'] verifylist = [ ('loadbalancer', self._lb.id), ('all_tag', True) ] try: parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) except Exception as e: self.fail("%s raised unexpectedly" % e) self.api_mock.load_balancer_set.assert_called_once_with( self._lb.id, json={'loadbalancer': {'tags': []}}) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/unit/osc/v2/test_member.py0000664000175000017500000005263300000000000026662 0ustar00zuulzuul00000000000000# 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. # import copy from unittest import mock import osc_lib.tests.utils as osc_test_utils from octaviaclient.osc.v2 import constants from octaviaclient.osc.v2 import member from octaviaclient.tests.unit.osc.v2 import constants as attr_consts from octaviaclient.tests.unit.osc.v2 import fakes class TestMember(fakes.TestOctaviaClient): def setUp(self): super().setUp() self._mem = fakes.createFakeResource('member') self.mem_info = copy.deepcopy(attr_consts.MEMBER_ATTRS) self.columns = copy.deepcopy(constants.MEMBER_COLUMNS) info_list = {'members': [ {k: v for k, v in attr_consts.MEMBER_ATTRS.items() if ( k in self.columns)} ]} self.api_mock = mock.Mock() self.api_mock.member_list.return_value = info_list pool_dict = copy.deepcopy({'pools': [attr_consts.POOL_ATTRS]}) pool_dict['pools'][0]['id'] = self._mem.pool_id self.api_mock.pool_list.return_value = pool_dict lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock lb_client.neutronclient = mock.MagicMock() class TestListMember(TestMember): def setUp(self): super().setUp() self.datalist = (tuple( attr_consts.MEMBER_ATTRS[k] for k in self.columns),) self.cmd = member.ListMember(self.app, None) def test_member_list_no_options(self): arglist = [] verifylist = [] self.assertRaises(osc_test_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) @mock.patch('octaviaclient.osc.v2.utils.get_member_attrs') def test_member_list(self, mock_attrs): mock_attrs.return_value = {'pool_id': 'pool_id', 'project_id': self._mem.project_id} arglist = ['pool_id'] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.member_list.assert_called_once_with( pool_id='pool_id', project_id=self._mem.project_id) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_member_list_with_tags(self): arglist = [self._mem.pool_id, '--tags', 'foo,bar'] verifylist = [('pool', self._mem.pool_id), ('tags', ['foo', 'bar'])] expected_attrs = { 'pool_id': self._mem.pool_id, 'tags': ['foo', 'bar'] } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.member_list.assert_called_with(**expected_attrs) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_member_list_with_any_tags(self): arglist = [self._mem.pool_id, '--any-tags', 'foo,bar'] verifylist = [('pool', self._mem.pool_id), ('any_tags', ['foo', 'bar'])] expected_attrs = { 'pool_id': self._mem.pool_id, 'tags-any': ['foo', 'bar'] } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.member_list.assert_called_with(**expected_attrs) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_member_list_with_not_tags(self): arglist = [self._mem.pool_id, '--not-tags', 'foo,bar'] verifylist = [('pool', self._mem.pool_id), ('not_tags', ['foo', 'bar'])] expected_attrs = { 'pool_id': self._mem.pool_id, 'not-tags': ['foo', 'bar'] } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.member_list.assert_called_with(**expected_attrs) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_member_list_with_not_any_tags(self): arglist = [self._mem.pool_id, '--not-any-tags', 'foo,bar'] verifylist = [('pool', self._mem.pool_id), ('not_any_tags', ['foo', 'bar'])] expected_attrs = { 'pool_id': self._mem.pool_id, 'not-tags-any': ['foo', 'bar'] } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.member_list.assert_called_with(**expected_attrs) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) class TestCreateMember(TestMember): def setUp(self): super().setUp() self.cmd = member.CreateMember(self.app, None) self.api_mock.member_create.return_value = { 'member': self.mem_info} @mock.patch('octaviaclient.osc.v2.utils.get_member_attrs') def test_member_create(self, mock_attrs): mock_attrs.return_value = { 'ip_address': '192.0.2.122', 'protocol_port': self._mem.protocol_port, 'weight': self._mem.weight, 'admin_state_up': True, 'pool_id': self._mem.pool_id, 'backup': False} arglist = ['pool_id', '--address', '192.0.2.122', '--protocol-port', '80', '--weight', '1', '--enable', '--disable-backup'] verifylist = [ ('address', '192.0.2.122'), ('protocol_port', 80), ('weight', 1) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.member_create.assert_called_with( pool_id=self._mem.pool_id, json={ 'member': {'ip_address': '192.0.2.122', 'protocol_port': self._mem.protocol_port, 'weight': self._mem.weight, 'admin_state_up': True, 'backup': False}}) @mock.patch('osc_lib.utils.wait_for_status') @mock.patch('octaviaclient.osc.v2.utils.get_member_attrs') def test_member_create_wait(self, mock_attrs, mock_wait): mock_attrs.return_value = { 'ip_address': '192.0.2.122', 'protocol_port': self._mem.protocol_port, 'weight': self._mem.weight, 'admin_state_up': True, 'pool_id': self._mem.pool_id, 'backup': False} self.api_mock.pool_show.return_value = { 'loadbalancers': [{'id': 'mock_lb_id'}]} self.api_mock.member_show.return_value = self.mem_info arglist = ['pool_id', '--address', '192.0.2.122', '--protocol-port', '80', '--weight', '1', '--enable', '--disable-backup', '--wait'] verifylist = [ ('address', '192.0.2.122'), ('protocol_port', 80), ('weight', 1), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.member_create.assert_called_with( pool_id=self._mem.pool_id, json={ 'member': {'ip_address': '192.0.2.122', 'protocol_port': self._mem.protocol_port, 'weight': self._mem.weight, 'admin_state_up': True, 'backup': False}}) mock_wait.assert_called_once_with( status_f=mock.ANY, res_id='mock_lb_id', sleep_time=mock.ANY, status_field='provisioning_status') @mock.patch('octaviaclient.osc.v2.utils.get_member_attrs') def test_member_create_with_tag(self, mock_attrs): mock_attrs.return_value = { 'ip_address': '192.0.2.122', 'protocol_port': self._mem.protocol_port, 'pool_id': self._mem.pool_id, 'tags': ['foo']} arglist = ['pool_id', '--address', '192.0.2.122', '--protocol-port', '80', '--tag', 'foo'] verifylist = [ ('address', '192.0.2.122'), ('protocol_port', 80), ('tags', ['foo']) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.member_create.assert_called_with( pool_id=self._mem.pool_id, json={ 'member': {'ip_address': '192.0.2.122', 'protocol_port': self._mem.protocol_port, 'tags': ['foo'] }}) class TestMemberDelete(TestMember): def setUp(self): super().setUp() self.cmd = member.DeleteMember(self.app, None) @mock.patch('octaviaclient.osc.v2.utils.get_member_attrs') def test_member_delete(self, mock_attrs): mock_attrs.return_value = {'pool_id': self._mem.pool_id, 'member_id': self._mem.id} arglist = [self._mem.pool_id, self._mem.id] verifylist = [ ('pool', self._mem.pool_id), ('member', self._mem.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.member_delete.assert_called_with( pool_id=self._mem.pool_id, member_id=self._mem.id) @mock.patch('osc_lib.utils.wait_for_delete') @mock.patch('octaviaclient.osc.v2.utils.get_member_attrs') def test_member_delete_wait(self, mock_attrs, mock_wait): mock_attrs.return_value = {'pool_id': self._mem.pool_id, 'member_id': self._mem.id} arglist = [self._mem.pool_id, self._mem.id, '--wait'] verifylist = [ ('pool', self._mem.pool_id), ('member', self._mem.id), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.member_delete.assert_called_with( pool_id=self._mem.pool_id, member_id=self._mem.id) mock_wait.assert_called_once_with( manager=mock.ANY, res_id=self._mem.id, sleep_time=mock.ANY, status_field='provisioning_status') class TestMemberSet(TestMember): def setUp(self): super().setUp() self.cmd = member.SetMember(self.app, None) @mock.patch('octaviaclient.osc.v2.utils.get_member_attrs') def test_member_set(self, mock_attrs): mock_attrs.return_value = {'pool_id': self._mem.pool_id, 'member_id': self._mem.id, 'name': 'new_name', 'backup': True} arglist = [self._mem.pool_id, self._mem.id, '--name', 'new_name', '--enable-backup'] verifylist = [ ('pool', self._mem.pool_id), ('member', self._mem.id), ('name', 'new_name'), ('enable_backup', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.member_set.assert_called_with( pool_id=self._mem.pool_id, member_id=self._mem.id, json={'member': {'name': 'new_name', 'backup': True}}) @mock.patch('osc_lib.utils.wait_for_status') @mock.patch('octaviaclient.osc.v2.utils.get_member_attrs') def test_member_set_wait(self, mock_attrs, mock_wait): mock_attrs.return_value = {'pool_id': self._mem.pool_id, 'member_id': self._mem.id, 'name': 'new_name'} arglist = [self._mem.pool_id, self._mem.id, '--name', 'new_name', '--wait'] verifylist = [ ('pool', self._mem.pool_id), ('member', self._mem.id), ('name', 'new_name'), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.member_set.assert_called_with( pool_id=self._mem.pool_id, member_id=self._mem.id, json={'member': {'name': 'new_name'}}) mock_wait.assert_called_once_with( status_f=mock.ANY, res_id=self._mem.id, sleep_time=mock.ANY, status_field='provisioning_status') @mock.patch('octaviaclient.osc.v2.utils.get_member_attrs') def test_member_set_tag(self, mock_attrs): self.api_mock.member_show.return_value = { 'tags': ['foo'] } mock_attrs.return_value = {'pool_id': self._mem.pool_id, 'member_id': self._mem.id, 'tags': ['bar']} arglist = [self._mem.pool_id, self._mem.id, '--tag', 'bar'] verifylist = [ ('pool', self._mem.pool_id), ('member', self._mem.id), ('tags', ['bar']) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.member_set.assert_called_once() kwargs = self.api_mock.member_set.mock_calls[0][2] tags = kwargs['json']['member']['tags'] self.assertEqual(2, len(tags)) self.assertIn('foo', tags) self.assertIn('bar', tags) @mock.patch('octaviaclient.osc.v2.utils.get_member_attrs') def test_member_set_tag_no_tag(self, mock_attrs): self.api_mock.member_show.return_value = { 'tags': ['foo'] } mock_attrs.return_value = {'pool_id': self._mem.pool_id, 'member_id': self._mem.id, 'tags': ['bar']} arglist = [self._mem.pool_id, self._mem.id, '--tag', 'bar', '--no-tag'] verifylist = [ ('pool', self._mem.pool_id), ('member', self._mem.id), ('tags', ['bar']) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.member_set.assert_called_once_with( pool_id=self._mem.pool_id, member_id=self._mem.id, json={'member': {'tags': ['bar']}}) class TestMemberShow(TestMember): def setUp(self): super().setUp() self.api_mock.member_show.return_value = self.mem_info lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = member.ShowMember(self.app, None) @mock.patch('octaviaclient.osc.v2.utils.get_member_attrs') def test_member_show(self, mock_attrs): mock_attrs.return_value = {'member_id': self._mem.id, 'pool_id': self._mem.pool_id} arglist = [self._mem.pool_id, self._mem.id] verifylist = [ ('pool', self._mem.pool_id), ('member', self._mem.id) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.member_show.assert_called_with( member_id=self._mem.id, pool_id=self._mem.pool_id ) class TestMemberUnset(TestMember): PARAMETERS = ('backup', 'monitor_address', 'monitor_port', 'name', 'weight') def setUp(self): super().setUp() self.cmd = member.UnsetMember(self.app, None) def test_member_unset_backup(self): self._test_member_unset_param('backup') def test_member_unset_monitor_address(self): self._test_member_unset_param('monitor_address') def test_member_unset_monitor_port(self): self._test_member_unset_param('monitor_port') def test_member_unset_name(self): self._test_member_unset_param('name') def test_member_unset_name_wait(self): self._test_member_unset_param_wait('name') def test_member_unset_weight(self): self._test_member_unset_param('weight') def _test_member_unset_param(self, param): self.api_mock.member_set.reset_mock() arg_param = param.replace('_', '-') if '_' in param else param arglist = [self._mem.pool_id, self._mem.id, '--%s' % arg_param] ref_body = {'member': {param: None}} verifylist = [ ('pool', self._mem.pool_id), ('member', self._mem.id), ] for ref_param in self.PARAMETERS: verifylist.append((ref_param, param == ref_param)) parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.member_set.assert_called_once_with( pool_id=self._mem.pool_id, member_id=self._mem.id, json=ref_body) @mock.patch('osc_lib.utils.wait_for_status') def _test_member_unset_param_wait(self, param, mock_wait): self.api_mock.member_set.reset_mock() arg_param = param.replace('_', '-') if '_' in param else param arglist = [self._mem.pool_id, self._mem.id, '--%s' % arg_param, '--wait'] ref_body = {'member': {param: None}} verifylist = [ ('pool', self._mem.pool_id), ('member', self._mem.id), ('wait', True), ] for ref_param in self.PARAMETERS: verifylist.append((ref_param, param == ref_param)) parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.member_set.assert_called_once_with( pool_id=self._mem.pool_id, member_id=self._mem.id, json=ref_body) mock_wait.assert_called_once_with( status_f=mock.ANY, res_id=self._mem.id, sleep_time=mock.ANY, status_field='provisioning_status') def test_member_unset_all(self): self.api_mock.pool_set.reset_mock() ref_body = {'member': {x: None for x in self.PARAMETERS}} arglist = [self._mem.pool_id, self._mem.id] for ref_param in self.PARAMETERS: arg_param = (ref_param.replace('_', '-') if '_' in ref_param else ref_param) arglist.append('--%s' % arg_param) verifylist = list(zip(self.PARAMETERS, [True] * len(self.PARAMETERS))) verifylist = [('member', self._mem.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.member_set.assert_called_once_with( member_id=self._mem.id, pool_id=self._mem.pool_id, json=ref_body) def test_member_unset_none(self): self.api_mock.pool_set.reset_mock() arglist = [self._mem.pool_id, self._mem.id] verifylist = list(zip(self.PARAMETERS, [False] * len(self.PARAMETERS))) verifylist = [('member', self._mem.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.member_set.assert_not_called() @mock.patch('octaviaclient.osc.v2.utils.get_member_attrs') def test_member_unset_tag(self, mock_attrs): self.api_mock.member_show.return_value = { 'tags': ['foo', 'bar'] } mock_attrs.return_value = {'pool_id': self._mem.pool_id, 'member_id': self._mem.id, 'tags': ['bar']} arglist = [self._mem.pool_id, self._mem.id, '--tag', 'bar'] verifylist = [ ('pool', self._mem.pool_id), ('member', self._mem.id), ('tags', ['bar']) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.member_set.assert_called_once_with( pool_id=self._mem.pool_id, member_id=self._mem.id, json={'member': {'tags': ['foo']}}) @mock.patch('octaviaclient.osc.v2.utils.get_member_attrs') def test_member_unset_all_tags(self, mock_attrs): self.api_mock.member_show.return_value = { 'tags': ['foo', 'bar'] } mock_attrs.return_value = {'pool_id': self._mem.pool_id, 'member_id': self._mem.id, 'tags': ['foo', 'bar']} arglist = [self._mem.pool_id, self._mem.id, '--all-tag'] verifylist = [ ('pool', self._mem.pool_id), ('member', self._mem.id), ('all_tag', True) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.member_set.assert_called_once_with( pool_id=self._mem.pool_id, member_id=self._mem.id, json={'member': {'tags': []}}) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/unit/osc/v2/test_pool.py0000664000175000017500000004524700000000000026367 0ustar00zuulzuul00000000000000# Copyright 2019 Red Hat, Inc. All rights reserved. # 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. # import copy from unittest import mock from osc_lib import exceptions from octaviaclient.osc.v2 import constants from octaviaclient.osc.v2 import pool as pool from octaviaclient.tests.unit.osc.v2 import constants as attr_consts from octaviaclient.tests.unit.osc.v2 import fakes class TestPool(fakes.TestOctaviaClient): def setUp(self): super().setUp() self._po = fakes.createFakeResource('pool') self.pool_info = copy.deepcopy(attr_consts.POOL_ATTRS) self.columns = copy.deepcopy(constants.POOL_COLUMNS) self.api_mock = mock.Mock() self.api_mock.pool_list.return_value = copy.deepcopy( {'pools': [attr_consts.POOL_ATTRS]}) lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock class TestPoolList(TestPool): def setUp(self): super().setUp() self.datalist = (tuple( attr_consts.POOL_ATTRS[k] for k in self.columns ),) self.cmd = pool.ListPool(self.app, None) def test_pool_list_no_options(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.pool_list.assert_called_with() self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_pool_list_with_tags(self): arglist = ['--tags', 'foo,bar'] verifylist = [('tags', ['foo', 'bar'])] expected_attrs = { 'tags': ['foo', 'bar'] } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.pool_list.assert_called_with(**expected_attrs) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_pool_list_with_any_tags(self): arglist = ['--any-tags', 'foo,bar'] verifylist = [('any_tags', ['foo', 'bar'])] expected_attrs = { 'tags-any': ['foo', 'bar'] } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.pool_list.assert_called_with(**expected_attrs) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_pool_list_with_not_tags(self): arglist = ['--not-tags', 'foo,bar'] verifylist = [('not_tags', ['foo', 'bar'])] expected_attrs = { 'not-tags': ['foo', 'bar'] } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.pool_list.assert_called_with(**expected_attrs) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) def test_pool_list_with_not_any_tags(self): arglist = ['--not-any-tags', 'foo,bar'] verifylist = [('not_any_tags', ['foo', 'bar'])] expected_attrs = { 'not-tags-any': ['foo', 'bar'] } parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.pool_list.assert_called_with(**expected_attrs) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) class TestPoolDelete(TestPool): def setUp(self): super().setUp() self.cmd = pool.DeletePool(self.app, None) def test_pool_delete(self): arglist = [self._po.id] verifylist = [ ('pool', self._po.id) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.pool_delete.assert_called_with( pool_id=self._po.id) @mock.patch('osc_lib.utils.wait_for_delete') def test_pool_delete_wait(self, mock_wait): arglist = [self._po.id, '--wait'] verifylist = [ ('pool', self._po.id), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.pool_delete.assert_called_with( pool_id=self._po.id) mock_wait.assert_called_once_with( manager=mock.ANY, res_id=self._po.id, sleep_time=mock.ANY, status_field='provisioning_status') def test_listener_delete_failure(self): arglist = ['unknown_pool'] verifylist = [ ('pool', 'unknown_pool') ] self.api_mock.pool_list.return_value = {'pools': []} parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertNotCalled(self.api_mock.pool_delete) class TestPoolCreate(TestPool): def setUp(self): super().setUp() self.api_mock.pool_create.return_value = { 'pool': self.pool_info} lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = pool.CreatePool(self.app, None) @mock.patch('octaviaclient.osc.v2.utils.get_pool_attrs') def test_pool_create(self, mock_attrs): mock_attrs.return_value = self.pool_info arglist = ['--loadbalancer', 'mock_lb_id', '--name', self._po.name, '--protocol', 'HTTP', '--lb-algorithm', 'ROUND_ROBIN', '--enable-tls', '--tls-container-ref', self._po.tls_container_ref, '--ca-tls-container-ref', self._po.ca_tls_container_ref, '--crl-container-ref', self._po.crl_container_ref, '--tls-ciphers', self._po.tls_ciphers, '--tls-version', self._po.tls_versions[0], '--tls-version', self._po.tls_versions[1], '--alpn-protocol', self._po.alpn_protocols[0], '--alpn-protocol', self._po.alpn_protocols[1]] verifylist = [ ('loadbalancer', 'mock_lb_id'), ('name', self._po.name), ('protocol', 'HTTP'), ('lb_algorithm', 'ROUND_ROBIN'), ('enable_tls', self._po.tls_enabled), ('tls_container_ref', self._po.tls_container_ref), ('ca_tls_container_ref', self._po.ca_tls_container_ref), ('crl_container_ref', self._po.crl_container_ref), ('tls_ciphers', self._po.tls_ciphers), ('tls_versions', self._po.tls_versions), ('alpn_protocols', self._po.alpn_protocols), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.pool_create.assert_called_with( json={'pool': self.pool_info}) @mock.patch('octaviaclient.osc.v2.utils.get_pool_attrs') def test_pool_create_with_tag(self, mock_attrs): mock_attrs.return_value = self.pool_info arglist = ['--loadbalancer', 'mock_lb_id', '--name', self._po.name, '--protocol', 'HTTP', '--lb-algorithm', 'ROUND_ROBIN', '--tag', 'foo'] verifylist = [ ('loadbalancer', 'mock_lb_id'), ('name', self._po.name), ('protocol', 'HTTP'), ('lb_algorithm', 'ROUND_ROBIN'), ('tags', ['foo']) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.pool_create.assert_called_with( json={'pool': self.pool_info}) @mock.patch('osc_lib.utils.wait_for_status') @mock.patch('octaviaclient.osc.v2.utils.get_pool_attrs') def test_pool_create_wait(self, mock_attrs, mock_wait): self.pool_info['loadbalancers'] = [{'id': 'mock_lb_id'}] mock_attrs.return_value = self.pool_info self.api_mock.pool_show.return_value = self.pool_info arglist = ['--loadbalancer', 'mock_lb_id', '--name', self._po.name, '--protocol', 'HTTP', '--lb-algorithm', 'ROUND_ROBIN', '--wait'] verifylist = [ ('loadbalancer', 'mock_lb_id'), ('name', self._po.name), ('protocol', 'HTTP'), ('lb_algorithm', 'ROUND_ROBIN'), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.pool_create.assert_called_with( json={'pool': self.pool_info}) mock_wait.assert_called_once_with( status_f=mock.ANY, res_id='mock_lb_id', sleep_time=mock.ANY, status_field='provisioning_status') class TestPoolShow(TestPool): def setUp(self): super().setUp() self.api_mock.pool_show.return_value = self.pool_info lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = pool.ShowPool(self.app, None) def test_pool_show(self,): arglist = [self._po.id] verifylist = [ ('pool', self._po.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.pool_show.assert_called_with(pool_id=self._po.id) class TestPoolSet(TestPool): def setUp(self): super().setUp() self.cmd = pool.SetPool(self.app, None) def test_pool_set(self): new_tls_id, new_ca_id, new_crl_id = ( 'test-tls-container-id', 'test-ca-tls-container-id', 'test-crl-container-id') arglist = [self._po.id, '--name', 'new_name', '--tls-container-ref', new_tls_id, '--ca-tls-container-ref', new_ca_id, '--crl-container-ref', new_crl_id, '--enable-tls', '--tls-ciphers', self._po.tls_ciphers, '--tls-version', self._po.tls_versions[0], '--tls-version', self._po.tls_versions[1], '--alpn-protocol', self._po.alpn_protocols[0], '--alpn-protocol', self._po.alpn_protocols[1]] verifylist = [ ('pool', self._po.id), ('name', 'new_name'), ('tls_ciphers', self._po.tls_ciphers), ('tls_versions', self._po.tls_versions), ('alpn_protocols', self._po.alpn_protocols) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.pool_set.assert_called_with( self._po.id, json={'pool': {'name': 'new_name', 'tls_container_ref': new_tls_id, 'ca_tls_container_ref': new_ca_id, 'crl_container_ref': new_crl_id, 'tls_enabled': True, 'tls_ciphers': self._po.tls_ciphers, 'tls_versions': self._po.tls_versions, 'alpn_protocols': self._po.alpn_protocols, }}) @mock.patch('osc_lib.utils.wait_for_status') def test_pool_set_wait(self, mock_wait): arglist = [self._po.id, '--name', 'new_name', '--wait'] verifylist = [ ('pool', self._po.id), ('name', 'new_name'), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.pool_set.assert_called_with( self._po.id, json={'pool': {'name': 'new_name'}}) mock_wait.assert_called_once_with( status_f=mock.ANY, res_id=self._po.id, sleep_time=mock.ANY, status_field='provisioning_status') def test_pool_set_tag(self): self.api_mock.pool_show.return_value = { 'tags': ['foo'] } arglist = [self._po.id, '--tag', 'bar'] verifylist = [ ('pool', self._po.id), ('tags', ['bar']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.pool_set.assert_called_once() kwargs = self.api_mock.pool_set.mock_calls[0][2] tags = kwargs['json']['pool']['tags'] self.assertEqual(2, len(tags)) self.assertIn('foo', tags) self.assertIn('bar', tags) def test_pool_set_tag_no_tag(self): self.api_mock.pool_show.return_value = { 'tags': ['foo'] } arglist = [self._po.id, '--tag', 'bar', '--no-tag'] verifylist = [ ('pool', self._po.id), ('tags', ['bar']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.pool_set.assert_called_once_with( self._po.id, json={"pool": {"tags": ["bar"]}}) class TestPoolUnset(TestPool): PARAMETERS = ('name', 'description', 'ca_tls_container_ref', 'crl_container_ref', 'session_persistence', 'tls_container_ref', 'tls_versions', 'tls_ciphers') def setUp(self): super().setUp() self.cmd = pool.UnsetPool(self.app, None) def test_pool_unset_name(self): self._test_pool_unset_param('name') def test_pool_unset_name_wait(self): self._test_pool_unset_param_wait('name') def test_pool_unset_description(self): self._test_pool_unset_param('description') def test_pool_unset_ca_tls_container_ref(self): self._test_pool_unset_param('ca_tls_container_ref') def test_pool_unset_crl_container_ref(self): self._test_pool_unset_param('crl_container_ref') def test_pool_unset_session_persistence(self): self._test_pool_unset_param('session_persistence') def test_pool_unset_tls_container_ref(self): self._test_pool_unset_param('tls_container_ref') def test_pool_unset_tls_versions(self): self._test_pool_unset_param('tls_versions') def test_pool_unset_tls_ciphers(self): self._test_pool_unset_param('tls_ciphers') def _test_pool_unset_param(self, param): self.api_mock.pool_set.reset_mock() arg_param = param.replace('_', '-') if '_' in param else param arglist = [self._po.id, '--%s' % arg_param] ref_body = {'pool': {param: None}} verifylist = [ ('pool', self._po.id), ] for ref_param in self.PARAMETERS: verifylist.append((ref_param, param == ref_param)) parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.pool_set.assert_called_once_with( self._po.id, json=ref_body) @mock.patch('osc_lib.utils.wait_for_status') def _test_pool_unset_param_wait(self, param, mock_wait): self.api_mock.pool_set.reset_mock() arg_param = param.replace('_', '-') if '_' in param else param arglist = [self._po.id, '--%s' % arg_param, '--wait'] ref_body = {'pool': {param: None}} verifylist = [ ('pool', self._po.id), ('wait', True), ] for ref_param in self.PARAMETERS: verifylist.append((ref_param, param == ref_param)) parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.pool_set.assert_called_once_with( self._po.id, json=ref_body) mock_wait.assert_called_once_with( status_f=mock.ANY, res_id=self._po.id, sleep_time=mock.ANY, status_field='provisioning_status') def test_pool_unset_all(self): self.api_mock.pool_set.reset_mock() ref_body = {'pool': {x: None for x in self.PARAMETERS}} arglist = [self._po.id] for ref_param in self.PARAMETERS: arg_param = (ref_param.replace('_', '-') if '_' in ref_param else ref_param) arglist.append('--%s' % arg_param) verifylist = list(zip(self.PARAMETERS, [True] * len(self.PARAMETERS))) verifylist = [('pool', self._po.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.pool_set.assert_called_once_with( self._po.id, json=ref_body) def test_pool_unset_none(self): self.api_mock.pool_set.reset_mock() arglist = [self._po.id] verifylist = list(zip(self.PARAMETERS, [False] * len(self.PARAMETERS))) verifylist = [('pool', self._po.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.pool_set.assert_not_called() def test_pool_unset_tag(self): self.api_mock.pool_set.reset_mock() self.api_mock.pool_show.return_value = { 'tags': ['foo', 'bar'] } arglist = [self._po.id, '--tag', 'foo'] verifylist = [ ('pool', self._po.id), ('tags', ['foo']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.pool_set.assert_called_once_with( self._po.id, json={"pool": {"tags": ["bar"]}}) def test_pool_unset_all_tag(self): self.api_mock.pool_set.reset_mock() self.api_mock.pool_show.return_value = { 'tags': ['foo', 'bar'] } arglist = [self._po.id, '--all-tag'] verifylist = [ ('pool', self._po.id), ('all_tag', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.pool_set.assert_called_once_with( self._po.id, json={"pool": {"tags": []}}) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/unit/osc/v2/test_provider.py0000664000175000017500000001164600000000000027244 0ustar00zuulzuul00000000000000# Copyright (c) 2018 China Telecom Corporation # All Rights Reserved. # # 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. import copy from unittest import mock from octaviaclient.osc.v2 import constants from octaviaclient.osc.v2 import provider from octaviaclient.tests.unit.osc.v2 import constants as attr_consts from octaviaclient.tests.unit.osc.v2 import fakes class TestProvider(fakes.TestOctaviaClient): def setUp(self): super().setUp() self.columns = copy.deepcopy(constants.PROVIDER_COLUMNS) self.api_mock = mock.Mock() self.api_mock.provider_list.return_value = copy.deepcopy( {'providers': [attr_consts.PROVIDER_ATTRS]}) lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock class TestProviderList(TestProvider): def setUp(self): super().setUp() self.datalist = (tuple( attr_consts.PROVIDER_ATTRS[k] for k in self.columns),) self.cmd = provider.ListProvider(self.app, None) def test_provider_list(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.provider_list.assert_called_with() self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) class TestProviderCapability(fakes.TestOctaviaClient): def setUp(self): super().setUp() self.api_mock = mock.Mock() self.api_mock.provider_flavor_capability_list.return_value = ( copy.deepcopy( {'flavor_capabilities': [attr_consts.CAPABILITY_ATTRS]})) (self.api_mock.provider_availability_zone_capability_list. return_value) = ( copy.deepcopy( {'availability_zone_capabilities': [ attr_consts.CAPABILITY_ATTRS]})) lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock class TestProviderCapabilityShow(TestProviderCapability): def setUp(self): super().setUp() lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = provider.ListProviderCapability(self.app, None) def test_provider_capability_list_flavor(self): arglist = ['--flavor', 'provider1'] verifylist = [ ('provider', 'provider1'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) capabilities = list(result[1]) self.api_mock.provider_flavor_capability_list.assert_called_with( provider='provider1') (self.api_mock.provider_availability_zone_capability_list. assert_not_called()) self.assertIn( tuple(['flavor'] + list(attr_consts.CAPABILITY_ATTRS.values())), capabilities) def test_provider_capability_list_availability_zone(self): arglist = ['--availability-zone', 'provider1'] verifylist = [ ('provider', 'provider1'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) capabilities = list(result[1]) self.api_mock.provider_flavor_capability_list.assert_not_called() (self.api_mock.provider_availability_zone_capability_list. assert_called_with(provider='provider1')) self.assertIn( tuple( ['availability_zone'] + list(attr_consts.CAPABILITY_ATTRS.values())), capabilities) def test_provider_capability_list_all(self): arglist = ['provider1'] verifylist = [ ('provider', 'provider1'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) capabilities = list(result[1]) self.api_mock.provider_flavor_capability_list.assert_called_with( provider='provider1') (self.api_mock.provider_availability_zone_capability_list. assert_called_with(provider='provider1')) self.assertIn( tuple(['flavor'] + list(attr_consts.CAPABILITY_ATTRS.values())), capabilities) self.assertIn( tuple( ['availability_zone'] + list(attr_consts.CAPABILITY_ATTRS.values())), capabilities) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/unit/osc/v2/test_quota.py0000664000175000017500000002327400000000000026543 0ustar00zuulzuul00000000000000# 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. # import copy from unittest import mock from osc_lib import exceptions from octaviaclient.osc.v2 import constants from octaviaclient.osc.v2 import quota from octaviaclient.tests.unit.osc.v2 import constants as attr_consts from octaviaclient.tests.unit.osc.v2 import fakes class TestQuota(fakes.TestOctaviaClient): def setUp(self): super().setUp() self._qt = fakes.createFakeResource('quota') self.quota_info = copy.deepcopy(attr_consts.QUOTA_ATTRS) self.columns = copy.deepcopy(constants.QUOTA_COLUMNS) self.api_mock = mock.Mock() self.api_mock.quota_list.return_value = copy.deepcopy( {'quotas': [attr_consts.QUOTA_ATTRS]}) lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock class TestQuotaList(TestQuota): def setUp(self): super().setUp() self.datalist = (tuple( attr_consts.QUOTA_ATTRS[k] for k in self.columns),) self.cmd = quota.ListQuota(self.app, None) def test_quota_list_no_options(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.api_mock.quota_list.assert_called_with() self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, tuple(data)) class TestQuotaShow(TestQuota): def setUp(self): super().setUp() self.api_mock.quota_show.return_value = { 'quota': self.quota_info} lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = quota.ShowQuota(self.app, None) @mock.patch('octaviaclient.osc.v2.utils.get_quota_attrs') def test_quota_show(self, mock_attrs): mock_attrs.return_value = self.quota_info arglist = [self._qt.project_id] verifylist = [ ('project', self._qt.project_id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.quota_show.assert_called_with( project_id=self._qt.project_id) class TestQuotaDefaultsShow(TestQuota): qt_defaults = { "health_monitor": 1, "listener": 2, "load_balancer": 3, "member": 4, "pool": 5, "l7policy": 6, "l7rule": 7 } def setUp(self): super().setUp() self.api_mock.quota_defaults_show.return_value = { 'quota': self.qt_defaults} lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = quota.ShowQuotaDefaults(self.app, None) def test_quota_defaults_show(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) rows, data = self.cmd.take_action(parsed_args) data = dict(zip(rows, data)) self.api_mock.quota_defaults_show.assert_called_with() self.assertEqual(self.qt_defaults, data) class TestQuotaSet(TestQuota): def setUp(self): super().setUp() self.api_mock.quota_set.return_value = { 'quota': self.quota_info} lb_client = self.app.client_manager lb_client.load_balancer = self.api_mock self.cmd = quota.SetQuota(self.app, None) @mock.patch('octaviaclient.osc.v2.utils.get_quota_attrs') def test_quota_set(self, mock_attrs): mock_attrs.return_value = { 'project_id': self._qt.project_id, 'health_monitor': '-1', 'listener': '1', 'load_balancer': '2', 'member': '3', 'pool': '4', 'l7policy': '5', 'l7rule': '6', } arglist = [self._qt.project_id, '--healthmonitor', '-1', '--listener', '1', '--loadbalancer', '2', '--member', '3', '--pool', '4', '--l7policy', '5', '--l7rule', '6'] verifylist = [ ('project', self._qt.project_id), ('health_monitor', '-1'), ('listener', '1'), ('load_balancer', '2'), ('member', '3'), ('pool', '4'), ('l7policy', '5'), ('l7rule', '6') ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.quota_set.assert_called_with( self._qt.project_id, json={'quota': {'health_monitor': '-1', 'listener': '1', 'load_balancer': '2', 'member': '3', 'pool': '4', 'l7policy': '5', 'l7rule': '6'}}) @mock.patch('octaviaclient.osc.v2.utils.get_quota_attrs') def test_quota_set_no_args(self, mock_attrs): project_id = ['fake_project_id'] mock_attrs.return_value = {'project_id': project_id} arglist = [project_id] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertNotCalled(self.api_mock.quota_set) class TestQuotaReset(TestQuota): def setUp(self): super().setUp() self.cmd = quota.ResetQuota(self.app, None) @mock.patch('octaviaclient.osc.v2.utils.get_quota_attrs') def test_quota_reset(self, mock_attrs): # create new quota, otherwise other quota tests will fail occasionally # due to a race condition project_id = 'fake_project_id' attrs = {'project_id': project_id} qt_reset = fakes.createFakeResource('quota', attrs) mock_attrs.return_value = qt_reset.to_dict() arglist = [project_id] verifylist = [ ('project', project_id) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.quota_reset.assert_called_with( project_id=qt_reset.project_id) class TestQuotaUnset(TestQuota): PARAMETERS = ('loadbalancer', 'listener', 'pool', 'member', 'healthmonitor', 'l7policy', 'l7rule') def setUp(self): super().setUp() self.cmd = quota.UnsetQuota(self.app, None) def test_quota_unset_loadbalancer(self): self._test_quota_unset_param('loadbalancer') def test_quota_unset_listener(self): self._test_quota_unset_param('listener') def test_quota_unset_pool(self): self._test_quota_unset_param('pool') def test_quota_unset_health_monitor(self): self._test_quota_unset_param('healthmonitor') def test_quota_unset_member(self): self._test_quota_unset_param('member') def test_quota_unset_l7policy(self): self._test_quota_unset_param('l7policy') def test_quota_unset_l7rule(self): self._test_quota_unset_param('l7rule') @mock.patch('octaviaclient.osc.v2.utils.get_resource_id') def _test_quota_unset_param(self, param, mock_get_resource): self.api_mock.quota_set.reset_mock() mock_get_resource.return_value = self._qt.project_id arg_param = param.replace('_', '-') if '_' in param else param arglist = [self._qt.project_id, '--%s' % arg_param] ref_body = {'quota': {param: None}} verifylist = [ ('project', self._qt.project_id), ] for ref_param in self.PARAMETERS: verifylist.append((ref_param, param == ref_param)) parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.quota_set.assert_called_once_with( self._qt.project_id, json=ref_body) @mock.patch('octaviaclient.osc.v2.utils.get_resource_id') def test_quota_unset_all(self, mock_get_resource): self.api_mock.quota_set.reset_mock() mock_get_resource.return_value = self._qt.project_id ref_body = {'quota': {x: None for x in self.PARAMETERS}} arglist = [self._qt.project_id] for ref_param in self.PARAMETERS: arg_param = (ref_param.replace('_', '-') if '_' in ref_param else ref_param) arglist.append('--%s' % arg_param) verifylist = list(zip(self.PARAMETERS, [True] * len(self.PARAMETERS))) verifylist = [('project', self._qt.project_id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.quota_set.assert_called_once_with( self._qt.project_id, json=ref_body) def test_quota_unset_none(self): self.api_mock.quota_set.reset_mock() arglist = [self._qt.project_id] verifylist = list(zip(self.PARAMETERS, [False] * len(self.PARAMETERS))) verifylist = [('project', self._qt.project_id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.api_mock.quota_set.assert_not_called() ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/unit/osc/v2/test_validations.py0000664000175000017500000001555400000000000027731 0ustar00zuulzuul00000000000000# 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. # from osc_lib import exceptions from osc_lib.tests import utils from octaviaclient.osc.v2 import constants from octaviaclient.osc.v2 import validate class TestValidations(utils.TestCommand): def setUp(self): super().setUp() def test_check_l7policy_attrs(self): attrs_dict = { "action": "redirect_to_pool".upper(), "redirect_pool_id": "id"} try: validate.check_l7policy_attrs(attrs_dict) except exceptions.CommandError as e: self.fail("%s raised unexpectedly" % e) attrs_dict.pop("redirect_pool_id") self.assertRaises( exceptions.CommandError, validate.check_l7policy_attrs, attrs_dict) attrs_dict = { "action": "redirect_to_url".upper(), "redirect_url": "url"} try: validate.check_l7policy_attrs(attrs_dict) except exceptions.CommandError as e: self.fail("%s raised unexpectedly" % e) attrs_dict.pop("redirect_url") self.assertRaises( exceptions.CommandError, validate.check_l7policy_attrs, attrs_dict) attrs_dict = { "action": "redirect_prefix".upper(), "redirect_prefix": "prefix", } try: validate.check_l7policy_attrs(attrs_dict) except exceptions.CommandError as e: self.fail("%s raised unexpectedly" % e) attrs_dict.pop("redirect_prefix") self.assertRaises( exceptions.CommandError, validate.check_l7policy_attrs, attrs_dict) def test_check_l7rule_attrs(self): for i in ("cookie", "header"): attrs_dict = { "type": i.upper(), "key": "key", } try: validate.check_l7rule_attrs(attrs_dict) except exceptions.CommandError as e: self.fail("%s raised unexpectedly" % e) attrs_dict.pop("key") self.assertRaises( exceptions.CommandError, validate.check_l7rule_attrs, attrs_dict) def test_validate_TCP_UDP_SCTP_port_range(self): # Positive tests, should not raise validate._validate_TCP_UDP_SCTP_port_range(constants.MIN_PORT_NUMBER, "fake-parameter") validate._validate_TCP_UDP_SCTP_port_range(constants.MAX_PORT_NUMBER, "fake-parameter") # Negative tests, should raise self.assertRaises(exceptions.InvalidValue, validate._validate_TCP_UDP_SCTP_port_range, constants.MIN_PORT_NUMBER - 1, "fake-parameter") self.assertRaises(exceptions.InvalidValue, validate._validate_TCP_UDP_SCTP_port_range, constants.MAX_PORT_NUMBER + 1, "fake-parameter") def test_check_listener_attrs(self): # Positive tests, should not raise attrs_dict = {'protocol_port': constants.MIN_PORT_NUMBER} validate.check_listener_attrs(attrs_dict) attrs_dict = {'protocol_port': constants.MAX_PORT_NUMBER} validate.check_listener_attrs(attrs_dict) # Negative tests, should raise attrs_dict = {'protocol_port': constants.MIN_PORT_NUMBER - 1} self.assertRaises(exceptions.InvalidValue, validate.check_listener_attrs, attrs_dict) attrs_dict = {'protocol_port': constants.MAX_PORT_NUMBER + 1} self.assertRaises(exceptions.InvalidValue, validate.check_listener_attrs, attrs_dict) for key in ('hsts_preload', 'hsts_include_subdomains'): attrs_dict = {key: True} self.assertRaises(exceptions.InvalidValue, validate.check_listener_attrs, attrs_dict) def test_check_member_attrs(self): # Positive tests, should not raise attrs_dict = {'protocol_port': constants.MIN_PORT_NUMBER, 'member_port': constants.MIN_PORT_NUMBER, 'weight': constants.MIN_WEIGHT} validate.check_member_attrs(attrs_dict) attrs_dict = {'protocol_port': constants.MAX_PORT_NUMBER, 'member_port': constants.MAX_PORT_NUMBER, 'weight': constants.MAX_WEIGHT} validate.check_member_attrs(attrs_dict) # Negative tests, should raise - protocol-port attrs_dict = {'protocol_port': constants.MIN_PORT_NUMBER - 1, 'member_port': constants.MIN_PORT_NUMBER, 'weight': constants.MIN_WEIGHT} self.assertRaises(exceptions.InvalidValue, validate.check_member_attrs, attrs_dict) attrs_dict = {'protocol_port': constants.MAX_PORT_NUMBER + 1, 'member_port': constants.MIN_PORT_NUMBER, 'weight': constants.MIN_WEIGHT} self.assertRaises(exceptions.InvalidValue, validate.check_member_attrs, attrs_dict) # Negative tests, should raise - member-port attrs_dict = {'protocol_port': constants.MIN_PORT_NUMBER, 'member_port': constants.MIN_PORT_NUMBER - 1, 'weight': constants.MIN_WEIGHT} self.assertRaises(exceptions.InvalidValue, validate.check_member_attrs, attrs_dict) attrs_dict = {'protocol_port': constants.MIN_PORT_NUMBER, 'member_port': constants.MAX_PORT_NUMBER + 1, 'weight': constants.MIN_WEIGHT} self.assertRaises(exceptions.InvalidValue, validate.check_member_attrs, attrs_dict) # Negative tests, should raise - weight attrs_dict = {'protocol_port': constants.MIN_PORT_NUMBER, 'member_port': constants.MIN_PORT_NUMBER, 'weight': constants.MIN_WEIGHT - 1} self.assertRaises(exceptions.InvalidValue, validate.check_member_attrs, attrs_dict) attrs_dict = {'protocol_port': constants.MIN_PORT_NUMBER, 'member_port': constants.MIN_PORT_NUMBER, 'weight': constants.MAX_WEIGHT + 1} self.assertRaises(exceptions.InvalidValue, validate.check_member_attrs, attrs_dict) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/tests/unit/test_hacking.py0000664000175000017500000002151500000000000025677 0ustar00zuulzuul00000000000000# Copyright 2015 # # 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. import testtools from oslotest import base from octaviaclient.hacking import checks class HackingTestCase(base.BaseTestCase): """Hacking test class. This class tests the hacking checks in octaviaclient.hacking.checks by passing strings to the check methods like the pep8/flake8 parser would. The parser loops over each line in the file and then passes the parameters to the check method. The parameter names in the check method dictate what type of object is passed to the check method. The parameter types are:: logical_line: A processed line with the following modifications: - Multi-line statements converted to a single line. - Stripped left and right. - Contents of strings replaced with "xxx" of same length. - Comments removed. physical_line: Raw line of text from the input file. lines: a list of the raw lines from the input file tokens: the tokens that contribute to this logical line line_number: line number in the input file total_lines: number of lines in the input file blank_lines: blank lines before this one indent_char: indentation character in this file (" " or "\t") indent_level: indentation (with tabs expanded to multiples of 8) previous_indent_level: indentation on previous line previous_logical: previous logical line filename: Path of the file being run through pep8 When running a test on a check method the return will be False/None if there is no violation in the sample input. If there is an error a tuple is returned with a position in the line, and a message. So to check the result just assertTrue if the check is expected to fail and assertFalse if it should pass. """ def assertLinePasses(self, func, *args): with testtools.ExpectedException(StopIteration): next(func(*args)) def assertLineFails(self, func, *args): self.assertIsInstance(next(func(*args)), tuple) def test_assert_true_instance(self): self.assertEqual(1, len(list(checks.assert_true_instance( "self.assertTrue(isinstance(e, " "exception.BuildAbortException))")))) self.assertEqual(0, len(list(checks.assert_true_instance( "self.assertTrue()")))) def test_assert_equal_or_not_none(self): self.assertEqual(1, len(list(checks.assert_equal_or_not_none( "self.assertEqual(A, None)")))) self.assertEqual(1, len(list(checks.assert_equal_or_not_none( "self.assertEqual(None, A)")))) self.assertEqual(1, len(list(checks.assert_equal_or_not_none( "self.assertNotEqual(A, None)")))) self.assertEqual(1, len(list(checks.assert_equal_or_not_none( "self.assertNotEqual(None, A)")))) self.assertEqual(0, len(list(checks.assert_equal_or_not_none( "self.assertIsNone()")))) self.assertEqual(0, len(list(checks.assert_equal_or_not_none( "self.assertIsNotNone()")))) def test_no_mutable_default_args(self): self.assertEqual(0, len(list(checks.no_mutable_default_args( "def foo (bar):")))) self.assertEqual(1, len(list(checks.no_mutable_default_args( "def foo (bar=[]):")))) self.assertEqual(1, len(list(checks.no_mutable_default_args( "def foo (bar={}):")))) def test_assert_equal_in(self): self.assertEqual(1, len(list(checks.assert_equal_in( "self.assertEqual(a in b, True)")))) self.assertEqual(1, len(list(checks.assert_equal_in( "self.assertEqual('str' in 'string', True)")))) self.assertEqual(0, len(list(checks.assert_equal_in( "self.assertEqual(any(a==1 for a in b), True)")))) self.assertEqual(1, len(list(checks.assert_equal_in( "self.assertEqual(True, a in b)")))) self.assertEqual(1, len(list(checks.assert_equal_in( "self.assertEqual(True, 'str' in 'string')")))) self.assertEqual(0, len(list(checks.assert_equal_in( "self.assertEqual(True, any(a==1 for a in b))")))) self.assertEqual(1, len(list(checks.assert_equal_in( "self.assertEqual(a in b, False)")))) self.assertEqual(1, len(list(checks.assert_equal_in( "self.assertEqual('str' in 'string', False)")))) self.assertEqual(0, len(list(checks.assert_equal_in( "self.assertEqual(any(a==1 for a in b), False)")))) self.assertEqual(1, len(list(checks.assert_equal_in( "self.assertEqual(False, a in b)")))) self.assertEqual(1, len(list(checks.assert_equal_in( "self.assertEqual(False, 'str' in 'string')")))) self.assertEqual(0, len(list(checks.assert_equal_in( "self.assertEqual(False, any(a==1 for a in b))")))) def test_assert_equal_true_or_false(self): self.assertEqual(1, len(list(checks.assert_equal_true_or_false( "self.assertEqual(True, A)")))) self.assertEqual(1, len(list(checks.assert_equal_true_or_false( "self.assertEqual(False, A)")))) self.assertEqual(0, len(list(checks.assert_equal_true_or_false( "self.assertTrue()")))) self.assertEqual(0, len(list(checks.assert_equal_true_or_false( "self.assertFalse()")))) def test_no_log_warn(self): self.assertEqual(1, len(list(checks.no_log_warn( "LOG.warn()")))) self.assertEqual(0, len(list(checks.no_log_warn( "LOG.warning()")))) def test_no_xrange(self): self.assertEqual(1, len(list(checks.no_xrange( "xrange(45)")))) self.assertEqual(0, len(list(checks.no_xrange( "range(45)")))) def test_no_log_translations(self): for log in checks._all_log_levels: for hint in checks._all_hints: bad = 'LOG.%s(%s("Bad"))' % (log, hint) self.assertEqual( 1, len(list(checks.no_translate_logs(bad, 'f')))) # Catch abuses when used with a variable and not a literal bad = 'LOG.%s(%s(msg))' % (log, hint) self.assertEqual( 1, len(list(checks.no_translate_logs(bad, 'f')))) # Do not do validations in tests ok = 'LOG.%s(_("OK - unit tests"))' % log self.assertEqual( 0, len(list(checks.no_translate_logs(ok, 'f/tests/f')))) def test_check_localized_exception_messages(self): f = checks.check_raised_localized_exceptions self.assertLineFails(f, " raise KeyError('Error text')", '') self.assertLineFails(f, ' raise KeyError("Error text")', '') self.assertLinePasses(f, ' raise KeyError(_("Error text"))', '') self.assertLinePasses(f, ' raise KeyError(_ERR("Error text"))', '') self.assertLinePasses(f, " raise KeyError(translated_msg)", '') self.assertLinePasses(f, '# raise KeyError("Not translated")', '') self.assertLinePasses(f, 'print("raise KeyError("Not ' 'translated")")', '') def test_check_localized_exception_message_skip_tests(self): f = checks.check_raised_localized_exceptions self.assertLinePasses(f, "raise KeyError('Error text')", 'neutron_lib/tests/unit/mytest.py') def test_check_no_basestring(self): self.assertEqual(1, len(list(checks.check_no_basestring( "isinstance('foo', basestring)")))) self.assertEqual(0, len(list(checks.check_no_basestring( "isinstance('foo', six.string_types)")))) def test_check_no_eventlet_imports(self): f = checks.check_no_eventlet_imports self.assertLinePasses(f, 'from not_eventlet import greenthread') self.assertLineFails(f, 'from eventlet import greenthread') self.assertLineFails(f, 'import eventlet') def test_line_continuation_no_backslash(self): results = list(checks.check_line_continuation_no_backslash( '', [(1, 'import', (2, 0), (2, 6), 'import \\\n'), (1, 'os', (3, 4), (3, 6), ' os\n')])) self.assertEqual(1, len(results)) self.assertEqual((2, 7), results[0][0]) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/octaviaclient/version.py0000664000175000017500000000174400000000000022602 0ustar00zuulzuul00000000000000# Copyright 2011-2014 OpenStack Foundation # # 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. import pbr.version OCTAVIA_CLIENT_VENDOR = "OpenStack Foundation" OCTAVIA_CLIENT_PRODUCT = "OpenStack Octavia client" version_info = pbr.version.VersionInfo('python-octaviaclient') def vendor_string(): return OCTAVIA_CLIENT_VENDOR def product_string(): return OCTAVIA_CLIENT_PRODUCT def version_string_with_package(): return version_info.version_string() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0309224 python-octaviaclient-3.7.0/python_octaviaclient.egg-info/0000775000175000017500000000000000000000000023630 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220677.0 python-octaviaclient-3.7.0/python_octaviaclient.egg-info/PKG-INFO0000664000175000017500000000600500000000000024726 0ustar00zuulzuul00000000000000Metadata-Version: 1.2 Name: python-octaviaclient Version: 3.7.0 Summary: Octavia client for OpenStack Load Balancing Home-page: https://docs.openstack.org/python-octaviaclient/latest/ Author: OpenStack Author-email: openstack-discuss@lists.openstack.org License: UNKNOWN Description: Team and repository tags ======================== .. image:: https://governance.openstack.org/tc/badges/python-octaviaclient.svg :target: https://governance.openstack.org/tc/reference/tags/index.html .. Change things from this point on python-octaviaclient ==================== Octavia client for OpenStack Load Balancing This is an OpenStack Client (OSC) plugin for Octavia, an OpenStack Load Balancing project. For more information about Octavia see: https://docs.openstack.org/octavia/latest/ For more information about the OpenStack Client see: https://docs.openstack.org/python-openstackclient/latest/ * Free software: Apache license * Documentation: https://docs.openstack.org/python-octaviaclient/latest/ * Source: https://opendev.org/openstack/python-octaviaclient * Release notes: https://docs.openstack.org/releasenotes/python-octaviaclient/ * Bugs: https://storyboard.openstack.org/#!/project/911 Getting Started =============== .. note:: This is an OpenStack Client plugin. The ``python-openstackclient`` project should be installed to use this plugin. .. note:: This project is only intended to be used for the OpenStack Client CLI. The `openstacksdk `_ should be used for python bindings. Octavia client can be installed from PyPI using pip .. code-block:: bash pip install python-octaviaclient If you want to make changes to the Octavia client for testing and contribution, make any changes and then run .. code-block:: bash python setup.py develop or .. code-block:: bash pip install -e . Platform: UNKNOWN Classifier: Environment :: OpenStack Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: 3 :: Only Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Requires-Python: >=3.8 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220678.0 python-octaviaclient-3.7.0/python_octaviaclient.egg-info/SOURCES.txt0000664000175000017500000001614100000000000025517 0ustar00zuulzuul00000000000000.coveragerc .mailmap .pylintrc .stestr.conf AUTHORS CONTRIBUTING.rst ChangeLog HACKING.rst LICENSE README.rst bindep.txt requirements.txt setup.cfg setup.py test-requirements.txt tox.ini doc/requirements.txt doc/source/conf.py doc/source/index.rst doc/source/readme.rst doc/source/cli/index.rst doc/source/contributor/index.rst doc/source/install/index.rst doc/source/reference/index.rst doc/source/reference/data/lbaas.csv octaviaclient/__init__.py octaviaclient/version.py octaviaclient/api/__init__.py octaviaclient/api/constants.py octaviaclient/api/exceptions.py octaviaclient/api/v2/__init__.py octaviaclient/api/v2/octavia.py octaviaclient/hacking/__init__.py octaviaclient/hacking/checks.py octaviaclient/osc/__init__.py octaviaclient/osc/plugin.py octaviaclient/osc/v2/__init__.py octaviaclient/osc/v2/amphora.py octaviaclient/osc/v2/availabilityzone.py octaviaclient/osc/v2/availabilityzoneprofile.py octaviaclient/osc/v2/constants.py octaviaclient/osc/v2/flavor.py octaviaclient/osc/v2/flavorprofile.py octaviaclient/osc/v2/health_monitor.py octaviaclient/osc/v2/l7policy.py octaviaclient/osc/v2/l7rule.py octaviaclient/osc/v2/listener.py octaviaclient/osc/v2/load_balancer.py octaviaclient/osc/v2/member.py octaviaclient/osc/v2/pool.py octaviaclient/osc/v2/provider.py octaviaclient/osc/v2/quota.py octaviaclient/osc/v2/utils.py octaviaclient/osc/v2/validate.py octaviaclient/tests/__init__.py octaviaclient/tests/fakes.py octaviaclient/tests/functional/__init__.py octaviaclient/tests/functional/base.py octaviaclient/tests/functional/osc/__init__.py octaviaclient/tests/functional/osc/v2/__init__.py octaviaclient/tests/unit/__init__.py octaviaclient/tests/unit/test_hacking.py octaviaclient/tests/unit/api/__init__.py octaviaclient/tests/unit/api/test_octavia.py octaviaclient/tests/unit/osc/__init__.py octaviaclient/tests/unit/osc/v2/__init__.py octaviaclient/tests/unit/osc/v2/constants.py octaviaclient/tests/unit/osc/v2/fakes.py octaviaclient/tests/unit/osc/v2/test_amphora.py octaviaclient/tests/unit/osc/v2/test_availabilityzone.py octaviaclient/tests/unit/osc/v2/test_availabilityzoneprofile.py octaviaclient/tests/unit/osc/v2/test_flavor.py octaviaclient/tests/unit/osc/v2/test_flavorprofile.py octaviaclient/tests/unit/osc/v2/test_health_monitor.py octaviaclient/tests/unit/osc/v2/test_l7policy.py octaviaclient/tests/unit/osc/v2/test_l7rule.py octaviaclient/tests/unit/osc/v2/test_listener.py octaviaclient/tests/unit/osc/v2/test_load_balancer.py octaviaclient/tests/unit/osc/v2/test_member.py octaviaclient/tests/unit/osc/v2/test_pool.py octaviaclient/tests/unit/osc/v2/test_provider.py octaviaclient/tests/unit/osc/v2/test_quota.py octaviaclient/tests/unit/osc/v2/test_validations.py python_octaviaclient.egg-info/PKG-INFO python_octaviaclient.egg-info/SOURCES.txt python_octaviaclient.egg-info/dependency_links.txt python_octaviaclient.egg-info/entry_points.txt python_octaviaclient.egg-info/not-zip-safe python_octaviaclient.egg-info/pbr.json python_octaviaclient.egg-info/requires.txt python_octaviaclient.egg-info/top_level.txt releasenotes/notes/.placeholder releasenotes/notes/Add-PROMETHEUS-listener-protocol-23f5054f524d9332.yaml releasenotes/notes/Add-proxyv2-7a540796c60241c3.yaml releasenotes/notes/Add-support-for-UDP-5476caa65b1253a6.yaml releasenotes/notes/Add-unset-commands-15490df414a70df0.yaml releasenotes/notes/Add-vip_vnic_type-load-balancer-field-f1bc1345ee741f88.yaml releasenotes/notes/Client-to-request-JSON-responses-8d942dafca785c70.yaml releasenotes/notes/Improve-client-performance-when-using-a-name-instead-of-ID-51a6637050386a90.yaml releasenotes/notes/add-ability-set-listener-cipher-list-fe379d0d0821ed42.yaml releasenotes/notes/add-ability-set-pool-cipher-list-70128f983506fbdb.yaml releasenotes/notes/add-alpn-support-listeners-6508704b5c8944d2.yaml releasenotes/notes/add-amphora-configure-command-cda75053a72c0cdf.yaml releasenotes/notes/add-amphora-delete-0fe5f2097da92b5c.yaml releasenotes/notes/add-amphora-stats-show-48bc0fadf08f1057.yaml releasenotes/notes/add-amphorae-failover-suuport-9fa0b1c25026e123.yaml releasenotes/notes/add-az-and-profiles-ed79c945c4e0d418.yaml releasenotes/notes/add-flavor-support-75c6d5bec48b1d18.yaml releasenotes/notes/add-hsts-support-f612ec171e28a3b3.yaml releasenotes/notes/add-l7policy-and-l7rule-quota-support-73098a090b252901.yaml releasenotes/notes/add-lb-algorithm-source-ip-port-3e2d4b60f6916259.yaml releasenotes/notes/add-lb-flavor-b917faa0298c3a74.yaml releasenotes/notes/add-listener-allowed-cirds-2ef9fa2e1c650166.yaml releasenotes/notes/add-missing-flavor-set-description-option-d49f3103ef15e778.yaml releasenotes/notes/add-new-commands-and-options-d520b36d870cbcb4.yaml releasenotes/notes/add-pool-tls-alpn-support-59758ea78c78952e.yaml releasenotes/notes/add-provider-load-balancer-create-4d151209dee32f81.yaml releasenotes/notes/add-qos-policy-argument-1741126d759630da.yaml releasenotes/notes/add-quota-support-effed2cf2a8c7ad4.yaml releasenotes/notes/add-redirect-prefix-2f66455b3eacf5b6.yaml releasenotes/notes/add-support-for-provider-4e60045ea54f1d30.yaml releasenotes/notes/add-support-for-sctp-protocol-f23b58db8522cc4b.yaml releasenotes/notes/add-tag-support-01087c4b3c4360dc.yaml releasenotes/notes/add-tls-version-support-for-listeners-4a6a661af5f9de9a.yaml releasenotes/notes/add-tls-version-support-to-pools-852f02b034f436f9.yaml releasenotes/notes/add-tls-versions-ciphers-unsets-8d06a502c8ad38ff.yaml releasenotes/notes/add-wait-option-to-CUD-commands-97375387e7762b83.yaml releasenotes/notes/add_backup_member_support-8b406bb72654ba88.yaml releasenotes/notes/add_loadbalancer_status_support-f960d89f1b77fd16.yaml releasenotes/notes/amphora-list-long-option-55390b5abef5b82e.yaml releasenotes/notes/drop-python-2-7-7b427838d72ef248.yaml releasenotes/notes/drop-python-3-6-and-3-7-5675086892fe7d16.yaml releasenotes/notes/exposed-timeouts-eb29f55de5e56261.yaml releasenotes/notes/fix-cli-pagination-792ad8cd386eb0e7.yaml releasenotes/notes/fix-inconsistent-parameter-name-in-azp-0267d025b7c78fc2.yaml releasenotes/notes/fix-pool-protocols-090b2a6f4e82516f.yaml releasenotes/notes/improve-error-messages-for-invalid-calls-bc9eb3d18d3e4fdf.yaml releasenotes/notes/initial-list-command-90c9fa39fc10540e.yaml releasenotes/notes/list-l7policies-by-listener-a11322c8e03a11e9.yaml releasenotes/notes/listener-stats-db49f99a8a0dd90f.yaml releasenotes/notes/load-balancer-commands-options-83cfdbb1bc5d8998.yaml releasenotes/notes/remove-unneeded-attributes-in-listener-create-2e7cb2de281ac7fe.yaml releasenotes/notes/show-command-enhancement-df414a70df0a7089.yml releasenotes/notes/support-additional-vips-cd0164f1838ee676.yaml releasenotes/source/2023.1.rst releasenotes/source/2023.2.rst releasenotes/source/conf.py releasenotes/source/index.rst releasenotes/source/pike.rst releasenotes/source/queens.rst releasenotes/source/rocky.rst releasenotes/source/stein.rst releasenotes/source/train.rst releasenotes/source/unreleased.rst releasenotes/source/ussuri.rst releasenotes/source/victoria.rst releasenotes/source/wallaby.rst releasenotes/source/xena.rst releasenotes/source/yoga.rst releasenotes/source/zed.rst releasenotes/source/_static/.placeholder releasenotes/source/_templates/.placeholder tools/coding-checks.sh zuul.d/projects.yaml././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220677.0 python-octaviaclient-3.7.0/python_octaviaclient.egg-info/dependency_links.txt0000664000175000017500000000000100000000000027676 0ustar00zuulzuul00000000000000 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220677.0 python-octaviaclient-3.7.0/python_octaviaclient.egg-info/entry_points.txt0000664000175000017500000001453200000000000027133 0ustar00zuulzuul00000000000000[openstack.cli.extension] load_balancer = octaviaclient.osc.plugin [openstack.load_balancer.v2] loadbalancer_amphora_configure = octaviaclient.osc.v2.amphora:ConfigureAmphora loadbalancer_amphora_delete = octaviaclient.osc.v2.amphora:DeleteAmphora loadbalancer_amphora_failover = octaviaclient.osc.v2.amphora:FailoverAmphora loadbalancer_amphora_list = octaviaclient.osc.v2.amphora:ListAmphora loadbalancer_amphora_show = octaviaclient.osc.v2.amphora:ShowAmphora loadbalancer_amphora_stats_show = octaviaclient.osc.v2.amphora:ShowAmphoraStats loadbalancer_availabilityzone_create = octaviaclient.osc.v2.availabilityzone:CreateAvailabilityzone loadbalancer_availabilityzone_delete = octaviaclient.osc.v2.availabilityzone:DeleteAvailabilityzone loadbalancer_availabilityzone_list = octaviaclient.osc.v2.availabilityzone:ListAvailabilityzone loadbalancer_availabilityzone_set = octaviaclient.osc.v2.availabilityzone:SetAvailabilityzone loadbalancer_availabilityzone_show = octaviaclient.osc.v2.availabilityzone:ShowAvailabilityzone loadbalancer_availabilityzone_unset = octaviaclient.osc.v2.availabilityzone:UnsetAvailabilityzone loadbalancer_availabilityzoneprofile_create = octaviaclient.osc.v2.availabilityzoneprofile:CreateAvailabilityzoneProfile loadbalancer_availabilityzoneprofile_delete = octaviaclient.osc.v2.availabilityzoneprofile:DeleteAvailabilityzoneProfile loadbalancer_availabilityzoneprofile_list = octaviaclient.osc.v2.availabilityzoneprofile:ListAvailabilityzoneProfile loadbalancer_availabilityzoneprofile_set = octaviaclient.osc.v2.availabilityzoneprofile:SetAvailabilityzoneProfile loadbalancer_availabilityzoneprofile_show = octaviaclient.osc.v2.availabilityzoneprofile:ShowAvailabilityzoneProfile loadbalancer_create = octaviaclient.osc.v2.load_balancer:CreateLoadBalancer loadbalancer_delete = octaviaclient.osc.v2.load_balancer:DeleteLoadBalancer loadbalancer_failover = octaviaclient.osc.v2.load_balancer:FailoverLoadBalancer loadbalancer_flavor_create = octaviaclient.osc.v2.flavor:CreateFlavor loadbalancer_flavor_delete = octaviaclient.osc.v2.flavor:DeleteFlavor loadbalancer_flavor_list = octaviaclient.osc.v2.flavor:ListFlavor loadbalancer_flavor_set = octaviaclient.osc.v2.flavor:SetFlavor loadbalancer_flavor_show = octaviaclient.osc.v2.flavor:ShowFlavor loadbalancer_flavor_unset = octaviaclient.osc.v2.flavor:UnsetFlavor loadbalancer_flavorprofile_create = octaviaclient.osc.v2.flavorprofile:CreateFlavorProfile loadbalancer_flavorprofile_delete = octaviaclient.osc.v2.flavorprofile:DeleteFlavorProfile loadbalancer_flavorprofile_list = octaviaclient.osc.v2.flavorprofile:ListFlavorProfile loadbalancer_flavorprofile_set = octaviaclient.osc.v2.flavorprofile:SetFlavorProfile loadbalancer_flavorprofile_show = octaviaclient.osc.v2.flavorprofile:ShowFlavorProfile loadbalancer_healthmonitor_create = octaviaclient.osc.v2.health_monitor:CreateHealthMonitor loadbalancer_healthmonitor_delete = octaviaclient.osc.v2.health_monitor:DeleteHealthMonitor loadbalancer_healthmonitor_list = octaviaclient.osc.v2.health_monitor:ListHealthMonitor loadbalancer_healthmonitor_set = octaviaclient.osc.v2.health_monitor:SetHealthMonitor loadbalancer_healthmonitor_show = octaviaclient.osc.v2.health_monitor:ShowHealthMonitor loadbalancer_healthmonitor_unset = octaviaclient.osc.v2.health_monitor:UnsetHealthMonitor loadbalancer_l7policy_create = octaviaclient.osc.v2.l7policy:CreateL7Policy loadbalancer_l7policy_delete = octaviaclient.osc.v2.l7policy:DeleteL7Policy loadbalancer_l7policy_list = octaviaclient.osc.v2.l7policy:ListL7Policy loadbalancer_l7policy_set = octaviaclient.osc.v2.l7policy:SetL7Policy loadbalancer_l7policy_show = octaviaclient.osc.v2.l7policy:ShowL7Policy loadbalancer_l7policy_unset = octaviaclient.osc.v2.l7policy:UnsetL7Policy loadbalancer_l7rule_create = octaviaclient.osc.v2.l7rule:CreateL7Rule loadbalancer_l7rule_delete = octaviaclient.osc.v2.l7rule:DeleteL7Rule loadbalancer_l7rule_list = octaviaclient.osc.v2.l7rule:ListL7Rule loadbalancer_l7rule_set = octaviaclient.osc.v2.l7rule:SetL7Rule loadbalancer_l7rule_show = octaviaclient.osc.v2.l7rule:ShowL7Rule loadbalancer_l7rule_unset = octaviaclient.osc.v2.l7rule:UnsetL7Rule loadbalancer_list = octaviaclient.osc.v2.load_balancer:ListLoadBalancer loadbalancer_listener_create = octaviaclient.osc.v2.listener:CreateListener loadbalancer_listener_delete = octaviaclient.osc.v2.listener:DeleteListener loadbalancer_listener_list = octaviaclient.osc.v2.listener:ListListener loadbalancer_listener_set = octaviaclient.osc.v2.listener:SetListener loadbalancer_listener_show = octaviaclient.osc.v2.listener:ShowListener loadbalancer_listener_stats_show = octaviaclient.osc.v2.listener:ShowListenerStats loadbalancer_listener_unset = octaviaclient.osc.v2.listener:UnsetListener loadbalancer_member_create = octaviaclient.osc.v2.member:CreateMember loadbalancer_member_delete = octaviaclient.osc.v2.member:DeleteMember loadbalancer_member_list = octaviaclient.osc.v2.member:ListMember loadbalancer_member_set = octaviaclient.osc.v2.member:SetMember loadbalancer_member_show = octaviaclient.osc.v2.member:ShowMember loadbalancer_member_unset = octaviaclient.osc.v2.member:UnsetMember loadbalancer_pool_create = octaviaclient.osc.v2.pool:CreatePool loadbalancer_pool_delete = octaviaclient.osc.v2.pool:DeletePool loadbalancer_pool_list = octaviaclient.osc.v2.pool:ListPool loadbalancer_pool_set = octaviaclient.osc.v2.pool:SetPool loadbalancer_pool_show = octaviaclient.osc.v2.pool:ShowPool loadbalancer_pool_unset = octaviaclient.osc.v2.pool:UnsetPool loadbalancer_provider_capability_list = octaviaclient.osc.v2.provider:ListProviderCapability loadbalancer_provider_list = octaviaclient.osc.v2.provider:ListProvider loadbalancer_quota_defaults_show = octaviaclient.osc.v2.quota:ShowQuotaDefaults loadbalancer_quota_list = octaviaclient.osc.v2.quota:ListQuota loadbalancer_quota_reset = octaviaclient.osc.v2.quota:ResetQuota loadbalancer_quota_set = octaviaclient.osc.v2.quota:SetQuota loadbalancer_quota_show = octaviaclient.osc.v2.quota:ShowQuota loadbalancer_quota_unset = octaviaclient.osc.v2.quota:UnsetQuota loadbalancer_set = octaviaclient.osc.v2.load_balancer:SetLoadBalancer loadbalancer_show = octaviaclient.osc.v2.load_balancer:ShowLoadBalancer loadbalancer_stats_show = octaviaclient.osc.v2.load_balancer:ShowLoadBalancerStats loadbalancer_status_show = octaviaclient.osc.v2.load_balancer:ShowLoadBalancerStatus loadbalancer_unset = octaviaclient.osc.v2.load_balancer:UnsetLoadBalancer ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220677.0 python-octaviaclient-3.7.0/python_octaviaclient.egg-info/not-zip-safe0000664000175000017500000000000100000000000026056 0ustar00zuulzuul00000000000000 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220677.0 python-octaviaclient-3.7.0/python_octaviaclient.egg-info/pbr.json0000664000175000017500000000005600000000000025307 0ustar00zuulzuul00000000000000{"git_version": "51ed435", "is_release": true}././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220677.0 python-octaviaclient-3.7.0/python_octaviaclient.egg-info/requires.txt0000664000175000017500000000032100000000000026224 0ustar00zuulzuul00000000000000cliff!=2.9.0,>=2.8.0 keystoneauth1>=3.18.0 osc-lib>=1.14.1 oslo.serialization!=2.19.1,>=2.18.0 oslo.utils>=3.33.0 pbr!=2.1.0,>=2.0.0 python-neutronclient>=6.7.0 python-openstackclient>=3.12.0 requests>=2.14.2 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220677.0 python-octaviaclient-3.7.0/python_octaviaclient.egg-info/top_level.txt0000664000175000017500000000001600000000000026357 0ustar00zuulzuul00000000000000octaviaclient ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0189226 python-octaviaclient-3.7.0/releasenotes/0000775000175000017500000000000000000000000020401 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0389223 python-octaviaclient-3.7.0/releasenotes/notes/0000775000175000017500000000000000000000000021531 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/.placeholder0000664000175000017500000000000000000000000024002 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/Add-PROMETHEUS-listener-protocol-23f5054f524d9332.yaml0000664000175000017500000000011400000000000032250 0ustar00zuulzuul00000000000000--- features: - | Added support for the PROMETHEUS listener protocol. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/Add-proxyv2-7a540796c60241c3.yaml0000664000175000017500000000010000000000000026515 0ustar00zuulzuul00000000000000--- features: - | Added support for the PROXYV2 protocol. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/Add-support-for-UDP-5476caa65b1253a6.yaml0000664000175000017500000000011500000000000030155 0ustar00zuulzuul00000000000000--- features: - | Adds client support for UDP protocol load balancers. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/Add-unset-commands-15490df414a70df0.yaml0000664000175000017500000000026600000000000030171 0ustar00zuulzuul00000000000000--- features: - | The loadbalancer commands now have unset actions. These will either clear the field back to None or it will reset the value to the API default value. ././@PaxHeader0000000000000000000000000000021100000000000011447 xustar0000000000000000115 path=python-octaviaclient-3.7.0/releasenotes/notes/Add-vip_vnic_type-load-balancer-field-f1bc1345ee741f88.yaml 22 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/Add-vip_vnic_type-load-balancer-field-f1bc1345ee741f880000664000175000017500000000023000000000000033000 0ustar00zuulzuul00000000000000--- features: - | Added support for the vip_vnic_type field on load balancers. A vip_vnic_type of 'direct' indicates the VIP is using SR-IOV. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/Client-to-request-JSON-responses-8d942dafca785c70.yaml0000664000175000017500000000027300000000000033036 0ustar00zuulzuul00000000000000--- fixes: - | The client will now always ask for a JSON format response from the Octavia API. This resolves a client side bug should certain errors be returned by the API. ././@PaxHeader0000000000000000000000000000023600000000000011456 xustar0000000000000000136 path=python-octaviaclient-3.7.0/releasenotes/notes/Improve-client-performance-when-using-a-name-instead-of-ID-51a6637050386a90.yaml 22 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/Improve-client-performance-when-using-a-name-instead-o0000664000175000017500000000014700000000000033751 0ustar00zuulzuul00000000000000--- fixes: - | Improved the client performance when using a name instead of the resource ID. ././@PaxHeader0000000000000000000000000000021000000000000011446 xustar0000000000000000114 path=python-octaviaclient-3.7.0/releasenotes/notes/add-ability-set-listener-cipher-list-fe379d0d0821ed42.yaml 22 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-ability-set-listener-cipher-list-fe379d0d0821ed42.0000664000175000017500000000021700000000000032767 0ustar00zuulzuul00000000000000--- features: - | Added an optional Argument ``--tls-ciphers`` for passing OpenSSL cipher strings when creating a new listener. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-ability-set-pool-cipher-list-70128f983506fbdb.yaml0000664000175000017500000000022200000000000032717 0ustar00zuulzuul00000000000000--- features: - | Added an optional Argument ``--tls-ciphers`` for passing OpenSSL cipher strings when creating or updating a pool. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-alpn-support-listeners-6508704b5c8944d2.yaml0000664000175000017500000000047600000000000031630 0ustar00zuulzuul00000000000000--- features: - | Added ALPN support for listeners with parameter ``--alpn-protocol`` (can be set multiple times). Users can define a list of application layer protocols to be negotiated over a secure connection. For example, users can limit to HTTP/2 or to HTTP/2 and HTTP/1.1 but exclude HTTP/1.0. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-amphora-configure-command-cda75053a72c0cdf.yaml0000664000175000017500000000022300000000000032525 0ustar00zuulzuul00000000000000--- features: - | Adds the ability to refresh the configuration of an amphora agent with the ``loadbalancer amphora configure`` command. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-amphora-delete-0fe5f2097da92b5c.yaml0000664000175000017500000000007200000000000030330 0ustar00zuulzuul00000000000000--- features: - | Added the amphora delete command. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-amphora-stats-show-48bc0fadf08f1057.yaml0000664000175000017500000000011200000000000031170 0ustar00zuulzuul00000000000000--- features: - | Adds support for querying the amphora statistics. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-amphorae-failover-suuport-9fa0b1c25026e123.yaml0000664000175000017500000000014000000000000032373 0ustar00zuulzuul00000000000000--- features: - | Add force failover an amphora command ``loadbalancer amphora failover``.././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-az-and-profiles-ed79c945c4e0d418.yaml0000664000175000017500000000056300000000000030372 0ustar00zuulzuul00000000000000--- features: - | Added management of availability zone and availability zone profiles. Creating a load balanacer now takes an optional availability-zone argument. Provider capability list now displays capabilities for both AZ and flavor, and includes an extra column ``type``. It can be filtered by passing ``--flavor`` or ``--availability-zone``.././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-flavor-support-75c6d5bec48b1d18.yaml0000664000175000017500000000013400000000000030445 0ustar00zuulzuul00000000000000--- features: - | Adds client support for octavia provider flavor and flavor_profile. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-hsts-support-f612ec171e28a3b3.yaml0000664000175000017500000000045000000000000030042 0ustar00zuulzuul00000000000000--- features: - | Added support for HTTP Strict Transport Security (HSTS). This new feature can be enabled and configured during listener creation and update using the new ``--hsts-max-age`` option and the optional ``--hsts-include-subdomains`` and ``--hsts-prefetch`` options. ././@PaxHeader0000000000000000000000000000021100000000000011447 xustar0000000000000000115 path=python-octaviaclient-3.7.0/releasenotes/notes/add-l7policy-and-l7rule-quota-support-73098a090b252901.yaml 22 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-l7policy-and-l7rule-quota-support-73098a090b2529010000664000175000017500000000011400000000000032460 0ustar00zuulzuul00000000000000--- features: - Add l7policy and l7rule's quota support to octaviaclient. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-lb-algorithm-source-ip-port-3e2d4b60f6916259.yaml0000664000175000017500000000011200000000000032467 0ustar00zuulzuul00000000000000--- features: - | Adds client support for SOURCE_IP_PORT algorithm. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-lb-flavor-b917faa0298c3a74.yaml0000664000175000017500000000014100000000000027240 0ustar00zuulzuul00000000000000--- features: - | Adds the ``flavor`` option to loadbalancer create and loadbalancer list. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-listener-allowed-cirds-2ef9fa2e1c650166.yaml0000664000175000017500000000007400000000000031735 0ustar00zuulzuul00000000000000--- features: - Added support to VIP access control list. ././@PaxHeader0000000000000000000000000000021500000000000011453 xustar0000000000000000119 path=python-octaviaclient-3.7.0/releasenotes/notes/add-missing-flavor-set-description-option-d49f3103ef15e778.yaml 22 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-missing-flavor-set-description-option-d49f3103ef150000664000175000017500000000022600000000000033316 0ustar00zuulzuul00000000000000--- fixes: - | Added a missing option to the "loadbalancer flavor set" command, admins can now update the description of an Octavia flavor. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-new-commands-and-options-d520b36d870cbcb4.yaml0000664000175000017500000000036000000000000032247 0ustar00zuulzuul00000000000000--- features: - Loadbalancer failover command, which allows to trigger failover protocol. - Amphora commands, to query amphorae by ID or by loadbalancer ID, etc. - Filter 'list' calls by loadbalancer ID, for both listeners and pools. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-pool-tls-alpn-support-59758ea78c78952e.yaml0000664000175000017500000000047200000000000031474 0ustar00zuulzuul00000000000000--- features: - | Added ALPN support for pools with parameter ``--alpn-protocol`` (can be set multiple times). Users can define a list of application layer protocols to be negotiated over a secure connection. For example, users can limit to HTTP/2 or to HTTP/2 and HTTP/1.1 but exclude HTTP/1.0. ././@PaxHeader0000000000000000000000000000020500000000000011452 xustar0000000000000000111 path=python-octaviaclient-3.7.0/releasenotes/notes/add-provider-load-balancer-create-4d151209dee32f81.yaml 22 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-provider-load-balancer-create-4d151209dee32f81.yam0000664000175000017500000000012700000000000032675 0ustar00zuulzuul00000000000000--- features: - | Added --provider as optional argument to load balancer create. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-qos-policy-argument-1741126d759630da.yaml0000664000175000017500000000016000000000000031051 0ustar00zuulzuul00000000000000--- features: - | Optional QoS policy argument for VIP, in loadbalancer create, and loadbalancer set. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-quota-support-effed2cf2a8c7ad4.yaml0000664000175000017500000000021600000000000030605 0ustar00zuulzuul00000000000000--- features: - | Octavia quota support for the OpenStack client plugin. * List, show, set, reset quotas * Show quota defaults ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-redirect-prefix-2f66455b3eacf5b6.yaml0000664000175000017500000000014300000000000030535 0ustar00zuulzuul00000000000000--- features: - Add REDIRECT_PREFIX action for L7 Policy in l7policy create, and set command ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-support-for-provider-4e60045ea54f1d30.yaml0000664000175000017500000000010700000000000031413 0ustar00zuulzuul00000000000000--- features: - | Adds client support for loadbalancer provider. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-support-for-sctp-protocol-f23b58db8522cc4b.yaml0000664000175000017500000000014400000000000032542 0ustar00zuulzuul00000000000000--- features: - | Add support for SCTP protocol in listener, pool and health-monitor objects. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-tag-support-01087c4b3c4360dc.yaml0000664000175000017500000000066700000000000027561 0ustar00zuulzuul00000000000000--- features: - | Add support for tags for Octavia resources. Tags are supported with load balancers, listeners, pools, members, health monitors, l7policies and l7rules. Tags can be added when creating a resource, and they can be set and unset. Tags allow also to filter elements when listing Octavia resources. fixes: - | Fix errors when combining set/unset CLI for l7rule resources and the --wait option. ././@PaxHeader0000000000000000000000000000021100000000000011447 xustar0000000000000000115 path=python-octaviaclient-3.7.0/releasenotes/notes/add-tls-version-support-for-listeners-4a6a661af5f9de9a.yaml 22 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-tls-version-support-for-listeners-4a6a661af5f9de9a0000664000175000017500000000025500000000000033361 0ustar00zuulzuul00000000000000--- features: - | Added a repeatable optional argument ``--tls-version`` for setting one or more TLS protocol versions when createing or updating a listener. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-tls-version-support-to-pools-852f02b034f436f9.yaml0000664000175000017500000000025000000000000032770 0ustar00zuulzuul00000000000000--- features: - | Added a repeatable optional argument ``--tls-version`` for setting one or more TLS protocol versions when creating or updating a pool. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-tls-versions-ciphers-unsets-8d06a502c8ad38ff.yaml0000664000175000017500000000012500000000000033061 0ustar00zuulzuul00000000000000--- features: - | Added TLS versions and ciphers unset to listeners and pools. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add-wait-option-to-CUD-commands-97375387e7762b83.yaml0000664000175000017500000000037500000000000032220 0ustar00zuulzuul00000000000000--- features: - | Commands that can cause loadbalancers to enter an immutable status (Create, Update, and Delete operations) now have a ``--wait`` argument. If set, the client will continue to poll until the status is no longer immutable. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add_backup_member_support-8b406bb72654ba88.yaml0000664000175000017500000000017500000000000031760 0ustar00zuulzuul00000000000000--- features: - | Optional backup argument for member, in loadbalancer member create, and loadbalancer member set. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/add_loadbalancer_status_support-f960d89f1b77fd16.yaml0000664000175000017500000000021300000000000033266 0ustar00zuulzuul00000000000000--- features: - | Adds the "openstack loadbalancer status show" command to display the load balancer status tree in JSON format. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/amphora-list-long-option-55390b5abef5b82e.yaml0000664000175000017500000000023300000000000031554 0ustar00zuulzuul00000000000000--- features: - | Amphora list now supports a ``--long`` option, which will include a few additional columns (compute_id, cached_zone, image_id).././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/drop-python-2-7-7b427838d72ef248.yaml0000664000175000017500000000022300000000000027274 0ustar00zuulzuul00000000000000--- upgrade: - | Python 2.7 support has been dropped. The minimum version of Python now supported by python-octaviaclient is Python 3.6. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/drop-python-3-6-and-3-7-5675086892fe7d16.yaml0000664000175000017500000000020100000000000030262 0ustar00zuulzuul00000000000000--- upgrade: - | Python 3.6 & 3.7 support has been dropped. The minimum version of Python now supported is Python 3.8. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/exposed-timeouts-eb29f55de5e56261.yaml0000664000175000017500000000050400000000000030160 0ustar00zuulzuul00000000000000--- features: - | Added ``--timeout-client-data``, ``--timeout-member-connect``, ``--timeout-member-data`` and ``--timeout-tcp-inspect`` options to ``listener create`` and ``listener set`` commands. Those options control the connection, inactivity and content inspection timeouts on the load balancer. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/fix-cli-pagination-792ad8cd386eb0e7.yaml0000664000175000017500000000027100000000000030406 0ustar00zuulzuul00000000000000--- fixes: - | Fixed some issues when the number of Octavia resources exceeded the 'pagination_max_limit' parameter in Octavia API. The list calls now support pagination. ././@PaxHeader0000000000000000000000000000021200000000000011450 xustar0000000000000000116 path=python-octaviaclient-3.7.0/releasenotes/notes/fix-inconsistent-parameter-name-in-azp-0267d025b7c78fc2.yaml 22 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/fix-inconsistent-parameter-name-in-azp-0267d025b7c78fc0000664000175000017500000000056500000000000033131 0ustar00zuulzuul00000000000000--- fixes: - | The ``--availabilityzone-data`` parameter is renamed to ``--availability-zone-data`` in the ``openstack loadbalancer availabilityzoneprofile set`` command. This change also fixes an issue with this CLI call, the availabilityzone data parameter was dropped when calling the API, leaving the availabilizyzoneprofile object untouched. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/fix-pool-protocols-090b2a6f4e82516f.yaml0000664000175000017500000000011600000000000030326 0ustar00zuulzuul00000000000000--- fixes: - | Removed an unsupported protocol from the pool protocols. ././@PaxHeader0000000000000000000000000000021400000000000011452 xustar0000000000000000118 path=python-octaviaclient-3.7.0/releasenotes/notes/improve-error-messages-for-invalid-calls-bc9eb3d18d3e4fdf.yaml 22 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/improve-error-messages-for-invalid-calls-bc9eb3d18d3e40000664000175000017500000000015200000000000033435 0ustar00zuulzuul00000000000000--- fixes: - | Improve CLI error messages when a user performs an unauthorized/invalid request. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/initial-list-command-90c9fa39fc10540e.yaml0000664000175000017500000000012100000000000030642 0ustar00zuulzuul00000000000000--- features: - | Add initial load balancer command ``loadbalancer list``. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/list-l7policies-by-listener-a11322c8e03a11e9.yaml0000664000175000017500000000013500000000000032005 0ustar00zuulzuul00000000000000--- features: - Added support to query l7policies by a given listener using ``--listener``.././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/listener-stats-db49f99a8a0dd90f.yaml0000664000175000017500000000011300000000000027762 0ustar00zuulzuul00000000000000--- features: - | Adds support for querying the listener statistics. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/load-balancer-commands-options-83cfdbb1bc5d8998.yaml0000664000175000017500000000034000000000000032760 0ustar00zuulzuul00000000000000--- features: - Add the following options "--vip-network-id", "--vip-subnet-id", "--vip-qos-policy-id", "--vip-port-id", "--provisioning-status", "--operating-status", "--provider" to "load balancer list" command. ././@PaxHeader0000000000000000000000000000022100000000000011450 xustar0000000000000000123 path=python-octaviaclient-3.7.0/releasenotes/notes/remove-unneeded-attributes-in-listener-create-2e7cb2de281ac7fe.yaml 22 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/remove-unneeded-attributes-in-listener-create-2e7cb2de0000664000175000017500000000051500000000000033706 0ustar00zuulzuul00000000000000--- fixes: - | Removed unneeded attributes that could have been passed to the API when calling "listener create", hsts_include_subdomains and hsts_preload were passed even when not used. It fixes an issue when using a recent python-octaviaclient release with older Octavia releases (without this HSTS feature). ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/show-command-enhancement-df414a70df0a7089.yml0000664000175000017500000000035400000000000031350 0ustar00zuulzuul00000000000000--- features: - | If ID of resource is passed to resource show command - call is done directly using passed UUID. If name of resource is in UUID format - list of resources will be still executed to get correct resource ID.././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/notes/support-additional-vips-cd0164f1838ee676.yaml0000664000175000017500000000042500000000000031365 0ustar00zuulzuul00000000000000--- features: - | It is now possible to create a loadbalancer with more than one VIP by passing ``--additional-vip subnet-id=[,ip-address=]`` to the create command. Additional VIPs will also appear in the ``show`` details of a loadbalancer. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0389223 python-octaviaclient-3.7.0/releasenotes/source/0000775000175000017500000000000000000000000021701 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/source/2023.1.rst0000664000175000017500000000020200000000000023152 0ustar00zuulzuul00000000000000=========================== 2023.1 Series Release Notes =========================== .. release-notes:: :branch: stable/2023.1 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/source/2023.2.rst0000664000175000017500000000020200000000000023153 0ustar00zuulzuul00000000000000=========================== 2023.2 Series Release Notes =========================== .. release-notes:: :branch: stable/2023.2 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0389223 python-octaviaclient-3.7.0/releasenotes/source/_static/0000775000175000017500000000000000000000000023327 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/source/_static/.placeholder0000664000175000017500000000000000000000000025600 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0389223 python-octaviaclient-3.7.0/releasenotes/source/_templates/0000775000175000017500000000000000000000000024036 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/source/_templates/.placeholder0000664000175000017500000000000000000000000026307 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/source/conf.py0000664000175000017500000002056400000000000023207 0ustar00zuulzuul00000000000000# -*- coding: utf-8 -*- # 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. # Glance Release Notes documentation build configuration file, created by # sphinx-quickstart on Tue Nov 3 17:40:50 2015. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # sys.path.insert(0, os.path.abspath('.')) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'openstackdocstheme', 'reno.sphinxext', ] # openstackdocstheme options openstackdocs_repo_name = 'openstack/python-octaviaclient' openstackdocs_use_storyboard = True # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. # source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. copyright = '2016, OpenStack Foundation' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: # today = '' # Else, today_fmt is used as the format for a strftime call. # today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = [] # The reST default role (used for this markup: `text`) to use for all # documents. # default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. # add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). # add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. # show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'native' # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. # keep_warnings = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'openstackdocs' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. # html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". # html_title = None # A shorter title for the navigation bar. Default is the same as html_title. # html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. # html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. # html_extra_path = [] # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. # html_use_smartypants = True # Custom sidebar templates, maps document names to template names. # html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. # html_additional_pages = {} # If false, no module index is generated. # html_domain_indices = True # If false, no index is generated. # html_use_index = True # If true, the index is split into individual pages for each letter. # html_split_index = False # If true, links to the reST sources are added to the pages. # html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. # html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. # html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. # html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). # html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'PythonOctaviaClientReleaseNotesdoc' # -- Options for LaTeX output --------------------------------------------- # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # documentclass [howto, manual, or own class]). latex_documents = [ ('index', 'PythonOctaviaClientReleaseNotes.tex', 'python-octaviaclient Release Notes Documentation', 'Octavia Developers', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. # latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. # latex_use_parts = False # If true, show page references after internal links. # latex_show_pagerefs = False # If true, show URL addresses after external links. # latex_show_urls = False # Documents to append as an appendix to all manuals. # latex_appendices = [] # If false, no module index is generated. # latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'pythonoctaviaclientreleasenotes', 'python-octaviaclient Release Notes Documentation', ['Octavia Developers'], 1) ] # If true, show URL addresses after external links. # man_show_urls = False # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', 'PythonOctaviaClientReleaseNotes', 'python-octaviaclient Release Notes Documentation', 'Octavia Developers', 'PythonOctaviaClientReleaseNotes', 'OpenStack client plugin for Octavia.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. # texinfo_appendices = [] # If false, no module index is generated. # texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. # texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. # texinfo_no_detailmenu = False # -- Options for Internationalization output ------------------------------ locale_dirs = ['locale/'] ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/source/index.rst0000664000175000017500000000043500000000000023544 0ustar00zuulzuul00000000000000============================================ octaviaclient Release Notes ============================================ .. toctree:: :maxdepth: 1 unreleased 2023.2 2023.1 zed yoga xena wallaby victoria ussuri train stein rocky queens pike ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/source/pike.rst0000664000175000017500000000021700000000000023363 0ustar00zuulzuul00000000000000=================================== Pike Series Release Notes =================================== .. release-notes:: :branch: stable/pike ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/source/queens.rst0000664000175000017500000000022300000000000023730 0ustar00zuulzuul00000000000000=================================== Queens Series Release Notes =================================== .. release-notes:: :branch: stable/queens ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/source/rocky.rst0000664000175000017500000000022100000000000023555 0ustar00zuulzuul00000000000000=================================== Rocky Series Release Notes =================================== .. release-notes:: :branch: stable/rocky ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/source/stein.rst0000664000175000017500000000022100000000000023550 0ustar00zuulzuul00000000000000=================================== Stein Series Release Notes =================================== .. release-notes:: :branch: stable/stein ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/source/train.rst0000664000175000017500000000017600000000000023554 0ustar00zuulzuul00000000000000========================== Train Series Release Notes ========================== .. release-notes:: :branch: stable/train ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/source/unreleased.rst0000664000175000017500000000016000000000000024557 0ustar00zuulzuul00000000000000============================== Current Series Release Notes ============================== .. release-notes:: ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/source/ussuri.rst0000664000175000017500000000020200000000000023757 0ustar00zuulzuul00000000000000=========================== Ussuri Series Release Notes =========================== .. release-notes:: :branch: stable/ussuri ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/source/victoria.rst0000664000175000017500000000021200000000000024246 0ustar00zuulzuul00000000000000============================= Victoria Series Release Notes ============================= .. release-notes:: :branch: stable/victoria ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/source/wallaby.rst0000664000175000017500000000020600000000000024064 0ustar00zuulzuul00000000000000============================ Wallaby Series Release Notes ============================ .. release-notes:: :branch: stable/wallaby ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/source/xena.rst0000664000175000017500000000017200000000000023366 0ustar00zuulzuul00000000000000========================= Xena Series Release Notes ========================= .. release-notes:: :branch: stable/xena ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/source/yoga.rst0000664000175000017500000000020000000000000023362 0ustar00zuulzuul00000000000000========================= Yoga Series Release Notes ========================= .. release-notes:: :branch: unmaintained/yoga ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/releasenotes/source/zed.rst0000664000175000017500000000016600000000000023220 0ustar00zuulzuul00000000000000======================== Zed Series Release Notes ======================== .. release-notes:: :branch: stable/zed ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/requirements.txt0000664000175000017500000000137400000000000021201 0ustar00zuulzuul00000000000000# Requirements lower bounds listed here are our best effort to keep them up to # date but we do not test them so no guarantee of having them all correct. If # you find any incorrect lower bounds, let us know or propose a fix. # The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. cliff!=2.9.0,>=2.8.0 # Apache-2.0 keystoneauth1>=3.18.0 # Apache-2.0 python-neutronclient>=6.7.0 # Apache-2.0 python-openstackclient>=3.12.0 # Apache-2.0 osc-lib>=1.14.1 # Apache-2.0 oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0 oslo.utils>=3.33.0 # Apache-2.0 pbr!=2.1.0,>=2.0.0 # Apache-2.0 requests>=2.14.2 # Apache-2.0 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0429223 python-octaviaclient-3.7.0/setup.cfg0000664000175000017500000001651700000000000017543 0ustar00zuulzuul00000000000000[metadata] name = python-octaviaclient summary = Octavia client for OpenStack Load Balancing description_file = README.rst author = OpenStack author_email = openstack-discuss@lists.openstack.org home_page = https://docs.openstack.org/python-octaviaclient/latest/ python_requires = >=3.8 classifier = Environment :: OpenStack Intended Audience :: Information Technology Intended Audience :: System Administrators License :: OSI Approved :: Apache Software License Operating System :: POSIX :: Linux Programming Language :: Python Programming Language :: Python :: Implementation :: CPython Programming Language :: Python :: 3 :: Only Programming Language :: Python :: 3 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 [files] packages = octaviaclient [entry_points] openstack.cli.extension = load_balancer = octaviaclient.osc.plugin openstack.load_balancer.v2 = loadbalancer_create = octaviaclient.osc.v2.load_balancer:CreateLoadBalancer loadbalancer_list = octaviaclient.osc.v2.load_balancer:ListLoadBalancer loadbalancer_show = octaviaclient.osc.v2.load_balancer:ShowLoadBalancer loadbalancer_delete = octaviaclient.osc.v2.load_balancer:DeleteLoadBalancer loadbalancer_set = octaviaclient.osc.v2.load_balancer:SetLoadBalancer loadbalancer_unset = octaviaclient.osc.v2.load_balancer:UnsetLoadBalancer loadbalancer_stats_show = octaviaclient.osc.v2.load_balancer:ShowLoadBalancerStats loadbalancer_status_show = octaviaclient.osc.v2.load_balancer:ShowLoadBalancerStatus loadbalancer_failover = octaviaclient.osc.v2.load_balancer:FailoverLoadBalancer loadbalancer_listener_create = octaviaclient.osc.v2.listener:CreateListener loadbalancer_listener_list = octaviaclient.osc.v2.listener:ListListener loadbalancer_listener_show = octaviaclient.osc.v2.listener:ShowListener loadbalancer_listener_delete = octaviaclient.osc.v2.listener:DeleteListener loadbalancer_listener_set = octaviaclient.osc.v2.listener:SetListener loadbalancer_listener_unset = octaviaclient.osc.v2.listener:UnsetListener loadbalancer_listener_stats_show = octaviaclient.osc.v2.listener:ShowListenerStats loadbalancer_pool_create = octaviaclient.osc.v2.pool:CreatePool loadbalancer_pool_list = octaviaclient.osc.v2.pool:ListPool loadbalancer_pool_show = octaviaclient.osc.v2.pool:ShowPool loadbalancer_pool_delete = octaviaclient.osc.v2.pool:DeletePool loadbalancer_pool_set = octaviaclient.osc.v2.pool:SetPool loadbalancer_pool_unset = octaviaclient.osc.v2.pool:UnsetPool loadbalancer_member_create = octaviaclient.osc.v2.member:CreateMember loadbalancer_member_list = octaviaclient.osc.v2.member:ListMember loadbalancer_member_show = octaviaclient.osc.v2.member:ShowMember loadbalancer_member_delete = octaviaclient.osc.v2.member:DeleteMember loadbalancer_member_set = octaviaclient.osc.v2.member:SetMember loadbalancer_member_unset = octaviaclient.osc.v2.member:UnsetMember loadbalancer_l7policy_create = octaviaclient.osc.v2.l7policy:CreateL7Policy loadbalancer_l7policy_list = octaviaclient.osc.v2.l7policy:ListL7Policy loadbalancer_l7policy_show = octaviaclient.osc.v2.l7policy:ShowL7Policy loadbalancer_l7policy_delete = octaviaclient.osc.v2.l7policy:DeleteL7Policy loadbalancer_l7policy_unset = octaviaclient.osc.v2.l7policy:UnsetL7Policy loadbalancer_l7policy_set = octaviaclient.osc.v2.l7policy:SetL7Policy loadbalancer_l7rule_create = octaviaclient.osc.v2.l7rule:CreateL7Rule loadbalancer_l7rule_list = octaviaclient.osc.v2.l7rule:ListL7Rule loadbalancer_l7rule_show = octaviaclient.osc.v2.l7rule:ShowL7Rule loadbalancer_l7rule_delete = octaviaclient.osc.v2.l7rule:DeleteL7Rule loadbalancer_l7rule_set = octaviaclient.osc.v2.l7rule:SetL7Rule loadbalancer_l7rule_unset = octaviaclient.osc.v2.l7rule:UnsetL7Rule loadbalancer_healthmonitor_create = octaviaclient.osc.v2.health_monitor:CreateHealthMonitor loadbalancer_healthmonitor_list = octaviaclient.osc.v2.health_monitor:ListHealthMonitor loadbalancer_healthmonitor_show = octaviaclient.osc.v2.health_monitor:ShowHealthMonitor loadbalancer_healthmonitor_delete = octaviaclient.osc.v2.health_monitor:DeleteHealthMonitor loadbalancer_healthmonitor_set = octaviaclient.osc.v2.health_monitor:SetHealthMonitor loadbalancer_healthmonitor_unset = octaviaclient.osc.v2.health_monitor:UnsetHealthMonitor loadbalancer_quota_list = octaviaclient.osc.v2.quota:ListQuota loadbalancer_quota_show = octaviaclient.osc.v2.quota:ShowQuota loadbalancer_quota_defaults_show = octaviaclient.osc.v2.quota:ShowQuotaDefaults loadbalancer_quota_reset = octaviaclient.osc.v2.quota:ResetQuota loadbalancer_quota_set = octaviaclient.osc.v2.quota:SetQuota loadbalancer_quota_unset = octaviaclient.osc.v2.quota:UnsetQuota loadbalancer_amphora_list = octaviaclient.osc.v2.amphora:ListAmphora loadbalancer_amphora_show = octaviaclient.osc.v2.amphora:ShowAmphora loadbalancer_amphora_configure = octaviaclient.osc.v2.amphora:ConfigureAmphora loadbalancer_amphora_delete = octaviaclient.osc.v2.amphora:DeleteAmphora loadbalancer_amphora_failover = octaviaclient.osc.v2.amphora:FailoverAmphora loadbalancer_amphora_stats_show = octaviaclient.osc.v2.amphora:ShowAmphoraStats loadbalancer_provider_list = octaviaclient.osc.v2.provider:ListProvider loadbalancer_provider_capability_list = octaviaclient.osc.v2.provider:ListProviderCapability loadbalancer_flavorprofile_create = octaviaclient.osc.v2.flavorprofile:CreateFlavorProfile loadbalancer_flavorprofile_list = octaviaclient.osc.v2.flavorprofile:ListFlavorProfile loadbalancer_flavorprofile_delete = octaviaclient.osc.v2.flavorprofile:DeleteFlavorProfile loadbalancer_flavorprofile_show = octaviaclient.osc.v2.flavorprofile:ShowFlavorProfile loadbalancer_flavorprofile_set = octaviaclient.osc.v2.flavorprofile:SetFlavorProfile loadbalancer_flavor_create = octaviaclient.osc.v2.flavor:CreateFlavor loadbalancer_flavor_list = octaviaclient.osc.v2.flavor:ListFlavor loadbalancer_flavor_delete = octaviaclient.osc.v2.flavor:DeleteFlavor loadbalancer_flavor_show = octaviaclient.osc.v2.flavor:ShowFlavor loadbalancer_flavor_set = octaviaclient.osc.v2.flavor:SetFlavor loadbalancer_flavor_unset = octaviaclient.osc.v2.flavor:UnsetFlavor loadbalancer_availabilityzoneprofile_create = octaviaclient.osc.v2.availabilityzoneprofile:CreateAvailabilityzoneProfile loadbalancer_availabilityzoneprofile_list = octaviaclient.osc.v2.availabilityzoneprofile:ListAvailabilityzoneProfile loadbalancer_availabilityzoneprofile_delete = octaviaclient.osc.v2.availabilityzoneprofile:DeleteAvailabilityzoneProfile loadbalancer_availabilityzoneprofile_show = octaviaclient.osc.v2.availabilityzoneprofile:ShowAvailabilityzoneProfile loadbalancer_availabilityzoneprofile_set = octaviaclient.osc.v2.availabilityzoneprofile:SetAvailabilityzoneProfile loadbalancer_availabilityzone_create = octaviaclient.osc.v2.availabilityzone:CreateAvailabilityzone loadbalancer_availabilityzone_list = octaviaclient.osc.v2.availabilityzone:ListAvailabilityzone loadbalancer_availabilityzone_delete = octaviaclient.osc.v2.availabilityzone:DeleteAvailabilityzone loadbalancer_availabilityzone_show = octaviaclient.osc.v2.availabilityzone:ShowAvailabilityzone loadbalancer_availabilityzone_set = octaviaclient.osc.v2.availabilityzone:SetAvailabilityzone loadbalancer_availabilityzone_unset = octaviaclient.osc.v2.availabilityzone:UnsetAvailabilityzone [egg_info] tag_build = tag_date = 0 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/setup.py0000664000175000017500000000127100000000000017423 0ustar00zuulzuul00000000000000# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. # # 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. import setuptools setuptools.setup( setup_requires=['pbr>=2.0.0'], pbr=True) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/test-requirements.txt0000664000175000017500000000113100000000000022145 0ustar00zuulzuul00000000000000# The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. hacking>=6.1.0,<6.2.0 # Apache-2.0 requests-mock>=1.2.0 # Apache-2.0 coverage!=4.4,>=4.0 # Apache-2.0 doc8>=0.6.0 # Apache-2.0 Pygments>=2.2.0 # BSD license bandit!=1.6.0,>=1.1.0 # Apache-2.0 flake8-import-order>=0.18.0,<0.19.0 # LGPLv3 pylint>=2.5.3 # GPLv2 python-subunit>=1.0.0 # Apache-2.0/BSD oslotest>=3.2.0 # Apache-2.0 stestr>=2.0.0 # Apache-2.0 testscenarios>=0.4 # Apache-2.0/BSD ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0389223 python-octaviaclient-3.7.0/tools/0000775000175000017500000000000000000000000017050 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/tools/coding-checks.sh0000775000175000017500000000304600000000000022113 0ustar00zuulzuul00000000000000#!/bin/sh # This script is copied from neutron and adapted for octavia. set -eu usage () { echo "Usage: $0 [OPTION]..." echo "Run octavia's coding check(s)" echo "" echo " -Y, --pylint [] Run pylint check on the entire octavia module or just files changed in basecommit (e.g. HEAD~1)" echo " -h, --help Print this usage message" echo exit 0 } join_args() { if [ -z "$scriptargs" ]; then scriptargs="$opt" else scriptargs="$scriptargs $opt" fi } process_options () { i=1 while [ $i -le $# ]; do eval opt=\$$i case $opt in -h|--help) usage;; -Y|--pylint) pylint=1;; *) join_args;; esac i=$((i+1)) done } run_pylint () { local target="${scriptargs:-all}" if [ "$target" = "all" ]; then files="octaviaclient" else case "$target" in *HEAD~[0-9]*) files=$(git diff --diff-filter=AM --name-only $target -- "*.py");; *) echo "$target is an unrecognized basecommit"; exit 1;; esac fi echo "Running pylint..." echo "You can speed this up by running it on 'HEAD~[0-9]' (e.g. HEAD~1, this change only)..." if [ -n "${files}" ]; then pylint -j 0 --max-nested-blocks 7 --rcfile=.pylintrc --output-format=colorized ${files} else echo "No python changes in this commit, pylint check not required." exit 0 fi } scriptargs= pylint=1 process_options $@ if [ $pylint -eq 1 ]; then run_pylint exit 0 fi ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/tox.ini0000664000175000017500000001024200000000000017222 0ustar00zuulzuul00000000000000[tox] minversion = 3.18.0 envlist = py3,pep8 ignore_basepython_conflict = True [testenv] usedevelop = True allowlist_externals = find rm install_command = pip install {opts} {packages} setenv = VIRTUAL_ENV={envdir} PYTHONWARNINGS=default::DeprecationWarning deps = -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt commands = find . -type f -name "*.pyc" -delete stestr run {posargs} stestr slowest [testenv:pep8] commands = flake8 # RST linter doc8 doc/source octaviaclient HACKING.rst README.rst \ CONTRIBUTING.rst # Run security linter {[testenv:bandit]commands} {toxinidir}/tools/coding-checks.sh --pylint {posargs} allowlist_externals = sh find bash {toxinidir}/tools/coding-checks.sh [testenv:venv] commands = {posargs} [testenv:cover] setenv = {[testenv]setenv} PYTHON=coverage run --source octaviaclient --parallel-mode allowlist_externals = find commands = find octaviaclient -type f -name "*.pyc" -delete coverage erase stestr run {posargs} coverage combine coverage html -d cover coverage xml -o cover/coverage.xml coverage report --fail-under=90 --skip-covered [testenv:docs] deps = -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} -r{toxinidir}/doc/requirements.txt commands = rm -rf doc/build/html sphinx-build -W -b html doc/source doc/build/html [testenv:pdf-docs] deps = {[testenv:docs]deps} allowlist_externals = make rm commands = rm -rf doc/build/pdf sphinx-build -W -b latex doc/source doc/build/pdf make -C doc/build/pdf [testenv:releasenotes] deps = -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} -r{toxinidir}/doc/requirements.txt commands = rm -rf releasenotes/build sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html [testenv:debug] passenv = OS_* commands = pip install -q -U ipdb oslo_debug_helper -t octaviaclient/tests {posargs} [flake8] # [H104]: Empty file with only comments # [W504]: Line break after binary operator # [I202]: Additional newline in a group of imports. ignore = H104,W504,I202 show-source = true builtins = _ exclude = .venv,.git,.tox,dist,doc,*lib/python*,*egg,build import-order-style = pep8 # [H106]: Don't put vim configuration in source files # [H203]: Use assertIs(Not)None to check for None # [H204]: Use assert(Not)Equal to check for equality # [H205]: Use assert(Greater|Less)(Equal) for comparison # [H904]: Delay string interpolations at logging calls enable-extensions=H106,H203,H204,H205,H904 [testenv:bashate] envdir = {toxworkdir}/shared commands = bash -c "find {toxinidir} \ -not \( -type d -name .tox\* -prune \) \ -not \( -type d -name .venv\* -prune \) \ -type f \ -name \*.sh \ # [E005]: File does not begin with #! or have a .sh prefix # [E006]: Check for lines longer than 79 columns # [E042]: Local declaration hides errors # [E043]: Arithmetic compound has inconsistent return semantics -print0 | xargs -0 bashate -v -iE006 -eE005,E042,E043" [flake8:local-plugins] extension = O316 = checks:assert_true_instance O318 = checks:assert_equal_or_not_none O323 = checks:assert_equal_true_or_false O324 = checks:no_mutable_default_args O338 = checks:assert_equal_in O339 = checks:no_log_warn O340 = checks:no_xrange O341 = checks:no_translate_logs O342 = checks:check_raised_localized_exceptions O343 = checks:check_no_basestring O345 = checks:check_no_eventlet_imports O346 = checks:check_line_continuation_no_backslash paths = ./octaviaclient/hacking [testenv:requirements] deps = -egit+https://opendev.org/openstack/requirements#egg=openstack-requirements allowlist_externals = sh commands = sh -c '{envdir}/src/openstack-requirements/playbooks/files/project-requirements-change.py --req {envdir}/src/openstack-requirements --local {toxinidir} master' [testenv:bandit] commands = bandit -r octaviaclient -ll -ii -x tests ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709220678.0389223 python-octaviaclient-3.7.0/zuul.d/0000775000175000017500000000000000000000000017131 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709220649.0 python-octaviaclient-3.7.0/zuul.d/projects.yaml0000664000175000017500000000033300000000000021645 0ustar00zuulzuul00000000000000- project: templates: - check-requirements - openstack-cover-jobs - openstack-python3-jobs - openstackclient-plugin-jobs - publish-openstack-docs-pti - release-notes-jobs-python3