os-client-config-1.31.2/0000775000175000017500000000000013311601303014747 5ustar zuulzuul00000000000000os-client-config-1.31.2/tox.ini0000666000175000017500000000425513311600770016301 0ustar zuulzuul00000000000000[tox] minversion = 1.6 envlist = py35,py27,pep8 skipsdist = True [testenv] usedevelop = True passenv = UPPER_CONSTRAINTS_FILE install_command = pip install -U {opts} {packages} setenv = VIRTUAL_ENV={envdir} LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=C OS_STDOUT_CAPTURE=1 OS_STDERR_CAPTURE=1 OS_TEST_TIMEOUT=60 deps = -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt commands = stestr run {posargs} stestr slowest [testenv:pep8] basepython = python3 usedevelop = False skip_install = True deps = -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} doc8 hacking pygments readme commands = doc8 doc/source python setup.py check -r -s flake8 os_client_config [testenv:venv] basepython = python3 commands = {posargs} [testenv:cover] basepython = python3 setenv = {[testenv]setenv} PYTHON=coverage run --source os_client_config --parallel-mode commands = stestr run {posargs} coverage combine coverage html -d cover coverage xml -o cover/coverage.xml [testenv:docs] basepython = python3 skip_install = True deps = -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} -r{toxinidir}/requirements.txt -r{toxinidir}/doc/requirements.txt commands = sphinx-build -W -d doc/build/doctrees -b html doc/source/ doc/build/html [testenv:releasenotes] basepython = python3 skip_install = True deps = -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} -r{toxinidir}/doc/requirements.txt commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html [flake8] show-source = True builtins = _ exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build,releasenotes/source/conf.py [testenv:lower-constraints] basepython = python3 deps = -c{toxinidir}/lower-constraints.txt -r{toxinidir}/test-requirements.txt -r{toxinidir}/requirements.txt os-client-config-1.31.2/lower-constraints.txt0000666000175000017500000000164313311600770021222 0ustar zuulzuul00000000000000appdirs==1.3.0 asn1crypto==0.23.0 Babel==2.3.4 certifi==2018.1.18 cffi==1.7.0 chardet==3.0.4 coverage==4.0 cryptography==2.1 debtcollector==1.2.0 extras==1.0.0 fixtures==3.0.0 flake8==2.5.5 future==0.16.0 hacking==0.12.0 idna==2.6 iso8601==0.1.12 jsonpatch==1.16 jsonpointer==1.13 jsonschema==2.6.0 keystoneauth1==3.4.0 linecache2==1.0.0 mccabe==0.2.1 mock==2.0.0 monotonic==0.6 mox3==0.20.0 netaddr==0.7.18 netifaces==0.10.4 openstacksdk==0.13.0 oslo.i18n==3.15.3 oslo.utils==3.33.0 oslotest==3.2.0 pbr==3.1.1 pep8==1.5.7 prettytable==0.7.2 pycparser==2.18 pyflakes==0.8.1 pyOpenSSL==17.1.0 pyparsing==2.1.0 python-glanceclient==2.8.0 python-mimeparse==1.6.0 python-subunit==1.0.0 pytz==2013.6 PyYAML==3.12 requests==2.18.4 requestsexceptions==1.2.0 six==1.11.0 stestr==1.0.0 stevedore==1.28.0 testrepository==0.0.18 testscenarios==0.4 testtools==2.2.0 traceback2==1.4.0 unittest2==1.1.0 urllib3==1.22 warlock==1.2.0 wrapt==1.7.0 os-client-config-1.31.2/setup.py0000666000175000017500000000200613311600770016470 0ustar zuulzuul00000000000000# 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. # THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT import setuptools # In python < 2.7.4, a lazy loading of package `pbr` will break # setuptools if some other modules registered functions in `atexit`. # solution from: http://bugs.python.org/issue15881#msg170215 try: import multiprocessing # noqa except ImportError: pass setuptools.setup( setup_requires=['pbr>=2.0.0'], pbr=True) os-client-config-1.31.2/CONTRIBUTING.rst0000666000175000017500000000104213311600770017416 0ustar zuulzuul00000000000000If you would like to contribute to the development of OpenStack, you must follow the steps in this page: http://docs.openstack.org/infra/manual/developers.html Once those steps have been completed, changes to OpenStack should be submitted for review via the Gerrit tool, following the workflow documented at: http://docs.openstack.org/infra/manual/developers.html#development-workflow Pull requests submitted through GitHub will be ignored. Bugs should be filed on Launchpad, not GitHub: https://bugs.launchpad.net/os-client-configos-client-config-1.31.2/.coveragerc0000666000175000017500000000021213311600770017074 0ustar zuulzuul00000000000000[run] branch = True source = os_client_config omit = os_client_config/tests/*,os_client_config/openstack/* [report] ignore_errors = True os-client-config-1.31.2/README.rst0000666000175000017500000000246113311600770016452 0ustar zuulzuul00000000000000================ os-client-config ================ .. image:: http://governance.openstack.org/badges/os-client-config.svg :target: http://governance.openstack.org/reference/tags/index.html .. warning:: `os-client-config` has been superceded by `openstacksdk`_. While `os-client-config` will continue to exist, it is highly recommended that users transition to using `openstacksdk`_ directly. `os-client-config` is a library for collecting client configuration for using an OpenStack cloud in a consistent and comprehensive manner. It will find cloud config for as few as 1 cloud and as many as you want to put in a config file. It will read environment variables and config files, and it also contains some vendor specific default values so that you don't have to know extra info to use OpenStack * If you have a config file, you will get the clouds listed in it * If you have environment variables, you will get a cloud named `envvars` * If you have neither, you will get a cloud named `defaults` with base defaults Source ------ * Free software: Apache license * Documentation: http://docs.openstack.org/os-client-config/latest * Source: http://git.openstack.org/cgit/openstack/os-client-config * Bugs: http://bugs.launchpad.net/os-client-config .. _openstacksdk: http://docs.openstack.org/openstacksdk/latest os-client-config-1.31.2/PKG-INFO0000664000175000017500000000451013311601303016044 0ustar zuulzuul00000000000000Metadata-Version: 1.1 Name: os-client-config Version: 1.31.2 Summary: OpenStack Client Configuation Library Home-page: https://docs.openstack.org/os-client-config/latest Author: OpenStack Author-email: openstack-dev@lists.openstack.org License: UNKNOWN Description: ================ os-client-config ================ .. image:: http://governance.openstack.org/badges/os-client-config.svg :target: http://governance.openstack.org/reference/tags/index.html .. warning:: `os-client-config` has been superceded by `openstacksdk`_. While `os-client-config` will continue to exist, it is highly recommended that users transition to using `openstacksdk`_ directly. `os-client-config` is a library for collecting client configuration for using an OpenStack cloud in a consistent and comprehensive manner. It will find cloud config for as few as 1 cloud and as many as you want to put in a config file. It will read environment variables and config files, and it also contains some vendor specific default values so that you don't have to know extra info to use OpenStack * If you have a config file, you will get the clouds listed in it * If you have environment variables, you will get a cloud named `envvars` * If you have neither, you will get a cloud named `defaults` with base defaults Source ------ * Free software: Apache license * Documentation: http://docs.openstack.org/os-client-config/latest * Source: http://git.openstack.org/cgit/openstack/os-client-config * Bugs: http://bugs.launchpad.net/os-client-config .. _openstacksdk: http://docs.openstack.org/openstacksdk/latest 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 :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.5 os-client-config-1.31.2/.mailmap0000666000175000017500000000013013311600770016373 0ustar zuulzuul00000000000000# Format is: # # os-client-config-1.31.2/requirements.txt0000666000175000017500000000036413311600770020247 0ustar zuulzuul00000000000000# 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. openstacksdk>=0.13.0 # Apache-2.0 os-client-config-1.31.2/LICENSE0000666000175000017500000002363613311600770015777 0ustar zuulzuul00000000000000 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. os-client-config-1.31.2/.stestr.conf0000666000175000017500000000004113311600770017224 0ustar zuulzuul00000000000000[DEFAULT] test_path=. top_dir=./ os-client-config-1.31.2/setup.cfg0000666000175000017500000000157213311601303016577 0ustar zuulzuul00000000000000[metadata] name = os-client-config summary = OpenStack Client Configuation Library description-file = README.rst author = OpenStack author-email = openstack-dev@lists.openstack.org home-page = https://docs.openstack.org/os-client-config/latest 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 :: 2 Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 Programming Language :: Python :: 3.5 [files] packages = os_client_config [build_sphinx] source-dir = doc/source build-dir = doc/build all_files = 1 warning-is-error = 1 [upload_sphinx] upload-dir = doc/build/html [wheel] universal = 1 [egg_info] tag_build = tag_date = 0 os-client-config-1.31.2/doc/0000775000175000017500000000000013311601303015514 5ustar zuulzuul00000000000000os-client-config-1.31.2/doc/requirements.txt0000666000175000017500000000056013311600770021012 0ustar zuulzuul00000000000000# 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. docutils>=0.11 # OSI-Approved Open Source, Public Domain sphinx!=1.6.6,!=1.6.7,>=1.6.2 # BSD openstackdocstheme>=1.18.1 # Apache-2.0 reno>=2.5.0 # Apache-2.0 os-client-config-1.31.2/doc/source/0000775000175000017500000000000013311601303017014 5ustar zuulzuul00000000000000os-client-config-1.31.2/doc/source/install/0000775000175000017500000000000013311601303020462 5ustar zuulzuul00000000000000os-client-config-1.31.2/doc/source/install/index.rst0000666000175000017500000000033113311600770022331 0ustar zuulzuul00000000000000============ Installation ============ At the command line:: $ pip install os-client-config Or, if you have virtualenvwrapper installed:: $ mkvirtualenv os-client-config $ pip install os-client-config os-client-config-1.31.2/doc/source/contributor/0000775000175000017500000000000013311601303021366 5ustar zuulzuul00000000000000os-client-config-1.31.2/doc/source/contributor/index.rst0000666000175000017500000000011613311600770023236 0ustar zuulzuul00000000000000============ Contributing ============ .. include:: ../../../CONTRIBUTING.rst os-client-config-1.31.2/doc/source/index.rst0000666000175000017500000000241313311600770020666 0ustar zuulzuul00000000000000================ os-client-config ================ .. image:: http://governance.openstack.org/badges/os-client-config.svg :target: http://governance.openstack.org/reference/tags/index.html .. warning:: `os-client-config` has been superceded by `openstacksdk`_. While `os-client-config` will continue to exist, it is highly recommended that users transition to using `openstacksdk`_ directly. .. _openstacksdk: https://docs.openstack.org/openstacksdk/latest `os-client-config` is a library for collecting client configuration for using an OpenStack cloud in a consistent and comprehensive manner. It will find cloud config for as few as 1 cloud and as many as you want to put in a config file. It will read environment variables and config files, and it also contains some vendor specific default values so that you don't have to know extra info to use OpenStack * If you have a config file, you will get the clouds listed in it * If you have environment variables, you will get a cloud named `envvars` * If you have neither, you will get a cloud named `defaults` with base defaults .. toctree:: :maxdepth: 2 install/index user/index reference/index contributor/index Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` os-client-config-1.31.2/doc/source/reference/0000775000175000017500000000000013311601303020752 5ustar zuulzuul00000000000000os-client-config-1.31.2/doc/source/reference/index.rst0000666000175000017500000000031013311600770022616 0ustar zuulzuul00000000000000============= API Reference ============= .. module:: os_client_config :synopsis: OpenStack client configuration .. autoclass:: os_client_config.OpenStackConfig :members: :inherited-members: os-client-config-1.31.2/doc/source/conf.py0000777000175000017500000000534013311600770020331 0ustar zuulzuul00000000000000# -*- 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 os import sys import openstackdocstheme 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', #'sphinx.ext.intersphinx', 'reno.sphinxext', 'openstackdocstheme', ] # openstackdocstheme options repository_name = 'openstack/os-client-config' bug_project = 'os-client-config' bug_tag = '' html_last_updated_fmt = '%Y-%m-%d %H:%M' # 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. project = u'os-client-config' copyright = u'2015, various OpenStack developers' # 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 = 'sphinx' # -- 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_path = [openstackdocstheme.get_html_theme_path()] # Output file base name for HTML help builder. htmlhelp_basename = '%sdoc' % project # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass # [howto/manual]). latex_documents = [ ('index', '%s.tex' % project, u'%s Documentation' % project, u'OpenStack Foundation', 'manual'), ] # Example configuration for intersphinx: refer to the Python standard library. #intersphinx_mapping = {'http://docs.python.org/': None} os-client-config-1.31.2/doc/source/user/0000775000175000017500000000000013311601303017772 5ustar zuulzuul00000000000000os-client-config-1.31.2/doc/source/user/configuration.rst0000666000175000017500000002277213311600770023416 0ustar zuulzuul00000000000000=========================================== Configuring os-client-config Applications =========================================== Environment Variables --------------------- `os-client-config` honors all of the normal `OS_*` variables. It does not provide backwards compatibility to service-specific variables such as `NOVA_USERNAME`. If you have OpenStack environment variables set, `os-client-config` will produce a cloud config object named `envvars` containing your values from the environment. If you don't like the name `envvars`, that's ok, you can override it by setting `OS_CLOUD_NAME`. Service specific settings, like the nova service type, are set with the default service type as a prefix. For instance, to set a special service_type for trove set .. code-block:: bash export OS_DATABASE_SERVICE_TYPE=rax:database Config Files ------------ `os-client-config` will look for a file called `clouds.yaml` in the following locations: * Current Directory * ~/.config/openstack * /etc/openstack The first file found wins. You can also set the environment variable `OS_CLIENT_CONFIG_FILE` to an absolute path of a file to look for and that location will be inserted at the front of the file search list. The keys are all of the keys you'd expect from `OS_*` - except lower case and without the OS prefix. So, region name is set with `region_name`. Service specific settings, like the nova service type, are set with the default service type as a prefix. For instance, to set a special service_type for trove (because you're using Rackspace) set: .. code-block:: yaml database_service_type: 'rax:database' Site Specific File Locations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In addition to `~/.config/openstack` and `/etc/openstack` - some platforms have other locations they like to put things. `os-client-config` will also look in an OS specific config dir * `USER_CONFIG_DIR` * `SITE_CONFIG_DIR` `USER_CONFIG_DIR` is different on Linux, OSX and Windows. * Linux: `~/.config/openstack` * OSX: `~/Library/Application Support/openstack` * Windows: `C:\\Users\\USERNAME\\AppData\\Local\\OpenStack\\openstack` `SITE_CONFIG_DIR` is different on Linux, OSX and Windows. * Linux: `/etc/openstack` * OSX: `/Library/Application Support/openstack` * Windows: `C:\\ProgramData\\OpenStack\\openstack` An example config file is probably helpful: .. code-block:: yaml clouds: mtvexx: profile: vexxhost auth: username: mordred@inaugust.com password: XXXXXXXXX project_name: mordred@inaugust.com region_name: ca-ymq-1 dns_api_version: 1 mordred: region_name: RegionOne auth: username: 'mordred' password: XXXXXXX project_name: 'shade' auth_url: 'https://montytaylor-sjc.openstack.blueboxgrid.com:5001/v2.0' infra: profile: rackspace auth: username: openstackci password: XXXXXXXX project_id: 610275 regions: - DFW - ORD - IAD You may note a few things. First, since `auth_url` settings are silly and embarrassingly ugly, known cloud vendor profile information is included and may be referenced by name. One of the benefits of that is that `auth_url` isn't the only thing the vendor defaults contain. For instance, since Rackspace lists `rax:database` as the service type for trove, `os-client-config` knows that so that you don't have to. In case the cloud vendor profile is not available, you can provide one called `clouds-public.yaml`, following the same location rules previously mentioned for the config files. `regions` can be a list of regions. When you call `get_all_clouds`, you'll get a cloud config object for each cloud/region combo. As seen with `dns_service_type`, any setting that makes sense to be per-service, like `service_type` or `endpoint` or `api_version` can be set by prefixing the setting with the default service type. That might strike you funny when setting `service_type` and it does me too - but that's just the world we live in. Auth Settings ------------- Keystone has auth plugins - which means it's not possible to know ahead of time which auth settings are needed. `os-client-config` sets the default plugin type to `password`, which is what things all were before plugins came about. In order to facilitate validation of values, all of the parameters that exist as a result of a chosen plugin need to go into the auth dict. For password auth, this includes `auth_url`, `username` and `password` as well as anything related to domains, projects and trusts. Splitting Secrets ----------------- In some scenarios, such as configuration management controlled environments, it might be easier to have secrets in one file and non-secrets in another. This is fully supported via an optional file `secure.yaml` which follows all the same location rules as `clouds.yaml`. It can contain anything you put in `clouds.yaml` and will take precedence over anything in the `clouds.yaml` file. .. code-block:: yaml # clouds.yaml clouds: internap: profile: internap auth: username: api-55f9a00fb2619 project_name: inap-17037 regions: - ams01 - nyj01 # secure.yaml clouds: internap: auth: password: XXXXXXXXXXXXXXXXX SSL Settings ------------ When the access to a cloud is done via a secure connection, `os-client-config` will always verify the SSL cert by default. This can be disabled by setting `verify` to `False`. In case the cert is signed by an unknown CA, a specific cacert can be provided via `cacert`. **WARNING:** `verify` will always have precedence over `cacert`, so when setting a CA cert but disabling `verify`, the cloud cert will never be validated. Client certs are also configurable. `cert` will be the client cert file location. In case the cert key is not included within the client cert file, its file location needs to be set via `key`. .. code-block:: yaml # clouds.yaml clouds: secure: auth: ... key: /home/myhome/client-cert.key cert: /home/myhome/client-cert.crt cacert: /home/myhome/ca.crt insecure: auth: ... verify: False Cache Settings -------------- Accessing a cloud is often expensive, so it's quite common to want to do some client-side caching of those operations. To facilitate that, `os-client-config` understands passing through cache settings to dogpile.cache, with the following behaviors: * Listing no config settings means you get a null cache. * `cache.expiration_time` and nothing else gets you memory cache. * Otherwise, `cache.class` and `cache.arguments` are passed in Different cloud behaviors are also differently expensive to deal with. If you want to get really crazy and tweak stuff, you can specify different expiration times on a per-resource basis by passing values, in seconds to an expiration mapping keyed on the singular name of the resource. A value of `-1` indicates that the resource should never expire. `os-client-config` does not actually cache anything itself, but it collects and presents the cache information so that your various applications that are connecting to OpenStack can share a cache should you desire. .. code-block:: yaml cache: class: dogpile.cache.pylibmc expiration_time: 3600 arguments: url: - 127.0.0.1 expiration: server: 5 flavor: -1 clouds: mtvexx: profile: vexxhost auth: username: mordred@inaugust.com password: XXXXXXXXX project_name: mordred@inaugust.com region_name: ca-ymq-1 dns_api_version: 1 IPv6 ---- IPv6 is the future, and you should always use it if your cloud supports it and if your local network supports it. Both of those are easily detectable and all friendly software should do the right thing. However, sometimes you might exist in a location where you have an IPv6 stack, but something evil has caused it to not actually function. In that case, there is a config option you can set to unbreak you `force_ipv4`, or `OS_FORCE_IPV4` boolean environment variable. .. code-block:: yaml client: force_ipv4: true clouds: mtvexx: profile: vexxhost auth: username: mordred@inaugust.com password: XXXXXXXXX project_name: mordred@inaugust.com region_name: ca-ymq-1 dns_api_version: 1 monty: profile: rax auth: username: mordred@inaugust.com password: XXXXXXXXX project_name: mordred@inaugust.com region_name: DFW The above snippet will tell client programs to prefer returning an IPv4 address. Per-region settings ------------------- Sometimes you have a cloud provider that has config that is common to the cloud, but also with some things you might want to express on a per-region basis. For instance, Internap provides a public and private network specific to the user in each region, and putting the values of those networks into config can make consuming programs more efficient. To support this, the region list can actually be a list of dicts, and any setting that can be set at the cloud level can be overridden for that region. .. code-block:: yaml clouds: internap: profile: internap auth: password: XXXXXXXXXXXXXXXXX username: api-55f9a00fb2619 project_name: inap-17037 regions: - name: ams01 values: networks: - name: inap-17037-WAN1654 routes_externally: true - name: inap-17037-LAN6745 - name: nyj01 values: networks: - name: inap-17037-WAN1654 routes_externally: true - name: inap-17037-LAN6745 os-client-config-1.31.2/doc/source/user/network-config.rst0000666000175000017500000000556113311600770023500 0ustar zuulzuul00000000000000============== Network Config ============== There are several different qualities that networks in OpenStack might have that might not be able to be automatically inferred from the available metadata. To help users navigate more complex setups, `os-client-config` allows configuring a list of network metadata. .. code-block:: yaml clouds: amazing: networks: - name: blue routes_externally: true - name: purple routes_externally: true default_interface: true - name: green routes_externally: false - name: yellow routes_externally: false nat_destination: true - name: chartreuse routes_externally: false routes_ipv6_externally: true - name: aubergine routes_ipv4_externally: false routes_ipv6_externally: true Every entry must have a name field, which can hold either the name or the id of the network. `routes_externally` is a boolean field that labels the network as handling north/south traffic off of the cloud. In a public cloud this might be thought of as the "public" network, but in private clouds it's possible it might be an RFC1918 address. In either case, it's provides IPs to servers that things not on the cloud can use. This value defaults to `false`, which indicates only servers on the same network can talk to it. `routes_ipv4_externally` and `routes_ipv6_externally` are boolean fields to help handle `routes_externally` in the case where a network has a split stack with different values for IPv4 and IPv6. Either entry, if not given, defaults to the value of `routes_externally`. `default_interface` is a boolean field that indicates that the network is the one that programs should use. It defaults to false. An example of needing to use this value is a cloud with two private networks, and where a user is running ansible in one of the servers to talk to other servers on the private network. Because both networks are private, there would otherwise be no way to determine which one should be used for the traffic. There can only be one `default_interface` per cloud. `nat_destination` is a boolean field that indicates which network floating ips should be attached to. It defaults to false. Normally this can be inferred by looking for a network that has subnets that have a gateway_ip. But it's possible to have more than one network that satisfies that condition, so the user might want to tell programs which one to pick. There can be only one `nat_destination` per cloud. `nat_source` is a boolean field that indicates which network floating ips should be requested from. It defaults to false. Normally this can be inferred by looking for a network that is attached to a router. But it's possible to have more than one network that satisfies that condition, so the user might want to tell programs which one to pick. There can be only one `nat_source` per cloud. os-client-config-1.31.2/doc/source/user/releasenotes.rst0000666000175000017500000000023113311600770023222 0ustar zuulzuul00000000000000============= Release Notes ============= Release notes for `os-client-config` can be found at http://docs.openstack.org/releasenotes/os-client-config/ os-client-config-1.31.2/doc/source/user/index.rst0000666000175000017500000000026713311600770021651 0ustar zuulzuul00000000000000======================== Using os-client-config ======================== .. toctree:: :maxdepth: 2 configuration using vendor-support network-config releasenotes os-client-config-1.31.2/doc/source/user/using.rst0000666000175000017500000001171013311600770021662 0ustar zuulzuul00000000000000========================================== Using os-client-config in an Application ========================================== Usage ----- The simplest and least useful thing you can do is: .. code-block:: python python -m os_client_config.config Which will print out whatever if finds for your config. If you want to use it from python, which is much more likely what you want to do, things like: Get a named cloud. .. code-block:: python import os_client_config cloud_config = os_client_config.OpenStackConfig().get_one_cloud( 'internap', region_name='ams01') print(cloud_config.name, cloud_config.region, cloud_config.config) Or, get all of the clouds. .. code-block:: python import os_client_config cloud_config = os_client_config.OpenStackConfig().get_all_clouds() for cloud in cloud_config: print(cloud.name, cloud.region, cloud.config) argparse -------- If you're using os-client-config from a program that wants to process command line options, there is a registration function to register the arguments that both os-client-config and keystoneauth know how to deal with - as well as a consumption argument. .. code-block:: python import argparse import sys import os_client_config cloud_config = os_client_config.OpenStackConfig() parser = argparse.ArgumentParser() cloud_config.register_argparse_arguments(parser, sys.argv) options = parser.parse_args() cloud = cloud_config.get_one_cloud(argparse=options) Constructing OpenStack SDK object --------------------------------- If what you want to do is get an OpenStack SDK Connection and you want it to do all the normal things related to clouds.yaml, `OS_` environment variables, a helper function is provided. The following will get you a fully configured `openstack.connection.Connection` instance. .. code-block:: python import os_client_config sdk = os_client_config.make_sdk() If you want to do the same thing but on a named cloud. .. code-block:: python import os_client_config sdk = os_client_config.make_sdk(cloud='mtvexx') If you want to do the same thing but also support command line parsing. .. code-block:: python import argparse import os_client_config sdk = os_client_config.make_sdk(options=argparse.ArgumentParser()) It should be noted that OpenStack SDK has ways to construct itself that allow for additional flexibility. If the helper function here does not meet your needs, you should see the `from_config` method of `openstack.connection.Connection `_ Constructing shade objects -------------------------- If what you want to do is get a `shade `_ OpenStackCloud object, a helper function that honors clouds.yaml and `OS_` environment variables is provided. The following will get you a fully configured `OpenStackCloud` instance. .. code-block:: python import os_client_config cloud = os_client_config.make_shade() If you want to do the same thing but on a named cloud. .. code-block:: python import os_client_config cloud = os_client_config.make_shade(cloud='mtvexx') If you want to do the same thing but also support command line parsing. .. code-block:: python import argparse import os_client_config cloud = os_client_config.make_shade(options=argparse.ArgumentParser()) Constructing REST API Clients ----------------------------- What if you want to make direct REST calls via a Session interface? You're in luck. A similar interface is available as with `openstacksdk` and `shade`. The main difference is that you need to specify which service you want to talk to and `make_rest_client` will return you a keystoneauth Session object that is mounted on the endpoint for the service you're looking for. .. code-block:: python import os_client_config session = os_client_config.make_rest_client('compute', cloud='vexxhost') response = session.get('/servers') server_list = response.json()['servers'] Constructing Legacy Client objects ---------------------------------- If you want get an old-style Client object from a python-\*client library, and you want it to do all the normal things related to clouds.yaml, `OS_` environment variables, a helper function is also provided. The following will get you a fully configured `novaclient` instance. .. code-block:: python import os_client_config nova = os_client_config.make_client('compute') If you want to do the same thing but on a named cloud. .. code-block:: python import os_client_config nova = os_client_config.make_client('compute', cloud='mtvexx') If you want to do the same thing but also support command line parsing. .. code-block:: python import argparse import os_client_config nova = os_client_config.make_client( 'compute', options=argparse.ArgumentParser()) If you want to get fancier than that in your python, then the rest of the API is available to you. But often times, you just want to do the one thing. os-client-config-1.31.2/doc/source/user/vendor-support.rst0000666000175000017500000000020113311600770023535 0ustar zuulzuul00000000000000============== Vendor Support ============== Please see https://docs.openstack.org/openstacksdk/latest/user/vendor-support.html os-client-config-1.31.2/HACKING.rst0000666000175000017500000000024513311600770016557 0ustar zuulzuul00000000000000os-client-config Style Commandments =============================================== Read the OpenStack Style Commandments https://docs.openstack.org/hacking/latest os-client-config-1.31.2/test-requirements.txt0000666000175000017500000000111113311600770021213 0ustar zuulzuul00000000000000# 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!=0.13.0,<0.14,>=0.12.0 # Apache-2.0 coverage!=4.4,>=4.0 # Apache-2.0 extras>=1.0.0 # MIT fixtures>=3.0.0 # Apache-2.0/BSD jsonschema<3.0.0,>=2.6.0 # MIT mock>=2.0.0 # BSD python-glanceclient>=2.8.0 # Apache-2.0 python-subunit>=1.0.0 # Apache-2.0/BSD oslotest>=3.2.0 # Apache-2.0 stestr>=1.0.0 # Apache-2.0 testscenarios>=0.4 # Apache-2.0/BSD testtools>=2.2.0 # MIT os-client-config-1.31.2/os_client_config.egg-info/0000775000175000017500000000000013311601303021745 5ustar zuulzuul00000000000000os-client-config-1.31.2/os_client_config.egg-info/not-zip-safe0000664000175000017500000000000113311601270024176 0ustar zuulzuul00000000000000 os-client-config-1.31.2/os_client_config.egg-info/pbr.json0000664000175000017500000000005613311601303023424 0ustar zuulzuul00000000000000{"git_version": "a024da3", "is_release": true}os-client-config-1.31.2/os_client_config.egg-info/PKG-INFO0000664000175000017500000000451013311601303023042 0ustar zuulzuul00000000000000Metadata-Version: 1.1 Name: os-client-config Version: 1.31.2 Summary: OpenStack Client Configuation Library Home-page: https://docs.openstack.org/os-client-config/latest Author: OpenStack Author-email: openstack-dev@lists.openstack.org License: UNKNOWN Description: ================ os-client-config ================ .. image:: http://governance.openstack.org/badges/os-client-config.svg :target: http://governance.openstack.org/reference/tags/index.html .. warning:: `os-client-config` has been superceded by `openstacksdk`_. While `os-client-config` will continue to exist, it is highly recommended that users transition to using `openstacksdk`_ directly. `os-client-config` is a library for collecting client configuration for using an OpenStack cloud in a consistent and comprehensive manner. It will find cloud config for as few as 1 cloud and as many as you want to put in a config file. It will read environment variables and config files, and it also contains some vendor specific default values so that you don't have to know extra info to use OpenStack * If you have a config file, you will get the clouds listed in it * If you have environment variables, you will get a cloud named `envvars` * If you have neither, you will get a cloud named `defaults` with base defaults Source ------ * Free software: Apache license * Documentation: http://docs.openstack.org/os-client-config/latest * Source: http://git.openstack.org/cgit/openstack/os-client-config * Bugs: http://bugs.launchpad.net/os-client-config .. _openstacksdk: http://docs.openstack.org/openstacksdk/latest 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 :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.5 os-client-config-1.31.2/os_client_config.egg-info/dependency_links.txt0000664000175000017500000000000113311601303026013 0ustar zuulzuul00000000000000 os-client-config-1.31.2/os_client_config.egg-info/requires.txt0000664000175000017500000000002513311601303024342 0ustar zuulzuul00000000000000openstacksdk>=0.13.0 os-client-config-1.31.2/os_client_config.egg-info/top_level.txt0000664000175000017500000000002113311601303024470 0ustar zuulzuul00000000000000os_client_config os-client-config-1.31.2/os_client_config.egg-info/SOURCES.txt0000664000175000017500000000603713311601303023637 0ustar zuulzuul00000000000000.coveragerc .mailmap .stestr.conf .zuul.yaml AUTHORS CONTRIBUTING.rst ChangeLog HACKING.rst LICENSE README.rst lower-constraints.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/contributor/index.rst doc/source/install/index.rst doc/source/reference/index.rst doc/source/user/configuration.rst doc/source/user/index.rst doc/source/user/network-config.rst doc/source/user/releasenotes.rst doc/source/user/using.rst doc/source/user/vendor-support.rst os_client_config/__init__.py os_client_config/cloud_config.py os_client_config/config.py os_client_config/constructors.json os_client_config/constructors.py os_client_config/defaults.json os_client_config/defaults.py os_client_config/exceptions.py os_client_config.egg-info/PKG-INFO os_client_config.egg-info/SOURCES.txt os_client_config.egg-info/dependency_links.txt os_client_config.egg-info/not-zip-safe os_client_config.egg-info/pbr.json os_client_config.egg-info/requires.txt os_client_config.egg-info/top_level.txt os_client_config/tests/__init__.py os_client_config/tests/base.py os_client_config/tests/test_cloud_config.py os_client_config/tests/test_config.py os_client_config/tests/test_environ.py os_client_config/tests/test_import_vendors.py os_client_config/tests/test_init.py os_client_config/vendors/__init__.py os_client_config/vendors/limestonenetworks.json releasenotes/notes/catch-up-release-notes-e385fad34e9f3d6e.yaml releasenotes/notes/cloud-profile-status-e0d29b5e2f10e95c.yaml releasenotes/notes/default-cloud-7ee0bcb9e5dd24b9.yaml releasenotes/notes/fix-compat-with-old-keystoneauth-66e11ee9d008b962.yaml releasenotes/notes/fix-vendor-import-ebd4ade0d5c17146.yaml releasenotes/notes/ironic-microversion-ba5b0f36f11196a6.yaml releasenotes/notes/load-yaml-3177efca78e5c67a.yaml releasenotes/notes/magic-fixes-dca4ae4dac2441a8.yaml releasenotes/notes/make-rest-client-dd3d365632a26fa0.yaml releasenotes/notes/make-rest-client-version-discovery-84125700f159491a.yaml releasenotes/notes/min-max-legacy-version-301242466ddefa93.yaml releasenotes/notes/nat-source-field-7c7db2a724616d59.yaml releasenotes/notes/network-list-e6e9dafdd8446263.yaml releasenotes/notes/option-precedence-1fecab21fdfb2c33.yaml releasenotes/notes/sdk-helper-41f8d815cfbcfb00.yaml releasenotes/notes/session-client-b581a6e5d18c8f04.yaml releasenotes/notes/shade-helper-568f8cb372eef6d9.yaml releasenotes/notes/started-using-reno-242e2b0cd27f9480.yaml releasenotes/notes/thin-shim-62c8e6f6942b83a5.yaml releasenotes/notes/vendor-add-betacloud-03872c3485104853.yaml releasenotes/notes/vendor-add-limestonenetworks-99b2ffab9fc23b08.yaml releasenotes/notes/vendor-updates-f11184ba56bb27cf.yaml releasenotes/source/conf.py releasenotes/source/index.rst releasenotes/source/mitaka.rst releasenotes/source/newton.rst releasenotes/source/ocata.rst releasenotes/source/pike.rst releasenotes/source/queens.rst releasenotes/source/unreleased.rst releasenotes/source/_static/.placeholder releasenotes/source/_templates/.placeholder tools/keystone_version.py tools/nova_version.pyos-client-config-1.31.2/AUTHORS0000664000175000017500000000470013311601303016020 0ustar zuulzuul00000000000000Alex Gaynor Alexander D Alvaro Lopez Garcia Andreas Jaeger Andy Botting Anita Kuno Arie Bregman Artem Goncharov Cao Xuan Hoang Cedric Brandily ChangBo Guo(gcb) Chris Church Christian Berendt Clark Boylan Clint Byrum Colleen Murphy David Shrewsbury Davide Guerri Dean Troyer Dean Troyer Dirk Mueller Doug Hellmann Doug Wiegley Eric Harney Flavio Percoco Ghe Rivero Gregory Haynes Ilya Shakhat James E. Blair James E. Blair Jamie Lennox Javier Pena Jeremy Stanley Jim Rollenhagen John Dennis Jordan Pittier Joshua Harlow Julia Kreger LiuNanke Logan V Mathieu Gagné Matthew Booth Mohammed Naser Monty Taylor Nick Jones OpenStack Release Bot Paulo Matias Pavlo Shchelokovskyy Saju Sean Handley Shuquan Huang Simon Leinen Spencer Krum Steve Martinelli Steve Martinelli TerryHowe Thomas Bechtold Tim Burke Tony Xu Xav Paice Yaguang Tang Yuriy Taraday Zuul avnish lifeless lingyongxu ricolin xhzhf os-client-config-1.31.2/os_client_config/0000775000175000017500000000000013311601303020253 5ustar zuulzuul00000000000000os-client-config-1.31.2/os_client_config/config.py0000666000175000017500000000412113311600770022101 0ustar zuulzuul00000000000000# Copyright (c) 2014 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 copy import sys from openstack.config import loader from openstack.config.loader import * # noqa from os_client_config import cloud_config from os_client_config import defaults class OpenStackConfig(loader.OpenStackConfig): _cloud_region_class = cloud_config.CloudConfig _defaults_module = defaults get_one_cloud = loader.OpenStackConfig.get_one get_all_clouds = loader.OpenStackConfig.get_all def get_cache_expiration_time(self): return int(self._cache_expiration_time) def get_cache_interval(self): return self.get_cache_expiration_time() def get_cache_max_age(self): return self.get_cache_expiration_time() def get_cache_path(self): return self._cache_path def get_cache_class(self): return self._cache_class def get_cache_arguments(self): return copy.deepcopy(self._cache_arguments) def get_cache_expiration(self): return copy.deepcopy(self._cache_expiration) if __name__ == '__main__': config = OpenStackConfig().get_all_clouds() for cloud in config: print_cloud = False if len(sys.argv) == 1: print_cloud = True elif len(sys.argv) == 3 and ( sys.argv[1] == cloud.name and sys.argv[2] == cloud.region): print_cloud = True elif len(sys.argv) == 2 and ( sys.argv[1] == cloud.name): print_cloud = True if print_cloud: print(cloud.name, cloud.region, cloud.config) os-client-config-1.31.2/os_client_config/__init__.py0000666000175000017500000001022613311600770022376 0ustar zuulzuul00000000000000# Copyright (c) 2014 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 sys import pbr.version from os_client_config import cloud_config from os_client_config.config import OpenStackConfig # noqa from os_client_config import vendors # noqa __version__ = pbr.version.VersionInfo('os_client_config').version_string() _config = None def get_config( service_key=None, options=None, app_name=None, app_version=None, **kwargs): load_yaml_config = kwargs.pop('load_yaml_config', True) global _config if not _config: _config = OpenStackConfig( load_yaml_config=load_yaml_config, app_name=app_name, app_version=app_version) if options: _config.register_argparse_arguments(options, sys.argv, service_key) parsed_options = options.parse_known_args(sys.argv) else: parsed_options = None return _config.get_one_cloud(options=parsed_options, **kwargs) def make_rest_client( service_key, options=None, app_name=None, app_version=None, version=None, **kwargs): """Simple wrapper function. It has almost no features. This will get you a raw requests Session Adapter that is mounted on the given service from the keystone service catalog. If you leave off cloud and region_name, it will assume that you've got env vars set, but if you give them, it'll use clouds.yaml as you'd expect. This function is deliberately simple. It has no flexibility. If you want flexibility, you can make a cloud config object and call get_session_client on it. This function is to make it easy to poke at OpenStack REST APIs with a properly configured keystone session. """ cloud = get_config( service_key=service_key, options=options, app_name=app_name, app_version=app_version, **kwargs) return cloud.get_session_client(service_key, version=version) # Backwards compat - simple_client was a terrible name simple_client = make_rest_client # Backwards compat - session_client was a terrible name session_client = make_rest_client def make_client(service_key, constructor=None, options=None, **kwargs): """Simple wrapper for getting a client instance from a client lib. OpenStack Client Libraries all have a fairly consistent constructor interface which os-client-config supports. In the simple case, there is one and only one right way to construct a client object. If as a user you don't want to do fancy things, just use this. It honors OS_ environment variables and clouds.yaml - and takes as **kwargs anything you'd expect to pass in. """ cloud = get_config(service_key=service_key, options=options, **kwargs) if not constructor: constructor = cloud_config._get_client(service_key) return cloud.get_legacy_client(service_key, constructor) def make_sdk(options=None, **kwargs): """Simple wrapper for getting an OpenStack SDK Connection. For completeness, provide a mechanism that matches make_client and make_rest_client. The heavy lifting here is done in openstacksdk. :rtype: :class:`~openstack.connection.Connection` """ from openstack import connection cloud = get_config(options=options, **kwargs) return connection.from_config(cloud_config=cloud, options=options) def make_shade(options=None, **kwargs): """Simple wrapper for getting a Shade OpenStackCloud object A mechanism that matches make_sdk, make_client and make_rest_client. :rtype: :class:`~shade.OpenStackCloud` """ import shade cloud = get_config(options=options, **kwargs) return shade.OpenStackCloud(cloud_config=cloud, **kwargs) os-client-config-1.31.2/os_client_config/constructors.py0000666000175000017500000000237013311600770023410 0ustar zuulzuul00000000000000# Copyright (c) 2014 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 json import os import threading _json_path = os.path.join( os.path.dirname(os.path.realpath(__file__)), 'constructors.json') _class_mapping = None _class_mapping_lock = threading.Lock() def get_constructor_mapping(): global _class_mapping if _class_mapping is not None: return _class_mapping.copy() with _class_mapping_lock: if _class_mapping is not None: return _class_mapping.copy() tmp_class_mapping = {} with open(_json_path, 'r') as json_file: tmp_class_mapping.update(json.load(json_file)) _class_mapping = tmp_class_mapping return tmp_class_mapping.copy() os-client-config-1.31.2/os_client_config/cloud_config.py0000666000175000017500000002524013311600770023274 0ustar zuulzuul00000000000000# Copyright (c) 2014 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 importlib from openstack import _log from openstack.config import cloud_region import os_client_config from os_client_config import constructors from os_client_config import exceptions def _get_client(service_key): class_mapping = constructors.get_constructor_mapping() if service_key not in class_mapping: raise exceptions.OpenStackConfigException( "Service {service_key} is unkown. Please pass in a client" " constructor or submit a patch to os-client-config".format( service_key=service_key)) mod_name, ctr_name = class_mapping[service_key].rsplit('.', 1) lib_name = mod_name.split('.')[0] try: mod = importlib.import_module(mod_name) except ImportError: raise exceptions.OpenStackConfigException( "Client for '{service_key}' was requested, but" " {mod_name} was unable to be imported. Either import" " the module yourself and pass the constructor in as an argument," " or perhaps you do not have python-{lib_name} installed.".format( service_key=service_key, mod_name=mod_name, lib_name=lib_name)) try: ctr = getattr(mod, ctr_name) except AttributeError: raise exceptions.OpenStackConfigException( "Client for '{service_key}' was requested, but although" " {mod_name} imported fine, the constructor at {fullname}" " as not found. Please check your installation, we have no" " clue what is wrong with your computer.".format( service_key=service_key, mod_name=mod_name, fullname=class_mapping[service_key])) return ctr class CloudConfig(cloud_region.CloudRegion): def __init__(self, *args, **kwargs): super(CloudConfig, self).__init__(*args, **kwargs) self.log = _log.setup_logging(__name__) def __getattr__(self, key): """Return arbitrary attributes.""" if key.startswith('os_'): key = key[3:] if key in [attr.replace('-', '_') for attr in self.config]: return self.config[key] else: return None def insert_user_agent(self): self._keystone_session.additional_user_agent.append( ('os-client-config', os_client_config.__version__)) super(CloudConfig, self).insert_user_agent() @property def region(self): return self.region_name def get_region_name(self, *args): return self.region_name def get_cache_expiration(self): return self.get_cache_expirations() def get_legacy_client( self, service_key, client_class=None, interface_key=None, pass_version_arg=True, version=None, min_version=None, max_version=None, **kwargs): """Return a legacy OpenStack client object for the given config. Most of the OpenStack python-*client libraries have the same interface for their client constructors, but there are several parameters one wants to pass given a :class:`CloudConfig` object. In the future, OpenStack API consumption should be done through the OpenStack SDK, but that's not ready yet. This is for getting Client objects from python-*client only. :param service_key: Generic key for service, such as 'compute' or 'network' :param client_class: Class of the client to be instantiated. This should be the unversioned version if there is one, such as novaclient.client.Client, or the versioned one, such as neutronclient.v2_0.client.Client if there isn't :param interface_key: (optional) Some clients, such as glanceclient only accept the parameter 'interface' instead of 'endpoint_type' - this is a get-out-of-jail parameter for those until they can be aligned. os-client-config understands this to be the case if service_key is image, so this is really only for use with other unknown broken clients. :param pass_version_arg: (optional) If a versioned Client constructor was passed to client_class, set this to False, which will tell get_client to not pass a version parameter. os-client-config already understand that this is the case for network, so it can be omitted in that case. :param version: (optional) Version string to override the configured version string. :param min_version: (options) Minimum version acceptable. :param max_version: (options) Maximum version acceptable. :param kwargs: (optional) keyword args are passed through to the Client constructor, so this is in case anything additional needs to be passed in. """ if not client_class: client_class = _get_client(service_key) interface = self.get_interface(service_key) # trigger exception on lack of service endpoint = self.get_session_endpoint( service_key, min_version=min_version, max_version=max_version) endpoint_override = self.get_endpoint(service_key) if service_key == 'object-store': constructor_kwargs = dict( session=self.get_session(), os_options=dict( service_type=self.get_service_type(service_key), object_storage_url=endpoint_override, region_name=self.region)) else: constructor_kwargs = dict( session=self.get_session(), service_name=self.get_service_name(service_key), service_type=self.get_service_type(service_key), endpoint_override=endpoint_override, region_name=self.region) if service_key == 'image': # os-client-config does not depend on glanceclient, but if # the user passed in glanceclient.client.Client, which they # would need to do if they were requesting 'image' - then # they necessarily have glanceclient installed from glanceclient.common import utils as glance_utils endpoint, detected_version = glance_utils.strip_version(endpoint) # If the user has passed in a version, that's explicit, use it if not version: version = detected_version # If the user has passed in or configured an override, use it. # Otherwise, ALWAYS pass in an endpoint_override becuase # we've already done version stripping, so we don't want version # reconstruction to happen twice if not endpoint_override: constructor_kwargs['endpoint_override'] = endpoint constructor_kwargs.update(kwargs) if pass_version_arg and service_key != 'object-store': if not version: version = self.get_api_version(service_key) if not version and service_key == 'volume': from cinderclient import client as cinder_client version = cinder_client.get_volume_api_from_url(endpoint) # Temporary workaround while we wait for python-openstackclient # to be able to handle 2.0 which is what neutronclient expects if service_key == 'network' and version == '2': version = '2.0' if service_key == 'identity': # Workaround for bug#1513839 if 'endpoint' not in constructor_kwargs: endpoint = self.get_session_endpoint('identity') constructor_kwargs['endpoint'] = endpoint if service_key == 'network': constructor_kwargs['api_version'] = version elif service_key == 'baremetal': if version != '1': # Set Ironic Microversion constructor_kwargs['os_ironic_api_version'] = version # Version arg is the major version, not the full microstring constructor_kwargs['version'] = version[0] else: constructor_kwargs['version'] = version if min_version and min_version > float(version): raise exceptions.OpenStackConfigVersionException( "Minimum version {min_version} requested but {version}" " found".format(min_version=min_version, version=version), version=version) if max_version and max_version < float(version): raise exceptions.OpenStackConfigVersionException( "Maximum version {max_version} requested but {version}" " found".format(max_version=max_version, version=version), version=version) if service_key == 'database': # TODO(mordred) Remove when https://review.openstack.org/314032 # has landed and released. We're passing in a Session, but the # trove Client object has username and password as required # args constructor_kwargs['username'] = None constructor_kwargs['password'] = None if not interface_key: if service_key in ('image', 'key-manager'): interface_key = 'interface' elif (service_key == 'identity' and version and version.startswith('3')): interface_key = 'interface' else: interface_key = 'endpoint_type' if service_key == 'object-store': constructor_kwargs['os_options'][interface_key] = interface else: constructor_kwargs[interface_key] = interface return client_class(**constructor_kwargs) os-client-config-1.31.2/os_client_config/constructors.json0000666000175000017500000000124513311600770023731 0ustar zuulzuul00000000000000{ "application-catalog": "muranoclient.client.Client", "baremetal": "ironicclient.client.Client", "compute": "novaclient.client.Client", "container-infra": "magnumclient.client.Client", "database": "troveclient.client.Client", "dns": "designateclient.client.Client", "identity": "keystoneclient.client.Client", "image": "glanceclient.Client", "key-manager": "barbicanclient.client.Client", "metering": "ceilometerclient.client.Client", "network": "neutronclient.neutron.client.Client", "object-store": "swiftclient.client.Connection", "orchestration": "heatclient.client.Client", "volume": "cinderclient.client.Client" } os-client-config-1.31.2/os_client_config/exceptions.py0000666000175000017500000000171013311600770023016 0ustar zuulzuul00000000000000# Copyright (c) 2014 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. from openstack import exceptions OpenStackConfigException = exceptions.ConfigException class OpenStackConfigVersionException(OpenStackConfigException): """A version was requested that is different than what was found.""" def __init__(self, version): super(OpenStackConfigVersionException, self).__init__() self.version = version os-client-config-1.31.2/os_client_config/tests/0000775000175000017500000000000013311601303021415 5ustar zuulzuul00000000000000os-client-config-1.31.2/os_client_config/tests/base.py0000666000175000017500000001754313311600770022724 0ustar zuulzuul00000000000000# -*- coding: utf-8 -*- # Copyright 2010-2011 OpenStack Foundation # 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 copy import os import tempfile from os_client_config import cloud_config import extras import fixtures from oslotest import base import yaml VENDOR_CONF = { 'public-clouds': { '_test_cloud_in_our_cloud': { 'auth': { 'auth_url': 'http://example.com/v2', 'username': 'testotheruser', 'project_name': 'testproject', }, }, } } USER_CONF = { 'cache': { 'max_age': '1', 'expiration': { 'server': 5, 'image': '7', }, }, 'client': { 'force_ipv4': True, }, 'clouds': { '_test-cloud_': { 'profile': '_test_cloud_in_our_cloud', 'auth': { 'auth_url': 'http://example.com/v2', 'username': 'testuser', 'password': 'testpass', }, 'region_name': 'test-region', }, '_test_cloud_no_vendor': { 'profile': '_test_non_existant_cloud', 'auth': { 'auth_url': 'http://example.com/v2', 'username': 'testuser', 'project_name': 'testproject', }, 'region-name': 'test-region', }, '_test-cloud-int-project_': { 'auth': { 'username': 'testuser', 'password': 'testpass', 'domain_id': 'awesome-domain', 'project_id': 12345, 'auth_url': 'http://example.com/v2', }, 'region_name': 'test-region', }, '_test-cloud-domain-id_': { 'auth': { 'username': 'testuser', 'password': 'testpass', 'project_id': 12345, 'auth_url': 'http://example.com/v2', 'domain_id': '6789', 'project_domain_id': '123456789', }, 'region_name': 'test-region', }, '_test-cloud-networks_': { 'auth': { 'username': 'testuser', 'password': 'testpass', 'project_id': 12345, 'auth_url': 'http://example.com/v2', 'domain_id': '6789', 'project_domain_id': '123456789', }, 'networks': [{ 'name': 'a-public', 'routes_externally': True, 'nat_source': True, }, { 'name': 'another-public', 'routes_externally': True, 'default_interface': True, }, { 'name': 'a-private', 'routes_externally': False, }, { 'name': 'another-private', 'routes_externally': False, 'nat_destination': True, }, { 'name': 'split-default', 'routes_externally': True, 'routes_ipv4_externally': False, }, { 'name': 'split-no-default', 'routes_ipv6_externally': False, 'routes_ipv4_externally': True, }], 'region_name': 'test-region', }, '_test_cloud_regions': { 'auth': { 'username': 'testuser', 'password': 'testpass', 'project-id': 'testproject', 'auth_url': 'http://example.com/v2', }, 'regions': [ { 'name': 'region1', 'values': { 'external_network': 'region1-network', } }, { 'name': 'region2', 'values': { 'external_network': 'my-network', } } ], }, '_test_cloud_hyphenated': { 'auth': { 'username': 'testuser', 'password': 'testpass', 'project-id': '12345', 'auth_url': 'http://example.com/v2', }, 'region_name': 'test-region', }, '_test-cloud_no_region': { 'profile': '_test_cloud_in_our_cloud', 'auth': { 'auth_url': 'http://example.com/v2', 'username': 'testuser', 'password': 'testpass', }, }, '_test-cloud-domain-scoped_': { 'auth': { 'auth_url': 'http://example.com/v2', 'username': 'testuser', 'password': 'testpass', 'domain-id': '12345', }, }, }, 'ansible': { 'expand-hostvars': False, 'use_hostnames': True, }, } SECURE_CONF = { 'clouds': { '_test_cloud_no_vendor': { 'auth': { 'password': 'testpass', }, } } } NO_CONF = { 'cache': {'max_age': 1}, } def _write_yaml(obj): # Assume NestedTempfile so we don't have to cleanup with tempfile.NamedTemporaryFile(delete=False) as obj_yaml: obj_yaml.write(yaml.safe_dump(obj).encode('utf-8')) return obj_yaml.name class TestCase(base.BaseTestCase): """Test case base class for all unit tests.""" def setUp(self): super(TestCase, self).setUp() self.useFixture(fixtures.NestedTempfile()) conf = copy.deepcopy(USER_CONF) tdir = self.useFixture(fixtures.TempDir()) conf['cache']['path'] = tdir.path self.cloud_yaml = _write_yaml(conf) self.secure_yaml = _write_yaml(SECURE_CONF) self.vendor_yaml = _write_yaml(VENDOR_CONF) self.no_yaml = _write_yaml(NO_CONF) self.useFixture(fixtures.MonkeyPatch( 'os_client_config.__version__', '1.2.3')) self.useFixture(fixtures.MonkeyPatch( 'openstack.version.__version__', '3.4.5')) # Isolate the test runs from the environment # Do this as two loops because you can't modify the dict in a loop # over the dict in 3.4 keys_to_isolate = [] for env in os.environ.keys(): if env.startswith('OS_'): keys_to_isolate.append(env) for env in keys_to_isolate: self.useFixture(fixtures.EnvironmentVariable(env)) def _assert_cloud_details(self, cc): self.assertIsInstance(cc, cloud_config.CloudConfig) self.assertTrue(extras.safe_hasattr(cc, 'auth')) self.assertIsInstance(cc.auth, dict) self.assertIsNone(cc.cloud) self.assertIn('username', cc.auth) self.assertEqual('testuser', cc.auth['username']) self.assertEqual('testpass', cc.auth['password']) self.assertFalse(cc.config['image_api_use_tasks']) self.assertTrue('project_name' in cc.auth or 'project_id' in cc.auth) if 'project_name' in cc.auth: self.assertEqual('testproject', cc.auth['project_name']) elif 'project_id' in cc.auth: self.assertEqual('testproject', cc.auth['project_id']) self.assertEqual(cc.get_cache_expiration_time(), 1) self.assertEqual(cc.get_cache_resource_expiration('server'), 5.0) self.assertEqual(cc.get_cache_resource_expiration('image'), 7.0) os-client-config-1.31.2/os_client_config/tests/test_config.py0000666000175000017500000013212713311600770024312 0ustar zuulzuul00000000000000# Copyright (c) 2014 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 argparse import copy import os import extras import fixtures import testtools import yaml from openstack.config import defaults from os_client_config import cloud_config from os_client_config import config from os_client_config import exceptions from os_client_config.tests import base def prompt_for_password(prompt=None): """Fake prompt function that just returns a constant string""" return 'promptpass' class TestConfig(base.TestCase): def test_get_all_clouds(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml], secure_files=[self.no_yaml]) clouds = c.get_all_clouds() # We add one by hand because the regions cloud is going to exist # twice since it has two regions in it user_clouds = [ cloud for cloud in base.USER_CONF['clouds'].keys() ] + ['_test_cloud_regions'] configured_clouds = [cloud.name for cloud in clouds] self.assertItemsEqual(user_clouds, configured_clouds) def test_get_one_cloud(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cloud = c.get_one_cloud(validate=False) self.assertIsInstance(cloud, cloud_config.CloudConfig) self.assertEqual(cloud.name, '') def test_get_one_cloud_default_cloud_from_file(self): single_conf = base._write_yaml({ 'clouds': { 'single': { 'auth': { 'auth_url': 'http://example.com/v2', 'username': 'testuser', 'password': 'testpass', 'project_name': 'testproject', }, 'region_name': 'test-region', } } }) c = config.OpenStackConfig(config_files=[single_conf], vendor_files=[self.vendor_yaml]) cc = c.get_one_cloud() self.assertEqual(cc.name, 'single') def test_get_one_cloud_auth_defaults(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml]) cc = c.get_one_cloud(cloud='_test-cloud_', auth={'username': 'user'}) self.assertEqual('user', cc.auth['username']) self.assertEqual( defaults._defaults['auth_type'], cc.auth_type, ) self.assertEqual( defaults._defaults['identity_api_version'], cc.identity_api_version, ) def test_get_one_cloud_auth_override_defaults(self): default_options = {'compute_api_version': '4'} c = config.OpenStackConfig(config_files=[self.cloud_yaml], override_defaults=default_options) cc = c.get_one_cloud(cloud='_test-cloud_', auth={'username': 'user'}) self.assertEqual('user', cc.auth['username']) self.assertEqual('4', cc.compute_api_version) self.assertEqual( defaults._defaults['identity_api_version'], cc.identity_api_version, ) def test_get_one_cloud_with_config_files(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml], secure_files=[self.secure_yaml]) self.assertIsInstance(c.cloud_config, dict) self.assertIn('cache', c.cloud_config) self.assertIsInstance(c.cloud_config['cache'], dict) self.assertIn('max_age', c.cloud_config['cache']) self.assertIn('path', c.cloud_config['cache']) cc = c.get_one_cloud('_test-cloud_') self._assert_cloud_details(cc) cc = c.get_one_cloud('_test_cloud_no_vendor') self._assert_cloud_details(cc) def test_get_one_cloud_with_int_project_id(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cc = c.get_one_cloud('_test-cloud-int-project_') self.assertEqual('12345', cc.auth['project_id']) def test_get_one_cloud_with_domain_id(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cc = c.get_one_cloud('_test-cloud-domain-id_') self.assertEqual('6789', cc.auth['user_domain_id']) self.assertEqual('123456789', cc.auth['project_domain_id']) self.assertNotIn('domain_id', cc.auth) self.assertNotIn('domain-id', cc.auth) self.assertNotIn('domain_id', cc) def test_get_one_cloud_domain_scoped(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cc = c.get_one_cloud('_test-cloud-domain-scoped_') self.assertEqual('12345', cc.auth['domain_id']) self.assertNotIn('user_domain_id', cc.auth) self.assertNotIn('project_domain_id', cc.auth) def test_get_one_cloud_infer_user_domain(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cc = c.get_one_cloud('_test-cloud-int-project_') self.assertEqual('awesome-domain', cc.auth['user_domain_id']) self.assertEqual('awesome-domain', cc.auth['project_domain_id']) self.assertNotIn('domain_id', cc.auth) self.assertNotIn('domain_id', cc) def test_get_one_cloud_with_hyphenated_project_id(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cc = c.get_one_cloud('_test_cloud_hyphenated') self.assertEqual('12345', cc.auth['project_id']) def test_get_one_cloud_with_hyphenated_kwargs(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) args = { 'auth': { 'username': 'testuser', 'password': 'testpass', 'project-id': '12345', 'auth-url': 'http://example.com/v2', }, 'region_name': 'test-region', } cc = c.get_one_cloud(**args) self.assertEqual('http://example.com/v2', cc.auth['auth_url']) def test_no_environ(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) self.assertRaises( exceptions.OpenStackConfigException, c.get_one_cloud, 'envvars') def test_fallthrough(self): c = config.OpenStackConfig(config_files=[self.no_yaml], vendor_files=[self.no_yaml], secure_files=[self.no_yaml]) for k in os.environ.keys(): if k.startswith('OS_'): self.useFixture(fixtures.EnvironmentVariable(k)) c.get_one_cloud(cloud='defaults', validate=False) def test_prefer_ipv6_true(self): c = config.OpenStackConfig(config_files=[self.no_yaml], vendor_files=[self.no_yaml], secure_files=[self.no_yaml]) cc = c.get_one_cloud(cloud='defaults', validate=False) self.assertTrue(cc.prefer_ipv6) def test_prefer_ipv6_false(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cc = c.get_one_cloud(cloud='_test-cloud_') self.assertFalse(cc.prefer_ipv6) def test_force_ipv4_true(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cc = c.get_one_cloud(cloud='_test-cloud_') self.assertTrue(cc.force_ipv4) def test_force_ipv4_false(self): c = config.OpenStackConfig(config_files=[self.no_yaml], vendor_files=[self.no_yaml], secure_files=[self.no_yaml]) cc = c.get_one_cloud(cloud='defaults', validate=False) self.assertFalse(cc.force_ipv4) def test_get_one_cloud_auth_merge(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml]) cc = c.get_one_cloud(cloud='_test-cloud_', auth={'username': 'user'}) self.assertEqual('user', cc.auth['username']) self.assertEqual('testpass', cc.auth['password']) def test_get_one_cloud_networks(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cc = c.get_one_cloud('_test-cloud-networks_') self.assertEqual( ['a-public', 'another-public', 'split-default'], cc.get_external_networks()) self.assertEqual( ['a-private', 'another-private', 'split-no-default'], cc.get_internal_networks()) self.assertEqual('a-public', cc.get_nat_source()) self.assertEqual('another-private', cc.get_nat_destination()) self.assertEqual('another-public', cc.get_default_network()) self.assertEqual( ['a-public', 'another-public', 'split-no-default'], cc.get_external_ipv4_networks()) self.assertEqual( ['a-public', 'another-public', 'split-default'], cc.get_external_ipv6_networks()) def test_get_one_cloud_no_networks(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cc = c.get_one_cloud('_test-cloud-domain-scoped_') self.assertEqual([], cc.get_external_networks()) self.assertEqual([], cc.get_internal_networks()) self.assertIsNone(cc.get_nat_source()) self.assertIsNone(cc.get_nat_destination()) self.assertIsNone(cc.get_default_network()) def test_only_secure_yaml(self): c = config.OpenStackConfig(config_files=['nonexistent'], vendor_files=['nonexistent'], secure_files=[self.secure_yaml]) cc = c.get_one_cloud(cloud='_test_cloud_no_vendor', validate=False) self.assertEqual('testpass', cc.auth['password']) def test_get_cloud_names(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], secure_files=[self.no_yaml]) self.assertEqual( ['_test-cloud-domain-id_', '_test-cloud-domain-scoped_', '_test-cloud-int-project_', '_test-cloud-networks_', '_test-cloud_', '_test-cloud_no_region', '_test_cloud_hyphenated', '_test_cloud_no_vendor', '_test_cloud_regions', ], sorted(c.get_cloud_names())) c = config.OpenStackConfig(config_files=[self.no_yaml], vendor_files=[self.no_yaml], secure_files=[self.no_yaml]) for k in os.environ.keys(): if k.startswith('OS_'): self.useFixture(fixtures.EnvironmentVariable(k)) c.get_one_cloud(cloud='defaults', validate=False) self.assertEqual(['defaults'], sorted(c.get_cloud_names())) def test_set_one_cloud_creates_file(self): config_dir = fixtures.TempDir() self.useFixture(config_dir) config_path = os.path.join(config_dir.path, 'clouds.yaml') config.OpenStackConfig.set_one_cloud(config_path, '_test_cloud_') self.assertTrue(os.path.isfile(config_path)) with open(config_path) as fh: self.assertEqual({'clouds': {'_test_cloud_': {}}}, yaml.safe_load(fh)) def test_set_one_cloud_updates_cloud(self): new_config = { 'cloud': 'new_cloud', 'auth': { 'password': 'newpass' } } resulting_cloud_config = { 'auth': { 'password': 'newpass', 'username': 'testuser', 'auth_url': 'http://example.com/v2', }, 'cloud': 'new_cloud', 'profile': '_test_cloud_in_our_cloud', 'region_name': 'test-region' } resulting_config = copy.deepcopy(base.USER_CONF) resulting_config['clouds']['_test-cloud_'] = resulting_cloud_config config.OpenStackConfig.set_one_cloud(self.cloud_yaml, '_test-cloud_', new_config) with open(self.cloud_yaml) as fh: written_config = yaml.safe_load(fh) # We write a cache config for testing written_config['cache'].pop('path', None) self.assertEqual(written_config, resulting_config) def test_get_region_no_region_default(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml], secure_files=[self.no_yaml]) region = c._get_region(cloud='_test-cloud_no_region') self.assertEqual(region, {'name': '', 'values': {}}) def test_get_region_no_region(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml], secure_files=[self.no_yaml]) region = c._get_region(cloud='_test-cloud_no_region', region_name='override-region') self.assertEqual(region, {'name': 'override-region', 'values': {}}) def test_get_region_region_is_none(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml], secure_files=[self.no_yaml]) region = c._get_region(cloud='_test-cloud_no_region', region_name=None) self.assertEqual(region, {'name': '', 'values': {}}) def test_get_region_region_set(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml], secure_files=[self.no_yaml]) region = c._get_region(cloud='_test-cloud_', region_name='test-region') self.assertEqual(region, {'name': 'test-region', 'values': {}}) def test_get_region_many_regions_default(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml], secure_files=[self.no_yaml]) region = c._get_region(cloud='_test_cloud_regions', region_name='') self.assertEqual(region, {'name': 'region1', 'values': {'external_network': 'region1-network'}}) def test_get_region_many_regions(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml], secure_files=[self.no_yaml]) region = c._get_region(cloud='_test_cloud_regions', region_name='region2') self.assertEqual(region, {'name': 'region2', 'values': {'external_network': 'my-network'}}) def test_get_region_invalid_region(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml], secure_files=[self.no_yaml]) self.assertRaises( exceptions.OpenStackConfigException, c._get_region, cloud='_test_cloud_regions', region_name='invalid-region') def test_get_region_no_cloud(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml], secure_files=[self.no_yaml]) region = c._get_region(region_name='no-cloud-region') self.assertEqual(region, {'name': 'no-cloud-region', 'values': {}}) class TestExcludedFormattedConfigValue(base.TestCase): # verify LaunchPad bug #1635696 # # get_one_cloud() and get_one_cloud_osc() iterate over config # values and try to expand any variables in those values by # calling value.format(), however some config values # (e.g. password) should never have format() applied to them, not # only might that change the password but it will also cause the # format() function to raise an exception if it can not parse the # format string. Examples would be single brace (e.g. 'foo{') # which raises an ValueError because it's looking for a matching # end brace or a brace pair with a key value that cannot be found # (e.g. 'foo{bar}') which raises a KeyError. def setUp(self): super(TestExcludedFormattedConfigValue, self).setUp() self.args = dict( auth_url='http://example.com/v2', username='user', project_name='project', region_name='region2', snack_type='cookie', os_auth_token='no-good-things', ) self.options = argparse.Namespace(**self.args) def test_get_one_cloud_password_brace(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) password = 'foo{' # Would raise ValueError, single brace self.options.password = password cc = c.get_one_cloud( cloud='_test_cloud_regions', argparse=self.options, validate=False) self.assertEqual(cc.password, password) password = 'foo{bar}' # Would raise KeyError, 'bar' not found self.options.password = password cc = c.get_one_cloud( cloud='_test_cloud_regions', argparse=self.options, validate=False) self.assertEqual(cc.password, password) def test_get_one_cloud_osc_password_brace(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) password = 'foo{' # Would raise ValueError, single brace self.options.password = password cc = c.get_one_cloud_osc( cloud='_test_cloud_regions', argparse=self.options, validate=False) self.assertEqual(cc.password, password) password = 'foo{bar}' # Would raise KeyError, 'bar' not found self.options.password = password cc = c.get_one_cloud_osc( cloud='_test_cloud_regions', argparse=self.options, validate=False) self.assertEqual(cc.password, password) class TestConfigArgparse(base.TestCase): def setUp(self): super(TestConfigArgparse, self).setUp() self.args = dict( auth_url='http://example.com/v2', username='user', password='password', project_name='project', region_name='region2', snack_type='cookie', os_auth_token='no-good-things', ) self.options = argparse.Namespace(**self.args) def test_get_one_cloud_bad_region_argparse(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) self.assertRaises( exceptions.OpenStackConfigException, c.get_one_cloud, cloud='_test-cloud_', argparse=self.options) def test_get_one_cloud_argparse(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cc = c.get_one_cloud( cloud='_test_cloud_regions', argparse=self.options, validate=False) self.assertEqual(cc.region_name, 'region2') self.assertEqual(cc.snack_type, 'cookie') def test_get_one_cloud_precedence(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) kwargs = { 'auth': { 'username': 'testuser', 'password': 'authpass', 'project-id': 'testproject', 'auth_url': 'http://example.com/v2', }, 'region_name': 'kwarg_region', 'password': 'ansible_password', 'arbitrary': 'value', } args = dict( auth_url='http://example.com/v2', username='user', password='argpass', project_name='project', region_name='region2', snack_type='cookie', ) options = argparse.Namespace(**args) cc = c.get_one_cloud( argparse=options, **kwargs) self.assertEqual(cc.region_name, 'region2') self.assertEqual(cc.auth['password'], 'authpass') self.assertEqual(cc.snack_type, 'cookie') def test_get_one_cloud_precedence_osc(self): c = config.OpenStackConfig( config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml], ) kwargs = { 'auth': { 'username': 'testuser', 'password': 'authpass', 'project-id': 'testproject', 'auth_url': 'http://example.com/v2', }, 'region_name': 'kwarg_region', 'password': 'ansible_password', 'arbitrary': 'value', } args = dict( auth_url='http://example.com/v2', username='user', password='argpass', project_name='project', region_name='region2', snack_type='cookie', ) options = argparse.Namespace(**args) cc = c.get_one_cloud_osc( argparse=options, **kwargs ) self.assertEqual(cc.region_name, 'region2') self.assertEqual(cc.auth['password'], 'argpass') self.assertEqual(cc.snack_type, 'cookie') def test_get_one_cloud_precedence_no_argparse(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) kwargs = { 'auth': { 'username': 'testuser', 'password': 'authpass', 'project-id': 'testproject', 'auth_url': 'http://example.com/v2', }, 'region_name': 'kwarg_region', 'password': 'ansible_password', 'arbitrary': 'value', } cc = c.get_one_cloud(**kwargs) self.assertEqual(cc.region_name, 'kwarg_region') self.assertEqual(cc.auth['password'], 'authpass') self.assertIsNone(cc.password) def test_get_one_cloud_just_argparse(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cc = c.get_one_cloud(argparse=self.options, validate=False) self.assertIsNone(cc.cloud) self.assertEqual(cc.region_name, 'region2') self.assertEqual(cc.snack_type, 'cookie') def test_get_one_cloud_just_kwargs(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cc = c.get_one_cloud(validate=False, **self.args) self.assertIsNone(cc.cloud) self.assertEqual(cc.region_name, 'region2') self.assertEqual(cc.snack_type, 'cookie') def test_get_one_cloud_dash_kwargs(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) args = { 'auth-url': 'http://example.com/v2', 'username': 'user', 'password': 'password', 'project_name': 'project', 'region_name': 'other-test-region', 'snack_type': 'cookie', } cc = c.get_one_cloud(**args) self.assertIsNone(cc.cloud) self.assertEqual(cc.region_name, 'other-test-region') self.assertEqual(cc.snack_type, 'cookie') def test_get_one_cloud_no_argparse(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cc = c.get_one_cloud(cloud='_test-cloud_', argparse=None) self._assert_cloud_details(cc) self.assertEqual(cc.region_name, 'test-region') self.assertIsNone(cc.snack_type) def test_get_one_cloud_no_argparse_regions(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cc = c.get_one_cloud(cloud='_test_cloud_regions', argparse=None) self._assert_cloud_details(cc) self.assertEqual(cc.region_name, 'region1') self.assertIsNone(cc.snack_type) def test_get_one_cloud_bad_region(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) self.assertRaises( exceptions.OpenStackConfigException, c.get_one_cloud, cloud='_test_cloud_regions', region_name='bad') def test_get_one_cloud_bad_region_no_regions(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) self.assertRaises( exceptions.OpenStackConfigException, c.get_one_cloud, cloud='_test-cloud_', region_name='bad_region') def test_get_one_cloud_no_argparse_region2(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cc = c.get_one_cloud( cloud='_test_cloud_regions', region_name='region2', argparse=None) self._assert_cloud_details(cc) self.assertEqual(cc.region_name, 'region2') self.assertIsNone(cc.snack_type) def test_get_one_cloud_network(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cc = c.get_one_cloud( cloud='_test_cloud_regions', region_name='region1', argparse=None) self._assert_cloud_details(cc) self.assertEqual(cc.region_name, 'region1') self.assertEqual('region1-network', cc.config['external_network']) def test_get_one_cloud_per_region_network(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cc = c.get_one_cloud( cloud='_test_cloud_regions', region_name='region2', argparse=None) self._assert_cloud_details(cc) self.assertEqual(cc.region_name, 'region2') self.assertEqual('my-network', cc.config['external_network']) def test_get_one_cloud_no_yaml_no_cloud(self): c = config.OpenStackConfig(load_yaml_config=False) self.assertRaises( exceptions.OpenStackConfigException, c.get_one_cloud, cloud='_test_cloud_regions', region_name='region2', argparse=None) def test_get_one_cloud_no_yaml(self): c = config.OpenStackConfig(load_yaml_config=False) cc = c.get_one_cloud( region_name='region2', argparse=None, **base.USER_CONF['clouds']['_test_cloud_regions']) # Not using assert_cloud_details because of cache settings which # are not present without the file self.assertIsInstance(cc, cloud_config.CloudConfig) self.assertTrue(extras.safe_hasattr(cc, 'auth')) self.assertIsInstance(cc.auth, dict) self.assertIsNone(cc.cloud) self.assertIn('username', cc.auth) self.assertEqual('testuser', cc.auth['username']) self.assertEqual('testpass', cc.auth['password']) self.assertFalse(cc.config['image_api_use_tasks']) self.assertTrue('project_name' in cc.auth or 'project_id' in cc.auth) if 'project_name' in cc.auth: self.assertEqual('testproject', cc.auth['project_name']) elif 'project_id' in cc.auth: self.assertEqual('testproject', cc.auth['project_id']) self.assertEqual(cc.region_name, 'region2') def test_fix_env_args(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) env_args = {'os-compute-api-version': 1} fixed_args = c._fix_args(env_args) self.assertDictEqual({'compute_api_version': 1}, fixed_args) def test_extra_config(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) defaults = {'use_hostnames': False, 'other-value': 'something'} ansible_options = c.get_extra_config('ansible', defaults) # This should show that the default for use_hostnames above is # overridden by the value in the config file defined in base.py # It should also show that other-value key is normalized and passed # through even though there is no corresponding value in the config # file, and that expand-hostvars key is normalized and the value # from the config comes through even though there is no default. self.assertDictEqual( { 'expand_hostvars': False, 'use_hostnames': True, 'other_value': 'something', }, ansible_options) def test_register_argparse_cloud(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) parser = argparse.ArgumentParser() c.register_argparse_arguments(parser, []) opts, _remain = parser.parse_known_args(['--os-cloud', 'foo']) self.assertEqual(opts.os_cloud, 'foo') def test_env_argparse_precedence(self): self.useFixture(fixtures.EnvironmentVariable( 'OS_TENANT_NAME', 'tenants-are-bad')) c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cc = c.get_one_cloud( cloud='envvars', argparse=self.options, validate=False) self.assertEqual(cc.auth['project_name'], 'project') def test_argparse_default_no_token(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) parser = argparse.ArgumentParser() c.register_argparse_arguments(parser, []) # novaclient will add this parser.add_argument('--os-auth-token') opts, _remain = parser.parse_known_args() cc = c.get_one_cloud( cloud='_test_cloud_regions', argparse=opts) self.assertEqual(cc.config['auth_type'], 'password') self.assertNotIn('token', cc.config['auth']) def test_argparse_token(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) parser = argparse.ArgumentParser() c.register_argparse_arguments(parser, []) # novaclient will add this parser.add_argument('--os-auth-token') opts, _remain = parser.parse_known_args( ['--os-auth-token', 'very-bad-things', '--os-auth-type', 'token']) cc = c.get_one_cloud(argparse=opts, validate=False) self.assertEqual(cc.config['auth_type'], 'token') self.assertEqual(cc.config['auth']['token'], 'very-bad-things') def test_argparse_underscores(self): c = config.OpenStackConfig(config_files=[self.no_yaml], vendor_files=[self.no_yaml], secure_files=[self.no_yaml]) parser = argparse.ArgumentParser() parser.add_argument('--os_username') argv = [ '--os_username', 'user', '--os_password', 'pass', '--os-auth-url', 'auth-url', '--os-project-name', 'project'] c.register_argparse_arguments(parser, argv=argv) opts, _remain = parser.parse_known_args(argv) cc = c.get_one_cloud(argparse=opts) self.assertEqual(cc.config['auth']['username'], 'user') self.assertEqual(cc.config['auth']['password'], 'pass') self.assertEqual(cc.config['auth']['auth_url'], 'auth-url') def test_argparse_action_append_no_underscore(self): c = config.OpenStackConfig(config_files=[self.no_yaml], vendor_files=[self.no_yaml], secure_files=[self.no_yaml]) parser = argparse.ArgumentParser() parser.add_argument('--foo', action='append') argv = ['--foo', '1', '--foo', '2'] c.register_argparse_arguments(parser, argv=argv) opts, _remain = parser.parse_known_args(argv) self.assertEqual(opts.foo, ['1', '2']) def test_argparse_underscores_duplicate(self): c = config.OpenStackConfig(config_files=[self.no_yaml], vendor_files=[self.no_yaml], secure_files=[self.no_yaml]) parser = argparse.ArgumentParser() parser.add_argument('--os_username') argv = [ '--os_username', 'user', '--os_password', 'pass', '--os-username', 'user1', '--os-password', 'pass1', '--os-auth-url', 'auth-url', '--os-project-name', 'project'] self.assertRaises( exceptions.OpenStackConfigException, c.register_argparse_arguments, parser=parser, argv=argv) def test_register_argparse_bad_plugin(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) parser = argparse.ArgumentParser() self.assertRaises( exceptions.OpenStackConfigException, c.register_argparse_arguments, parser, ['--os-auth-type', 'foo']) def test_register_argparse_not_password(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) parser = argparse.ArgumentParser() args = [ '--os-auth-type', 'v3token', '--os-token', 'some-secret', ] c.register_argparse_arguments(parser, args) opts, _remain = parser.parse_known_args(args) self.assertEqual(opts.os_token, 'some-secret') def test_register_argparse_password(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) parser = argparse.ArgumentParser() args = [ '--os-password', 'some-secret', ] c.register_argparse_arguments(parser, args) opts, _remain = parser.parse_known_args(args) self.assertEqual(opts.os_password, 'some-secret') with testtools.ExpectedException(AttributeError): opts.os_token def test_register_argparse_service_type(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) parser = argparse.ArgumentParser() args = [ '--os-service-type', 'network', '--os-endpoint-type', 'admin', '--http-timeout', '20', ] c.register_argparse_arguments(parser, args) opts, _remain = parser.parse_known_args(args) self.assertEqual(opts.os_service_type, 'network') self.assertEqual(opts.os_endpoint_type, 'admin') self.assertEqual(opts.http_timeout, '20') with testtools.ExpectedException(AttributeError): opts.os_network_service_type cloud = c.get_one_cloud(argparse=opts, validate=False) self.assertEqual(cloud.config['service_type'], 'network') self.assertEqual(cloud.config['interface'], 'admin') self.assertEqual(cloud.config['api_timeout'], '20') self.assertNotIn('http_timeout', cloud.config) def test_register_argparse_network_service_type(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) parser = argparse.ArgumentParser() args = [ '--os-endpoint-type', 'admin', '--network-api-version', '4', ] c.register_argparse_arguments(parser, args, ['network']) opts, _remain = parser.parse_known_args(args) self.assertEqual(opts.os_service_type, 'network') self.assertEqual(opts.os_endpoint_type, 'admin') self.assertIsNone(opts.os_network_service_type) self.assertIsNone(opts.os_network_api_version) self.assertEqual(opts.network_api_version, '4') cloud = c.get_one_cloud(argparse=opts, validate=False) self.assertEqual(cloud.config['service_type'], 'network') self.assertEqual(cloud.config['interface'], 'admin') self.assertEqual(cloud.config['network_api_version'], '4') self.assertNotIn('http_timeout', cloud.config) def test_register_argparse_network_service_types(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) parser = argparse.ArgumentParser() args = [ '--os-compute-service-name', 'cloudServers', '--os-network-service-type', 'badtype', '--os-endpoint-type', 'admin', '--network-api-version', '4', ] c.register_argparse_arguments( parser, args, ['compute', 'network', 'volume']) opts, _remain = parser.parse_known_args(args) self.assertEqual(opts.os_network_service_type, 'badtype') self.assertIsNone(opts.os_compute_service_type) self.assertIsNone(opts.os_volume_service_type) self.assertEqual(opts.os_service_type, 'compute') self.assertEqual(opts.os_compute_service_name, 'cloudServers') self.assertEqual(opts.os_endpoint_type, 'admin') self.assertIsNone(opts.os_network_api_version) self.assertEqual(opts.network_api_version, '4') cloud = c.get_one_cloud(argparse=opts, validate=False) self.assertEqual(cloud.config['service_type'], 'compute') self.assertEqual(cloud.config['network_service_type'], 'badtype') self.assertEqual(cloud.config['interface'], 'admin') self.assertEqual(cloud.config['network_api_version'], '4') self.assertNotIn('volume_service_type', cloud.config) self.assertNotIn('http_timeout', cloud.config) class TestConfigPrompt(base.TestCase): def setUp(self): super(TestConfigPrompt, self).setUp() self.args = dict( auth_url='http://example.com/v2', username='user', project_name='project', # region_name='region2', auth_type='password', ) self.options = argparse.Namespace(**self.args) def test_get_one_cloud_prompt(self): c = config.OpenStackConfig( config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml], pw_func=prompt_for_password, ) # This needs a cloud definition without a password. # If this starts failing unexpectedly check that the cloud_yaml # and/or vendor_yaml do not have a password in the selected cloud. cc = c.get_one_cloud( cloud='_test_cloud_no_vendor', argparse=self.options, ) self.assertEqual('promptpass', cc.auth['password']) class TestConfigDefault(base.TestCase): def setUp(self): super(TestConfigDefault, self).setUp() # Reset defaults after each test so that other tests are # not affected by any changes. self.addCleanup(self._reset_defaults) def _reset_defaults(self): defaults._defaults = None def test_set_no_default(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cc = c.get_one_cloud(cloud='_test-cloud_', argparse=None) self._assert_cloud_details(cc) self.assertEqual('password', cc.auth_type) class TestBackwardsCompatibility(base.TestCase): def test_set_no_default(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cloud = { 'identity_endpoint_type': 'admin', 'compute_endpoint_type': 'private', 'endpoint_type': 'public', 'auth_type': 'v3password', } result = c._fix_backwards_interface(cloud) expected = { 'identity_interface': 'admin', 'compute_interface': 'private', 'interface': 'public', 'auth_type': 'v3password', } self.assertDictEqual(expected, result) def test_project_v2password(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cloud = { 'auth_type': 'v2password', 'auth': { 'project-name': 'my_project_name', 'project-id': 'my_project_id' } } result = c._fix_backwards_project(cloud) expected = { 'auth_type': 'v2password', 'auth': { 'tenant_name': 'my_project_name', 'tenant_id': 'my_project_id' } } self.assertEqual(expected, result) def test_project_password(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cloud = { 'auth_type': 'password', 'auth': { 'project-name': 'my_project_name', 'project-id': 'my_project_id' } } result = c._fix_backwards_project(cloud) expected = { 'auth_type': 'password', 'auth': { 'project_name': 'my_project_name', 'project_id': 'my_project_id' } } self.assertEqual(expected, result) def test_backwards_network_fail(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cloud = { 'external_network': 'public', 'networks': [ {'name': 'private', 'routes_externally': False}, ] } self.assertRaises( exceptions.OpenStackConfigException, c._fix_backwards_networks, cloud) def test_backwards_network(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cloud = { 'external_network': 'public', 'internal_network': 'private', } result = c._fix_backwards_networks(cloud) expected = { 'external_network': 'public', 'internal_network': 'private', 'networks': [ {'name': 'public', 'routes_externally': True, 'nat_destination': False, 'default_interface': True}, {'name': 'private', 'routes_externally': False, 'nat_destination': True, 'default_interface': False}, ] } self.assertEqual(expected, result) def test_normalize_network(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cloud = { 'networks': [ {'name': 'private'} ] } result = c._fix_backwards_networks(cloud) expected = { 'networks': [ {'name': 'private', 'routes_externally': False, 'nat_destination': False, 'default_interface': False, 'nat_source': False, 'routes_ipv4_externally': False, 'routes_ipv6_externally': False}, ] } self.assertEqual(expected, result) def test_single_default_interface(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cloud = { 'networks': [ {'name': 'blue', 'default_interface': True}, {'name': 'purple', 'default_interface': True}, ] } self.assertRaises( exceptions.OpenStackConfigException, c._fix_backwards_networks, cloud) os-client-config-1.31.2/os_client_config/tests/test_environ.py0000666000175000017500000002003413311600770024516 0ustar zuulzuul00000000000000# Copyright (c) 2014 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. from os_client_config import cloud_config from os_client_config import config from os_client_config import exceptions from os_client_config.tests import base import fixtures class TestEnviron(base.TestCase): def setUp(self): super(TestEnviron, self).setUp() self.useFixture( fixtures.EnvironmentVariable('OS_AUTH_URL', 'https://example.com')) self.useFixture( fixtures.EnvironmentVariable('OS_USERNAME', 'testuser')) self.useFixture( fixtures.EnvironmentVariable('OS_PASSWORD', 'testpass')) self.useFixture( fixtures.EnvironmentVariable('OS_PROJECT_NAME', 'testproject')) self.useFixture( fixtures.EnvironmentVariable('NOVA_PROJECT_ID', 'testnova')) def test_get_one_cloud(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) self.assertIsInstance(c.get_one_cloud(), cloud_config.CloudConfig) def test_no_fallthrough(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) self.assertRaises( exceptions.OpenStackConfigException, c.get_one_cloud, 'openstack') def test_envvar_name_override(self): self.useFixture( fixtures.EnvironmentVariable('OS_CLOUD_NAME', 'override')) c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cc = c.get_one_cloud('override') self._assert_cloud_details(cc) def test_envvar_prefer_ipv6_override(self): self.useFixture( fixtures.EnvironmentVariable('OS_PREFER_IPV6', 'false')) c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml], secure_files=[self.secure_yaml]) cc = c.get_one_cloud('_test-cloud_') self.assertFalse(cc.prefer_ipv6) def test_environ_exists(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml], secure_files=[self.secure_yaml]) cc = c.get_one_cloud('envvars') self._assert_cloud_details(cc) self.assertNotIn('auth_url', cc.config) self.assertIn('auth_url', cc.config['auth']) self.assertNotIn('project_id', cc.config['auth']) self.assertNotIn('auth_url', cc.config) cc = c.get_one_cloud('_test-cloud_') self._assert_cloud_details(cc) cc = c.get_one_cloud('_test_cloud_no_vendor') self._assert_cloud_details(cc) def test_environ_prefix(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml], envvar_prefix='NOVA_', secure_files=[self.secure_yaml]) cc = c.get_one_cloud('envvars') self._assert_cloud_details(cc) self.assertNotIn('auth_url', cc.config) self.assertIn('auth_url', cc.config['auth']) self.assertIn('project_id', cc.config['auth']) self.assertNotIn('auth_url', cc.config) cc = c.get_one_cloud('_test-cloud_') self._assert_cloud_details(cc) cc = c.get_one_cloud('_test_cloud_no_vendor') self._assert_cloud_details(cc) def test_get_one_cloud_with_config_files(self): c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml], secure_files=[self.secure_yaml]) self.assertIsInstance(c.cloud_config, dict) self.assertIn('cache', c.cloud_config) self.assertIsInstance(c.cloud_config['cache'], dict) self.assertIn('max_age', c.cloud_config['cache']) self.assertIn('path', c.cloud_config['cache']) cc = c.get_one_cloud('_test-cloud_') self._assert_cloud_details(cc) cc = c.get_one_cloud('_test_cloud_no_vendor') self._assert_cloud_details(cc) def test_config_file_override(self): self.useFixture( fixtures.EnvironmentVariable( 'OS_CLIENT_CONFIG_FILE', self.cloud_yaml)) c = config.OpenStackConfig(config_files=[], vendor_files=[self.vendor_yaml]) cc = c.get_one_cloud('_test-cloud_') self._assert_cloud_details(cc) class TestEnvvars(base.TestCase): def test_no_envvars(self): self.useFixture( fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova')) c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) self.assertRaises( exceptions.OpenStackConfigException, c.get_one_cloud, 'envvars') def test_test_envvars(self): self.useFixture( fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova')) self.useFixture( fixtures.EnvironmentVariable('OS_STDERR_CAPTURE', 'True')) c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) self.assertRaises( exceptions.OpenStackConfigException, c.get_one_cloud, 'envvars') def test_incomplete_envvars(self): self.useFixture( fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova')) self.useFixture( fixtures.EnvironmentVariable('OS_USERNAME', 'user')) config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) # This is broken due to an issue that's fixed in a subsequent patch # commenting it out in this patch to keep the patch size reasonable # self.assertRaises( # keystoneauth1.exceptions.auth_plugins.MissingRequiredOptions, # c.get_one_cloud, 'envvars') def test_have_envvars(self): self.useFixture( fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova')) self.useFixture( fixtures.EnvironmentVariable('OS_AUTH_URL', 'http://example.com')) self.useFixture( fixtures.EnvironmentVariable('OS_USERNAME', 'user')) self.useFixture( fixtures.EnvironmentVariable('OS_PASSWORD', 'password')) self.useFixture( fixtures.EnvironmentVariable('OS_PROJECT_NAME', 'project')) c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]) cc = c.get_one_cloud('envvars') self.assertEqual(cc.config['auth']['username'], 'user') def test_old_envvars(self): self.useFixture( fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova')) self.useFixture( fixtures.EnvironmentVariable( 'NOVA_AUTH_URL', 'http://example.com')) self.useFixture( fixtures.EnvironmentVariable('NOVA_PASSWORD', 'password')) self.useFixture( fixtures.EnvironmentVariable('NOVA_PROJECT_NAME', 'project')) c = config.OpenStackConfig(config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml], envvar_prefix='NOVA_') cc = c.get_one_cloud('envvars') self.assertEqual(cc.config['auth']['username'], 'nova') os-client-config-1.31.2/os_client_config/tests/__init__.py0000666000175000017500000000000013311600770023525 0ustar zuulzuul00000000000000os-client-config-1.31.2/os_client_config/tests/test_import_vendors.py0000666000175000017500000000150113311600770026106 0ustar zuulzuul00000000000000# Copyright (c) 2014 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. from os_client_config.tests import base class TestImportVendors(base.TestCase): def test_get_profile(self): import os_client_config # noqa os_client_config.vendors.get_profile(profile_name="dummy") os-client-config-1.31.2/os_client_config/tests/test_cloud_config.py0000666000175000017500000005177013311600770025504 0ustar zuulzuul00000000000000# 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 keystoneauth1 import exceptions as ksa_exceptions from keystoneauth1 import session as ksa_session import mock from openstack.config import cloud_region from os_client_config import cloud_config from os_client_config import defaults from os_client_config import exceptions from os_client_config.tests import base fake_config_dict = {'a': 1, 'os_b': 2, 'c': 3, 'os_c': 4} fake_services_dict = { 'compute_api_version': '2', 'compute_endpoint_override': 'http://compute.example.com', 'telemetry_endpoint': 'http://telemetry.example.com', 'interface': 'public', 'image_service_type': 'mage', 'identity_interface': 'admin', 'identity_service_name': 'locks', 'volume_api_version': '1', 'auth': {'password': 'hunter2', 'username': 'AzureDiamond'}, } class TestCloudConfig(base.TestCase): def test_arbitrary_attributes(self): cc = cloud_config.CloudConfig("test1", "region-al", fake_config_dict) self.assertEqual("test1", cc.name) self.assertEqual("region-al", cc.region) # Look up straight value self.assertEqual('1', cc.a) # Look up prefixed attribute, fail - returns None self.assertIsNone(cc.os_b) # Look up straight value, then prefixed value self.assertEqual('3', cc.c) self.assertEqual('3', cc.os_c) # Lookup mystery attribute self.assertIsNone(cc.x) # Test default ipv6 self.assertFalse(cc.force_ipv4) def test_iteration(self): cc = cloud_config.CloudConfig("test1", "region-al", fake_config_dict) self.assertTrue('a' in cc) self.assertFalse('x' in cc) def test_equality(self): cc1 = cloud_config.CloudConfig("test1", "region-al", fake_config_dict) cc2 = cloud_config.CloudConfig("test1", "region-al", fake_config_dict) self.assertEqual(cc1, cc2) def test_inequality(self): cc1 = cloud_config.CloudConfig("test1", "region-al", fake_config_dict) cc2 = cloud_config.CloudConfig("test2", "region-al", fake_config_dict) self.assertNotEqual(cc1, cc2) cc2 = cloud_config.CloudConfig("test1", "region-xx", fake_config_dict) self.assertNotEqual(cc1, cc2) cc2 = cloud_config.CloudConfig("test1", "region-al", {}) self.assertNotEqual(cc1, cc2) def test_verify(self): config_dict = copy.deepcopy(fake_config_dict) config_dict['cacert'] = None config_dict['verify'] = False cc = cloud_config.CloudConfig("test1", "region-xx", config_dict) (verify, cert) = cc.get_requests_verify_args() self.assertFalse(verify) config_dict['verify'] = True cc = cloud_config.CloudConfig("test1", "region-xx", config_dict) (verify, cert) = cc.get_requests_verify_args() self.assertTrue(verify) def test_verify_cacert(self): config_dict = copy.deepcopy(fake_config_dict) config_dict['cacert'] = "certfile" config_dict['verify'] = False cc = cloud_config.CloudConfig("test1", "region-xx", config_dict) (verify, cert) = cc.get_requests_verify_args() self.assertFalse(verify) config_dict['verify'] = True cc = cloud_config.CloudConfig("test1", "region-xx", config_dict) (verify, cert) = cc.get_requests_verify_args() self.assertEqual("certfile", verify) def test_cert_with_key(self): config_dict = copy.deepcopy(fake_config_dict) config_dict['cacert'] = None config_dict['verify'] = False config_dict['cert'] = 'cert' config_dict['key'] = 'key' cc = cloud_config.CloudConfig("test1", "region-xx", config_dict) (verify, cert) = cc.get_requests_verify_args() self.assertEqual(("cert", "key"), cert) def test_ipv6(self): cc = cloud_config.CloudConfig( "test1", "region-al", fake_config_dict, force_ipv4=True) self.assertTrue(cc.force_ipv4) def test_getters(self): cc = cloud_config.CloudConfig("test1", "region-al", fake_services_dict) self.assertEqual(['compute', 'identity', 'image', 'volume'], sorted(cc.get_services())) self.assertEqual({'password': 'hunter2', 'username': 'AzureDiamond'}, cc.get_auth_args()) self.assertEqual('public', cc.get_interface()) self.assertEqual('public', cc.get_interface('compute')) self.assertEqual('admin', cc.get_interface('identity')) self.assertEqual('region-al', cc.get_region_name()) self.assertEqual('region-al', cc.get_region_name('image')) self.assertIsNone(cc.get_api_version('image')) self.assertEqual('2', cc.get_api_version('compute')) self.assertEqual('mage', cc.get_service_type('image')) self.assertEqual('compute', cc.get_service_type('compute')) self.assertEqual('1', cc.get_api_version('volume')) self.assertIn( cc.get_service_type('volume'), ['block-storage', 'volume']) self.assertEqual('http://compute.example.com', cc.get_endpoint('compute')) self.assertIsNone(cc.get_endpoint('image')) self.assertIsNone(cc.get_service_name('compute')) self.assertEqual('locks', cc.get_service_name('identity')) def test_get_session_no_auth(self): config_dict = defaults.get_defaults() config_dict.update(fake_services_dict) cc = cloud_config.CloudConfig("test1", "region-al", config_dict) self.assertRaises( exceptions.OpenStackConfigException, cc.get_session) @mock.patch.object(ksa_session, 'Session') def test_override_session_endpoint_override(self, mock_session): config_dict = defaults.get_defaults() config_dict.update(fake_services_dict) cc = cloud_config.CloudConfig( "test1", "region-al", config_dict, auth_plugin=mock.Mock()) self.assertEqual( cc.get_session_endpoint('compute'), fake_services_dict['compute_endpoint_override']) @mock.patch.object(ksa_session, 'Session') def test_override_session_endpoint(self, mock_session): config_dict = defaults.get_defaults() config_dict.update(fake_services_dict) cc = cloud_config.CloudConfig( "test1", "region-al", config_dict, auth_plugin=mock.Mock()) self.assertEqual( cc.get_session_endpoint('telemetry'), fake_services_dict['telemetry_endpoint']) @mock.patch.object(cloud_region.CloudRegion, 'get_session') def test_session_endpoint(self, mock_get_session): mock_session = mock.Mock() mock_get_session.return_value = mock_session config_dict = defaults.get_defaults() config_dict.update(fake_services_dict) cc = cloud_config.CloudConfig( "test1", "region-al", config_dict, auth_plugin=mock.Mock()) cc.get_session_endpoint('orchestration') mock_session.get_endpoint.assert_called_with( interface='public', service_name=None, region_name='region-al', service_type='orchestration') @mock.patch.object(cloud_region.CloudRegion, 'get_session') def test_session_endpoint_not_found(self, mock_get_session): exc_to_raise = ksa_exceptions.catalog.EndpointNotFound mock_get_session.return_value.get_endpoint.side_effect = exc_to_raise cc = cloud_config.CloudConfig( "test1", "region-al", {}, auth_plugin=mock.Mock()) self.assertIsNone(cc.get_session_endpoint('notfound')) @mock.patch.object(cloud_region.CloudRegion, 'get_api_version') @mock.patch.object(cloud_region.CloudRegion, 'get_auth_args') @mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint') def test_legacy_client_object_store_password( self, mock_get_session_endpoint, mock_get_auth_args, mock_get_api_version): mock_client = mock.Mock() mock_get_session_endpoint.return_value = 'http://swift.example.com' mock_get_api_version.return_value = '3' mock_get_auth_args.return_value = dict( username='testuser', password='testpassword', project_name='testproject', auth_url='http://example.com', ) config_dict = defaults.get_defaults() config_dict.update(fake_services_dict) cc = cloud_config.CloudConfig( "test1", "region-al", config_dict, auth_plugin=mock.Mock()) cc.get_legacy_client('object-store', mock_client) mock_client.assert_called_with( session=mock.ANY, os_options={ 'region_name': 'region-al', 'service_type': 'object-store', 'object_storage_url': None, 'endpoint_type': 'public', }) @mock.patch.object(cloud_region.CloudRegion, 'get_auth_args') @mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint') def test_legacy_client_object_store_password_v2( self, mock_get_session_endpoint, mock_get_auth_args): mock_client = mock.Mock() mock_get_session_endpoint.return_value = 'http://swift.example.com' mock_get_auth_args.return_value = dict( username='testuser', password='testpassword', project_name='testproject', auth_url='http://example.com', ) config_dict = defaults.get_defaults() config_dict.update(fake_services_dict) cc = cloud_config.CloudConfig( "test1", "region-al", config_dict, auth_plugin=mock.Mock()) cc.get_legacy_client('object-store', mock_client) mock_client.assert_called_with( session=mock.ANY, os_options={ 'region_name': 'region-al', 'service_type': 'object-store', 'object_storage_url': None, 'endpoint_type': 'public', }) @mock.patch.object(cloud_region.CloudRegion, 'get_auth_args') @mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint') def test_legacy_client_object_store( self, mock_get_session_endpoint, mock_get_auth_args): mock_client = mock.Mock() mock_get_session_endpoint.return_value = 'http://example.com/v2' mock_get_auth_args.return_value = {} config_dict = defaults.get_defaults() config_dict.update(fake_services_dict) cc = cloud_config.CloudConfig( "test1", "region-al", config_dict, auth_plugin=mock.Mock()) cc.get_legacy_client('object-store', mock_client) mock_client.assert_called_with( session=mock.ANY, os_options={ 'region_name': 'region-al', 'service_type': 'object-store', 'object_storage_url': None, 'endpoint_type': 'public', }) @mock.patch.object(cloud_region.CloudRegion, 'get_auth_args') @mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint') def test_legacy_client_object_store_timeout( self, mock_get_session_endpoint, mock_get_auth_args): mock_client = mock.Mock() mock_get_session_endpoint.return_value = 'http://example.com/v2' mock_get_auth_args.return_value = {} config_dict = defaults.get_defaults() config_dict.update(fake_services_dict) config_dict['api_timeout'] = 9 cc = cloud_config.CloudConfig( name="test1", region_name="region-al", config=config_dict, auth_plugin=mock.Mock()) cc.get_legacy_client('object-store', mock_client) mock_client.assert_called_with( session=mock.ANY, os_options={ 'region_name': 'region-al', 'service_type': 'object-store', 'object_storage_url': None, 'endpoint_type': 'public', }) @mock.patch.object(cloud_region.CloudRegion, 'get_auth_args') def test_legacy_client_object_store_endpoint( self, mock_get_auth_args): mock_client = mock.Mock() mock_get_auth_args.return_value = {} config_dict = defaults.get_defaults() config_dict.update(fake_services_dict) config_dict['object_store_endpoint'] = 'http://example.com/swift' cc = cloud_config.CloudConfig( "test1", "region-al", config_dict, auth_plugin=mock.Mock()) cc.get_legacy_client('object-store', mock_client) mock_client.assert_called_with( session=mock.ANY, os_options={ 'region_name': 'region-al', 'service_type': 'object-store', 'object_storage_url': 'http://example.com/swift', 'endpoint_type': 'public', }) @mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint') def test_legacy_client_image(self, mock_get_session_endpoint): mock_client = mock.Mock() mock_get_session_endpoint.return_value = 'http://example.com/v2' config_dict = defaults.get_defaults() config_dict.update(fake_services_dict) cc = cloud_config.CloudConfig( "test1", "region-al", config_dict, auth_plugin=mock.Mock()) cc.get_legacy_client('image', mock_client) mock_client.assert_called_with( version=2.0, service_name=None, endpoint_override='http://example.com', region_name='region-al', interface='public', session=mock.ANY, # Not a typo - the config dict above overrides this service_type='mage' ) @mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint') def test_legacy_client_image_override(self, mock_get_session_endpoint): mock_client = mock.Mock() mock_get_session_endpoint.return_value = 'http://example.com/v2' config_dict = defaults.get_defaults() config_dict.update(fake_services_dict) config_dict['image_endpoint_override'] = 'http://example.com/override' cc = cloud_config.CloudConfig( "test1", "region-al", config_dict, auth_plugin=mock.Mock()) cc.get_legacy_client('image', mock_client) mock_client.assert_called_with( version=2.0, service_name=None, endpoint_override='http://example.com/override', region_name='region-al', interface='public', session=mock.ANY, # Not a typo - the config dict above overrides this service_type='mage' ) @mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint') def test_legacy_client_image_versioned(self, mock_get_session_endpoint): mock_client = mock.Mock() mock_get_session_endpoint.return_value = 'http://example.com/v2' config_dict = defaults.get_defaults() config_dict.update(fake_services_dict) # v2 endpoint was passed, 1 requested in config, endpoint wins config_dict['image_api_version'] = '1' cc = cloud_config.CloudConfig( "test1", "region-al", config_dict, auth_plugin=mock.Mock()) cc.get_legacy_client('image', mock_client) mock_client.assert_called_with( version=2.0, service_name=None, endpoint_override='http://example.com', region_name='region-al', interface='public', session=mock.ANY, # Not a typo - the config dict above overrides this service_type='mage' ) @mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint') def test_legacy_client_image_unversioned(self, mock_get_session_endpoint): mock_client = mock.Mock() mock_get_session_endpoint.return_value = 'http://example.com/' config_dict = defaults.get_defaults() config_dict.update(fake_services_dict) # Versionless endpoint, config wins config_dict['image_api_version'] = '1' cc = cloud_config.CloudConfig( "test1", "region-al", config_dict, auth_plugin=mock.Mock()) cc.get_legacy_client('image', mock_client) mock_client.assert_called_with( version='1', service_name=None, endpoint_override='http://example.com', region_name='region-al', interface='public', session=mock.ANY, # Not a typo - the config dict above overrides this service_type='mage' ) @mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint') def test_legacy_client_image_argument(self, mock_get_session_endpoint): mock_client = mock.Mock() mock_get_session_endpoint.return_value = 'http://example.com/v3' config_dict = defaults.get_defaults() config_dict.update(fake_services_dict) # Versionless endpoint, config wins config_dict['image_api_version'] = '6' cc = cloud_config.CloudConfig( "test1", "region-al", config_dict, auth_plugin=mock.Mock()) cc.get_legacy_client('image', mock_client, version='beef') mock_client.assert_called_with( version='beef', service_name=None, endpoint_override='http://example.com', region_name='region-al', interface='public', session=mock.ANY, # Not a typo - the config dict above overrides this service_type='mage' ) @mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint') def test_legacy_client_network(self, mock_get_session_endpoint): mock_client = mock.Mock() mock_get_session_endpoint.return_value = 'http://example.com/v2' config_dict = defaults.get_defaults() config_dict.update(fake_services_dict) cc = cloud_config.CloudConfig( "test1", "region-al", config_dict, auth_plugin=mock.Mock()) cc.get_legacy_client('network', mock_client) mock_client.assert_called_with( api_version='2.0', endpoint_type='public', endpoint_override=None, region_name='region-al', service_type='network', session=mock.ANY, service_name=None) @mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint') def test_legacy_client_compute(self, mock_get_session_endpoint): mock_client = mock.Mock() mock_get_session_endpoint.return_value = 'http://example.com/v2' config_dict = defaults.get_defaults() config_dict.update(fake_services_dict) cc = cloud_config.CloudConfig( "test1", "region-al", config_dict, auth_plugin=mock.Mock()) cc.get_legacy_client('compute', mock_client) mock_client.assert_called_with( version='2', endpoint_type='public', endpoint_override='http://compute.example.com', region_name='region-al', service_type='compute', session=mock.ANY, service_name=None) @mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint') def test_legacy_client_identity(self, mock_get_session_endpoint): mock_client = mock.Mock() mock_get_session_endpoint.return_value = 'http://example.com/v2' config_dict = defaults.get_defaults() config_dict.update(fake_services_dict) cc = cloud_config.CloudConfig( "test1", "region-al", config_dict, auth_plugin=mock.Mock()) cc.get_legacy_client('identity', mock_client) mock_client.assert_called_with( version='2.0', endpoint='http://example.com/v2', endpoint_type='admin', endpoint_override=None, region_name='region-al', service_type='identity', session=mock.ANY, service_name='locks') @mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint') def test_legacy_client_identity_v3(self, mock_get_session_endpoint): mock_client = mock.Mock() mock_get_session_endpoint.return_value = 'http://example.com' config_dict = defaults.get_defaults() config_dict.update(fake_services_dict) config_dict['identity_api_version'] = '3' cc = cloud_config.CloudConfig( "test1", "region-al", config_dict, auth_plugin=mock.Mock()) cc.get_legacy_client('identity', mock_client) mock_client.assert_called_with( version='3', endpoint='http://example.com', interface='admin', endpoint_override=None, region_name='region-al', service_type='identity', session=mock.ANY, service_name='locks') os-client-config-1.31.2/os_client_config/tests/test_init.py0000666000175000017500000000231613311600770024004 0ustar zuulzuul00000000000000# 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 os_client_config from os_client_config.tests import base class TestInit(base.TestCase): def test_get_config_without_arg_parser(self): cloud_config = os_client_config.get_config( options=None, validate=False) self.assertIsInstance( cloud_config, os_client_config.cloud_config.CloudConfig ) def test_get_config_with_arg_parser(self): cloud_config = os_client_config.get_config( options=argparse.ArgumentParser(), validate=False) self.assertIsInstance( cloud_config, os_client_config.cloud_config.CloudConfig ) os-client-config-1.31.2/os_client_config/defaults.py0000666000175000017500000000147713311600770022456 0ustar zuulzuul00000000000000# Copyright (c) 2014 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 os from openstack.config import defaults _json_path = os.path.join( os.path.dirname(os.path.realpath(__file__)), 'defaults.json') def get_defaults(): return defaults.get_defaults(json_path=_json_path) os-client-config-1.31.2/os_client_config/vendors/0000775000175000017500000000000013311601303021733 5ustar zuulzuul00000000000000os-client-config-1.31.2/os_client_config/vendors/__init__.py0000666000175000017500000000123413311600770024055 0ustar zuulzuul00000000000000# Copyright (c) 2014 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. from openstack.config.vendors import get_profile # noqa os-client-config-1.31.2/os_client_config/vendors/limestonenetworks.json0000666000175000017500000000046213311600770026435 0ustar zuulzuul00000000000000{ "name": "limestonenetworks", "profile": { "auth": { "auth_url": "https://auth.cloud.lstn.net:5000/v3" }, "regions": [ "us-dfw-1", "us-slc" ], "identity_api_version": "3", "image_format": "raw", "volume_api_version": "3" } } os-client-config-1.31.2/os_client_config/defaults.json0000666000175000017500000000140313311600770022764 0ustar zuulzuul00000000000000{ "application_catalog_api_version": "1", "auth_type": "password", "baremetal_api_version": "1", "container_api_version": "1", "container_infra_api_version": "1", "compute_api_version": "2", "database_api_version": "1.0", "disable_vendor_agent": {}, "dns_api_version": "2", "interface": "public", "floating_ip_source": "neutron", "identity_api_version": "2.0", "image_api_use_tasks": false, "image_api_version": "2", "image_format": "qcow2", "key_manager_api_version": "v1", "message": "", "metering_api_version": "2", "network_api_version": "2", "object_store_api_version": "1", "orchestration_api_version": "1", "secgroup_source": "neutron", "status": "active", "volume_api_version": "2", "workflow_api_version": "2" } os-client-config-1.31.2/ChangeLog0000664000175000017500000004203513311601303016525 0ustar zuulzuul00000000000000CHANGES ======= 1.31.2 ------ * fix tox python3 overrides * Remove app\_name config tests * Add release note for the vendor data regression * fix saltstack breakage introduced in v1.31.0 * Remove service-type override tests * Fix F405 additional strictness 1.31.1 ------ * Add cache methods back to OpenSackConfig * fix link to openstacksdk in deprecation block 1.31.0 ------ * Replace guts with openstack.config 1.30.0 ------ * Remove DataCentred from list of vendors * add lower-constraints job * Add Limestone Networks vendor info * Rename python-openstacksdk to openstacksdk * pypy is not checked at gate * Add image\_format for VEXXHOST profile * Updated from global requirements * Use 'none' auth plugin * Updated from global requirements * Add os-client-config tips jobs * Updated from global requirements * Add osc tips jobs back * Add missing auth url from betacloud to docs * Update reno for stable/queens * Updated from global requirements 1.29.0 ------ * Updated from global requirements * Split docs requirements and update tox.ini * Zuul: Remove project name * Add betacloud to the vendors * Make the get\_service\_type() overrides tolernat of no defaults * Remove osc devstack tips jobs * Do not apply format expansions to passwords * Updated from global requirements * Remove setting of version/release from releasenotes * Add shade-functional-tips jobs * Consume the osc-functional-devstack-tips job * Fix doc typo * Added nat\_source flag for networks * Add shade-tox-tips jobs * Update make\_rest\_client to work with version discovery * Protect against p\_opt not having prompt attribute * Treat clouds.yaml with one cloud like envvars * Updated from global requirements * Fix requires\_floating\_ip * Updates for stestr * Updated from global requirements * Updated from global requirements * Updated from global requirements * Updated from global requirements * DataCentred supports Keystone V3 and Glance V2 * Update globals safely * Update the documentation link for doc migration * Remove OSIC * Update reno for stable/pike * Updated from global requirements * Manually sync with g-r 1.28.0 ------ * use openstackdocstheme html context * switch from oslosphinx to openstackdocstheme * turn on warning-is-error in documentation build * rearrange existing documentation to follow the new standard layout * Don't pop from os.environ * Keep a singleton to support multiple get\_config calls * Revert "Revert "Use interface not endpoint\_type for keystoneclient"" * Revert "Use interface not endpoint\_type for keystoneclient" * Add ironicclient to constructors list * Add helper method to fetch service catalog * Fix interactions with keystoneauth from newton 1.27.0 ------ * Make \_fix\_argv() somewhat compatible with Argparse action='append' * Add ability to pass in user\_agent * Docs: add a note about rackspace API keys * Remove out of date comment * Stop special-casing idenity catalog lookups * Add designateclient to constructors list * OVH supports qcow2 * Use interface not endpoint\_type for keystoneclient * Add support for bailing on invalid service versions * modify test-requirement according to requirements project * [Fix gate]Update test requirement * Pass ironic microversion through from api\_version * Add ability to skip yaml loading * Remove the keystoneclient auth fallback * Add support for overriding mistral service type * Add helper scripts to print version discovery info * Add support for indicating required floating IPs * Update reno for stable/ocata * fix location of team tags in README * Fix typo for baremetal\_service\_type 1.26.0 ------ * Revert "Fix interface\_key for identity clients" * Add support for Murano 1.25.0 ------ * Add OpenTelekomCloud to the vendors * Remove 3.4 from tox envlist * Use upper-constraints for tox envs * Update swift constructor to be Session aware * Magnum's service\_type is container\_infra * Add docutils contraint on 0.13.1 to fix building * Fix interface\_key for identity clients * Show team and repo badges on README 1.24.0 ------ * Revert "Remove validate\_auth\_ksc" 1.23.0 ------ * Remove validate\_auth\_ksc * Add fuga.io to vendors * Support token\_endpoint as an auth\_type * Add support for volumev3 service type * Normalize cloud config before osc-lib call * Fix a bunch of tests * Clarify how to set SSL settings * Update ECS image\_api\_version to 1 1.22.0 ------ * Revert "Split auth plugin loading into its own method" * Add setter for session constructor * Enable release notes translation * cloud\_config:get\_session\_endpoint: catch Keystone EndpointNotFound * Using assertIsNone() instead of assertEqual(None, ...) * Update homepage with developer documentation page * List py35 in the default tox env list * Fix AttributeError in \`get\_config\` * modify the home-page info with the developer documentation * Don't create envvars cloud if cloud or region are set * Don't build releasenotes in normal docs build * Update reno for stable/newton * Add ability to configure Session constructor * Split auth plugin loading into its own method 1.21.1 ------ * Go ahead and handle YAML list in region\_name 1.21.0 ------ * Add prompting for KSA options * Clean up vendor support list 1.20.1 ------ * Precedence final solution 1.20.0 ------ * Add support for configuring split-stack networks * Pop domain-id from the config if we infer values * Update Internap information 1.19.1 ------ * Add test for precedence rules * Pass the argparse data into to validate\_auth * Revert "Fix precedence for pass-in options" 1.19.0 ------ * Add release notes for 1.19.0 release * Add the new DreamCompute cloud * Fix precedence for pass-in options * Update citycloud to list new regions * Add support for listing a cloud as shut down * Add support for deprecating cloud profiles * Refactor fix magic in get\_one\_cloud() 1.18.0 ------ * Reword the entries in the README a bit * Add shade constructor helper method * Rename session\_client to make\_rest\_client * Add helper method for OpenStack SDK constructor * Add missing "cloud" argument to \_validate\_auth\_ksc * Workaround bad required params in troveclient * Trivial: Remove 'MANIFEST.in' * Trivial: remove openstack/common from flake8 exclude list * drop python3.3 support in classifier * Fix formatting in readme file * Remove discover from test-requirements.txt * Add version string 1.17.0 ------ * Pull the network settings from the actual dict * Clarify one-per-cloud network values * Flesh out netowrk config list * Change network info indication to a generic list * Update reno for stable/mitaka * Add osic vendor profile 1.16.0 ------ * Update the README a bit * Allow session\_client to take the same args as make\_client * Fix formulation 1.15.0 ------ * Add release notes * Send swiftclient username/password and token * Remove HP and RunAbove from vendor profiles * Added SSL support for VEXXHOST * Add support for zetta.io * Stop ignoring v2password plugin * Go ahead and remove final excludes * Don't set project\_domain if not project scoped * Clean up removed hacking rule from [flake8] ignore lists * set up release notes build 1.14.0 ------ * Fix a precedence problem with auth arguments * Return empty dict instead of None for lack of file * Pass version arg by name not position * Use \_get\_client in make\_client helper function * Add barbicanclient support * Remove openstack-common.conf * Add IBM Public Cloud * Replace assertEqual(None, \*) with assertIsNone in tests * Update auth urls and identity API versions * Stop hardcoding compute in simple\_client * Update volume API default version from v1 to v2 * Debug log a deferred keystone exception, else we mask some useful diag * Fix README.rst, add a check for it to fit PyPI rules * Use reno for release notes * add URLs for release announcement tools * Allow filtering clouds on command line 1.13.1 ------ * Munge region\_name to '' if set to None * Fix some README typos * Fix token\_endpoint usage * remove python 2.6 os-client-config classifier * If cloud doesn't list regions expand passed name 1.13.0 ------ * Fix glance endpoints with endpoint\_override * Allow passing in explicit version for legacy\_client * Pass endpoint override to constructors * Support backwards compat for \_ args * Add backwards compat mapping for auth-token * Replace assertEqual(None, \*) with assertIsNone in tests * Allow arbitrary client-specific options * Add ceilometer constructor to known constructors * Add support for generalized per-region settings * Fix a README typo - hepler is not actually a thing * Make client constructor optional * Updated README to clarify legacy client usage * Add simple helper function for client construction * Add method for registering argparse options * Update vexxhost to Identity v3 * Make sure that cloud always has a name * Remove optional keystoneauth1 imports 1.12.0 ------ * Add BHS1 to OVH * Handle cinder v2 * Add support for secure.yaml file for auth info 1.11.1 ------ * Fix lack of parenthesis around boolean logic 1.11.0 ------ * Only pass timeout to swift if we have a value * Fix name of the object-store api key * Refactor per-service key making * Add support for legacy envvar prefixes * Fix JSON schema 1.10.2 ------ * Workaround a dispute between osc and neutronclient * Workaround for int value with verbose\_level * Remove unneeded workaround for ksc * Add default API version for magnum service 1.10.1 ------ * Work around a bug in keystoneclient constructor * Return cache settings as numbers not strings * Add method to get a mounted session from config 1.10.0 ------ * Convert floats to string * Don't assume pass\_version\_arg=False for network * Update network api version in defaults.json * Dont turn bools into strings * Use requestsexceptions for urllib squelching * Normalize int config values to string * Disable spurious urllib warnings * Add logging module support * Add methods for getting Session and Client objects * Update conoha's vendor profile to include SJC * Use json for in-tree cloud data * Update auro to indicate move to neutron * Copy values in backwards\_interface differently * Fix typo in Catalyst region configs * Aligned a few words in the docs * Sort vendor list * Add conoha public cloud * Allow for templated variables in auth\_url * Use assertDictEqual to test dict equality * Always pull regions from vendor profiles 1.9.0 ----- * Clean up cache interface, add support for services * Add Rackspace LON region * Validate requested region against region list * Fix documentation around regions * Add an API reference to the docs * Pass OpenStackConfig in to CloudConfig for caches * Add auth hook for OpenStackClient * Adds some lines to complete table formatting 1.8.1 ----- * Add universal=1 to setup.cfg to build python 3 wheels * Some cleanup 1.8.0 ----- * Fix two typos * Put in override for Rackspace broken neutron * Support passing force\_ipv4 to the constructor * identity version is 2.0 * Handle OS\_CLOUD and OS\_REGION\_NAME friendly-like * Added SWITCHengines vendor file * update RST for readme so pypi looks pretty 1.7.5 ----- * Fix a little error with the None auth type * Add support for Catalyst as vendor * Change ignore-errors to ignore\_errors 1.7.4 ----- * Handle ksa opt with no deprecated field 1.7.3 ----- * Fall back to keystoneclient arg processing * Fix typo in ovh region names 1.7.2 ----- * Move plugin loader creation to try block 1.7.1 ----- * Convert auth kwargs '-' to '\_' * Properly handle os- prefixed args in fix\_args * Test kwargs passing not just argparse 1.7.0 ----- * Allow configuring domain id once * Add internap to the vendor list * Fix typo in comment - we use ksa not ksc * Defer plugin validation to keystoneauth 1.6.4 ----- * Remove an extra line * Add Datacentred to the vendor list * Add ultimum to list of vendors * Add Enter Cloud Suite to vendors list * Add elastx to vendor support matrix * Switch the image default to v2 * Update auro auth\_url and region information * Add citycloud to the vendors list * Return keystoneauth plugins based on auth args * Remove duplicate lines that are the same as default * Add default version number for heat * Update OVH public cloud information * Handle empty defaults.yaml file * Do not treat project\_name and project\_id the same * Revert "Revert "Use the correct auth\_plugin for token authentication"" 1.6.3 ----- * Revert "Use the correct auth\_plugin for token authentication" 1.6.2 ----- * Ignore infra CI env vars * Use the correct auth\_plugin for token authentication 1.6.1 ----- * Align to generic password auth-type 1.6.0 ----- * Clarify floating ip use for vendors * Add per-service endpoint overrides 1.5.0 ----- * Remove requirements.txt from tox.ini * Remove py26 and py33 from tox.ini * Rename 'endpoint\_type' to 'interface' * Have service name default to None * Remove region list from single cloud * Fix set\_default() when used before config init * Specify the config file with environment variable * Add support for configuring region lists with yaml * Fix rendering issue in Readme * Clean up vendor data * Add support for indicating preference for IPv6 * Normalize project\_name aliases 1.4.0 ----- * Add some accessor methods to CloudConfig * Add missing tests * Add test to check cert and key as a tuple * Use one yaml file per vendor * Raise warning when a vendor profile is missing * Some cleanup in the README.rst * Add support for OVH Public Cloud * Add SSL documentation to README.rst * Stringify project details * Raise a warning with conflicting SSL params * Change references of "clouds.yaml" for real file * Raise a warning when using 'cloud' in config * Add cloud vendor files config in doc 1.3.0 ----- * Provide a helper method to get requests ssl values * Add more defaults to our defaults file * Change naming in vendor doc to match vendors.py * Add auro to list of known vendors * Add list of image params needed to disable agents 1.2.0 ----- * Add set\_one\_cloud method * Add tests for get\_cloud\_names * Add flag to indicate handling of security groups * Don't normalize too deeply 1.1.0 ----- * Add tests for cloud config comparison * Add inequality method * Add an equality method for CloudConfig * Capture the filename used for config * Normalize all keys down to \_ instead of - * Expose method for getting a list of cloud names * Rename cloud to profile * Don't pass None as the cloud name 1.0.0 ----- * Change overriding defaults to kwarg * Add tests for OSC usage * Use appdirs for platform-independent locations * Add UnitedStack * Expose function to get defaults dict * Add default versions for trove and ironic * Sort defaults list for less conflicts * Only add fall through cloud as a fall through 0.8.2 ----- * Add flag to indicate where floating ips come from * get\_one\_cloud should use auth merge * Also accept .yml as a suffix * Remove crufty lines from README * Update vendor support to reflect v2 non-task 0.8.1 ----- * Add flag to trigger task interface for rackspace 0.8.0 ----- * Document vendor support information * Reset cache default to 0 * add .venv to gitignore * Move region\_names out of auth dict * Add runabove to vendors * Add image information to vexxhost account * Add vexxhost * Add DreamCompute to vendors list * Allow overriding envvars as the name of the cloud * Put env vars into their own cloud config * Add keystoneclient to test-requirements * Actually put some content into our sphinx docs 0.7.0 ----- * Update .gitreview for git section rename * Change dogpile cache defaults * Add cover to .gitignore 0.6.0 ----- * Flesh out api version defaults * Handle project\_name/tenant\_name in the auth dict * Add two newlines to the ends of files * Rename auth\_plugin to auth\_type 0.5.0 ----- * Add support for configuring dogpile.cache * Fix coverage report * Add more testing of vendor yaml loading * More comprehensive unit tests for os-client-config * Allow keystone validation bypass for noauth usage * Add basic unit test for config 0.4.3 ----- * Prefer dest value when option is depricated * Allow region\_name to be None 0.4.2 ----- * Don't return the auth dict inside the loop * Make sure we're deep-copying the auth dict 0.4.1 ----- * Remove runtime depend on pbr * Provide Rackspace service\_name override 0.4.0 ----- * Start keeping default versions for all services * Support keystone auth plugins in a generic way * Replace defaults\_dict with scanning env vars * Workflow documentation is now in infra-manual * Corrections to readme * Use yaml.safe\_load instead of load * Throw error if a non-existent cloud is requested 0.3.0 ----- * Fix a missed argument from a previous refactor * Map CloudConfig attributes to CloudConfig.config * Add support for argparse Namespace objects * Add support for command line argument processing * Handle lack of username for project\_name defaults * Handle the project/tenant nonesense more cleanly * Add cache control settings * Handle no vendor clouds config files * Remove unused class method get\_services * Add clouds-public.yaml * Prep for move to stackforge 0.2.0 ----- * Handle missing vendor key * Make env vars lowest priority * Handle null region * Update the README file for more completeness 0.1.0 ----- * Get rid of extra complexity with service values * Remove babel and add pyyaml * Port in config reading from shade * Initial Cookiecutter Commit os-client-config-1.31.2/tools/0000775000175000017500000000000013311601303016107 5ustar zuulzuul00000000000000os-client-config-1.31.2/tools/keystone_version.py0000666000175000017500000000542513311600770022106 0ustar zuulzuul00000000000000# Copyright (c) 2017 Red Hat, 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 os_client_config import pprint import sys import urlparse def print_versions(r): if 'version' in r: for version in r['version']: print_version(version) if 'values' in r: for version in r['values']: print_version(version) if isinstance(r, list): for version in r: print_version(version) def print_version(version): if version['status'] in ('CURRENT', 'stable'): print( "\tVersion ID: {id} updated {updated}".format( id=version.get('id'), updated=version.get('updated'))) verbose = '-v' in sys.argv ran = [] for cloud in os_client_config.OpenStackConfig().get_all_clouds(): if cloud.name in ran: continue ran.append(cloud.name) # We don't actually need a compute client - but we'll be getting full urls # anyway. Without this SSL cert info becomes wrong. c = cloud.get_session_client('compute') endpoint = cloud.config['auth']['auth_url'] try: print(endpoint) r = c.get(endpoint).json() if verbose: pprint.pprint(r) except Exception as e: print("Error with {cloud}: {e}".format(cloud=cloud.name, e=str(e))) continue if 'version' in r: print_version(r['version']) url = urlparse.urlparse(endpoint) parts = url.path.split(':') if len(parts) == 2: path, port = parts else: path = url.path port = None stripped = path.rsplit('/', 2)[0] if port: stripped = '{stripped}:{port}'.format(stripped=stripped, port=port) endpoint = urlparse.urlunsplit( (url.scheme, url.netloc, stripped, url.params, url.query)) print(" also {endpoint}".format(endpoint=endpoint)) try: r = c.get(endpoint).json() if verbose: pprint.pprint(r) except Exception: print("\tUnauthorized") continue if 'version' in r: print_version(r) elif 'versions' in r: print_versions(r['versions']) else: print("\n\nUNKNOWN\n\n{r}".format(r=r)) else: print_versions(r['versions']) os-client-config-1.31.2/tools/nova_version.py0000666000175000017500000000410713311600770021204 0ustar zuulzuul00000000000000# Copyright (c) 2017 Red Hat, 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 os_client_config ran = [] for cloud in os_client_config.OpenStackConfig().get_all_clouds(): if cloud.name in ran: continue ran.append(cloud.name) c = cloud.get_session_client('compute') try: raw_endpoint = c.get_endpoint() have_current = False endpoint = raw_endpoint.rsplit('/', 2)[0] print(endpoint) r = c.get(endpoint).json() except Exception: print("Error with %s" % cloud.name) continue for version in r['versions']: if version['status'] == 'CURRENT': have_current = True print( "\tVersion ID: {id} updated {updated}".format( id=version.get('id'), updated=version.get('updated'))) print( "\tVersion Max: {max}".format(max=version.get('version'))) print( "\tVersion Min: {min}".format(min=version.get('min_version'))) if not have_current: for version in r['versions']: if version['status'] == 'SUPPORTED': have_current = True print( "\tVersion ID: {id} updated {updated}".format( id=version.get('id'), updated=version.get('updated'))) print( "\tVersion Max: {max}".format(max=version.get('version'))) print( "\tVersion Min: {min}".format( min=version.get('min_version'))) os-client-config-1.31.2/releasenotes/0000775000175000017500000000000013311601303017440 5ustar zuulzuul00000000000000os-client-config-1.31.2/releasenotes/notes/0000775000175000017500000000000013311601303020570 5ustar zuulzuul00000000000000os-client-config-1.31.2/releasenotes/notes/ironic-microversion-ba5b0f36f11196a6.yaml0000666000175000017500000000017013311600770027670 0ustar zuulzuul00000000000000--- features: - Add support for passing Ironic microversion to the ironicclient constructor in get_legacy_client. os-client-config-1.31.2/releasenotes/notes/min-max-legacy-version-301242466ddefa93.yaml0000666000175000017500000000147313311600770030116 0ustar zuulzuul00000000000000--- features: - Add min_version and max_version to get_legacy_client and to get_session_endpoint. At the moment this is only really fully plumbed through for cinder, which has extra special fun around volume, volumev2 and volumev3. Min and max versions to both methods will look through the options available in the service catalog and try to return the latest one available from the span of requested versions. This means a user can say volume_api_version=None, min_version=2, max_version=3 will get an endpoint from get_session_endpoint or a Client from cinderclient that will be either v2 or v3 but not v1. In the future, min and max version for get_session_endpoint should be able to sort out appropriate endpoints via version discovery, but that does not currently exist. os-client-config-1.31.2/releasenotes/notes/default-cloud-7ee0bcb9e5dd24b9.yaml0000666000175000017500000000042313311600770026655 0ustar zuulzuul00000000000000--- issues: - If there was only one cloud defined in clouds.yaml os-client-config was requiring the cloud parameter be passed. This is inconsistent with how the envvars cloud works which WILL work without setting the cloud parameter if it's the only cloud. os-client-config-1.31.2/releasenotes/notes/option-precedence-1fecab21fdfb2c33.yaml0000666000175000017500000000040413311600770027565 0ustar zuulzuul00000000000000--- fixes: - Reverse the order of option selction in ``OpenStackConfig._validate_auth()`` to prefer auth options passed in (from argparse) over those found in clouds.yaml. This allows the application to override config profile auth settings. os-client-config-1.31.2/releasenotes/notes/shade-helper-568f8cb372eef6d9.yaml0000666000175000017500000000013113311600770026343 0ustar zuulzuul00000000000000--- features: - Added helper method for constructing shade OpenStackCloud objects. os-client-config-1.31.2/releasenotes/notes/fix-vendor-import-ebd4ade0d5c17146.yaml0000666000175000017500000000015213311600770027421 0ustar zuulzuul00000000000000--- fixes: - | Fixed regression in vendor data importing caused by the merge with openstacksdk. os-client-config-1.31.2/releasenotes/notes/load-yaml-3177efca78e5c67a.yaml0000666000175000017500000000044013311600770025652 0ustar zuulzuul00000000000000--- features: - Added a flag, 'load_yaml_config' that defaults to True. If set to false, no clouds.yaml files will be loaded. This is beneficial if os-client-config wants to be used inside of a service where end-user clouds.yaml files would make things more confusing. os-client-config-1.31.2/releasenotes/notes/sdk-helper-41f8d815cfbcfb00.yaml0000666000175000017500000000013513311600770026072 0ustar zuulzuul00000000000000--- features: - Added helper method for constructing OpenStack SDK Connection objects. os-client-config-1.31.2/releasenotes/notes/session-client-b581a6e5d18c8f04.yaml0000666000175000017500000000030613311600770026643 0ustar zuulzuul00000000000000--- features: - Added kwargs and argparse processing for session_client. deprecations: - Renamed simple_client to session_client. simple_client will remain as an alias for backwards compat. os-client-config-1.31.2/releasenotes/notes/make-rest-client-version-discovery-84125700f159491a.yaml0000666000175000017500000000032013311600770032230 0ustar zuulzuul00000000000000--- features: - Add version argument to make_rest_client and plumb version discovery through get_session_client so that versioned endpoints are properly found if unversioned are in the catalog. os-client-config-1.31.2/releasenotes/notes/magic-fixes-dca4ae4dac2441a8.yaml0000666000175000017500000000033713311600770026303 0ustar zuulzuul00000000000000--- fixes: - Refactor ``OpenStackConfig._fix_backward_madness()`` into ``OpenStackConfig.magic_fixes()`` that allows subclasses to inject more fixup magic into the flow during ``get_one_cloud()`` processing. os-client-config-1.31.2/releasenotes/notes/nat-source-field-7c7db2a724616d59.yaml0000666000175000017500000000046513311600770026776 0ustar zuulzuul00000000000000--- features: - Added nat_source flag for networks. In some more complex clouds there can not only be more than one valid network on a server that NAT can attach to, there can also be more than one valid network from which to get a NAT address. Allow flagging a network so that it can be found. os-client-config-1.31.2/releasenotes/notes/vendor-add-betacloud-03872c3485104853.yaml0000666000175000017500000000006013311600770027301 0ustar zuulzuul00000000000000--- other: - Add betacloud region for Germany os-client-config-1.31.2/releasenotes/notes/started-using-reno-242e2b0cd27f9480.yaml0000666000175000017500000000006313311600770027347 0ustar zuulzuul00000000000000--- other: - Started using reno for release notes. os-client-config-1.31.2/releasenotes/notes/vendor-add-limestonenetworks-99b2ffab9fc23b08.yaml0000666000175000017500000000013013311600770031657 0ustar zuulzuul00000000000000--- other: - | Add Limestone Networks vendor info for us-dfw-1 and us-slc regions os-client-config-1.31.2/releasenotes/notes/network-list-e6e9dafdd8446263.yaml0000666000175000017500000000065013311600770026442 0ustar zuulzuul00000000000000--- features: - Support added for configuring metadata about networks for a cloud in a list of dicts, rather than in the external_network and internal_network entries. The dicts support a name, a routes_externally field, a nat_destination field and a default_interface field. deprecations: - external_network and internal_network are deprecated and should be replaced with the list of network dicts. os-client-config-1.31.2/releasenotes/notes/catch-up-release-notes-e385fad34e9f3d6e.yaml0000666000175000017500000000156213311600770030333 0ustar zuulzuul00000000000000--- prelude: > Swiftclient instantiation now provides authentication information so that long lived swiftclient objects can reauthenticate if necessary. This should be a temporary situation until swiftclient supports keystoneauth sessions at which point os-client-config will instantiate swiftclient with a keystoneauth session. features: - Swiftclient instantiation now provides authentication information so that long lived swiftclient objects can reauthenticate if necessary. - Add support for explicit v2password auth type. - Add SSL support to VEXXHOST vendor profile. - Add zetta.io cloud vendor profile. fixes: - Fix bug where project_domain_{name,id} was set even if project_{name,id} was not set. other: - HPCloud vendor profile removed due to cloud shutdown. - RunAbove vendor profile removed due to migration to OVH. os-client-config-1.31.2/releasenotes/notes/thin-shim-62c8e6f6942b83a5.yaml0000666000175000017500000000125313311600770025537 0ustar zuulzuul00000000000000--- prelude: > os-client-config is now a thin shim around openstacksdk. It exists and will continue to exist provide backward compatibility. upgrade: - | ``get_region_name`` no longer supports pre-service region name overrides. An ``os_client_config.cloud_config.CloudConfig`` object represents a region of a cloud. The support was originally added for compatibility with the similar feature in openstacksdk's ``Profile``. Both the support for service regions and the ``Profile`` object have been removed from openstacksdk, so there is no need to attempt to add a compatibility layer here as there is nothing that has the ability to consume it. os-client-config-1.31.2/releasenotes/notes/fix-compat-with-old-keystoneauth-66e11ee9d008b962.yaml0000666000175000017500000000044513311600770032147 0ustar zuulzuul00000000000000--- issues: - Fixed a regression when using latest os-client-config with the keystoneauth from stable/newton. Although this isn't a super common combination, the added feature that broke the interaction is really not worthy of the incompatibility, so a workaround was added. os-client-config-1.31.2/releasenotes/notes/make-rest-client-dd3d365632a26fa0.yaml0000666000175000017500000000022013311600770027030 0ustar zuulzuul00000000000000--- deprecations: - Renamed session_client to make_rest_client. session_client will continue to be supported for backwards compatability. os-client-config-1.31.2/releasenotes/notes/cloud-profile-status-e0d29b5e2f10e95c.yaml0000666000175000017500000000034313311600770030046 0ustar zuulzuul00000000000000--- features: - Add a field to vendor cloud profiles to indicate active, deprecated and shutdown status. A message to the user is triggered when attempting to use cloud with either deprecated or shutdown status. os-client-config-1.31.2/releasenotes/notes/vendor-updates-f11184ba56bb27cf.yaml0000666000175000017500000000022413311600770026711 0ustar zuulzuul00000000000000--- other: - Add citycloud regions for Buffalo, Frankfurt, Karlskrona and Los Angles - Add new DreamCompute cloud and deprecate DreamHost cloud os-client-config-1.31.2/releasenotes/source/0000775000175000017500000000000013311601303020740 5ustar zuulzuul00000000000000os-client-config-1.31.2/releasenotes/source/_static/0000775000175000017500000000000013311601303022366 5ustar zuulzuul00000000000000os-client-config-1.31.2/releasenotes/source/_static/.placeholder0000666000175000017500000000000013311600770024650 0ustar zuulzuul00000000000000os-client-config-1.31.2/releasenotes/source/pike.rst0000666000175000017500000000021713311600770022433 0ustar zuulzuul00000000000000=================================== Pike Series Release Notes =================================== .. release-notes:: :branch: stable/pike os-client-config-1.31.2/releasenotes/source/ocata.rst0000666000175000017500000000023013311600770022565 0ustar zuulzuul00000000000000=================================== Ocata Series Release Notes =================================== .. release-notes:: :branch: origin/stable/ocata os-client-config-1.31.2/releasenotes/source/unreleased.rst0000666000175000017500000000015313311600770023631 0ustar zuulzuul00000000000000============================ Current Series Release Notes ============================ .. release-notes:: os-client-config-1.31.2/releasenotes/source/queens.rst0000666000175000017500000000022313311600770023000 0ustar zuulzuul00000000000000=================================== Queens Series Release Notes =================================== .. release-notes:: :branch: stable/queens os-client-config-1.31.2/releasenotes/source/index.rst0000666000175000017500000000043313311600770022612 0ustar zuulzuul00000000000000================================ os-client-config Release Notes ================================ Contents ======== .. toctree:: :maxdepth: 2 unreleased queens pike ocata newton mitaka Indices and tables ================== * :ref:`genindex` * :ref:`search` os-client-config-1.31.2/releasenotes/source/mitaka.rst0000666000175000017500000000023213311600770022746 0ustar zuulzuul00000000000000=================================== Mitaka Series Release Notes =================================== .. release-notes:: :branch: origin/stable/mitaka os-client-config-1.31.2/releasenotes/source/_templates/0000775000175000017500000000000013311601303023075 5ustar zuulzuul00000000000000os-client-config-1.31.2/releasenotes/source/_templates/.placeholder0000666000175000017500000000000013311600770025357 0ustar zuulzuul00000000000000os-client-config-1.31.2/releasenotes/source/newton.rst0000666000175000017500000000023213311600770023012 0ustar zuulzuul00000000000000=================================== Newton Series Release Notes =================================== .. release-notes:: :branch: origin/stable/newton os-client-config-1.31.2/releasenotes/source/conf.py0000666000175000017500000002037713311600770022261 0ustar zuulzuul00000000000000# -*- coding: utf-8 -*- # # Os-Client-Config Release Notes documentation build configuration file, created by # sphinx-quickstart on Thu Nov 5 11:50:32 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' import openstackdocstheme # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'reno.sphinxext', ] # 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. project = u'os-client-config Release Notes' copyright = u'2015, os-client-config developers' # Release notes do not need a version in the title, they span # multiple versions. # The short X.Y version. version = '' # The full version, including alpha/beta/rc tags. release = '' # 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 = 'sphinx' # 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 = [] html_theme_path = [openstackdocstheme.get_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 not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # 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 = 'OCCReleaseNotesdoc' # -- Options for LaTeX output --------------------------------------------- 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. #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ ('index', 'OCCReleaseNotes.tex', u'os-client-config Release Notes Documentation', u'os-client-config 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', 'occreleasenotes', u'os-client-config Release Notes Documentation', [u'os-client-config 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', 'OCCReleaseNotes', u'os-client-config Release Notes Documentation', u'os-client-config developers', 'OCCReleaseNotes', 'One line description of project.', '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/'] os-client-config-1.31.2/.zuul.yaml0000666000175000017500000000255013311600770016723 0ustar zuulzuul00000000000000- job: name: os-client-config-tox-py27-tips parent: openstack-tox-py27 description: | Run tox python 27 unittests against master of important libs vars: tox_install_siblings: true zuul_work_dir: src/git.openstack.org/openstack/os-client-config required-projects: - openstack/keystoneauth - openstack/openstacksdk - openstack/os-client-config - job: name: os-client-config-tox-py35-tips parent: openstack-tox-py35 description: | Run tox python 35 unittests against master of important libs vars: tox_install_siblings: true zuul_work_dir: src/git.openstack.org/openstack/os-client-config required-projects: - openstack/keystoneauth - openstack/openstacksdk - openstack/os-client-config - project-template: name: os-client-config-tox-tips check: jobs: - os-client-config-tox-py27-tips - os-client-config-tox-py35-tips gate: jobs: - os-client-config-tox-py27-tips - os-client-config-tox-py35-tips - project: templates: - os-client-config-tox-tips - shade-functional-tips - shade-tox-tips check: jobs: - osc-functional-devstack-tips - openstack-tox-lower-constraints gate: jobs: - osc-functional-devstack-tips - openstack-tox-lower-constraints