python-designateclient-2.9.0/0000775000175100017510000000000013232475552016237 5ustar zuulzuul00000000000000python-designateclient-2.9.0/PKG-INFO0000664000175100017510000000560313232475552017340 0ustar zuulzuul00000000000000Metadata-Version: 1.1 Name: python-designateclient Version: 2.9.0 Summary: OpenStack DNS-as-a-Service - Client Home-page: https://docs.openstack.org/python-designateclient/latest Author: OpenStack Author-email: openstack-dev@lists.openstack.org License: Apache License, Version 2.0 Description-Content-Type: UNKNOWN Description: ======================== Team and repository tags ======================== .. image:: https://governance.openstack.org/tc/badges/python-designateclient.svg :target: https://governance.openstack.org/tc/reference/tags/index.html .. Change things from this point on Python bindings to the Designate API ===================================== .. image:: https://img.shields.io/pypi/v/python-designateclient.svg :target: https://pypi.python.org/pypi/python-designateclient/ :alt: Latest Version .. image:: https://img.shields.io/pypi/dm/python-designateclient.svg :target: https://pypi.python.org/pypi/python-designateclient/ :alt: Downloads This is a client library for Designate built on the Designate API. It provides a Python API (the ``designateclient`` module) and a command-line tool (``designate``). Development takes place via the usual OpenStack processes as outlined in the `developer guide `_. The master repository is in `Git `_. See release notes and more at ``_. * License: Apache License, Version 2.0 * `PyPi`_ - package installation * `Online Documentation`_ * `Bugs`_ - issue tracking * `Source`_ * `How to Contribute`_ .. _PyPi: https://pypi.python.org/pypi/python-designateclient .. _Online Documentation: https://docs.openstack.org/python-designateclient/latest/ .. _Bugs: https://bugs.launchpad.net/python-designateclient .. _Source: https://git.openstack.org/cgit/openstack/python-designateclient .. _How to Contribute: https://docs.openstack.org/infra/manual/developers.html 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 Classifier: Topic :: Internet :: Name Service (DNS) python-designateclient-2.9.0/.zuul.yaml0000666000175100017510000000007213232475203020172 0ustar zuulzuul00000000000000- project: templates: - designate-devstack-jobs python-designateclient-2.9.0/CONTRIBUTING.rst0000666000175100017510000000105413232475203020673 0ustar zuulzuul00000000000000If you would like to contribute to the development of OpenStack, you must follow the steps documented at: https://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: https://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/python-designateclient python-designateclient-2.9.0/ChangeLog0000664000175100017510000003622113232475551020014 0ustar zuulzuul00000000000000CHANGES ======= 2.9.0 ----- * Updated from global requirements * Partial Revert "Remove unneeded requirements file" * Updated from global requirements 2.8.0 ----- * Updated from global requirements * Split doc requirements into their own file * Remove unneeded requirements file * Improve recordset create UI * Avoid tox\_install.sh for constraints support * Use jobs from designate repo * Remove setting of version/release from releasenotes * Updated from global requirements * Updated from global requirements * Updated from global requirements * Updated from global requirements * Updated from global requirements * Make remote error handling more robust * Updated from global requirements * Update the documentation link for doc migration * Update reno for stable/pike * Updated from global requirements * Update and optimize documentation links 2.7.0 ----- * Updated from global requirements * switch from oslosphinx to openstackdocstheme * import cli-reference material from openstack-manuals * rearrange the existing docs into the new standard layout * use setuptools to build the docs even for testing * Update cli docs * Add tsig key support to python-designateclient * Updated from global requirements * Updated from global requirements * Updated from global requirements * Updated from global requirements * tox: Whitelist rm * doc: Remove cruft from conf.py * Use Sphinx 1.5 warning-is-error * Explicitly set 'builders' option * Updated from global requirements * [Fix gate]Update test requirement * Updated from global requirements * Simplify OSC doc structure * Updated from global requirements * Set client module \_\_version\_\_ * Update reno for stable/ocata 2.6.0 ----- * Add attribute support to create zone cli * Show proper error on over quota commands * Fix broken link for modindex 2.5.0 ----- * Updated from global requirements * Add Python 3.5 classifier and venv * Updated from global requirements * Remove 'coding: utf-8' from license statement * Removes unnecessary utf-8 encoding * Add Constraints support * Updated from global requirements 2.4.0 ----- * Ensure X-Designate-Edit-Managed-Records header value is a string * Updated from global requirements * Show team and repo badges on README * Use tempest instead of Tempest-lib * Replace 'assertFalse(a in b)' with 'assertNotIn(a, b)' * Updated from global requirements * Updated from global requirements * Ensure X-Auth-All-Projects header value is a string * Updated from global requirements * Add plug-in summary for osc doc * Updated from global requirements * Updated from global requirements * Fix for bug 1627945 * Enable release notes translation * Changed the author and author-email value * Replace 'assertTrue(a in b)' with 'assertIn(a, b)' * Updated from global requirements * Add oslo.config to test-requirements * Updated from global requirements * Fix pep8 E501 line too long * record-create/update: Account for priority being 0 * Update reno for stable/newton 2.3.0 ----- * Updated from global requirements * Resolve FloatingIP PTR records clis argument's description * Docs update for FloatingIP's ptr records * Fix clis related to FloatingIP's ptr records * Updated from global requirements * Remove discover from test-requirements * Updated from global requirements * Updated from global requirements 2.2.0 ----- * Updated from global requirements * Updated from global requirements * Use osc\_lib instead of cliff * Updated from global requirements * Add quota set / list / reset commands * Mark the v1 API Client as deprecated * Add global flags to cli * Updated from global requirements * Use osc-lib instead of openstackclient * Revert "Add Global Flags for filtering results" * Updated from global requirements * Add pool listing to python designate client * Add \`openstack zone transfer accept list\` cli to designateclient * Allow cli to query "v2/recordsets" * Updated from global requirements * Add Global Flags for filtering results * Updated from global requirements * Use the correct capitalization of OpenStack * Updated from global requirements * Update the home-page with developer documentation * Add reno support for release notes * Switch to keystoneauth * Added CONTRIBUTING.rst file * Docs Update * Updated from global requirements * Don't use the 'keystone' client (functional tests) * Update doc examples to use keystoneauth * Update designate cli page with more examples Closes-Bug: #1578207 * Add python-openstackclient to test-requirements * Improve python-designateclient docs * Updated from global requirements * Add support for service status * Fix a race condition in one of the zone import tests * Run the functional tests in a more verbose mode * Show responses on zone and recordset deletes * Implement zone import * Doc changes for installation webpage * Fix an issue causing a blacklist test to fail * Add filtering to recordsets CLI * Show "status" and "action" for recordsets * Move all V2 Controllers to inherit from the v2 * Fixes 'openstack tld list' command's exception * Implement zone export * Updated from global requirements * Improved TestRecordsetNegative * Add a service catalog override to the functional tests * Updated from global requirements * Stop using non-existent method of Mock * Log stacktraces of MultipleExceptions in functionaltests * Updated from global requirements * Updated from global requirements * Updated from global requirements * Python3: Add support for urlparse 2.0.0 ----- * Allow the OSC CLI Plugin to walk pages * Improvement in zone transfer request command description * Fixed grammar mistake in shell.rst * Updated from global requirements * Update typos * Show output on transfer accept * Change to ShowOne to display output upon update * Updated from global requirements * Updated from global requirements * Put py34 first in the env order of tox * Replace assertEqual(None, \*) with assertIsNone in tests * Add a missing whitespace * Deprecated tox -downloadcache option removed * Indicate py34 support * Removes MANIFEST.in as it is not needed explicitely by PBR * Pass environment variables of proxy to tox * Remove py26 support from designateclient * Updated from global requirements * Updated from global requirements * Improve logging in designateclient * Support OS\_INTERFACE and set V2 API as default * Pass OS\_ENDPOINT\_TYPE from shell to client * Updated from global requirements * Adds changes related to py3 compatibility * Clearing out .pyc file before a tox run * Fix support for --os-endpoint * Updates shell doc of v1 client * Fixes doc for v2 cli * Add functional tests for blacklists * Add functional tests for tlds * Adds different filter option for zone listing * Updated from global requirements * Resolve TLD's by name * improve readme contents * Removes --name argument from zone set command * Fixes error over quota update * Fixes order of argument in assertEqual * Fixes typos in zone transfer request show command description * Add functional tests for recordsets * Flesh out zone-related test cases * Fixes exception message for zone creation command * Fixes target-project-id argument in zone transfer command * Removes name argument from openstack recordset set command * Fixes openstack zone blacklist set command * Added test cases for v2 client * Adds test cases for servers in designateclient * Adds test cases for domain in designate v1 client * Makes error msg more helpful * Add period in help message * Layout some functional tests for the V2 CLI 1.5.0 ----- * Updated from global requirements * Add formatting of output data * Added appropriate error message for designate cli * Meaningful Exception for over-quota on domains * Added test cases for reports in designateclient * Added diagnostics,sync and touch test cases for v1 designateclient * V2 CLI Support * Added quotas and servers test cases for designateclient * Added test cases for designate v1 client * Make is so exceptions have some message * Updated from global requirements * Update github's URL * Updated from global requirements * Implement socket timeout in v1 * Don't wildcard resolve names * Updated from global requirements * Updated from global requirements * Improve help strings 1.4.0 ----- * Convert byte to str for py3 compatibilty * Updated from global requirements * Updated from global requirements * Add some missing Unit Tests to test\_utils.py * Solve some py3 compatibilty issues * Fix py3 compatibilty issues * Updated from global requirements * Replacing print with print() to provide py 2/3 compatibility * Updated from global requirements * Updated from global requirements * Fix for ttl values * Log error message from EndpointNotFound exceptions * Removed peronal email address from example 1.3.0 ----- * Updated from global requirements * Fix backwards compat for edit\_managed/all\_tenants * Add .eggs to gitignore * Add backwards compat for edit\_managed/all\_tenants * Updated from global requirements * Updated from global requirements * Updated from global requirements * Update github link * Sync tox.ini and add py34 * Use oslosphinx from PyPi * Drop incubating theme from docs * Move all\_tenants and edit\_managed attributes to designate Client * Log a more informative error upon EndpointNotFound * Updated from global requirements * V2 Bindings * Add --edit-managed flag to cli * Updated from global requirements * Allow relative names in record-create 1.2.0 ----- * Update README to work with release tools * Uncap library requirements for liberty * Allow to use domain names instead of ids * Updated from global requirements * Added extra previllege to list all domains from all tenants * Updated from global requirements * Updated from global requirements * Fix if checking on ttl for Create/Update commands * Updated from global requirements * Workflow documentation is now in infra-manual 1.1.1 ----- * Refactor KS session creation and support CA certs * Move some useful code outside v1 * Make token + endpoints work correctly * Move session creation up to shell * Set defaults for endpoint\_type and service\_type * Updated from global requirements * Use keystone sessions for v1 client * Fixes homepage in metadata and internal docs * Updated from global requirements * Updated from global requirements * Fixes pypi tarball not delivering Apache 2.0 LICENSE file * Updated from global requirements * Updated from global requirements 1.1.0 ----- * Add support for SOA records * sync and touch Commands Extend the base.DeleteCommand * Updated from global requirements * Updated from global requirements * Add support for quotas for v1 cli / bindings * Enable hacking check H104 * Added oslosphinx theme, and enabled the incubating option * Enabled hacking check H401 * Support Keystone V3 authentication * Support better logging (Fixes --debug option) * Update hacking package, fix/ignore new style errors * Updated from global requirements * Update .gitreview for repository move * Use six.add\_metaclass instead of \_\_metaclass\_\_ * Add dummy tests 1.0.3 ----- * designate record-list should display record data * Correct Python bindings create-record example * Standardize doc requirements 1.0.2 ----- * Ensure that url stripping is done correctly * Sync with global-requirements 1.0.1 ----- * Support versionless catalog URLs * Correctly support multiple regions * Update global requirements * Fix misspellings in python designateclient * Disable verbose logging by default * There are no mox tests, so remove dependency * Remove dependencies on pep8, pyflakes and flake8 * Sync with global requirements * Fix and enable gating on H306 * Support building wheels (PEP-427) * Add touch-domain to CLI * Move "sync" commands out of Diagnostics and fix them 1.0.0 ----- * Keyring is not actually used * Remove outdated version value from setup.cfg * Added domain and record description editing * Sync requirements with stable/havana requirements * Ensure TTL is treated as an int in the CLI 0.0.5 ----- * Update dependency versions * Ensure Invalid JSON and errors during deletes are displayed correctly * Correct two Record examples in the binding docs * Add Python bindings docs * first drop of python-designateclient docs * Ensure beta versions are not downloaded from pypi * Add a --insecure arg to ignore invalid SSL certs * Ensure we only list sphinx as a dep once * Use Python 3.x compatible except construct 0.0.4 ----- * Allow auth using a pre-fetched token * Update to PBR 0.5.21+ * doc/requirements.txt should be a proxy * Remove comments from \*requirements.txt (workaround pbr bug) * Sync with openstack/requirements * Rename to designate in .gitreview * Rename Moniker -> Designate * Add Hacking checks * Migrate to PBR * Always allow overriding the endpoint * Switch to flake8 and testr * Added reporting functionality to Moniker client * Correct diagnostics URI * Include type when listing records 0.0.3 ----- * Support loading resources from 3rd party packages. E.g. client extensions * Allow for controllers to be loaded dynamically * Add a command to list the nameservers for a domain * List commands should show a reduced set of columns * Add keyring to pip-requires * Clean error message display :) * Cleanup optional and obsolete CLI params * Rename OS\_SERVICE\_ENDPOINT env var to OS\_DNS\_ENDPOINT * Sync JSONSchemas * Rename OS\_SERVICE\_TYPE env var to OS\_DNS\_SERVICE\_TYPE 0.0.2 ----- * Sync JSONSchemas * Have tox.ini actually run nosetests * Pin to jsonschema less than 1.0 * Add support for administrative access (via X-Moniker-Sudo-Tenant-ID header) * Ensure resources and tools/\* are included in sdist * Add diagnostics to Python API and CLI 0.0.1 ----- * Bump JSONSchema version to 0.8, tracking the server component * Attempt to support both cliff 1.2 and 1.3 * Re-add version.py * Sync with Oslo 30a50c8a * Sync Schemas * Add support for supplying custom service type * Fixup MANIFEST.in * Ensure we supply Oslo Version with the correct \`python\_package\` name * Sync with oslo a8973c52 * Ensure \`moniker --version\` reports the correct version number * Sync with oslo-incubator ad93e4e3 0.0.1.alpha1 ------------ * Actually use the \*correct\* version of requests * Depend on and update for requests>1.0 (Matching {keystone,cinder,nova}client) * Depend on cliff>=1.2.1 * Support record priority in the CLI * Support CLI updating of domains/records/servers * Ensure Update Records and Servers works correctly in the Python API * Sync JSON-Schemas * Provide a sane error message when --os-auth-url or --os-endpoint have not been supplied * Handle HTTP 400 errors somewhat more sanely * Ensure Warlock passes the approperiate error message along with it's exceptions * Include setup-requires in tox.ini * Positionals don't need require=Bool * Sync with Oslo e6c576d9 * Remove unused code * Ensure Servers CLI args are defined correctly * Sync Server JSONSchema * Fixup pyflakes issue * Add Records and Servers CLI commands * Add ID as a positional argument to GetCommand * More helpers in the base Controller * Fix actual != expected row count for items * Initial Python client bindings and CLI * Initial Domain/Record/Server model skeletons * Sync tox.ini with moniker repo * Add PyFlakes tox env * Add JSONSchemas * Sync with OS-Common 3d6c2368 + Use OS-C's Version Module * Rename package to python-monikerclient * Add pypi trove classifiers * Cache pip downloads on Jenkins * Fixup tox.ini for Stackforge+Gerrit * Exit with the correct return code * Initial Commit - CLI Skeleton python-designateclient-2.9.0/python-designateclient.sublime-project0000666000175100017510000000136213232475203025743 0ustar zuulzuul00000000000000{ "folders": [ { "file_exclude_patterns": [ "*.pyc", "*.pyo", "*.exe", "*.dll", "*.obj", "*.o", "*.a", "*.lib", "*.so", "*.dylib", "*.ncb", "*.sdf", "*.suo", "*.pdb", "*.idb", ".DS_Store", "*.class", "*.psd", "*.db", ".vagrant", ".noseids" ], "folder_exclude_patterns": [ ".svn", ".git", ".hg", "CVS", "*.egg", "*.egg-info", ".tox", "venv" ], "path": "." } ], "settings": { "default_line_ending": "unix", "detect_indentation": false, "ensure_newline_at_eof_on_save": true, "rulers": [ 79 ], "tab_size": 4, "translate_tabs_to_spaces": true, "trim_trailing_white_space_on_save": true } } python-designateclient-2.9.0/README.rst0000666000175100017510000000325113232475203017722 0ustar zuulzuul00000000000000======================== Team and repository tags ======================== .. image:: https://governance.openstack.org/tc/badges/python-designateclient.svg :target: https://governance.openstack.org/tc/reference/tags/index.html .. Change things from this point on Python bindings to the Designate API ===================================== .. image:: https://img.shields.io/pypi/v/python-designateclient.svg :target: https://pypi.python.org/pypi/python-designateclient/ :alt: Latest Version .. image:: https://img.shields.io/pypi/dm/python-designateclient.svg :target: https://pypi.python.org/pypi/python-designateclient/ :alt: Downloads This is a client library for Designate built on the Designate API. It provides a Python API (the ``designateclient`` module) and a command-line tool (``designate``). Development takes place via the usual OpenStack processes as outlined in the `developer guide `_. The master repository is in `Git `_. See release notes and more at ``_. * License: Apache License, Version 2.0 * `PyPi`_ - package installation * `Online Documentation`_ * `Bugs`_ - issue tracking * `Source`_ * `How to Contribute`_ .. _PyPi: https://pypi.python.org/pypi/python-designateclient .. _Online Documentation: https://docs.openstack.org/python-designateclient/latest/ .. _Bugs: https://bugs.launchpad.net/python-designateclient .. _Source: https://git.openstack.org/cgit/openstack/python-designateclient .. _How to Contribute: https://docs.openstack.org/infra/manual/developers.html python-designateclient-2.9.0/LICENSE0000666000175100017510000002363713232475203017252 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. python-designateclient-2.9.0/.testr.conf0000666000175100017510000000070213232475203020317 0ustar zuulzuul00000000000000[DEFAULT] test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \ OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \ OS_LOG_CAPTURE=${OS_LOG_CAPTURE:-1} \ OS_DEBUG=${OS_DEBUG:-1} \ OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-160} \ ${PYTHON:-python} -m subunit.run discover -t ./ ${OS_TEST_PATH:-./designateclient/tests} $LISTOPT $IDOPTION test_id_option=--load-list $IDFILE test_list_option=--list python-designateclient-2.9.0/tox.ini0000666000175100017510000000403713232475203017551 0ustar zuulzuul00000000000000[tox] envlist = py35,py27,flake8 minversion = 2.0 skipsdist = True [testenv] usedevelop = True install_command = pip install {opts} {packages} setenv = VIRTUAL_ENV={envdir} LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=C 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 whitelist_externals = find sh rm commands = find . -type f -name "*.pyc" -delete sh tools/pretty_tox.sh '{posargs}' passenv = http_proxy HTTP_PROXY https_proxy HTTPS_PROXY no_proxy NO_PROXY [testenv:docs] 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 -b html doc/source doc/build/html [testenv:flake8] commands = flake8 [testenv:pep8] commands = flake8 [testenv:pyflakes] commands = flake8 [testenv:cover] commands = python setup.py testr --coverage --testr-args='{posargs}' [testenv:venv] commands = {posargs} [testenv:functional] usedevelop = False setenv = {[testenv]setenv} OS_TEST_PATH=designateclient/functionaltests/ passenv = OS_STDOUT_CAPTURE OS_STDERR_CAPTURE OS_LOG_CAPTURE OS_DEBUG TEMPEST_CONFIG [testenv:releasenotes] commands = sphinx-build -a -E -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html [flake8] # ignored flake8 codes: # H302 import only modules # H402 one line docstring needs punctuation # H404 multi line docstring should start with a summary # H405 multi line docstring summary not separated with an empty line # H904 Wrap long lines in parentheses instead of a backslash # See designate for other ignored codes that may apply here ignore = H105, H302,H402,H404,H405,H904 builtins = _ exclude = .venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,tools python-designateclient-2.9.0/python_designateclient.egg-info/0000775000175100017510000000000013232475552024474 5ustar zuulzuul00000000000000python-designateclient-2.9.0/python_designateclient.egg-info/not-zip-safe0000664000175100017510000000000113232475532026720 0ustar zuulzuul00000000000000 python-designateclient-2.9.0/python_designateclient.egg-info/PKG-INFO0000664000175100017510000000560313232475551025574 0ustar zuulzuul00000000000000Metadata-Version: 1.1 Name: python-designateclient Version: 2.9.0 Summary: OpenStack DNS-as-a-Service - Client Home-page: https://docs.openstack.org/python-designateclient/latest Author: OpenStack Author-email: openstack-dev@lists.openstack.org License: Apache License, Version 2.0 Description-Content-Type: UNKNOWN Description: ======================== Team and repository tags ======================== .. image:: https://governance.openstack.org/tc/badges/python-designateclient.svg :target: https://governance.openstack.org/tc/reference/tags/index.html .. Change things from this point on Python bindings to the Designate API ===================================== .. image:: https://img.shields.io/pypi/v/python-designateclient.svg :target: https://pypi.python.org/pypi/python-designateclient/ :alt: Latest Version .. image:: https://img.shields.io/pypi/dm/python-designateclient.svg :target: https://pypi.python.org/pypi/python-designateclient/ :alt: Downloads This is a client library for Designate built on the Designate API. It provides a Python API (the ``designateclient`` module) and a command-line tool (``designate``). Development takes place via the usual OpenStack processes as outlined in the `developer guide `_. The master repository is in `Git `_. See release notes and more at ``_. * License: Apache License, Version 2.0 * `PyPi`_ - package installation * `Online Documentation`_ * `Bugs`_ - issue tracking * `Source`_ * `How to Contribute`_ .. _PyPi: https://pypi.python.org/pypi/python-designateclient .. _Online Documentation: https://docs.openstack.org/python-designateclient/latest/ .. _Bugs: https://bugs.launchpad.net/python-designateclient .. _Source: https://git.openstack.org/cgit/openstack/python-designateclient .. _How to Contribute: https://docs.openstack.org/infra/manual/developers.html 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 Classifier: Topic :: Internet :: Name Service (DNS) python-designateclient-2.9.0/python_designateclient.egg-info/requires.txt0000664000175100017510000000027413232475551027076 0ustar zuulzuul00000000000000cliff!=2.9.0,>=2.8.0 jsonschema<3.0.0,>=2.6.0 osc-lib>=1.8.0 oslo.utils>=3.33.0 pbr!=2.1.0,>=2.0.0 keystoneauth1>=3.3.0 requests>=2.14.2 six>=1.10.0 stevedore>=1.20.0 debtcollector>=1.2.0 python-designateclient-2.9.0/python_designateclient.egg-info/SOURCES.txt0000664000175100017510000001216713232475552026367 0ustar zuulzuul00000000000000.testr.conf .zuul.yaml AUTHORS CONTRIBUTING.rst ChangeLog LICENSE README.rst python-designateclient.sublime-project requirements.txt setup.cfg setup.py test-requirements.txt tox.ini bin/designate designateclient/__init__.py designateclient/client.py designateclient/exceptions.py designateclient/shell.py designateclient/utils.py designateclient/version.py designateclient/warlock.py designateclient/cli/__init__.py designateclient/cli/base.py designateclient/cli/diagnostics.py designateclient/cli/domains.py designateclient/cli/quotas.py designateclient/cli/records.py designateclient/cli/reports.py designateclient/cli/servers.py designateclient/cli/sync.py designateclient/cli/touch.py designateclient/functionaltests/__init__.py designateclient/functionaltests/base.py designateclient/functionaltests/client.py designateclient/functionaltests/config.py designateclient/functionaltests/datagen.py designateclient/functionaltests/models.py designateclient/functionaltests/v2/__init__.py designateclient/functionaltests/v2/fixtures.py designateclient/functionaltests/v2/test_blacklist.py designateclient/functionaltests/v2/test_recordsets.py designateclient/functionaltests/v2/test_tlds.py designateclient/functionaltests/v2/test_tsigkeys.py designateclient/functionaltests/v2/test_zone.py designateclient/functionaltests/v2/test_zone_export.py designateclient/functionaltests/v2/test_zone_import.py designateclient/functionaltests/v2/test_zone_transfer.py designateclient/osc/__init__.py designateclient/osc/plugin.py designateclient/resources/schemas/v1/domain.json designateclient/resources/schemas/v1/record.json designateclient/resources/schemas/v1/server.json designateclient/tests/__init__.py designateclient/tests/base.py designateclient/tests/test_designateclient.py designateclient/tests/test_exceptions.py designateclient/tests/test_utils.py designateclient/tests/test_v1/__init__.py designateclient/tests/test_v1/test_client.py designateclient/tests/test_v1/test_diagnostics.py designateclient/tests/test_v1/test_domain.py designateclient/tests/test_v1/test_quotas.py designateclient/tests/test_v1/test_records.py designateclient/tests/test_v1/test_reports.py designateclient/tests/test_v1/test_servers.py designateclient/tests/test_v1/test_sync.py designateclient/tests/test_v1/test_touch.py designateclient/tests/v2/__init__.py designateclient/tests/v2/test_blacklists.py designateclient/tests/v2/test_client.py designateclient/tests/v2/test_limits.py designateclient/tests/v2/test_nameservers.py designateclient/tests/v2/test_recordsets.py designateclient/tests/v2/test_reverse.py designateclient/tests/v2/test_service_statuses.py designateclient/tests/v2/test_timeout.py designateclient/tests/v2/test_tlds.py designateclient/tests/v2/test_tsigkeys.py designateclient/tests/v2/test_zones.py designateclient/v1/__init__.py designateclient/v1/diagnostics.py designateclient/v1/domains.py designateclient/v1/quotas.py designateclient/v1/records.py designateclient/v1/reports.py designateclient/v1/servers.py designateclient/v1/sync.py designateclient/v1/touch.py designateclient/v2/__init__.py designateclient/v2/base.py designateclient/v2/blacklists.py designateclient/v2/client.py designateclient/v2/limits.py designateclient/v2/nameservers.py designateclient/v2/pools.py designateclient/v2/quotas.py designateclient/v2/recordsets.py designateclient/v2/reverse.py designateclient/v2/service_statuses.py designateclient/v2/tlds.py designateclient/v2/tsigkeys.py designateclient/v2/utils.py designateclient/v2/zones.py designateclient/v2/cli/__init__.py designateclient/v2/cli/blacklists.py designateclient/v2/cli/common.py designateclient/v2/cli/quotas.py designateclient/v2/cli/recordsets.py designateclient/v2/cli/reverse.py designateclient/v2/cli/service_statuses.py designateclient/v2/cli/tlds.py designateclient/v2/cli/tsigkeys.py designateclient/v2/cli/zones.py doc/requirements.txt doc/examples/recordset_create.py doc/examples/recordset_crud.py doc/examples/zone_create_primary.py doc/examples/zone_create_secondary.py doc/examples/zone_list_nameservers.py doc/examples/zone_list_paging.py doc/source/conf.py doc/source/index.rst doc/source/cli/index.rst doc/source/contributor/contributing.rst doc/source/contributor/functional-tests.rst doc/source/contributor/index.rst doc/source/install/index.rst doc/source/reference/index.rst doc/source/user/bindings.rst doc/source/user/index.rst doc/source/user/shell-examples.rst doc/source/user/shell-v2.rst doc/source/user/shell.rst python_designateclient.egg-info/PKG-INFO python_designateclient.egg-info/SOURCES.txt python_designateclient.egg-info/dependency_links.txt python_designateclient.egg-info/entry_points.txt python_designateclient.egg-info/not-zip-safe python_designateclient.egg-info/pbr.json python_designateclient.egg-info/requires.txt python_designateclient.egg-info/top_level.txt releasenotes/notes/.placeholder releasenotes/notes/quota-commands-7ff037bddae95771.yaml releasenotes/source/conf.py releasenotes/source/index.rst releasenotes/source/newton.rst releasenotes/source/ocata.rst releasenotes/source/pike.rst releasenotes/source/unreleased.rst releasenotes/source/_static/.placeholder releasenotes/source/_templates/.placeholder tools/pretty_tox.shpython-designateclient-2.9.0/python_designateclient.egg-info/dependency_links.txt0000664000175100017510000000000113232475551030541 0ustar zuulzuul00000000000000 python-designateclient-2.9.0/python_designateclient.egg-info/top_level.txt0000664000175100017510000000002013232475551027215 0ustar zuulzuul00000000000000designateclient python-designateclient-2.9.0/python_designateclient.egg-info/entry_points.txt0000664000175100017510000001424013232475551027772 0ustar zuulzuul00000000000000[designateclient.cli] diagnostics-ping = designateclient.cli.diagnostics:PingCommand domain-create = designateclient.cli.domains:CreateDomainCommand domain-delete = designateclient.cli.domains:DeleteDomainCommand domain-get = designateclient.cli.domains:GetDomainCommand domain-list = designateclient.cli.domains:ListDomainsCommand domain-servers-list = designateclient.cli.domains:ListDomainServersCommand domain-update = designateclient.cli.domains:UpdateDomainCommand quota-get = designateclient.cli.quotas:GetQuotaCommand quota-reset = designateclient.cli.quotas:ResetQuotaCommand quota-update = designateclient.cli.quotas:UpdateQuotaCommand record-create = designateclient.cli.records:CreateRecordCommand record-delete = designateclient.cli.records:DeleteRecordCommand record-get = designateclient.cli.records:GetRecordCommand record-list = designateclient.cli.records:ListRecordsCommand record-update = designateclient.cli.records:UpdateRecordCommand report-count-all = designateclient.cli.reports:CountsCommand report-count-domains = designateclient.cli.reports:DomainCountCommand report-count-records = designateclient.cli.reports:RecordCountCommand report-count-tenants = designateclient.cli.reports:TenantCountCommand report-tenant-domains = designateclient.cli.reports:TenantCommand report-tenants-all = designateclient.cli.reports:TenantsCommand server-create = designateclient.cli.servers:CreateServerCommand server-delete = designateclient.cli.servers:DeleteServerCommand server-get = designateclient.cli.servers:GetServerCommand server-list = designateclient.cli.servers:ListServersCommand server-update = designateclient.cli.servers:UpdateServerCommand sync-all = designateclient.cli.sync:SyncAllCommand sync-domain = designateclient.cli.sync:SyncDomainCommand sync-record = designateclient.cli.sync:SyncRecordCommand touch-domain = designateclient.cli.touch:TouchDomainCommand [designateclient.v1.controllers] diagnostics = designateclient.v1.diagnostics:DiagnosticsController domains = designateclient.v1.domains:DomainsController quotas = designateclient.v1.quotas:QuotasController records = designateclient.v1.records:RecordsController reports = designateclient.v1.reports:ReportsController servers = designateclient.v1.servers:ServersController sync = designateclient.v1.sync:SyncController touch = designateclient.v1.touch:TouchController [designateclient.versions] 1 = designateclient.v1:Client 2 = designateclient.v2.client:Client [openstack.cli.extension] dns = designateclient.osc.plugin [openstack.dns.v2] dns_quota_list = designateclient.v2.cli.quotas:ListQuotasCommand dns_quota_reset = designateclient.v2.cli.quotas:ResetQuotasCommand dns_quota_set = designateclient.v2.cli.quotas:SetQuotasCommand dns_service_list = designateclient.v2.cli.service_statuses:ListServiceStatusesCommand dns_service_show = designateclient.v2.cli.service_statuses:ShowServiceStatusCommand ptr_record_list = designateclient.v2.cli.reverse:ListFloatingIPCommand ptr_record_set = designateclient.v2.cli.reverse:SetFloatingIPCommand ptr_record_show = designateclient.v2.cli.reverse:ShowFloatingIPCommand ptr_record_unset = designateclient.v2.cli.reverse:UnsetFloatingIPCommand recordset_create = designateclient.v2.cli.recordsets:CreateRecordSetCommand recordset_delete = designateclient.v2.cli.recordsets:DeleteRecordSetCommand recordset_list = designateclient.v2.cli.recordsets:ListRecordSetsCommand recordset_set = designateclient.v2.cli.recordsets:SetRecordSetCommand recordset_show = designateclient.v2.cli.recordsets:ShowRecordSetCommand tld_create = designateclient.v2.cli.tlds:CreateTLDCommand tld_delete = designateclient.v2.cli.tlds:DeleteTLDCommand tld_list = designateclient.v2.cli.tlds:ListTLDsCommand tld_set = designateclient.v2.cli.tlds:SetTLDCommand tld_show = designateclient.v2.cli.tlds:ShowTLDCommand tsigkey_create = designateclient.v2.cli.tsigkeys:CreateTSIGKeyCommand tsigkey_delete = designateclient.v2.cli.tsigkeys:DeleteTSIGKeyCommand tsigkey_list = designateclient.v2.cli.tsigkeys:ListTSIGKeysCommand tsigkey_set = designateclient.v2.cli.tsigkeys:SetTSIGKeyCommand tsigkey_show = designateclient.v2.cli.tsigkeys:ShowTSIGKeyCommand zone_abandon = designateclient.v2.cli.zones:AbandonZoneCommand zone_axfr = designateclient.v2.cli.zones:AXFRZoneCommand zone_blacklist_create = designateclient.v2.cli.blacklists:CreateBlacklistCommand zone_blacklist_delete = designateclient.v2.cli.blacklists:DeleteBlacklistCommand zone_blacklist_list = designateclient.v2.cli.blacklists:ListBlacklistsCommand zone_blacklist_set = designateclient.v2.cli.blacklists:SetBlacklistCommand zone_blacklist_show = designateclient.v2.cli.blacklists:ShowBlacklistCommand zone_create = designateclient.v2.cli.zones:CreateZoneCommand zone_delete = designateclient.v2.cli.zones:DeleteZoneCommand zone_export_create = designateclient.v2.cli.zones:ExportZoneCommand zone_export_delete = designateclient.v2.cli.zones:DeleteZoneExportCommand zone_export_list = designateclient.v2.cli.zones:ListZoneExportsCommand zone_export_show = designateclient.v2.cli.zones:ShowZoneExportCommand zone_export_showfile = designateclient.v2.cli.zones:ShowZoneExportFileCommand zone_import_create = designateclient.v2.cli.zones:ImportZoneCommand zone_import_delete = designateclient.v2.cli.zones:DeleteZoneImportCommand zone_import_list = designateclient.v2.cli.zones:ListZoneImportsCommand zone_import_show = designateclient.v2.cli.zones:ShowZoneImportCommand zone_list = designateclient.v2.cli.zones:ListZonesCommand zone_set = designateclient.v2.cli.zones:SetZoneCommand zone_show = designateclient.v2.cli.zones:ShowZoneCommand zone_transfer_accept_list = designateclient.v2.cli.zones:ListTransferAcceptsCommand zone_transfer_accept_request = designateclient.v2.cli.zones:AcceptTransferRequestCommand zone_transfer_accept_show = designateclient.v2.cli.zones:ShowTransferAcceptCommand zone_transfer_request_create = designateclient.v2.cli.zones:CreateTransferRequestCommand zone_transfer_request_delete = designateclient.v2.cli.zones:DeleteTransferRequestCommand zone_transfer_request_list = designateclient.v2.cli.zones:ListTransferRequestsCommand zone_transfer_request_set = designateclient.v2.cli.zones:SetTransferRequestCommand zone_transfer_request_show = designateclient.v2.cli.zones:ShowTransferRequestCommand python-designateclient-2.9.0/python_designateclient.egg-info/pbr.json0000664000175100017510000000005613232475551026152 0ustar zuulzuul00000000000000{"git_version": "65cc292", "is_release": true}python-designateclient-2.9.0/setup.cfg0000666000175100017510000001744613232475552020076 0ustar zuulzuul00000000000000[metadata] name = python-designateclient summary = OpenStack DNS-as-a-Service - Client description-file = README.rst license = Apache License, Version 2.0 author = OpenStack author-email = openstack-dev@lists.openstack.org home-page = https://docs.openstack.org/python-designateclient/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 Topic :: Internet :: Name Service (DNS) [global] setup-hooks = pbr.hooks.setup_hook [files] packages = designateclient scripts = bin/designate [entry_points] designateclient.v1.controllers = reports = designateclient.v1.reports:ReportsController diagnostics = designateclient.v1.diagnostics:DiagnosticsController domains = designateclient.v1.domains:DomainsController records = designateclient.v1.records:RecordsController servers = designateclient.v1.servers:ServersController quotas = designateclient.v1.quotas:QuotasController sync = designateclient.v1.sync:SyncController touch = designateclient.v1.touch:TouchController designateclient.cli = domain-list = designateclient.cli.domains:ListDomainsCommand domain-get = designateclient.cli.domains:GetDomainCommand domain-create = designateclient.cli.domains:CreateDomainCommand domain-update = designateclient.cli.domains:UpdateDomainCommand domain-delete = designateclient.cli.domains:DeleteDomainCommand domain-servers-list = designateclient.cli.domains:ListDomainServersCommand record-list = designateclient.cli.records:ListRecordsCommand record-get = designateclient.cli.records:GetRecordCommand record-create = designateclient.cli.records:CreateRecordCommand record-update = designateclient.cli.records:UpdateRecordCommand record-delete = designateclient.cli.records:DeleteRecordCommand server-list = designateclient.cli.servers:ListServersCommand server-get = designateclient.cli.servers:GetServerCommand server-create = designateclient.cli.servers:CreateServerCommand server-update = designateclient.cli.servers:UpdateServerCommand server-delete = designateclient.cli.servers:DeleteServerCommand diagnostics-ping = designateclient.cli.diagnostics:PingCommand sync-all = designateclient.cli.sync:SyncAllCommand sync-domain = designateclient.cli.sync:SyncDomainCommand sync-record = designateclient.cli.sync:SyncRecordCommand touch-domain = designateclient.cli.touch:TouchDomainCommand report-count-all = designateclient.cli.reports:CountsCommand report-count-domains = designateclient.cli.reports:DomainCountCommand report-count-records = designateclient.cli.reports:RecordCountCommand report-count-tenants = designateclient.cli.reports:TenantCountCommand report-tenants-all = designateclient.cli.reports:TenantsCommand report-tenant-domains = designateclient.cli.reports:TenantCommand quota-get = designateclient.cli.quotas:GetQuotaCommand quota-update = designateclient.cli.quotas:UpdateQuotaCommand quota-reset = designateclient.cli.quotas:ResetQuotaCommand designateclient.versions = 1 = designateclient.v1:Client 2 = designateclient.v2.client:Client openstack.cli.extension = dns = designateclient.osc.plugin openstack.dns.v2 = zone_blacklist_create = designateclient.v2.cli.blacklists:CreateBlacklistCommand zone_blacklist_list = designateclient.v2.cli.blacklists:ListBlacklistsCommand zone_blacklist_show = designateclient.v2.cli.blacklists:ShowBlacklistCommand zone_blacklist_set = designateclient.v2.cli.blacklists:SetBlacklistCommand zone_blacklist_delete = designateclient.v2.cli.blacklists:DeleteBlacklistCommand tld_create = designateclient.v2.cli.tlds:CreateTLDCommand tld_list = designateclient.v2.cli.tlds:ListTLDsCommand tld_show = designateclient.v2.cli.tlds:ShowTLDCommand tld_set = designateclient.v2.cli.tlds:SetTLDCommand tld_delete = designateclient.v2.cli.tlds:DeleteTLDCommand zone_create = designateclient.v2.cli.zones:CreateZoneCommand zone_list = designateclient.v2.cli.zones:ListZonesCommand zone_show = designateclient.v2.cli.zones:ShowZoneCommand zone_set = designateclient.v2.cli.zones:SetZoneCommand zone_delete = designateclient.v2.cli.zones:DeleteZoneCommand zone_abandon = designateclient.v2.cli.zones:AbandonZoneCommand zone_axfr = designateclient.v2.cli.zones:AXFRZoneCommand zone_export_create = designateclient.v2.cli.zones:ExportZoneCommand zone_export_list = designateclient.v2.cli.zones:ListZoneExportsCommand zone_export_show = designateclient.v2.cli.zones:ShowZoneExportCommand zone_export_delete = designateclient.v2.cli.zones:DeleteZoneExportCommand zone_export_showfile = designateclient.v2.cli.zones:ShowZoneExportFileCommand zone_import_create = designateclient.v2.cli.zones:ImportZoneCommand zone_import_list = designateclient.v2.cli.zones:ListZoneImportsCommand zone_import_show = designateclient.v2.cli.zones:ShowZoneImportCommand zone_import_delete = designateclient.v2.cli.zones:DeleteZoneImportCommand zone_transfer_request_create = designateclient.v2.cli.zones:CreateTransferRequestCommand zone_transfer_request_list = designateclient.v2.cli.zones:ListTransferRequestsCommand zone_transfer_request_show = designateclient.v2.cli.zones:ShowTransferRequestCommand zone_transfer_request_set = designateclient.v2.cli.zones:SetTransferRequestCommand zone_transfer_request_delete = designateclient.v2.cli.zones:DeleteTransferRequestCommand zone_transfer_accept_request = designateclient.v2.cli.zones:AcceptTransferRequestCommand zone_transfer_accept_list = designateclient.v2.cli.zones:ListTransferAcceptsCommand zone_transfer_accept_show = designateclient.v2.cli.zones:ShowTransferAcceptCommand recordset_create = designateclient.v2.cli.recordsets:CreateRecordSetCommand recordset_list = designateclient.v2.cli.recordsets:ListRecordSetsCommand recordset_show = designateclient.v2.cli.recordsets:ShowRecordSetCommand recordset_set = designateclient.v2.cli.recordsets:SetRecordSetCommand recordset_delete = designateclient.v2.cli.recordsets:DeleteRecordSetCommand ptr_record_list = designateclient.v2.cli.reverse:ListFloatingIPCommand ptr_record_show = designateclient.v2.cli.reverse:ShowFloatingIPCommand ptr_record_set = designateclient.v2.cli.reverse:SetFloatingIPCommand ptr_record_unset = designateclient.v2.cli.reverse:UnsetFloatingIPCommand dns_service_list = designateclient.v2.cli.service_statuses:ListServiceStatusesCommand dns_service_show = designateclient.v2.cli.service_statuses:ShowServiceStatusCommand dns_quota_list = designateclient.v2.cli.quotas:ListQuotasCommand dns_quota_set = designateclient.v2.cli.quotas:SetQuotasCommand dns_quota_reset = designateclient.v2.cli.quotas:ResetQuotasCommand tsigkey_create = designateclient.v2.cli.tsigkeys:CreateTSIGKeyCommand tsigkey_list = designateclient.v2.cli.tsigkeys:ListTSIGKeysCommand tsigkey_show = designateclient.v2.cli.tsigkeys:ShowTSIGKeyCommand tsigkey_set = designateclient.v2.cli.tsigkeys:SetTSIGKeyCommand tsigkey_delete = designateclient.v2.cli.tsigkeys:DeleteTSIGKeyCommand [build_sphinx] builders = html,man all-files = 1 warning-is-error = 1 build-dir = doc/build source-dir = doc/source [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 [compile_catalog] directory = designateclient/locale domain = designateclient [update_catalog] domain = designateclient output_dir = designateclient/locale input_file = designateclient/locale/designateclient.pot [extract_messages] keywords = _ gettext ngettext l_ lazy_gettext mapping_file = babel.cfg output_file = designateclient/locale/designateclient.pot [wheel] universal = 1 [pbr] autodoc_index_modules = True api_doc_dir = reference/api autodoc_exclude_modules = designateclient.tests.* designateclient.functionaltests.* python-designateclient-2.9.0/setup.py0000666000175100017510000000200613232475203017742 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) python-designateclient-2.9.0/requirements.txt0000666000175100017510000000100213232475203021507 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. cliff!=2.9.0,>=2.8.0 # Apache-2.0 jsonschema<3.0.0,>=2.6.0 # MIT osc-lib>=1.8.0 # Apache-2.0 oslo.utils>=3.33.0 # Apache-2.0 pbr!=2.1.0,>=2.0.0 # Apache-2.0 keystoneauth1>=3.3.0 # Apache-2.0 requests>=2.14.2 # Apache-2.0 six>=1.10.0 # MIT stevedore>=1.20.0 # Apache-2.0 debtcollector>=1.2.0 # Apache-2.0 python-designateclient-2.9.0/designateclient/0000775000175100017510000000000013232475552021401 5ustar zuulzuul00000000000000python-designateclient-2.9.0/designateclient/version.py0000666000175100017510000000130713232475203023434 0ustar zuulzuul00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import pbr.version version_info = pbr.version.VersionInfo('python-designateclient') python-designateclient-2.9.0/designateclient/utils.py0000666000175100017510000001442313232475203023112 0ustar zuulzuul00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # 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 uuid from debtcollector import removals from keystoneauth1 import adapter from keystoneauth1.identity import generic from keystoneauth1 import session as ks_session from keystoneauth1 import token_endpoint import pkg_resources import six from designateclient import exceptions def resource_string(*args, **kwargs): if len(args) == 0: raise ValueError() package = kwargs.pop('package', None) if not package: package = 'designateclient' resource_path = os.path.join('resources', *args) if not pkg_resources.resource_exists(package, resource_path): raise exceptions.ResourceNotFound('Could not find the requested ' 'resource: %s' % resource_path) return pkg_resources.resource_string(package, resource_path) def load_schema(version, name, package=None): schema_string = resource_string('schemas', version, '%s.json' % name, package=package) return json.loads(schema_string.decode('utf-8')) def get_item_properties(item, fields, mixed_case_fields=[], formatters={}): """Return a tuple containing the item properties. :param item: a single item resource (e.g. Server, Tenant, etc) :param fields: tuple of strings with the desired field names :param mixed_case_fields: tuple of field names to preserve case :param formatters: dictionary mapping field names to callables to format the values """ row = [] for field in fields: if field in formatters: row.append(formatters[field](item)) else: if field in mixed_case_fields: field_name = field.replace(' ', '_') else: field_name = field.lower().replace(' ', '_') if not hasattr(item, field_name) and \ (isinstance(item, dict) and field_name in item): data = item[field_name] else: data = getattr(item, field_name, '') if data is None: data = '' row.append(data) return tuple(row) def get_columns(data): """ Some row's might have variable count of columns, ensure that we have the same. :param data: Results in [{}, {]}] """ columns = set() def _seen(col): columns.add(str(col)) six.moves.map(lambda item: six.moves.map(_seen, list(six.iterkeys(item))), data) return list(columns) @removals.removed_kwarg('all_tenants', removal_version='1.3.0') @removals.removed_kwarg('edit_managed', removal_version='1.3.0') def get_session(auth_url, endpoint, domain_id, domain_name, project_id, project_name, project_domain_name, project_domain_id, username, user_id, password, user_domain_id, user_domain_name, token, insecure, cacert, all_tenants=False, edit_managed=False): # NOTE: all_tenants and edit_managed are here for backwards compat # reasons, do not add additional modifiers here. session = ks_session.Session() # Build + Attach Authentication Plugin auth_args = { 'auth_url': auth_url, 'domain_id': domain_id, 'domain_name': domain_name, 'project_id': project_id, 'project_name': project_name, 'project_domain_name': project_domain_name, 'project_domain_id': project_domain_id, } if token and endpoint: session.auth = token_endpoint.Token(endpoint, token) elif token: auth_args.update({ 'token': token }) session.auth = generic.Token(**auth_args) else: auth_args.update({ 'username': username, 'user_id': user_id, 'password': password, 'user_domain_id': user_domain_id, 'user_domain_name': user_domain_name, }) session.auth = generic.Password(**auth_args) # SSL/TLS Server Cert Verification if insecure is True: session.verify = False else: session.verify = cacert # NOTE: all_tenants and edit_managed are here for backwards compat # reasons, do not add additional modifiers here. session.all_tenants = all_tenants session.edit_managed = edit_managed return session def find_resourceid_by_name_or_id(resource_client, name_or_id): """Find resource id from its id or name.""" try: # Try to return an uuid return str(uuid.UUID(name_or_id)) except ValueError: # Not an uuid => assume it is resource name pass resources = resource_client.list() candidate_ids = [r['id'] for r in resources if r.get('name') == name_or_id] if not candidate_ids: raise exceptions.ResourceNotFound( 'Could not find resource with name "%s"' % name_or_id) elif len(candidate_ids) > 1: str_ids = ','.join(candidate_ids) raise exceptions.NoUniqueMatch( 'Multiple resources with name "%s": %s' % (name_or_id, str_ids)) return candidate_ids[0] class AdapterWithTimeout(adapter.Adapter): """adapter.Adapter wraps around a Session. The user can pass a timeout keyword that will apply only to the Designate Client, in order: - timeout keyword passed to ``request()`` - timeout keyword passed to ``AdapterWithTimeout()`` - timeout attribute on keystone session """ def __init__(self, *args, **kw): self.timeout = kw.pop('timeout', None) super(self.__class__, self).__init__(*args, **kw) def request(self, *args, **kwargs): if self.timeout is not None: kwargs.setdefault('timeout', self.timeout) return super(AdapterWithTimeout, self).request(*args, **kwargs) python-designateclient-2.9.0/designateclient/resources/0000775000175100017510000000000013232475552023413 5ustar zuulzuul00000000000000python-designateclient-2.9.0/designateclient/resources/schemas/0000775000175100017510000000000013232475552025036 5ustar zuulzuul00000000000000python-designateclient-2.9.0/designateclient/resources/schemas/v1/0000775000175100017510000000000013232475552025364 5ustar zuulzuul00000000000000python-designateclient-2.9.0/designateclient/resources/schemas/v1/record.json0000666000175100017510000001510513232475203027532 0ustar zuulzuul00000000000000{ "id": "record", "$schema": "http://json-schema.org/draft-03/hyper-schema", "title": "record", "description": "Record", "additionalProperties": false, "properties": { "id": { "type": "string", "description": "Record Identifier", "pattern": "^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}$", "readonly": true }, "domain_id": { "type": "string", "description": "Domain Identifier", "pattern": "^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}$", "readonly": true }, "name": { "type": "string", "description": "DNS Record Name", "format": "host-name", "maxLength": 255, "required": true }, "type": { "type": "string", "description": "DNS Record Type", "enum": ["A", "AAAA", "CNAME", "MX", "SRV", "TXT", "SPF", "NS", "PTR", "SSHFP", "SOA"], "required": true }, "data": { "type": "string", "description": "DNS Record Value", "maxLength": 255, "required": true }, "priority": { "type": ["integer", "null"], "description": "DNS Record Priority", "minimum": 0, "maximum": 65535 }, "ttl": { "type": ["integer", "null"], "description": "Time to live", "minimum": 1, "maximum": 2147483647 }, "description": { "type": ["string", "null"], "description": "Description for the record", "maxLength": 160 }, "created_at": { "type": "string", "description": "Date and time of record creation", "format": "date-time", "readonly": true }, "updated_at": { "type": ["string", "null"], "description": "Date and time of last record update", "format": "date-time", "readonly": true } }, "oneOf": [{ "description": "An A Record", "properties": { "type": { "type": "string", "enum": ["A"] }, "data": { "format": "ip-address", "required": true }, "priority": { "type": "null" } } }, { "description": "An AAAA Record", "properties": { "type": { "type": "string", "enum": ["AAAA"] }, "data": { "format": "ipv6", "required": true }, "priority": { "type": "null" } } }, { "description": "A CNAME Record", "properties": { "type": { "type": "string", "enum": ["CNAME"] }, "data": { "format": "host-name", "required": true }, "priority": { "type": "null" } } }, { "description": "A MX Record", "properties": { "type": { "type": "string", "enum": ["MX"] }, "data": { "format": "host-name", "required": true }, "priority": { "type": "integer", "required": true } } }, { "description": "A SRV Record", "properties": { "type": { "type": "string", "enum": ["SRV"] }, "name": { "type": "string", "pattern": "^(?:_[A-Za-z0-9_\\-]{1,62}\\.){2}" }, "data": { "type": "string", "pattern": "^(?:(?:6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|[1-5][0-9]{4}|[1-9][0-9]{1,3}|[0-9])\\s){2}(?!.{255,})((?!\\-)[A-Za-z0-9_\\-]{1,63}(? # # 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 designateclient import client class ReportsController(client.Controller): def count_all(self): """ Domain, Records and tenant total count """ response = self.client.get('/reports/counts') return response.json() def count_domains(self): """ Domain total count """ response = self.client.get('/reports/counts/domains') return response.json() def count_tenants(self): """ Tenant total count """ response = self.client.get('/reports/counts/tenants') return response.json() def count_records(self): """ Record total count """ response = self.client.get('/reports/counts/records') return response.json() def tenants_all(self): """ Per tenant count """ response = self.client.get('/reports/tenants') return response.json()['tenants'] def tenant_domains(self, other_tenant_id): """ Tenant's domain count """ response = self.client.get('/reports/tenants/%s' % other_tenant_id) return [{'domain': d} for d in response.json()['domains']] python-designateclient-2.9.0/designateclient/v1/quotas.py0000666000175100017510000000234213232475203023611 0ustar zuulzuul00000000000000# Copyright 2014 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 from designateclient import client class QuotasController(client.Controller): def get(self, tenant_id): """ Ping a service on a given host """ response = self.client.get('/quotas/%s' % tenant_id) return response.json() def update(self, tenant_id, values): response = self.client.put('/quotas/%s' % tenant_id, data=json.dumps(values)) return response.json() def reset(self, tenant_id): response = self.client.delete('/quotas/%s' % tenant_id) return response python-designateclient-2.9.0/designateclient/v1/domains.py0000666000175100017510000000522113232475203023726 0ustar zuulzuul00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # 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 from designateclient import client from designateclient import utils from designateclient import warlock Domain = warlock.model_factory(utils.load_schema('v1', 'domain')) Server = warlock.model_factory(utils.load_schema('v1', 'server')) class DomainsController(client.CrudController): def list(self): """ Retrieve a list of domains :returns: A list of :class:`Domain` """ response = self.client.get('/domains') return [Domain(i) for i in response.json()['domains']] def get(self, domain_id): """ Retrieve a domain :param domain_id: Domain Identifier :returns: :class:`Domain` """ response = self.client.get('/domains/%s' % domain_id) return Domain(response.json()) def create(self, domain): """ Create a domain :param domain: A :class:`Domain` to create :returns: :class:`Domain` """ response = self.client.post('/domains', data=json.dumps(domain)) return Domain(response.json()) def update(self, domain): """ Update a domain :param domain: A :class:`Domain` to update :returns: :class:`Domain` """ response = self.client.put('/domains/%s' % domain.id, data=json.dumps(domain.changes)) return Domain(response.json()) def delete(self, domain): """ Delete a domain :param domain: A :class:`Domain`, or Domain Identifier to delete """ if isinstance(domain, Domain): self.client.delete('/domains/%s' % domain.id) else: self.client.delete('/domains/%s' % domain) def list_domain_servers(self, domain_id): """ Retrieve the list of nameservers for a domain :param domain_id: Domain Identifier :returns: A list of :class:`Server` """ response = self.client.get('/domains/%s/servers' % domain_id) return [Server(i) for i in response.json()['servers']] python-designateclient-2.9.0/designateclient/v1/servers.py0000666000175100017510000000436413232475203023774 0ustar zuulzuul00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # 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 from designateclient import client from designateclient import utils from designateclient import warlock Server = warlock.model_factory(utils.load_schema('v1', 'server')) class ServersController(client.CrudController): def list(self): """ Retrieve a list of servers :returns: A list of :class:`Server` """ response = self.client.get('/servers') return [Server(i) for i in response.json()['servers']] def get(self, server_id): """ Retrieve a server :param server_id: Server Identifier :returns: :class:`Server` """ response = self.client.get('/servers/%s' % server_id) return Server(response.json()) def create(self, server): """ Create a server :param server: A :class:`Server` to create :returns: :class:`Server` """ response = self.client.post('/servers', data=json.dumps(server)) return Server(response.json()) def update(self, server): """ Update a server :param server: A :class:`Server` to update :returns: :class:`Server` """ response = self.client.put('/servers/%s' % server.id, data=json.dumps(server.changes)) return Server(response.json()) def delete(self, server): """ Delete a server :param server: A :class:`Server`, or Server Identifier to delete """ if isinstance(server, Server): self.client.delete('/servers/%s' % server.id) else: self.client.delete('/servers/%s' % server) python-designateclient-2.9.0/designateclient/v1/diagnostics.py0000666000175100017510000000167413232475203024613 0ustar zuulzuul00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # 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 designateclient import client class DiagnosticsController(client.Controller): def ping(self, service, host): """ Ping a service on a given host """ response = self.client.get('/diagnostics/ping/%s/%s' % (service, host)) return response.json() python-designateclient-2.9.0/designateclient/v1/touch.py0000666000175100017510000000155113232475203023420 0ustar zuulzuul00000000000000# Copyright 2013 Hewlett-Packard Development Company, L.P. # # Author: Kiall Mac Innes # # 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 designateclient import client class TouchController(client.Controller): def domain(self, domain_id): """ Touch a single Domain """ self.client.post('/domains/%s/touch' % domain_id) python-designateclient-2.9.0/designateclient/v1/records.py0000666000175100017510000000666013232475203023745 0ustar zuulzuul00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # 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 from designateclient import client from designateclient import utils from designateclient.v1.domains import Domain from designateclient import warlock Record = warlock.model_factory(utils.load_schema('v1', 'record')) class RecordsController(client.CrudController): def list(self, domain): """ Retrieve a list of records :param domain: :class:`Domain` or Domain Identifier :returns: A list of :class:`Record` """ domain_id = domain.id if isinstance(domain, Domain) else domain response = self.client.get('/domains/%(domain_id)s/records' % { 'domain_id': domain_id }) return [Record(i) for i in response.json()['records']] def get(self, domain, record_id): """ Retrieve a record :param domain: :class:`Domain` or Domain Identifier :param record_id: Record Identifier :returns: :class:`Record` """ domain_id = domain.id if isinstance(domain, Domain) else domain uri = '/domains/%(domain_id)s/records/%(record_id)s' % { 'domain_id': domain_id, 'record_id': record_id } response = self.client.get(uri) return Record(response.json()) def create(self, domain, record): """ Create a record :param domain: :class:`Domain` or Domain Identifier :param record: A :class:`Record` to create :returns: :class:`Record` """ domain_id = domain.id if isinstance(domain, Domain) else domain uri = '/domains/%(domain_id)s/records' % { 'domain_id': domain_id } response = self.client.post(uri, data=json.dumps(record)) return Record(response.json()) def update(self, domain, record): """ Update a record :param domain: :class:`Domain` or Domain Identifier :param record: A :class:`Record` to update :returns: :class:`Record` """ domain_id = domain.id if isinstance(domain, Domain) else domain uri = '/domains/%(domain_id)s/records/%(record_id)s' % { 'domain_id': domain_id, 'record_id': record.id } response = self.client.put(uri, data=json.dumps(record.changes)) return Record(response.json()) def delete(self, domain, record): """ Delete a record :param domain: :class:`Domain` or Domain Identifier :param record: A :class:`Record`, or Record Identifier to delete """ domain_id = domain.id if isinstance(domain, Domain) else domain record_id = record.id if isinstance(record, Record) else record uri = '/domains/%(domain_id)s/records/%(record_id)s' % { 'domain_id': domain_id, 'record_id': record_id } self.client.delete(uri) python-designateclient-2.9.0/designateclient/v1/sync.py0000666000175100017510000000222413232475203023250 0ustar zuulzuul00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # 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 designateclient import client class SyncController(client.Controller): def sync_all(self): """ Sync Everything """ self.client.post('/domains/sync') def sync_domain(self, domain_id): """ Sync Single Domain """ self.client.post('/domains/%s/sync' % domain_id) def sync_record(self, domain_id, record_id): """ Sync Single Record """ self.client.post('/domains/%s/records/%s/sync' % (domain_id, record_id)) python-designateclient-2.9.0/designateclient/v1/__init__.py0000666000175100017510000001376313232475203024045 0ustar zuulzuul00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # 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 debtcollector import removals from stevedore import extension from designateclient import exceptions from designateclient import utils from designateclient import version @removals.removed_class( 'designateclient.v1.Client', replacement='designateclient.v2.client.Client', message='Designate v1 API is being retired, and the v1 Client class will ' 'stop functioning. Please update code to the ' 'designateclient.v2.client.Client class. The API is deprecated', version='2.2.0', removal_version='?', stacklevel=3) class Client(object): """Client for the Designate v1 API""" def __init__(self, endpoint=None, username=None, user_id=None, user_domain_id=None, user_domain_name=None, password=None, tenant_name=None, tenant_id=None, domain_name=None, domain_id=None, project_name=None, project_id=None, project_domain_name=None, project_domain_id=None, auth_url=None, token=None, endpoint_type='publicURL', region_name=None, service_type='dns', insecure=False, session=None, cacert=None, all_tenants=None, edit_managed=None, timeout=None): """ :param endpoint: Endpoint URL :param token: A token instead of username / password :param insecure: Allow "insecure" HTTPS requests """ if endpoint: endpoint = endpoint.rstrip('/') if not endpoint.endswith('v1'): endpoint = "%s/v1" % endpoint # Compatibility code to mimic the old behaviour of the client if session is None: session = utils.get_session( auth_url=auth_url, endpoint=endpoint, domain_id=domain_id, domain_name=domain_name, project_id=project_id or tenant_id, project_name=project_name or tenant_name, project_domain_name=project_domain_name, project_domain_id=project_domain_id, username=username, user_id=user_id, password=password, user_domain_id=user_domain_id, user_domain_name=user_domain_name, token=token, insecure=insecure, cacert=cacert, ) # NOTE: all_tenants and edit_managed are pulled from the session for # backwards compat reasons, do not pull additional modifiers from # here. Once removed, the kwargs above should default to False. if all_tenants is None: self.all_tenants = getattr(session, 'all_tenants', False) else: self.all_tenants = all_tenants if edit_managed is None: self.edit_managed = getattr(session, 'edit_managed', False) else: self.edit_managed = edit_managed # Since we have to behave nicely like a legacy client/bindings we use # an adapter around the session to not modify it's state. interface = endpoint_type.rstrip('URL') self.session = utils.AdapterWithTimeout( session, auth=session.auth, endpoint_override=endpoint, region_name=region_name, service_type=service_type, interface=interface, user_agent='python-designateclient-%s' % version.version_info, version='1', timeout=timeout, ) def _load_controller(ext): controller = ext.plugin(client=self) setattr(self, ext.name, controller) # Load all controllers mgr = extension.ExtensionManager('designateclient.v1.controllers') mgr.map(_load_controller) def wrap_api_call(self, func, *args, **kw): """ Wrap a self. with exception handling :param func: The function to wrap """ kw['raise_exc'] = False kw.setdefault('headers', {}) kw['headers'].setdefault('Content-Type', 'application/json') if self.all_tenants: kw['headers'].update({'X-Auth-All-Projects': 'true'}) if self.edit_managed: kw['headers'].update({'X-Designate-Edit-Managed-Records': 'true'}) # Trigger the request response = func(*args, **kw) # Decode is response, if possible try: response_payload = response.json() except ValueError: response_payload = {} if response.status_code == 400: raise exceptions.BadRequest(**response_payload) elif response.status_code in (401, 403, 413): raise exceptions.Forbidden(**response_payload) elif response.status_code == 404: raise exceptions.NotFound(**response_payload) elif response.status_code == 409: raise exceptions.Conflict(**response_payload) elif response.status_code >= 500: raise exceptions.Unknown(**response_payload) else: return response def get(self, path, **kw): return self.wrap_api_call(self.session.get, path, **kw) def post(self, path, **kw): return self.wrap_api_call(self.session.post, path, **kw) def put(self, path, **kw): return self.wrap_api_call(self.session.put, path, **kw) def delete(self, path, **kw): return self.wrap_api_call(self.session.delete, path, **kw) python-designateclient-2.9.0/designateclient/osc/0000775000175100017510000000000013232475552022165 5ustar zuulzuul00000000000000python-designateclient-2.9.0/designateclient/osc/plugin.py0000666000175100017510000000312013232475203024024 0ustar zuulzuul00000000000000# Copyright 2014 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """OpenStackClient plugin for DNS service.""" from osc_lib import utils as oscutils from designateclient import shell DEFAULT_API_VERSION = '2' API_NAME = 'dns' API_VERSION_OPTION = 'os_dns_api_version' API_VERSIONS = { '2': 'designateclient.v2.client.Client', } def make_client(instance): cls = oscutils.get_client_class( API_NAME, instance._api_version[API_NAME], API_VERSIONS) kwargs = oscutils.build_kwargs_dict('endpoint_type', instance._interface) return cls(session=instance.session, region_name=instance._region_name, **kwargs) def build_option_parser(parser): """Hook to add global options.""" parser.add_argument( '--os-dns-api-version', metavar='', default=shell.env('OS_DNS_API_VERSION', default="2"), help='DNS API version, default=' + DEFAULT_API_VERSION + ' (Env: OS_DNS_API_VERSION)') return parser python-designateclient-2.9.0/designateclient/osc/__init__.py0000666000175100017510000000000013232475203024257 0ustar zuulzuul00000000000000python-designateclient-2.9.0/designateclient/client.py0000666000175100017510000000732513232475203023233 0ustar zuulzuul00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # 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 abc import json import six from six.moves.urllib import parse from stevedore import extension from designateclient import exceptions @six.add_metaclass(abc.ABCMeta) class Controller(object): def __init__(self, client): self.client = client def build_url(self, url, criterion=None, marker=None, limit=None): params = criterion or {} if marker is not None: params['marker'] = marker if limit is not None: params['limit'] = limit q = parse.urlencode(params) if params else '' return '%(url)s%(params)s' % { 'url': url, 'params': '?%s' % q } def _serialize(self, kwargs): headers = kwargs.get('headers') content_type = headers.get('Content-Type') if headers else None if 'data' in kwargs and content_type in {None, 'application/json'}: kwargs['data'] = json.dumps(kwargs['data']) def _post(self, url, response_key=None, **kwargs): self._serialize(kwargs) resp, body = self.client.session.post(url, **kwargs) if response_key is not None: return body[response_key] return body def _get(self, url, response_key=None): resp, body = self.client.session.get(url) if response_key is not None: return body[response_key] return body def _patch(self, url, response_key=None, **kwargs): self._serialize(kwargs) resp, body = self.client.session.patch(url, **kwargs) if response_key is not None: return body[response_key] return body def _put(self, url, response_key=None, **kwargs): self._serialize(kwargs) resp, body = self.client.session.put(url, **kwargs) if response_key is not None: return body[response_key] return body def _delete(self, url, response_key=None, **kwargs): resp, body = self.client.session.delete(url, **kwargs) if response_key is not None: return body[response_key] return body @six.add_metaclass(abc.ABCMeta) class CrudController(Controller): @abc.abstractmethod def list(self, *args, **kw): """ List a resource """ @abc.abstractmethod def get(self, *args, **kw): """ Get a resource """ @abc.abstractmethod def create(self, *args, **kw): """ Create a resource """ @abc.abstractmethod def update(self, *args, **kw): """ Update a resource """ @abc.abstractmethod def delete(self, *args, **kw): """ Delete a resource """ def get_versions(): mgr = extension.ExtensionManager('designateclient.versions') return dict([(ep.name, ep.plugin) for ep in mgr.extensions]) def Client(version, *args, **kwargs): # noqa versions = get_versions() if version not in versions: msg = 'Version %s is not supported, use one of (%s)' % ( version, list(six.iterkeys(versions))) raise exceptions.UnsupportedVersion(msg) return versions[version](*args, **kwargs) python-designateclient-2.9.0/designateclient/exceptions.py0000666000175100017510000000405613232475203024134 0ustar zuulzuul00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. class Base(Exception): def __init__(self, message=None): if not message: message = self.__class__.__name__ super(Base, self).__init__(message) class UnsupportedVersion(Base): pass class ResourceNotFound(Base): pass class NoUniqueMatch(Base): pass class RemoteError(Base): def __init__(self, message=None, code=None, type=None, errors=None, request_id=None, **ignore): err_message = self._get_error_message(message, type, errors) self.message = err_message self.code = code self.type = type self.errors = errors self.request_id = request_id super(RemoteError, self).__init__(err_message) def _get_error_message(self, _message, _type, _errors): # Try to get a useful error msg if 'message' has nothing if not _message: if _errors and 'errors' in _errors: err_msg = list() for err in _errors['errors']: if 'message' in err: err_msg.append(err['message']) _message = '. '.join(err_msg) elif _type: _message = str(_type) return _message class Unknown(RemoteError): pass class BadRequest(RemoteError): pass class Forbidden(RemoteError): pass class Conflict(RemoteError): pass class NotFound(RemoteError): pass class OverQuota(RemoteError): pass python-designateclient-2.9.0/designateclient/v2/0000775000175100017510000000000013232475552021730 5ustar zuulzuul00000000000000python-designateclient-2.9.0/designateclient/v2/nameservers.py0000666000175100017510000000174613232475203024637 0ustar zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 designateclient.v2.base import V2Controller from designateclient.v2 import utils as v2_utils class NameServerController(V2Controller): def list(self, zone): zone = v2_utils.resolve_by_name(self.client.zones.list, zone) url = '/zones/%s/nameservers' % zone return self._get(url, response_key='nameservers') python-designateclient-2.9.0/designateclient/v2/utils.py0000666000175100017510000000455313232475203023444 0ustar zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from oslo_utils import uuidutils from six import iteritems from six import iterkeys from six.moves.urllib.parse import parse_qs from six.moves.urllib.parse import urlparse from designateclient import exceptions def resolve_by_name(func, name, *args): """ Helper to resolve a "name" a'la foo.com to it's ID by using REST api's query support and filtering on name. """ if uuidutils.is_uuid_like(name): return name results = func(criterion={"name": "%s" % name}, *args) length = len(results) if length == 1: return results[0]["id"] elif length == 0: raise exceptions.NotFound("Name %s didn't resolve" % name) else: msg = "Multiple matches found for %s, please use ID instead." % name raise exceptions.NoUniqueMatch(msg) def parse_query_from_url(url): """ Helper to get key bits of data from the "next" url returned from the API on collections :param url: :return: dict """ values = parse_qs(urlparse(url)[4]) return {k: values[k][0] for k in iterkeys(values)} def get_all(function, criterion=None, args=None): """ :param function: Function to be called to get data :param criterion: dict of filters to be applied :param args: arguments to be given to the function :return: DesignateList() """ criterion = criterion or {} args = args or [] data = function(*args, criterion=criterion) returned_data = data while True: if data.next_page: for k, v in iteritems(data.next_link_criterion): criterion[k] = v data = function(*args, criterion=criterion) returned_data.extend(data) else: break return returned_data python-designateclient-2.9.0/designateclient/v2/limits.py0000666000175100017510000000143613232475203023602 0ustar zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 designateclient.v2.base import V2Controller class LimitController(V2Controller): def get(self): return self._get('/limits') python-designateclient-2.9.0/designateclient/v2/reverse.py0000666000175100017510000000305013232475203023746 0ustar zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 designateclient.v2.base import V2Controller class FloatingIPController(V2Controller): def set(self, floatingip_id, ptrdname, description=None, ttl=None): data = { 'ptrdname': ptrdname } if description is not None: data["description"] = description if ttl is not None: data["ttl"] = ttl url = '/reverse/floatingips/%s' % floatingip_id return self._patch(url, data=data) def list(self, criterion=None): url = self.build_url('/reverse/floatingips', criterion) return self._get(url, response_key='floatingips') def get(self, floatingip_id): url = '/reverse/floatingips/%s' % floatingip_id return self._get(url) def unset(self, floatingip_id): data = {"ptrdname": None} url = '/reverse/floatingips/%s' % floatingip_id return self._patch(url, data=data) python-designateclient-2.9.0/designateclient/v2/client.py0000666000175100017510000001304213232475203023553 0ustar zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 keystoneauth1 import adapter from designateclient import exceptions from designateclient.v2.blacklists import BlacklistController from designateclient.v2.limits import LimitController from designateclient.v2.nameservers import NameServerController from designateclient.v2.pools import PoolController from designateclient.v2.quotas import QuotasController from designateclient.v2.recordsets import RecordSetController from designateclient.v2.reverse import FloatingIPController from designateclient.v2.service_statuses import ServiceStatusesController from designateclient.v2.tlds import TLDController from designateclient.v2.tsigkeys import TSIGKeysController from designateclient.v2.zones import ZoneController from designateclient.v2.zones import ZoneExportsController from designateclient.v2.zones import ZoneImportsController from designateclient.v2.zones import ZoneTransfersController from designateclient import version class DesignateAdapter(adapter.LegacyJsonAdapter): """Adapter around LegacyJsonAdapter. The user can pass a timeout keyword that will apply only to the Designate Client, in order: - timeout keyword passed to ``request()`` - timeout attribute on keystone session """ def __init__(self, *args, **kwargs): self.timeout = kwargs.pop('timeout', None) self.all_projects = kwargs.pop('all_projects', False) self.edit_managed = kwargs.pop('edit_managed', False) self.sudo_project_id = kwargs.pop('sudo_project_id', None) super(self.__class__, self).__init__(*args, **kwargs) def request(self, *args, **kwargs): kwargs.setdefault('raise_exc', False) if self.timeout is not None: kwargs.setdefault('timeout', self.timeout) kwargs.setdefault('headers', {}) if self.all_projects: kwargs['headers'].setdefault( 'X-Auth-All-Projects', str(self.all_projects) ) if self.edit_managed: kwargs['headers'].setdefault( 'X-Designate-Edit-Managed-Records', str(self.edit_managed) ) if self.sudo_project_id is not None: kwargs['headers'].setdefault( 'X-Auth-Sudo-Project-ID', self.sudo_project_id ) kwargs['headers'].setdefault( 'Content-Type', 'application/json') response, body = super(self.__class__, self).request(*args, **kwargs) # Decode is response, if possible try: response_payload = response.json() except ValueError: response_payload = {} body = response.text if response.status_code == 400: raise exceptions.BadRequest(**response_payload) elif response.status_code in (401, 403): raise exceptions.Forbidden(**response_payload) elif response.status_code == 404: raise exceptions.NotFound(**response_payload) elif response.status_code == 409: raise exceptions.Conflict(**response_payload) elif response.status_code == 413: raise exceptions.OverQuota(**response_payload) elif response.status_code >= 500: raise exceptions.Unknown(**response_payload) return response, body class Client(object): def __init__(self, region_name=None, endpoint_type='publicURL', extensions=None, service_type='dns', service_name=None, http_log_debug=False, session=None, auth=None, timeout=None, endpoint_override=None, all_projects=False, edit_managed=False, sudo_project_id=None): if session is None: raise ValueError("A session instance is required") self.session = DesignateAdapter( session, auth=auth, region_name=region_name, service_type=service_type, interface=endpoint_type.rstrip('URL'), user_agent='python-designateclient-%s' % version.version_info, version=('2'), endpoint_override=endpoint_override, timeout=timeout, all_projects=all_projects, edit_managed=edit_managed, sudo_project_id=sudo_project_id ) self.blacklists = BlacklistController(self) self.floatingips = FloatingIPController(self) self.limits = LimitController(self) self.nameservers = NameServerController(self) self.recordsets = RecordSetController(self) self.service_statuses = ServiceStatusesController(self) self.tlds = TLDController(self) self.zones = ZoneController(self) self.zone_transfers = ZoneTransfersController(self) self.zone_exports = ZoneExportsController(self) self.zone_imports = ZoneImportsController(self) self.pools = PoolController(self) self.quotas = QuotasController(self) self.tsigkeys = TSIGKeysController(self) python-designateclient-2.9.0/designateclient/v2/recordsets.py0000666000175100017510000000677713232475203024473 0ustar zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from oslo_utils import uuidutils import six from designateclient.v2.base import V2Controller from designateclient.v2 import utils as v2_utils class RecordSetController(V2Controller): def _canonicalize_record_name(self, zone, name): zone_info = None # If we get a zone name we'll need to get the ID of it before POST. if isinstance(zone, six.string_types) and not \ uuidutils.is_uuid_like(zone): zone_info = self.client.zones.get(zone) elif isinstance(zone, dict): zone_info = zone # We where given a name like "www" vs www.i.io., attempt to fix it on # the behalf of the actor. if not name.endswith("."): if not isinstance(zone_info, dict): zone_info = self.client.zones.get(zone) name = "%s.%s" % (name, zone_info["name"]) return name, zone_info def create(self, zone, name, type_, records, description=None, ttl=None): name, zone_info = self._canonicalize_record_name(zone, name) data = { 'name': name, 'type': type_, 'records': records } if ttl is not None: data['ttl'] = ttl if description is not None: data['description'] = description if zone_info is not None: zone_id = zone_info["id"] else: zone_id = zone url = '/zones/%s/recordsets' % zone_id return self._post(url, data=data) def list(self, zone, criterion=None, marker=None, limit=None): zone = v2_utils.resolve_by_name(self.client.zones.list, zone) url = self.build_url( '/zones/%s/recordsets' % zone, criterion, marker, limit) return self._get(url, response_key='recordsets') def list_all_zones(self, criterion=None, marker=None, limit=None): url = self.build_url('/recordsets', criterion, marker, limit) return self._get(url, response_key='recordsets') def get(self, zone, recordset): zone = v2_utils.resolve_by_name(self.client.zones.list, zone) recordset = v2_utils.resolve_by_name(self.list, recordset, zone) url = self.build_url('/zones/%s/recordsets/%s' % ( zone, recordset)) return self._get(url) def update(self, zone, recordset, values): zone = v2_utils.resolve_by_name(self.client.zones.list, zone) recordset = v2_utils.resolve_by_name(self.list, recordset, zone) url = '/zones/%s/recordsets/%s' % (zone, recordset) return self._put(url, data=values) def delete(self, zone, recordset): zone = v2_utils.resolve_by_name(self.client.zones.list, zone) recordset = v2_utils.resolve_by_name(self.list, recordset, zone) url = '/zones/%s/recordsets/%s' % (zone, recordset) return self._delete(url) python-designateclient-2.9.0/designateclient/v2/tsigkeys.py0000666000175100017510000000326313232475203024143 0ustar zuulzuul00000000000000# Copyright 2017 SAP SE # # Author: Rudolf Vriend # # 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 designateclient.v2.base import V2Controller from designateclient.v2 import utils as v2_utils class TSIGKeysController(V2Controller): def create(self, name, algorithm, secret, scope, resource_id): data = { 'name': name, 'algorithm': algorithm, 'secret': secret, 'scope': scope, 'resource_id': resource_id } return self._post('/tsigkeys', data=data) def list(self, criterion=None, marker=None, limit=None): url = self.build_url('/tsigkeys', criterion, marker, limit) return self._get(url, response_key='tsigkeys') def get(self, tsigkey): tsigkey = v2_utils.resolve_by_name(self.list, tsigkey) return self._get('/tsigkeys/%s' % tsigkey) def update(self, tsigkey, values): tsigkey = v2_utils.resolve_by_name(self.list, tsigkey) return self._patch('/tsigkeys/%s' % tsigkey, data=values) def delete(self, tsigkey): tsigkey = v2_utils.resolve_by_name(self.list, tsigkey) return self._delete('/tsigkeys/%s' % tsigkey) python-designateclient-2.9.0/designateclient/v2/quotas.py0000666000175100017510000000200313232475203023604 0ustar zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 designateclient.v2.base import V2Controller class QuotasController(V2Controller): def list(self, project_id): return self._get('/quotas/%s' % project_id) def update(self, project_id, values): return self._patch('/quotas/%s' % project_id, data=values) def reset(self, project_id): return self._delete('/quotas/%s' % project_id) python-designateclient-2.9.0/designateclient/v2/service_statuses.py0000666000175100017510000000207113232475203025670 0ustar zuulzuul00000000000000# Copyright 2016 Hewlett Packard Enterprise Development Company LP # # Author: Endre Karlson # # 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 designateclient.v2 import base class ServiceStatusesController(base.V2Controller): def list(self, criterion=None, marker=None, limit=None): url = self.build_url('/service_statuses', criterion, marker, limit) return self._get(url, response_key="service_statuses") def get(self, service_status_id): url = '/service_statuses/%s' % service_status_id return self._get(url) python-designateclient-2.9.0/designateclient/v2/cli/0000775000175100017510000000000013232475552022477 5ustar zuulzuul00000000000000python-designateclient-2.9.0/designateclient/v2/cli/common.py0000666000175100017510000000427113232475203024340 0ustar zuulzuul00000000000000# Copyright 2016 Hewlett Packard Enterprise Development Company LP # # Author: Graham Hayes # # 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. def add_all_projects_option(parser): parser.add_argument( '--all-projects', default=False, action='store_true', help='Show results from all projects. Default: False' ) def add_edit_managed_option(parser): parser.add_argument( '--edit-managed', default=False, action='store_true', help='Edit resources marked as managed. Default: False' ) def add_sudo_project_id_option(parser): parser.add_argument( '--sudo-project-id', default=None, help='Project ID to impersonate for this command. Default: None' ) def add_all_common_options(parser): add_all_projects_option(parser) add_edit_managed_option(parser) add_sudo_project_id_option(parser) def set_all_projects(client, value): client.session.all_projects = value def set_sudo_project_id(client, value): client.session.sudo_project_id = value def set_edit_managed(client, value): client.session.edit_managed = value def set_all_common_headers(client, parsed_args): if parsed_args.all_projects is not None and \ isinstance(parsed_args.all_projects, bool): set_all_projects(client, parsed_args.all_projects) if parsed_args.edit_managed is not None and \ isinstance(parsed_args.edit_managed, bool): set_edit_managed(client, parsed_args.edit_managed) if parsed_args.sudo_project_id is not None and \ isinstance(parsed_args.sudo_project_id, str): set_sudo_project_id(client, parsed_args.sudo_project_id) python-designateclient-2.9.0/designateclient/v2/cli/reverse.py0000666000175100017510000001077413232475203024530 0ustar zuulzuul00000000000000# Copyright 2014 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 logging from osc_lib.command import command import six from designateclient import utils from designateclient.v2.cli import common from designateclient.v2.utils import get_all LOG = logging.getLogger(__name__) def _format_floatingip(fip): # Remove unneeded fields for display output formatting fip.pop('links', None) class ListFloatingIPCommand(command.Lister): """List floatingip ptr records""" columns = ['id', 'ptrdname', 'description', 'ttl'] def get_parser(self, prog_name): parser = super(ListFloatingIPCommand, self).get_parser(prog_name) common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) cols = self.columns data = get_all(client.floatingips.list) return cols, (utils.get_item_properties(s, cols) for s in data) class ShowFloatingIPCommand(command.ShowOne): """Show floatingip ptr record details""" def get_parser(self, prog_name): parser = super(ShowFloatingIPCommand, self).get_parser(prog_name) parser.add_argument('floatingip_id', help="Floating IP ID in format " "region:floatingip_id") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.floatingips.get(parsed_args.floatingip_id) _format_floatingip(data) return six.moves.zip(*sorted(six.iteritems(data))) class SetFloatingIPCommand(command.ShowOne): """Set floatingip ptr record""" def get_parser(self, prog_name): parser = super(SetFloatingIPCommand, self).get_parser(prog_name) parser.add_argument('floatingip_id', help="Floating IP ID in format " "region:floatingip_id") parser.add_argument('ptrdname', help="PTRD Name") description_group = parser.add_mutually_exclusive_group() description_group.add_argument('--description', help="Description") description_group.add_argument('--no-description', action='store_true') ttl_group = parser.add_mutually_exclusive_group() ttl_group.add_argument('--ttl', type=int, help="TTL") ttl_group.add_argument('--no-ttl', action='store_true') common.add_all_common_options(parser) return parser def take_action(self, parsed_args): data = {} if parsed_args.no_description: data['description'] = None elif parsed_args.description: data['description'] = parsed_args.description if parsed_args.no_ttl: data['ttl'] = None elif parsed_args.ttl: data['ttl'] = parsed_args.ttl client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) fip = client.floatingips.set( parsed_args.floatingip_id, parsed_args.ptrdname, parsed_args.description, parsed_args.ttl) _format_floatingip(fip) return six.moves.zip(*sorted(six.iteritems(fip))) class UnsetFloatingIPCommand(command.Command): """Unset floatingip ptr record""" def get_parser(self, prog_name): parser = super(UnsetFloatingIPCommand, self).get_parser(prog_name) parser.add_argument('floatingip_id', help="Floating IP ID in format " "region:floatingip_id") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) client.floatingips.unset(parsed_args.floatingip_id) LOG.info('FloatingIP PTR %s was unset', parsed_args.floatingip_id) python-designateclient-2.9.0/designateclient/v2/cli/recordsets.py0000666000175100017510000002056213232475203025226 0ustar zuulzuul00000000000000# Copyright 2014 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 logging from osc_lib.command import command import six from designateclient import utils from designateclient.v2.cli import common from designateclient.v2.utils import get_all LOG = logging.getLogger(__name__) def _format_recordset(recordset): # Remove unneeded fields for display output formatting recordset['records'] = "\n".join(recordset['records']) recordset.pop('links', None) return recordset def _has_project_id(data): if len(data) < 1: return False if 'project_id' in data[0]: return True return False class ListRecordSetsCommand(command.Lister): """List recordsets""" columns = ['id', 'name', 'type', 'records', 'status', 'action'] def get_parser(self, prog_name): parser = super(ListRecordSetsCommand, self).get_parser(prog_name) parser.add_argument('--name', help="RecordSet Name", required=False) parser.add_argument('--type', help="RecordSet Type", required=False) parser.add_argument('--data', help="RecordSet Record Data", required=False) parser.add_argument('--ttl', help="Time To Live (Seconds)", required=False) parser.add_argument('--description', help="Description", required=False) parser.add_argument('--status', help="RecordSet Status", required=False) parser.add_argument('--action', help="RecordSet Action", required=False) parser.add_argument('zone_id', help="Zone ID. To list all" " recordsets specify 'all'") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) criterion = {} if parsed_args.type is not None: criterion["type"] = parsed_args.type if parsed_args.name is not None: criterion["name"] = parsed_args.name if parsed_args.data is not None: criterion["data"] = parsed_args.data if parsed_args.ttl is not None: criterion["ttl"] = parsed_args.ttl if parsed_args.description is not None: criterion["description"] = parsed_args.description if parsed_args.status is not None: criterion["status"] = parsed_args.status if parsed_args.action is not None: criterion["action"] = parsed_args.action cols = self.columns if parsed_args.zone_id == 'all': data = get_all(client.recordsets.list_all_zones, criterion=criterion) cols.insert(2, 'zone_name') else: data = get_all(client.recordsets.list, args=[parsed_args.zone_id], criterion=criterion) if client.session.all_projects and _has_project_id(data): cols.insert(1, 'project_id') for i, rs in enumerate(data): data[i] = _format_recordset(rs) return cols, (utils.get_item_properties(s, cols) for s in data) class ShowRecordSetCommand(command.ShowOne): """Show recordset details""" def get_parser(self, prog_name): parser = super(ShowRecordSetCommand, self).get_parser(prog_name) parser.add_argument('zone_id', help="Zone ID") parser.add_argument('id', help="RecordSet ID") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.recordsets.get(parsed_args.zone_id, parsed_args.id) _format_recordset(data) return six.moves.zip(*sorted(six.iteritems(data))) class CreateRecordSetCommand(command.ShowOne): """Create new recordset""" log = logging.getLogger('deprecated') def get_parser(self, prog_name): parser = super(CreateRecordSetCommand, self).get_parser(prog_name) parser.add_argument('zone_id', help="Zone ID") parser.add_argument('name', help="RecordSet Name") req_group = parser.add_mutually_exclusive_group(required=True) req_group.add_argument( '--records', help=argparse.SUPPRESS, nargs='+') req_group.add_argument( '--record', help="RecordSet Record, repeat if necessary", action='append') parser.add_argument('--type', help="RecordSet Type", required=True) parser.add_argument('--ttl', type=int, help="Time To Live (Seconds)") parser.add_argument('--description', help="Description") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) all_records = parsed_args.record or parsed_args.records if parsed_args.records: self.log.warning( "Option --records is deprecated, use --record instead.") data = client.recordsets.create( parsed_args.zone_id, parsed_args.name, parsed_args.type, all_records, description=parsed_args.description, ttl=parsed_args.ttl) _format_recordset(data) return six.moves.zip(*sorted(six.iteritems(data))) class SetRecordSetCommand(command.ShowOne): """Set recordset properties""" def get_parser(self, prog_name): parser = super(SetRecordSetCommand, self).get_parser(prog_name) parser.add_argument('zone_id', help="Zone ID") parser.add_argument('id', help="RecordSet ID") parser.add_argument('--records', help="Records", nargs='+') description_group = parser.add_mutually_exclusive_group() description_group.add_argument('--description', help="Description") description_group.add_argument('--no-description', action='store_true') ttl_group = parser.add_mutually_exclusive_group() ttl_group.add_argument('--ttl', type=int, help="TTL") ttl_group.add_argument('--no-ttl', action='store_true') common.add_all_common_options(parser) return parser def take_action(self, parsed_args): data = {} if parsed_args.no_description: data['description'] = None elif parsed_args.description: data['description'] = parsed_args.description if parsed_args.no_ttl: data['ttl'] = None elif parsed_args.ttl: data['ttl'] = parsed_args.ttl if parsed_args.records: data['records'] = parsed_args.records client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) updated = client.recordsets.update( parsed_args.zone_id, parsed_args.id, data) _format_recordset(updated) return six.moves.zip(*sorted(six.iteritems(updated))) class DeleteRecordSetCommand(command.ShowOne): """Delete recordset""" def get_parser(self, prog_name): parser = super(DeleteRecordSetCommand, self).get_parser(prog_name) parser.add_argument('zone_id', help="Zone ID") parser.add_argument('id', help="RecordSet ID") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.recordsets.delete(parsed_args.zone_id, parsed_args.id) LOG.info('RecordSet %s was deleted', parsed_args.id) _format_recordset(data) return six.moves.zip(*sorted(six.iteritems(data))) python-designateclient-2.9.0/designateclient/v2/cli/tsigkeys.py0000666000175100017510000001306313232475203024711 0ustar zuulzuul00000000000000# Copyright 2017 SAP SE # # Author: Rudolf Vriend # # 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 logging from osc_lib.command import command import six from designateclient import utils from designateclient.v2.cli import common from designateclient.v2.utils import get_all LOG = logging.getLogger(__name__) def _format_tsigkey(tsigkey): # Remove unneeded fields for display output formatting tsigkey.pop('links', None) class ListTSIGKeysCommand(command.Lister): """List tsigkeys""" columns = ['id', 'name', 'algorithm', 'secret', 'scope', 'resource_id'] def get_parser(self, prog_name): parser = super(ListTSIGKeysCommand, self).get_parser(prog_name) parser.add_argument('--name', help="TSIGKey NAME", required=False) parser.add_argument('--algorithm', help="TSIGKey algorithm", required=False) parser.add_argument('--scope', help="TSIGKey scope", required=False) common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) criterion = {} if parsed_args.name is not None: criterion["name"] = parsed_args.name if parsed_args.algorithm is not None: criterion["algorithm"] = parsed_args.algorithm if parsed_args.scope is not None: criterion["scope"] = parsed_args.scope data = get_all(client.tsigkeys.list, criterion) cols = self.columns return cols, (utils.get_item_properties(s, cols) for s in data) class ShowTSIGKeyCommand(command.ShowOne): """Show tsigkey details""" def get_parser(self, prog_name): parser = super(ShowTSIGKeyCommand, self).get_parser(prog_name) parser.add_argument('id', help="TSIGKey ID") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.tsigkeys.get(parsed_args.id) _format_tsigkey(data) return six.moves.zip(*sorted(six.iteritems(data))) class CreateTSIGKeyCommand(command.ShowOne): """Create new tsigkey""" def get_parser(self, prog_name): parser = super(CreateTSIGKeyCommand, self).get_parser(prog_name) parser.add_argument('--name', help="TSIGKey Name", required=True) parser.add_argument('--algorithm', help="TSIGKey algorithm", required=True) parser.add_argument('--secret', help="TSIGKey secret", required=True) parser.add_argument('--scope', help="TSIGKey scope", required=True) parser.add_argument('--resource-id', help="TSIGKey resource_id", required=True) common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.tsigkeys.create(parsed_args.name, parsed_args.algorithm, parsed_args.secret, parsed_args.scope, parsed_args.resource_id) _format_tsigkey(data) return six.moves.zip(*sorted(six.iteritems(data))) class SetTSIGKeyCommand(command.ShowOne): """Set tsigkey properties""" def get_parser(self, prog_name): parser = super(SetTSIGKeyCommand, self).get_parser(prog_name) parser.add_argument('id', help="TSIGKey ID") parser.add_argument('--name', help="TSIGKey Name") parser.add_argument('--algorithm', help="TSIGKey algorithm") parser.add_argument('--secret', help="TSIGKey secret") parser.add_argument('--scope', help="TSIGKey scope") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): data = {} if parsed_args.name: data['name'] = parsed_args.name if parsed_args.algorithm: data['algorithm'] = parsed_args.algorithm if parsed_args.secret: data['secret'] = parsed_args.secret if parsed_args.scope: data['scope'] = parsed_args.scope client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.tsigkeys.update(parsed_args.id, data) _format_tsigkey(data) return six.moves.zip(*sorted(six.iteritems(data))) class DeleteTSIGKeyCommand(command.Command): """Delete tsigkey""" def get_parser(self, prog_name): parser = super(DeleteTSIGKeyCommand, self).get_parser(prog_name) parser.add_argument('id', help="TSIGKey ID") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) client.tsigkeys.delete(parsed_args.id) LOG.info('TSIGKey %s was deleted', parsed_args.id) python-designateclient-2.9.0/designateclient/v2/cli/quotas.py0000666000175100017510000000757313232475203024374 0ustar zuulzuul00000000000000# Copyright 2014 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 itertools import logging from cliff import command from cliff import show import six from designateclient.v2.cli import common LOG = logging.getLogger(__name__) DNS_QUOTAS = { "api_export_size": "api-export-size", "recordset_records": "recordset-records", "zone_records": "zone-records", "zone_recordsets": "zone-recordsets", "zones": "zones" } class ListQuotasCommand(show.ShowOne): """List quotas""" # columns = ['resource', 'hard_limit'] def get_parser(self, prog_name): parser = super(ListQuotasCommand, self).get_parser(prog_name) common.add_all_common_options(parser) parser.add_argument( '--project-id', help="Project ID Default: current project") return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) proj_id = parsed_args.project_id or client.session.get_project_id() if parsed_args.project_id != client.session.get_project_id(): common.set_all_projects(client, True) data = client.quotas.list(proj_id) return six.moves.zip(*sorted(six.iteritems(data))) class SetQuotasCommand(show.ShowOne): """Set blacklist properties""" def _build_options_list(self): return itertools.chain(DNS_QUOTAS.items()) def get_parser(self, prog_name): parser = super(SetQuotasCommand, self).get_parser(prog_name) common.add_all_common_options(parser) parser.add_argument('--project-id', help="Project ID") for k, v in self._build_options_list(): parser.add_argument( '--%s' % v, metavar='<%s>' % v, dest=k, type=int, help='New value for the %s quota' % v, ) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) quotas = {} for k, v in DNS_QUOTAS.items(): value = getattr(parsed_args, k, None) if value is not None: quotas[k] = value proj_id = parsed_args.project_id or client.session.get_project_id() if parsed_args.project_id != client.session.get_project_id(): common.set_all_projects(client, True) updated = client.quotas.update(proj_id, quotas) return six.moves.zip(*sorted(six.iteritems(updated))) class ResetQuotasCommand(command.Command): """Delete blacklist""" def get_parser(self, prog_name): parser = super(ResetQuotasCommand, self).get_parser(prog_name) common.add_all_common_options(parser) parser.add_argument('--project-id', help="Project ID") return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) proj_id = parsed_args.project_id or client.session.get_project_id() if parsed_args.project_id != client.session.get_project_id(): common.set_all_projects(client, True) client.quotas.reset(proj_id) LOG.info('Quota for project %s was reset', parsed_args.project_id) python-designateclient-2.9.0/designateclient/v2/cli/service_statuses.py0000666000175100017510000000570213232475203026443 0ustar zuulzuul00000000000000# Copyright 2016 Hewlett Packard Enterprise Development Company LP # # Author: Endre Karlson # # 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 logging from osc_lib.command import command import six from designateclient import utils from designateclient.v2.cli import common from designateclient.v2 import utils as v2_utils LOG = logging.getLogger(__name__) def _format_status(status): status.pop("links", None) # Remove unneeded fields for display output formatting for k in ("capabilities", "stats"): status[k] = "\n".join(status[k]) if status[k] else "-" return status class ListServiceStatusesCommand(command.Lister): """List service statuses""" columns = ['id', 'hostname', 'service_name', 'status', 'stats', 'capabilities'] def get_parser(self, prog_name): parser = super(ListServiceStatusesCommand, self).get_parser(prog_name) parser.add_argument("--hostname", help="Hostname", required=False) parser.add_argument("--service_name", help="Service Name", required=False) parser.add_argument("--status", help="Status", required=False) common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) cols = self.columns criterion = {} for i in ["hostname", "service_name", "status"]: v = getattr(parsed_args, i) if v is not None: criterion[i] = v data = v2_utils.get_all(client.service_statuses.list, criterion=criterion) for i, s in enumerate(data): data[i] = _format_status(s) return cols, (utils.get_item_properties(s, cols) for s in data) class ShowServiceStatusCommand(command.ShowOne): """Show service status details""" def get_parser(self, prog_name): parser = super(ShowServiceStatusCommand, self).get_parser(prog_name) parser.add_argument('id', help="Service Status ID") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.service_statuses.get(parsed_args.id) _format_status(data) return six.moves.zip(*sorted(six.iteritems(data))) python-designateclient-2.9.0/designateclient/v2/cli/tlds.py0000666000175100017510000001077113232475203024020 0ustar zuulzuul00000000000000# Copyright 2014 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 logging from osc_lib.command import command import six from designateclient import utils from designateclient.v2.cli import common from designateclient.v2.utils import get_all LOG = logging.getLogger(__name__) def _format_tld(tld): # Remove unneeded fields for display output formatting tld.pop('links', None) class ListTLDsCommand(command.Lister): """List tlds""" columns = ['id', 'name', 'description'] def get_parser(self, prog_name): parser = super(ListTLDsCommand, self).get_parser(prog_name) parser.add_argument('--name', help="TLD NAME") parser.add_argument('--description', help="TLD Description") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = get_all(client.tlds.list) cols = self.columns return cols, (utils.get_item_properties(s, cols) for s in data) class ShowTLDCommand(command.ShowOne): """Show tld details""" def get_parser(self, prog_name): parser = super(ShowTLDCommand, self).get_parser(prog_name) parser.add_argument('id', help="TLD ID") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.tlds.get(parsed_args.id) _format_tld(data) return six.moves.zip(*sorted(six.iteritems(data))) class CreateTLDCommand(command.ShowOne): """Create new tld""" def get_parser(self, prog_name): parser = super(CreateTLDCommand, self).get_parser(prog_name) parser.add_argument('--name', help="TLD Name", required=True) parser.add_argument('--description', help="Description") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.tlds.create(parsed_args.name, parsed_args.description) _format_tld(data) return six.moves.zip(*sorted(six.iteritems(data))) class SetTLDCommand(command.ShowOne): """Set tld properties""" def get_parser(self, prog_name): parser = super(SetTLDCommand, self).get_parser(prog_name) parser.add_argument('id', help="TLD ID") parser.add_argument('--name', help="TLD Name") description_group = parser.add_mutually_exclusive_group() description_group.add_argument('--description', help="Description") description_group.add_argument('--no-description', action='store_true') common.add_all_common_options(parser) return parser def take_action(self, parsed_args): data = {} if parsed_args.name: data['name'] = parsed_args.name if parsed_args.no_description: data['description'] = None elif parsed_args.description: data['description'] = parsed_args.description client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.tlds.update(parsed_args.id, data) _format_tld(data) return six.moves.zip(*sorted(six.iteritems(data))) class DeleteTLDCommand(command.Command): """Delete tld""" def get_parser(self, prog_name): parser = super(DeleteTLDCommand, self).get_parser(prog_name) parser.add_argument('id', help="TLD ID") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) client.tlds.delete(parsed_args.id) LOG.info('TLD %s was deleted', parsed_args.id) python-designateclient-2.9.0/designateclient/v2/cli/zones.py0000666000175100017510000005245313232475203024213 0ustar zuulzuul00000000000000# Copyright 2014 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 logging from osc_lib.command import command from osc_lib import exceptions as osc_exc import six from designateclient import utils from designateclient.v2.cli import common from designateclient.v2.utils import get_all LOG = logging.getLogger(__name__) def _format_zone(zone): zone.pop('links', None) zone['masters'] = ", ".join(zone['masters']) attrib = '' for attr in zone['attributes']: attrib += "%s:%s\n" % (attr, zone['attributes'][attr]) zone['attributes'] = attrib def _format_zone_export_record(zone_export_record): zone_export_record.pop('links', None) def _format_zone_import_record(zone_import_record): zone_import_record.pop('links', None) class ListZonesCommand(command.Lister): """List zones""" columns = ['id', 'name', 'type', 'serial', 'status', 'action'] def get_parser(self, prog_name): parser = super(ListZonesCommand, self).get_parser(prog_name) parser.add_argument('--name', help="Zone Name", required=False) parser.add_argument('--email', help="Zone Email", required=False) parser.add_argument('--type', help="Zone Type", required=False) parser.add_argument('--ttl', help="Time To Live (Seconds)", required=False) parser.add_argument('--description', help="Description", required=False) parser.add_argument('--status', help="Zone Status", required=False) common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) common.set_all_common_headers(client, parsed_args) criterion = {} if parsed_args.type is not None: criterion["type"] = parsed_args.type if parsed_args.name is not None: criterion["name"] = parsed_args.name if parsed_args.ttl is not None: criterion["ttl"] = parsed_args.ttl if parsed_args.description is not None: criterion["description"] = parsed_args.description if parsed_args.email is not None: criterion["email"] = parsed_args.email if parsed_args.status is not None: criterion["status"] = parsed_args.status data = get_all(client.zones.list, criterion) cols = self.columns if client.session.all_projects: cols.insert(1, 'project_id') return cols, (utils.get_item_properties(s, cols) for s in data) class ShowZoneCommand(command.ShowOne): """Show zone details""" def get_parser(self, prog_name): parser = super(ShowZoneCommand, self).get_parser(prog_name) parser.add_argument('id', help="Zone ID") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.zones.get(parsed_args.id) _format_zone(data) return six.moves.zip(*sorted(six.iteritems(data))) class CreateZoneCommand(command.ShowOne): """Create new zone""" def get_parser(self, prog_name): parser = super(CreateZoneCommand, self).get_parser(prog_name) parser.add_argument('name', help="Zone Name") parser.add_argument('--email', help="Zone Email") parser.add_argument('--type', help="Zone Type", default='PRIMARY') parser.add_argument('--ttl', type=int, help="Time To Live (Seconds)") parser.add_argument('--description', help="Description") parser.add_argument('--masters', help="Zone Masters", nargs='+') parser.add_argument('--attributes', help="Zone Attributes", nargs='+') common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) payload = {} if parsed_args.description: payload["description"] = parsed_args.description if parsed_args.attributes: payload["attributes"] = {} for attr in parsed_args.attributes: try: k, v = attr.split(':') payload["attributes"][k] = v except ValueError: msg = "Attribute '%s' is in an incorrect format. "\ "Attributes are : formated" raise osc_exc.CommandError(msg % attr) if parsed_args.type == 'PRIMARY': # email is just for PRIMARY. if not parsed_args.email: msg = "Zone type PRIMARY requires --email." raise osc_exc.CommandError(msg) payload["email"] = parsed_args.email # TTL is just valid for PRIMARY if parsed_args.ttl is not None: payload["ttl"] = parsed_args.ttl elif parsed_args.type == 'SECONDARY': payload["masters"] = parsed_args.masters else: msg = "Type %s is not supported. Please choose between " \ "PRIMARY or SECONDARY" raise osc_exc.CommandError(msg % parsed_args.type) data = client.zones.create( parsed_args.name, parsed_args.type, **payload) _format_zone(data) return six.moves.zip(*sorted(six.iteritems(data))) class SetZoneCommand(command.ShowOne): """Set zone properties""" def get_parser(self, prog_name): parser = super(SetZoneCommand, self).get_parser(prog_name) parser.add_argument('id', help="Zone ID") parser.add_argument('--email', help="Zone Email") parser.add_argument('--ttl', type=int, help="Time To Live (Seconds)") description_group = parser.add_mutually_exclusive_group() description_group.add_argument('--description', help="Description") description_group.add_argument('--no-description', action='store_true') parser.add_argument('--masters', help="Zone Masters", nargs='+') common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = {} # TODO(kiall): API needs updating.. this get is silly if parsed_args.email: data['email'] = parsed_args.email if parsed_args.ttl: data['ttl'] = parsed_args.ttl if parsed_args.no_description: data['description'] = None elif parsed_args.description: data['description'] = parsed_args.description if parsed_args.masters: data['masters'] = parsed_args.masters updated = client.zones.update(parsed_args.id, data) _format_zone(updated) return six.moves.zip(*sorted(six.iteritems(updated))) class DeleteZoneCommand(command.ShowOne): """Delete zone""" def get_parser(self, prog_name): parser = super(DeleteZoneCommand, self).get_parser(prog_name) parser.add_argument('id', help="Zone ID") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.zones.delete(parsed_args.id) LOG.info('Zone %s was deleted', parsed_args.id) _format_zone(data) return six.moves.zip(*sorted(six.iteritems(data))) class AbandonZoneCommand(command.Command): """Abandon a zone""" def get_parser(self, prog_name): parser = super(AbandonZoneCommand, self).get_parser(prog_name) parser.add_argument('id', help="Zone ID") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) client.zones.abandon(parsed_args.id) LOG.info("Z %(zone_id)s abandoned", {"zone_id": parsed_args.id}) class AXFRZoneCommand(command.Command): """AXFR a zone""" def get_parser(self, prog_name): parser = super(AXFRZoneCommand, self).get_parser(prog_name) parser.add_argument('id', help="Zone ID") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) client.zones.axfr(parsed_args.id) LOG.info("Scheduled AXFR for zone %(zone_id)s", {"zone_id": parsed_args.id}) class CreateTransferRequestCommand(command.ShowOne): """Create new zone transfer request""" def get_parser(self, prog_name): parser = super(CreateTransferRequestCommand, self).get_parser( prog_name) parser.add_argument('zone_id', help="Zone ID to transfer.",) parser.add_argument( '--target-project-id', help="Target Project ID to transfer to.") parser.add_argument('--description', help="Description") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.zone_transfers.create_request( parsed_args.zone_id, parsed_args.target_project_id, parsed_args.description) return six.moves.zip(*sorted(six.iteritems(data))) class ListTransferRequestsCommand(command.Lister): """List Zone Transfer Requests""" columns = ['id', 'zone_id', 'zone_name', 'project_id', 'target_project_id', 'status', 'key'] def get_parser(self, prog_name): parser = super(ListTransferRequestsCommand, self).get_parser( prog_name) common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.zone_transfers.list_requests() cols = self.columns return cols, (utils.get_item_properties(s, cols) for s in data) class ShowTransferRequestCommand(command.ShowOne): """Show Zone Transfer Request Details""" def get_parser(self, prog_name): parser = super(ShowTransferRequestCommand, self).get_parser(prog_name) parser.add_argument('id', help="Zone Tranfer Request ID") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.zone_transfers.get_request(parsed_args.id) return six.moves.zip(*sorted(six.iteritems(data))) class SetTransferRequestCommand(command.ShowOne): """Set a Zone Transfer Request""" def get_parser(self, prog_name): parser = super(SetTransferRequestCommand, self).get_parser(prog_name) parser.add_argument('id', help="Zone Transfer Request ID") description_group = parser.add_mutually_exclusive_group() description_group.add_argument('--description', help="Description") description_group.add_argument('--no-description', action='store_true') common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = {} if parsed_args.no_description: data['description'] = None elif parsed_args.description: data['description'] = parsed_args.description updated = client.zone_transfers.update_request(parsed_args.id, data) return six.moves.zip(*sorted(six.iteritems(updated))) class DeleteTransferRequestCommand(command.Command): """Delete a Zone Transfer Request""" def get_parser(self, prog_name): parser = super(DeleteTransferRequestCommand, self).get_parser( prog_name) parser.add_argument('id', help="Zone Transfer Request ID") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) client.zone_transfers.delete_request(parsed_args.id) LOG.info('Zone Transfer %s was deleted', parsed_args.id) class AcceptTransferRequestCommand(command.ShowOne): """Accept a Zone Transfer Request""" def get_parser(self, prog_name): parser = super(AcceptTransferRequestCommand, self).get_parser( prog_name) parser.add_argument('--transfer-id', help="Transfer ID", type=str, required=True) parser.add_argument('--key', help="Transfer Key", type=str, required=True) common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.zone_transfers.accept_request( parsed_args.transfer_id, parsed_args.key) return six.moves.zip(*sorted(six.iteritems(data))) class ListTransferAcceptsCommand(command.Lister): """List Zone Transfer Accepts""" columns = ['id', 'zone_id', 'project_id', 'zone_transfer_request_id', 'status', 'key'] def get_parser(self, prog_name): parser = super(ListTransferAcceptsCommand, self).get_parser( prog_name) common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.zone_transfers.list_requests() cols = self.columns return cols, (utils.get_item_properties(s, cols) for s in data) class ShowTransferAcceptCommand(command.ShowOne): """Show Zone Transfer Accept""" def get_parser(self, prog_name): parser = super(ShowTransferAcceptCommand, self).get_parser(prog_name) parser.add_argument('id', help="Zone Tranfer Accept ID") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.zone_transfers.get_accept(parsed_args.id) return six.moves.zip(*sorted(six.iteritems(data))) class ExportZoneCommand(command.ShowOne): """Export a Zone""" def get_parser(self, prog_name): parser = super(ExportZoneCommand, self).get_parser( prog_name) common.add_all_common_options(parser) parser.add_argument('zone_id', help="Zone ID", type=str) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.zone_exports.create(parsed_args.zone_id) _format_zone_export_record(data) LOG.info('Zone Export %s was created', data['id']) return six.moves.zip(*sorted(six.iteritems(data))) class ListZoneExportsCommand(command.Lister): """List Zone Exports""" columns = [ 'id', 'zone_id', 'created_at', 'status', ] def get_parser(self, prog_name): parser = super(ListZoneExportsCommand, self).get_parser( prog_name) common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.zone_exports.list() cols = self.columns return cols, (utils.get_item_properties(s, cols) for s in data['exports']) class ShowZoneExportCommand(command.ShowOne): """Show a Zone Export""" def get_parser(self, prog_name): parser = super(ShowZoneExportCommand, self).get_parser( prog_name) parser.add_argument('zone_export_id', help="Zone Export ID", type=str) common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.zone_exports.get_export_record( parsed_args.zone_export_id) _format_zone_export_record(data) return six.moves.zip(*sorted(six.iteritems(data))) class DeleteZoneExportCommand(command.Command): """Delete a Zone Export""" def get_parser(self, prog_name): parser = super(DeleteZoneExportCommand, self).get_parser( prog_name) parser.add_argument('zone_export_id', help="Zone Export ID", type=str) common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) client.zone_exports.delete(parsed_args.zone_export_id) LOG.info('Zone Export %s was deleted', parsed_args.zone_export_id) class ShowZoneExportFileCommand(command.ShowOne): """Show the zone file for the Zone Export""" def get_parser(self, prog_name): parser = super(ShowZoneExportFileCommand, self).get_parser( prog_name) parser.add_argument('zone_export_id', help="Zone Export ID", type=str) common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.zone_exports.get_export(parsed_args.zone_export_id) return ['data'], [data] class ImportZoneCommand(command.ShowOne): """Import a Zone from a file on the filesystem""" def get_parser(self, prog_name): parser = super(ImportZoneCommand, self).get_parser( prog_name) parser.add_argument('zone_file_path', help="Path to a zone file", type=str) common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) with open(parsed_args.zone_file_path, 'r') as f: zone_file_contents = f.read() data = client.zone_imports.create(zone_file_contents) _format_zone_import_record(data) LOG.info('Zone Import %s was created', data['id']) return six.moves.zip(*sorted(six.iteritems(data))) class ListZoneImportsCommand(command.Lister): """List Zone Imports""" columns = [ 'id', 'zone_id', 'created_at', 'status', 'message', ] def get_parser(self, prog_name): parser = super(ListZoneImportsCommand, self).get_parser( prog_name) common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.zone_imports.list() cols = self.columns return cols, (utils.get_item_properties(s, cols) for s in data['imports']) class ShowZoneImportCommand(command.ShowOne): """Show a Zone Import""" def get_parser(self, prog_name): parser = super(ShowZoneImportCommand, self).get_parser( prog_name) parser.add_argument('zone_import_id', help="Zone Import ID", type=str) common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.zone_imports.get_import_record( parsed_args.zone_import_id) _format_zone_import_record(data) return six.moves.zip(*sorted(six.iteritems(data))) class DeleteZoneImportCommand(command.Command): """Delete a Zone Import""" def get_parser(self, prog_name): parser = super(DeleteZoneImportCommand, self).get_parser( prog_name) parser.add_argument('zone_import_id', help="Zone Import ID", type=str) common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) client.zone_imports.delete(parsed_args.zone_import_id) LOG.info('Zone Import %s was deleted', parsed_args.zone_import_id) python-designateclient-2.9.0/designateclient/v2/cli/blacklists.py0000666000175100017510000001121313232475203025175 0ustar zuulzuul00000000000000# Copyright 2014 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 logging from osc_lib.command import command import six from designateclient import utils from designateclient.v2.cli import common from designateclient.v2.utils import get_all LOG = logging.getLogger(__name__) def _format_blacklist(blacklist): # Remove unneeded fields for display output formatting blacklist.pop('links', None) class ListBlacklistsCommand(command.Lister): """List blacklists""" columns = ['id', 'pattern', 'description'] def get_parser(self, prog_name): parser = super(ListBlacklistsCommand, self).get_parser(prog_name) common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) cols = self.columns data = get_all(client.blacklists.list) return cols, (utils.get_item_properties(s, cols) for s in data) class ShowBlacklistCommand(command.ShowOne): """Show blacklist details""" def get_parser(self, prog_name): parser = super(ShowBlacklistCommand, self).get_parser(prog_name) parser.add_argument('id', help="Blacklist ID") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.blacklists.get(parsed_args.id) _format_blacklist(data) return six.moves.zip(*sorted(six.iteritems(data))) class CreateBlacklistCommand(command.ShowOne): """Create new blacklist""" def get_parser(self, prog_name): parser = super(CreateBlacklistCommand, self).get_parser(prog_name) parser.add_argument('--pattern', help="Blacklist pattern", required=True) parser.add_argument('--description', help="Description") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) data = client.blacklists.create( parsed_args.pattern, parsed_args.description) _format_blacklist(data) return six.moves.zip(*sorted(six.iteritems(data))) class SetBlacklistCommand(command.ShowOne): """Set blacklist properties""" def get_parser(self, prog_name): parser = super(SetBlacklistCommand, self).get_parser(prog_name) parser.add_argument('id', help="Blacklist ID") parser.add_argument('--pattern', help="Blacklist pattern") description_group = parser.add_mutually_exclusive_group() description_group.add_argument('--description', help="Description") description_group.add_argument('--no-description', action='store_true') common.add_all_common_options(parser) return parser def take_action(self, parsed_args): data = {} if parsed_args.pattern: data['pattern'] = parsed_args.pattern if parsed_args.no_description: data['description'] = None elif parsed_args.description: data['description'] = parsed_args.description client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) updated = client.blacklists.update(parsed_args.id, data) _format_blacklist(updated) return six.moves.zip(*sorted(six.iteritems(updated))) class DeleteBlacklistCommand(command.Command): """Delete blacklist""" def get_parser(self, prog_name): parser = super(DeleteBlacklistCommand, self).get_parser(prog_name) parser.add_argument('id', help="Blacklist ID") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.dns common.set_all_common_headers(client, parsed_args) client.blacklists.delete(parsed_args.id) LOG.info('Blacklist %s was deleted', parsed_args.id) python-designateclient-2.9.0/designateclient/v2/cli/__init__.py0000666000175100017510000000000013232475203024571 0ustar zuulzuul00000000000000python-designateclient-2.9.0/designateclient/v2/tlds.py0000666000175100017510000000310113232475203023236 0ustar zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 designateclient.v2.base import V2Controller from designateclient.v2 import utils as v2_utils class TLDController(V2Controller): def create(self, name, description=None): data = { 'name': name, } if description is not None: data["description"] = description return self._post('/tlds', data=data) def list(self, criterion=None, marker=None, limit=None): url = self.build_url('/tlds', criterion, marker, limit) return self._get(url, response_key='tlds') def get(self, tld): tld = v2_utils.resolve_by_name(self.list, tld) return self._get('/tlds/%s' % tld) def update(self, tld, values): tld = v2_utils.resolve_by_name(self.list, tld) return self._patch('/tlds/%s' % tld, data=values) def delete(self, tld): tld = v2_utils.resolve_by_name(self.list, tld) return self._delete('/tlds/%s' % tld) python-designateclient-2.9.0/designateclient/v2/zones.py0000666000175100017510000001217113232475203023435 0ustar zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 designateclient.v2.base import V2Controller from designateclient.v2 import utils as v2_utils class ZoneController(V2Controller): def create(self, name, type_=None, email=None, description=None, ttl=None, masters=None, attributes=None): type_ = type_ or "PRIMARY" data = { "name": name, "type": type_ } if type_ == "PRIMARY": if email: data["email"] = email if ttl is not None: data["ttl"] = ttl elif type_ == "SECONDARY" and masters: data["masters"] = masters if description is not None: data["description"] = description if attributes is not None: data["attributes"] = attributes return self._post('/zones', data=data) def list(self, criterion=None, marker=None, limit=None): url = self.build_url('/zones', criterion, marker, limit) return self._get(url, response_key="zones") def get(self, zone): zone = v2_utils.resolve_by_name(self.list, zone) return self._get('/zones/%s' % zone) def update(self, zone, values): zone = v2_utils.resolve_by_name(self.list, zone) url = self.build_url('/zones/%s' % zone) return self._patch(url, data=values) def delete(self, zone): zone = v2_utils.resolve_by_name(self.list, zone) url = self.build_url('/zones/%s' % zone) return self._delete(url) def abandon(self, zone): zone = v2_utils.resolve_by_name(self.list, zone) url = '/zones/%s/tasks/abandon' % zone self.client.session.post(url) def axfr(self, zone): zone = v2_utils.resolve_by_name(self.list, zone) url = '/zones/%s/tasks/xfr' % zone self.client.session.post(url) class ZoneTransfersController(V2Controller): def create_request(self, zone, target_project_id, description=None): zone = v2_utils.resolve_by_name(self.client.zones.list, zone) data = { "target_project_id": target_project_id } if description is not None: data["description"] = description url = '/zones/%s/tasks/transfer_requests' % zone return self._post(url, data=data) def get_request(self, transfer_id): url = '/zones/tasks/transfer_requests/%s' % transfer_id return self._get(url) def list_requests(self): url = '/zones/tasks/transfer_requests' return self._get(url, response_key="transfer_requests") def update_request(self, transfer_id, values): url = '/zones/tasks/transfer_requests/%s' % transfer_id return self._patch(url, data=values) def delete_request(self, transfer_id): url = '/zones/tasks/transfer_requests/%s' % transfer_id self._delete(url) def accept_request(self, transfer_id, key): url = '/zones/tasks/transfer_accepts' data = { "key": key, "zone_transfer_request_id": transfer_id } return self._post(url, data=data) def get_accept(self, accept_id): url = '/zones/tasks/transfer_accepts/%s' % accept_id return self._get(url) def list_accepts(self): url = '/zones/tasks/transfer_accepts' return self._get(url, response_key="transfer_accepts") class ZoneExportsController(V2Controller): def create(self, zone): zone_id = v2_utils.resolve_by_name(self.client.zones.list, zone) return self._post('/zones/%s/tasks/export' % zone_id) def get_export_record(self, zone_export_id): return self._get('/zones/tasks/exports/%s' % zone_export_id) def list(self): return self._get('/zones/tasks/exports') def delete(self, zone_export_id): return self._delete('/zones/tasks/exports/%s' % zone_export_id) def get_export(self, zone_export_id): return self._get('/zones/tasks/exports/%s/export' % zone_export_id, headers={'Accept': 'text/dns'}) class ZoneImportsController(V2Controller): def create(self, zone_file_contents): return self._post('/zones/tasks/imports', data=zone_file_contents, headers={'Content-Type': 'text/dns'}) def get_import_record(self, zone_import_id): return self._get('/zones/tasks/imports/%s' % zone_import_id) def list(self): return self._get('/zones/tasks/imports') def delete(self, zone_import_id): return self._delete('/zones/tasks/imports/%s' % zone_import_id) python-designateclient-2.9.0/designateclient/v2/blacklists.py0000666000175100017510000000301213232475203024424 0ustar zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 designateclient.v2.base import V2Controller class BlacklistController(V2Controller): def create(self, pattern, description=None): data = { 'pattern': pattern, } if description is not None: data['description'] = description return self._post('/blacklists', data=data) def list(self, criterion=None, marker=None, limit=None): url = self.build_url('/blacklists', criterion, marker, limit) return self._get(url, response_key="blacklists") def get(self, blacklist_id): url = '/blacklists/%s' % blacklist_id return self._get(url) def update(self, blacklist_id, values): url = '/blacklists/%s' % blacklist_id return self._patch(url, data=values) def delete(self, blacklist_id): url = '/blacklists/%s' % blacklist_id return self._delete(url) python-designateclient-2.9.0/designateclient/v2/pools.py0000666000175100017510000000144413232475203023434 0ustar zuulzuul00000000000000# Copyright (c) 2016 Hewlett-Packard Enterprise 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 designateclient.v2.base import V2Controller class PoolController(V2Controller): def list(self): url = '/pools' return self._get(url, response_key='pools') python-designateclient-2.9.0/designateclient/v2/__init__.py0000666000175100017510000000000013232475203024022 0ustar zuulzuul00000000000000python-designateclient-2.9.0/designateclient/v2/base.py0000666000175100017510000000250713232475203023213 0ustar zuulzuul00000000000000# Copyright 2016 Hewlett Packard Enterprise Development Company LP # # Author: Graham Hayes # # 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 designateclient import client from designateclient.v2.utils import parse_query_from_url class DesignateList(list): next_link_criterion = {} next_page = False class V2Controller(client.Controller): def _get(self, url, response_key=None, **kwargs): resp, body = self.client.session.get(url, **kwargs) if response_key is not None: data = DesignateList() data.extend(body[response_key]) if 'next' in body.get('links', {}): data.next_page = True data.next_link_criterion = parse_query_from_url( body['links']['next']) return data return body python-designateclient-2.9.0/designateclient/functionaltests/0000775000175100017510000000000013232475552024626 5ustar zuulzuul00000000000000python-designateclient-2.9.0/designateclient/functionaltests/client.py0000666000175100017510000003712213232475203026456 0ustar zuulzuul00000000000000""" Copyright 2015 Rackspace 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 logging import os from tempest.lib.cli import base from designateclient.functionaltests.config import cfg from designateclient.functionaltests.models import FieldValueModel from designateclient.functionaltests.models import ListModel LOG = logging.getLogger(__name__) def build_option_string(options): """Format a string of option flags (--key 'value'). This will quote the values, in case spaces are included. Any values that are None are excluded entirely. Usage:: build_option_string({ "--email": "me@example.com", "--name": "example.com." "--ttl": None, }) Returns:: "--email 'me@example.com' --name 'example.com.' """ return " ".join("{0} '{1}'".format(flag, value) for flag, value in options.items() if value is not None) def build_flags_string(flags): """Format a string of value-less flags. Pass in a dictionary mapping flags to booleans. Those flags set to true are included in the returned string. Usage:: build_flags_string({ '--no-ttl': True, '--no-name': False, '--verbose': True, }) Returns:: '--no-ttl --verbose' """ flags = {flag: is_set for flag, is_set in flags.items() if is_set} return " ".join(flags.keys()) class ZoneCommands(object): """This is a mixin that provides zone commands to DesignateCLI""" def zone_list(self, *args, **kwargs): return self.parsed_cmd('zone list', ListModel, *args, **kwargs) def zone_show(self, id, *args, **kwargs): return self.parsed_cmd('zone show %s' % id, FieldValueModel, *args, **kwargs) def zone_delete(self, id, *args, **kwargs): return self.parsed_cmd('zone delete %s' % id, FieldValueModel, *args, **kwargs) def zone_create(self, name, email=None, ttl=None, description=None, type=None, masters=None, *args, **kwargs): options_str = build_option_string({ "--email": email, "--ttl": ttl, "--description": description, "--masters": masters, "--type": type, }) cmd = 'zone create {0} {1}'.format(name, options_str) return self.parsed_cmd(cmd, FieldValueModel, *args, **kwargs) def zone_set(self, id, email=None, ttl=None, description=None, type=None, masters=None, *args, **kwargs): options_str = build_option_string({ "--email": email, "--ttl": ttl, "--description": description, "--masters": masters, "--type": type, }) cmd = 'zone set {0} {1}'.format(id, options_str) return self.parsed_cmd(cmd, FieldValueModel, *args, **kwargs) class ZoneTransferCommands(object): """A mixin for DesignateCLI to add zone transfer commands""" def zone_transfer_request_list(self, *args, **kwargs): cmd = 'zone transfer request list' return self.parsed_cmd(cmd, ListModel, *args, **kwargs) def zone_transfer_request_create(self, zone_id, target_project_id=None, description=None, *args, **kwargs): options_str = build_option_string({ "--target-project-id": target_project_id, "--description": description, }) cmd = 'zone transfer request create {0} {1}'.format( zone_id, options_str) return self.parsed_cmd(cmd, FieldValueModel, *args, **kwargs) def zone_transfer_request_show(self, id, *args, **kwargs): cmd = 'zone transfer request show {0}'.format(id) return self.parsed_cmd(cmd, FieldValueModel, *args, **kwargs) def zone_transfer_request_set(self, id, description=None, *args, **kwargs): options_str = build_option_string({"--description": description}) cmd = 'zone transfer request set {0} {1}'.format(options_str, id) return self.parsed_cmd(cmd, FieldValueModel, *args, **kwargs) def zone_transfer_request_delete(self, id, *args, **kwargs): cmd = 'zone transfer request delete {0}'.format(id) return self.parsed_cmd(cmd, *args, **kwargs) def zone_transfer_accept_request(self, id, key, *args, **kwargs): options_str = build_option_string({ "--transfer-id": id, "--key": key, }) cmd = 'zone transfer accept request {0}'.format(options_str) return self.parsed_cmd(cmd, *args, **kwargs) def zone_transfer_accept_show(self, id, *args, **kwargs): cmd = 'zone transfer accept show {0}'.format(id) return self.parsed_cmd(cmd, FieldValueModel, *args, **kwargs) class ZoneExportCommands(object): """A mixin for DesignateCLI to add zone export commands""" def zone_export_list(self, *args, **kwargs): cmd = 'zone export list' return self.parsed_cmd(cmd, ListModel, *args, **kwargs) def zone_export_create(self, zone_id, *args, **kwargs): cmd = 'zone export create {0}'.format( zone_id) return self.parsed_cmd(cmd, FieldValueModel, *args, **kwargs) def zone_export_show(self, zone_export_id, *args, **kwargs): cmd = 'zone export show {0}'.format(zone_export_id) return self.parsed_cmd(cmd, FieldValueModel, *args, **kwargs) def zone_export_delete(self, zone_export_id, *args, **kwargs): cmd = 'zone export delete {0}'.format(zone_export_id) return self.parsed_cmd(cmd, *args, **kwargs) def zone_export_showfile(self, zone_export_id, *args, **kwargs): cmd = 'zone export showfile {0}'.format(zone_export_id) return self.parsed_cmd(cmd, FieldValueModel, *args, **kwargs) class ZoneImportCommands(object): """A mixin for DesignateCLI to add zone import commands""" def zone_import_list(self, *args, **kwargs): cmd = 'zone import list' return self.parsed_cmd(cmd, ListModel, *args, **kwargs) def zone_import_create(self, zone_file_path, *args, **kwargs): cmd = 'zone import create {0}'.format(zone_file_path) return self.parsed_cmd(cmd, FieldValueModel, *args, **kwargs) def zone_import_show(self, zone_import_id, *args, **kwargs): cmd = 'zone import show {0}'.format(zone_import_id) return self.parsed_cmd(cmd, FieldValueModel, *args, **kwargs) def zone_import_delete(self, zone_import_id, *args, **kwargs): cmd = 'zone import delete {0}'.format(zone_import_id) return self.parsed_cmd(cmd, *args, **kwargs) class RecordsetCommands(object): def recordset_show(self, zone_id, id, *args, **kwargs): cmd = 'recordset show {0} {1}'.format(zone_id, id) return self.parsed_cmd(cmd, FieldValueModel, *args, **kwargs) def recordset_list(self, zone_id, *args, **kwargs): cmd = 'recordset list {0}'.format(zone_id) return self.parsed_cmd(cmd, ListModel, *args, **kwargs) def recordset_create(self, zone_id, name, records=None, type=None, description=None, ttl=None, *args, **kwargs): options_str = build_option_string({ '--records': records, '--type': type, '--description': description, '--ttl': ttl, }) cmd = 'recordset create {0} {1} {2}'.format(zone_id, name, options_str) return self.parsed_cmd(cmd, FieldValueModel, *args, **kwargs) def recordset_set(self, zone_id, id, records=None, type=None, description=None, ttl=None, no_description=False, no_ttl=False, *args, **kwargs): options_str = build_option_string({ '--records': records, '--type': type, '--description': description, '--ttl': ttl, }) flags_str = build_flags_string({ '--no-description': no_description, '--no-ttl': no_ttl, }) cmd = 'recordset set {0} {1} {2} {3}'.format( zone_id, id, flags_str, options_str) return self.parsed_cmd(cmd, FieldValueModel, *args, **kwargs) def recordset_delete(self, zone_id, id, *args, **kwargs): cmd = 'recordset delete {0} {1}'.format(zone_id, id) return self.parsed_cmd(cmd, FieldValueModel, *args, **kwargs) class TLDCommands(object): def tld_list(self, *args, **kwargs): return self.parsed_cmd('tld list', ListModel, *args, **kwargs) def tld_show(self, id, *args, **kwargs): return self.parsed_cmd('tld show {0}'.format(id), FieldValueModel, *args, **kwargs) def tld_delete(self, id, *args, **kwargs): return self.parsed_cmd('tld delete {0}'.format(id), *args, **kwargs) def tld_create(self, name, description=None, *args, **kwargs): options_str = build_option_string({ '--name': name, '--description': description, }) cmd = 'tld create {0}'.format(options_str) return self.parsed_cmd(cmd, FieldValueModel, *args, **kwargs) def tld_set(self, id, name=None, description=None, no_description=False, *args, **kwargs): options_str = build_option_string({ '--name': name, '--description': description, }) flags_str = build_flags_string({'--no-description': no_description}) cmd = 'tld set {0} {1} {2}'.format(id, options_str, flags_str) return self.parsed_cmd(cmd, FieldValueModel, *args, **kwargs) class TSIGKeyCommands(object): def tsigkey_list(self, *args, **kwargs): return self.parsed_cmd('tsigkey list', ListModel, *args, **kwargs) def tsigkey_show(self, id, *args, **kwargs): return self.parsed_cmd('tsigkey show {0}'.format(id), FieldValueModel, *args, **kwargs) def tsigkey_delete(self, id, *args, **kwargs): return self.parsed_cmd('tsigkey delete {0}'.format(id), *args, **kwargs) def tsigkey_create(self, name, algorithm, secret, scope, resource_id, *args, **kwargs): options_str = build_option_string({ '--name': name, '--algorithm': algorithm, '--secret': secret, '--scope': scope, '--resource-id': resource_id, }) cmd = 'tsigkey create {0}'.format(options_str) return self.parsed_cmd(cmd, FieldValueModel, *args, **kwargs) def tsigkey_set(self, id, name=None, algorithm=None, secret=None, scope=None, *args, **kwargs): options_str = build_option_string({ '--name': name, '--algorithm': algorithm, '--secret': secret, '--scope': scope, }) cmd = 'tsigkey set {0} {1}'.format(id, options_str) return self.parsed_cmd(cmd, FieldValueModel, *args, **kwargs) class BlacklistCommands(object): def zone_blacklist_list(self, *args, **kwargs): cmd = 'zone blacklist list' return self.parsed_cmd(cmd, ListModel, *args, **kwargs) def zone_blacklist_create(self, pattern, description=None, *args, **kwargs): options_str = build_option_string({ '--pattern': pattern, '--description': description, }) cmd = 'zone blacklist create {0}'.format(options_str) return self.parsed_cmd(cmd, FieldValueModel, *args, **kwargs) def zone_blacklist_set(self, id, pattern=None, description=None, no_description=False, *args, **kwargs): options_str = build_option_string({ '--pattern': pattern, '--description': description, }) flags_str = build_flags_string({'--no-description': no_description}) cmd = 'zone blacklist set {0} {1} {2}'.format(id, options_str, flags_str) return self.parsed_cmd(cmd, FieldValueModel, *args, **kwargs) def zone_blacklist_show(self, id, *args, **kwargs): cmd = 'zone blacklist show {0}'.format(id) return self.parsed_cmd(cmd, FieldValueModel, *args, **kwargs) def zone_blacklist_delete(self, id, *args, **kwargs): cmd = 'zone blacklist delete {0}'.format(id) return self.parsed_cmd(cmd, FieldValueModel, *args, **kwargs) class DesignateCLI(base.CLIClient, ZoneCommands, ZoneTransferCommands, ZoneExportCommands, ZoneImportCommands, RecordsetCommands, TLDCommands, BlacklistCommands): # instantiate this once to minimize requests to keystone _CLIENTS = None def __init__(self, *args, **kwargs): super(DesignateCLI, self).__init__(*args, **kwargs) # grab the project id. this is used for zone transfer requests resp = FieldValueModel(self.openstack('token issue')) self.project_id = resp.project_id @property def using_auth_override(self): return bool(cfg.CONF.identity.override_endpoint) @classmethod def get_clients(cls): if not cls._CLIENTS: cls._init_clients() return cls._CLIENTS @classmethod def _init_clients(cls): cls._CLIENTS = { 'default': DesignateCLI( cli_dir=cfg.CONF.designateclient.directory, username=cfg.CONF.identity.username, password=cfg.CONF.identity.password, tenant_name=cfg.CONF.identity.tenant_name, uri=cfg.CONF.identity.uri, ), 'alt': DesignateCLI( cli_dir=cfg.CONF.designateclient.directory, username=cfg.CONF.identity.alt_username, password=cfg.CONF.identity.alt_password, tenant_name=cfg.CONF.identity.alt_tenant_name, uri=cfg.CONF.identity.uri, ), 'admin': DesignateCLI( cli_dir=cfg.CONF.designateclient.directory, username=cfg.CONF.identity.admin_username, password=cfg.CONF.identity.admin_password, tenant_name=cfg.CONF.identity.admin_tenant_name, uri=cfg.CONF.identity.uri, ) } @classmethod def as_user(self, user): clients = self.get_clients() if user in clients: return clients[user] raise Exception("User '{0}' does not exist".format(user)) def parsed_cmd(self, cmd, model=None, *args, **kwargs): if self.using_auth_override: # use --os-url and --os-token func = self._openstack_noauth else: # use --os-username --os-tenant-name --os-password --os-auth-url func = self.openstack out = func(cmd, *args, **kwargs) LOG.debug(out) if model is not None: return model(out) return out def _openstack_noauth(self, cmd, *args, **kwargs): exe = os.path.join(cfg.CONF.designateclient.directory, 'openstack') options = build_option_string({ '--os-url': cfg.CONF.identity.override_endpoint, '--os-token': cfg.CONF.identity.override_token, }) cmd = options + " " + cmd return base.execute(exe, cmd, *args, **kwargs) python-designateclient-2.9.0/designateclient/functionaltests/v2/0000775000175100017510000000000013232475552025155 5ustar zuulzuul00000000000000python-designateclient-2.9.0/designateclient/functionaltests/v2/test_zone.py0000666000175100017510000001157313232475203027543 0ustar zuulzuul00000000000000""" Copyright 2015 Rackspace 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 tempest.lib.exceptions import CommandFailed from designateclient.functionaltests.base import BaseDesignateTest from designateclient.functionaltests.datagen import random_zone_name from designateclient.functionaltests.v2.fixtures import ZoneFixture class TestZone(BaseDesignateTest): def setUp(self): super(TestZone, self).setUp() self.ensure_tld_exists('com') self.fixture = self.useFixture(ZoneFixture( name=random_zone_name(), email='test@example.com', )) self.zone = self.fixture.zone def test_zone_list(self): zones = self.clients.zone_list() self.assertGreater(len(zones), 0) def test_zone_create_and_show(self): zone = self.clients.zone_show(self.zone.id) self.assertTrue(hasattr(zone, 'action')) self.assertEqual(self.zone.created_at, zone.created_at) self.assertEqual(self.zone.description, zone.description) self.assertEqual(self.zone.email, zone.email) self.assertEqual(self.zone.id, zone.id) self.assertEqual(self.zone.masters, zone.masters) self.assertEqual(self.zone.name, zone.name) self.assertEqual(self.zone.pool_id, zone.pool_id) self.assertEqual(self.zone.project_id, zone.project_id) self.assertEqual(self.zone.serial, zone.serial) self.assertTrue(hasattr(zone, 'status')) self.assertEqual(self.zone.transferred_at, zone.transferred_at) self.assertEqual(self.zone.ttl, zone.ttl) self.assertEqual(self.zone.type, zone.type) self.assertEqual(self.zone.updated_at, zone.updated_at) self.assertEqual(self.zone.version, zone.version) def test_zone_delete(self): zone = self.clients.zone_delete(self.zone.id) self.assertEqual(zone.action, 'DELETE') self.assertEqual(zone.status, 'PENDING') def test_zone_set(self): ttl = int(self.zone.ttl) + 123 email = 'updated{0}'.format(self.zone.email) description = 'new description' zone = self.clients.zone_set(self.zone.id, ttl=ttl, email=email, description=description) self.assertEqual(ttl, int(zone.ttl)) self.assertEqual(email, zone.email) self.assertEqual(description, zone.description) def test_invalid_option_on_zone_create(self): cmd = 'zone create %s --invalid "not a valid option"'.format( random_zone_name()) self.assertRaises(CommandFailed, self.clients.openstack, cmd) def test_invalid_zone_command(self): cmd = 'zone hopefullynotacommand' self.assertRaises(CommandFailed, self.clients.openstack, cmd) class TestsPassingZoneFlags(BaseDesignateTest): def setUp(self): super(TestsPassingZoneFlags, self).setUp() self.ensure_tld_exists('com') def test_zone_create_primary_with_all_args(self): zone_name = random_zone_name() fixture = self.useFixture(ZoneFixture( name=zone_name, email='primary@example.com', description='A primary zone', ttl=2345, type='PRIMARY', )) zone = fixture.zone self.assertEqual(zone_name, zone.name) self.assertEqual('primary@example.com', zone.email) self.assertEqual('A primary zone', zone.description) self.assertEqual('2345', zone.ttl) self.assertEqual('PRIMARY', zone.type) def test_zone_create_secondary_with_all_args(self): zone_name = random_zone_name() fixture = self.useFixture(ZoneFixture( name=zone_name, description='A secondary zone', type='SECONDARY', masters='127.0.0.1', )) zone = fixture.zone self.assertEqual(zone_name, zone.name) self.assertEqual('A secondary zone', zone.description) self.assertEqual('SECONDARY', zone.type) self.assertEqual('127.0.0.1', zone.masters) def test_zone_set_secondary_masters(self): fixture = self.useFixture(ZoneFixture( name=random_zone_name(), description='A secondary zone', type='SECONDARY', masters='127.0.0.1', )) zone = fixture.zone self.assertEqual('127.0.0.1', zone.masters) zone = self.clients.zone_set(zone.id, masters='127.0.0.2') self.assertEqual('127.0.0.2', zone.masters) python-designateclient-2.9.0/designateclient/functionaltests/v2/test_zone_import.py0000666000175100017510000000472713232475203031140 0ustar zuulzuul00000000000000""" Copyright 2016 Rackspace Author: Rahman Syed 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 designateclient.functionaltests.base import BaseDesignateTest from designateclient.functionaltests.datagen import random_zone_file from designateclient.functionaltests.v2.fixtures import ImportFixture class TestZoneImport(BaseDesignateTest): def setUp(self): super(TestZoneImport, self).setUp() self.ensure_tld_exists('com') self.zone_file_contents = random_zone_file() def test_list_zone_imports(self): zone_import = self.useFixture(ImportFixture( zone_file_contents=self.zone_file_contents )).zone_import zone_imports = self.clients.zone_import_list() self.assertGreater(len(zone_imports), 0) self.assertTrue(self._is_entity_in_list(zone_import, zone_imports)) def test_create_and_show_zone_import(self): zone_import = self.useFixture(ImportFixture( zone_file_contents=self.zone_file_contents )).zone_import fetched_import = self.clients.zone_import_show(zone_import.id) self.assertEqual(zone_import.created_at, fetched_import.created_at) self.assertEqual(zone_import.id, fetched_import.id) self.assertEqual(zone_import.project_id, fetched_import.project_id) # check both statuses to avoid a race condition, causing test failure. # we don't know when the import completes. self.assertIn(fetched_import.status, ['PENDING', 'COMPLETE']) def test_delete_zone_import(self): zone_import = self.useFixture(ImportFixture( zone_file_contents=self.zone_file_contents )).zone_import zone_imports = self.clients.zone_import_list() self.assertTrue(self._is_entity_in_list(zone_import, zone_imports)) self.clients.zone_import_delete(zone_import.id) zone_imports = self.clients.zone_import_list() self.assertFalse(self._is_entity_in_list(zone_import, zone_imports)) python-designateclient-2.9.0/designateclient/functionaltests/v2/test_tlds.py0000666000175100017510000000607513232475203027537 0ustar zuulzuul00000000000000""" Copyright 2015 Rackspace 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 tempest.lib.exceptions import CommandFailed from designateclient.functionaltests.base import BaseDesignateTest from designateclient.functionaltests.datagen import random_tld from designateclient.functionaltests.v2.fixtures import TLDFixture class TestTld(BaseDesignateTest): def setUp(self): super(TestTld, self).setUp() tld_name = random_tld() self.tld = self.useFixture(TLDFixture( name=tld_name, description='A random tld', )).tld self.assertEqual(self.tld.name, tld_name) self.assertEqual(self.tld.description, 'A random tld') def test_tld_list(self): tlds = self.clients.as_user('admin').tld_list() self.assertGreater(len(tlds), 0) def test_tld_create_and_show(self): tld = self.clients.as_user('admin').tld_show(self.tld.id) self.assertEqual(tld.name, self.tld.name) self.assertEqual(tld.created_at, self.tld.created_at) self.assertEqual(tld.id, self.tld.id) self.assertEqual(tld.name, self.tld.name) self.assertEqual(tld.updated_at, self.tld.updated_at) def test_tld_delete(self): client = self.clients.as_user('admin') client.tld_delete(self.tld.id) self.assertRaises(CommandFailed, client.tld_show, self.tld.id) def test_tld_set(self): client = self.clients.as_user('admin') updated_name = random_tld('updated') tld = client.tld_set(self.tld.id, name=updated_name, description='An updated tld') self.assertEqual(tld.description, 'An updated tld') self.assertEqual(tld.name, updated_name) def test_tld_set_no_description(self): client = self.clients.as_user('admin') tld = client.tld_set(self.tld.id, no_description=True) self.assertEqual(tld.description, 'None') def test_no_set_tld_with_description_and_no_description(self): client = self.clients.as_user('admin') self.assertRaises(CommandFailed, client.tld_set, self.tld.id, description='An updated tld', no_description=True) class TestTldNegative(BaseDesignateTest): def test_tld_invalid_commmand(self): client = self.clients.as_user('admin') self.assertRaises(CommandFailed, client.openstack, 'tld notacommand') def test_tld_create_invalid_flag(self): client = self.clients.as_user('admin') self.assertRaises(CommandFailed, client.openstack, 'tld create --notanoption "junk"') python-designateclient-2.9.0/designateclient/functionaltests/v2/test_zone_transfer.py0000666000175100017510000001101713232475203031440 0ustar zuulzuul00000000000000""" Copyright 2015 Rackspace 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 unittest from tempest.lib.exceptions import CommandFailed from designateclient.functionaltests.base import BaseDesignateTest from designateclient.functionaltests.client import DesignateCLI from designateclient.functionaltests.datagen import random_zone_name from designateclient.functionaltests.v2.fixtures import TransferRequestFixture from designateclient.functionaltests.v2.fixtures import ZoneFixture class TestZoneTransferRequest(BaseDesignateTest): def setUp(self): super(TestZoneTransferRequest, self).setUp() self.ensure_tld_exists('com') fixture = self.useFixture(ZoneFixture( name=random_zone_name(), email='test@example.com', )) self.zone = fixture.zone def test_list_zone_transfer_request(self): self.useFixture(TransferRequestFixture(self.zone)) xfrs = self.clients.zone_transfer_request_list() self.assertGreater(len(xfrs), 0) def test_create_and_show_zone_transfer_request(self): transfer_request = self.useFixture(TransferRequestFixture( zone=self.zone, user='default', target_user='alt', )).transfer_request fetched_xfr = self.clients.zone_transfer_request_show( transfer_request.id) self.assertEqual(fetched_xfr.created_at, transfer_request.created_at) self.assertEqual(fetched_xfr.description, transfer_request.description) self.assertEqual(fetched_xfr.id, transfer_request.id) self.assertEqual(fetched_xfr.key, transfer_request.key) self.assertEqual(fetched_xfr.links, transfer_request.links) self.assertEqual(fetched_xfr.target_project_id, transfer_request.target_project_id) self.assertEqual(fetched_xfr.updated_at, transfer_request.updated_at) self.assertEqual(fetched_xfr.status, transfer_request.status) self.assertEqual(fetched_xfr.zone_id, self.zone.id) self.assertEqual(fetched_xfr.zone_name, self.zone.name) def test_delete_zone_transfer_request(self): transfer_request = self.useFixture(TransferRequestFixture( zone=self.zone, user='default', target_user='alt', )).transfer_request self.clients.zone_transfer_request_delete(transfer_request.id) self.assertRaises(CommandFailed, self.clients.zone_transfer_request_show, transfer_request.id) @unittest.skip("Fails because `zone transfer request set` returns nothing") def test_set_zone_transfer_request(self): transfer_request = self.useFixture(TransferRequestFixture( zone=self.zone, description="old description", )).transfer_request self.assertEqual(transfer_request.description, "old description") updated_xfr = self.clients.zone_transfer_request_set( transfer_request.id, description="updated description") self.assertEqual(updated_xfr.description, "updated description") class TestZoneTransferAccept(BaseDesignateTest): def setUp(self): super(TestZoneTransferAccept, self).setUp() self.ensure_tld_exists('com') fixture = self.useFixture(ZoneFixture( name=random_zone_name(), email='test@example.com', )) self.zone = fixture.zone self.target_client = DesignateCLI.as_user('alt') fixture = self.useFixture(TransferRequestFixture( zone=self.zone, user='default', target_user='alt', target_project_id=self.target_client.project_id, )) self.transfer_request = fixture.transfer_request def test_zone_transfer_accept_request(self): self.target_client.zone_transfer_accept_request( id=self.transfer_request.id, key=self.transfer_request.key, ) self.target_client.zone_show(self.zone.id) self.assertRaises(CommandFailed, self.clients.zone_show, self.zone.id) python-designateclient-2.9.0/designateclient/functionaltests/v2/test_blacklist.py0000666000175100017510000000766013232475203030542 0ustar zuulzuul00000000000000""" Copyright 2015 Rackspace 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 tempest.lib.exceptions import CommandFailed from designateclient.functionaltests.base import BaseDesignateTest from designateclient.functionaltests.datagen import random_blacklist from designateclient.functionaltests.v2.fixtures import BlacklistFixture class TestBlacklist(BaseDesignateTest): def setUp(self): super(TestBlacklist, self).setUp() pattern = random_blacklist() self.blacklist = self.useFixture(BlacklistFixture( pattern=pattern, description='A random blacklist', )).blacklist self.assertEqual(self.blacklist.pattern, pattern) self.assertEqual(self.blacklist.description, 'A random blacklist') def test_zone_blacklist_list(self): blacklists = self.clients.as_user('admin').zone_blacklist_list() self.assertGreater(len(blacklists), 0) def test_zone_blacklist_create_and_show(self): client = self.clients.as_user('admin') blacklist = client.zone_blacklist_show(self.blacklist.id) self.assertEqual(self.blacklist.created_at, blacklist.created_at) self.assertEqual(self.blacklist.description, blacklist.description) self.assertEqual(self.blacklist.id, blacklist.id) self.assertEqual(self.blacklist.pattern, blacklist.pattern) self.assertEqual(self.blacklist.updated_at, blacklist.updated_at) def test_zone_blacklist_delete(self): client = self.clients.as_user('admin') client.zone_blacklist_delete(self.blacklist.id) self.assertRaises(CommandFailed, client.zone_blacklist_show, self.blacklist.id) def test_zone_blacklist_set(self): client = self.clients.as_user('admin') updated_pattern = random_blacklist('updatedblacklist') blacklist = client.zone_blacklist_set( id=self.blacklist.id, pattern=updated_pattern, description='An updated blacklist', ) self.assertEqual(blacklist.created_at, self.blacklist.created_at) self.assertEqual(blacklist.description, 'An updated blacklist') self.assertEqual(blacklist.id, self.blacklist.id) self.assertEqual(blacklist.pattern, updated_pattern) self.assertNotEqual(blacklist.updated_at, self.blacklist.updated_at) def test_zone_blacklist_set_no_description(self): client = self.clients.as_user('admin') blacklist = client.zone_blacklist_set( id=self.blacklist.id, no_description=True, ) self.assertEqual(blacklist.description, 'None') def test_cannot_set_description_with_no_description_flag(self): client = self.clients.as_user('admin') self.assertRaises(CommandFailed, client.zone_blacklist_set, self.blacklist.id, pattern=random_blacklist(), description='new description', no_description=True) class TestBlacklistNegative(BaseDesignateTest): def test_invalid_blacklist_command(self): client = self.clients.as_user('admin') cmd = 'zone blacklist notacommand' self.assertRaises(CommandFailed, client.openstack, cmd) def test_blacklist_create_invalid_flag(self): client = self.clients.as_user('admin') cmd = 'zone blacklist create --pattern helloworld --notaflag invalid' self.assertRaises(CommandFailed, client.openstack, cmd) python-designateclient-2.9.0/designateclient/functionaltests/v2/test_tsigkeys.py0000666000175100017510000000736013232475203030431 0ustar zuulzuul00000000000000""" Copyright 2017 SAP SE 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 tempest.lib.exceptions import CommandFailed from designateclient.functionaltests.base import BaseDesignateTest from designateclient.functionaltests.datagen import random_tsigkey_name from designateclient.functionaltests.datagen import random_tsigkey_secret from designateclient.functionaltests.datagen import random_zone_name from designateclient.functionaltests.v2.fixtures import TSIGKeyFixture from designateclient.functionaltests.v2.fixtures import ZoneFixture class TestTSIGKey(BaseDesignateTest): def setUp(self): super(TestTSIGKey, self).setUp() self.ensure_tsigkey_exists('com') self.zone = self.useFixture(ZoneFixture( name=random_zone_name(), email='test@example.com', )).zone tsig_name = random_tsigkey_name() tsig_algorithm = "hmac-sha256" tsig_secret = random_tsigkey_secret() tsig_scope = 'ZONE' self.tsig = self.useFixture(TSIGKeyFixture( name=tsig_name, algorithm=tsig_algorithm, secret=tsig_secret, scope=tsig_scope, resource_id=self.zone.id )).tsig self.assertEqual(self.tsig.name, tsig_name) self.assertEqual(self.tsig.algorithm, tsig_algorithm) self.assertEqual(self.tsig.secret, tsig_secret) self.assertEqual(self.tsig.scope, tsig_scope) self.assertEqual(self.tsig.resource_id, self.zone.id) def test_tsigkey_list(self): tsigkeys = self.clients.as_user('admin').tsigkey_list() self.assertGreater(len(tsigkeys), 0) def test_tsigkey_create_and_show(self): tsigkey = self.clients.as_user('admin').tsigkey_show(self.tsigkey.id) self.assertEqual(tsigkey.name, self.tsigkey.name) self.assertEqual(tsigkey.created_at, self.tsigkey.created_at) self.assertEqual(tsigkey.id, self.tsigkey.id) self.assertEqual(self.tsig.algorithm, self.tsig_algorithm) self.assertEqual(self.tsig.secret, self.tsig_secret) self.assertEqual(self.tsig.scope, self.tsig_scope) self.assertEqual(self.tsig.resource_id, self.zone.id) self.assertEqual(tsigkey.updated_at, self.tsigkey.updated_at) def test_tsigkey_delete(self): client = self.clients.as_user('admin') client.tsigkey_delete(self.tsigkey.id) self.assertRaises(CommandFailed, client.tsigkey_show, self.tsigkey.id) def test_tsigkey_set(self): client = self.clients.as_user('admin') updated_name = random_tsigkey_name('updated') tsigkey = client.tsigkey_set(self.tsigkey.id, name=updated_name, secret='An updated tsigsecret') self.assertEqual(tsigkey.secret, 'An updated tsigsecret') self.assertEqual(tsigkey.name, updated_name) class TestTSIGKeyNegative(BaseDesignateTest): def test_tsigkey_invalid_commmand(self): client = self.clients.as_user('admin') self.assertRaises(CommandFailed, client.openstack, 'tsigkey notacommand') def test_tsigkey_create_invalid_flag(self): client = self.clients.as_user('admin') self.assertRaises(CommandFailed, client.openstack, 'tsigkey create --notanoption "junk"') python-designateclient-2.9.0/designateclient/functionaltests/v2/test_zone_export.py0000666000175100017510000000573413232475203031146 0ustar zuulzuul00000000000000""" Copyright 2016 Rackspace Author: Rahman Syed 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 designateclient.functionaltests.base import BaseDesignateTest from designateclient.functionaltests.datagen import random_zone_name from designateclient.functionaltests.v2.fixtures import ExportFixture from designateclient.functionaltests.v2.fixtures import ZoneFixture class TestZoneExport(BaseDesignateTest): def setUp(self): super(TestZoneExport, self).setUp() self.ensure_tld_exists('com') fixture = self.useFixture(ZoneFixture( name=random_zone_name(), email='test@example.com', )) self.zone = fixture.zone def test_list_zone_exports(self): zone_export = self.useFixture(ExportFixture( zone=self.zone )).zone_export zone_exports = self.clients.zone_export_list() self.assertGreater(len(zone_exports), 0) self.assertTrue(self._is_entity_in_list(zone_export, zone_exports)) def test_create_and_show_zone_export(self): zone_export = self.useFixture(ExportFixture( zone=self.zone )).zone_export fetched_export = self.clients.zone_export_show(zone_export.id) self.assertEqual(zone_export.created_at, fetched_export.created_at) self.assertEqual(zone_export.id, fetched_export.id) self.assertEqual(zone_export.message, fetched_export.message) self.assertEqual(zone_export.project_id, fetched_export.project_id) self.assertEqual(zone_export.zone_id, fetched_export.zone_id) def test_delete_zone_export(self): zone_export = self.useFixture(ExportFixture( zone=self.zone )).zone_export zone_exports = self.clients.zone_export_list() self.assertTrue(self._is_entity_in_list(zone_export, zone_exports)) self.clients.zone_export_delete(zone_export.id) zone_exports = self.clients.zone_export_list() self.assertFalse(self._is_entity_in_list(zone_export, zone_exports)) def test_show_export_file(self): zone_export = self.useFixture(ExportFixture( zone=self.zone )).zone_export fetched_export = self.clients.zone_export_showfile(zone_export.id) self.assertIn('$ORIGIN', fetched_export.data) self.assertIn('$TTL', fetched_export.data) self.assertIn('SOA', fetched_export.data) self.assertIn('NS', fetched_export.data) self.assertIn(self.zone.name, fetched_export.data) python-designateclient-2.9.0/designateclient/functionaltests/v2/test_recordsets.py0000666000175100017510000001036313232475203030741 0ustar zuulzuul00000000000000""" Copyright 2015 Rackspace 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 tempest.lib.exceptions import CommandFailed from designateclient.functionaltests.base import BaseDesignateTest from designateclient.functionaltests.datagen import random_a_recordset_name from designateclient.functionaltests.datagen import random_zone_name from designateclient.functionaltests.v2.fixtures import RecordsetFixture from designateclient.functionaltests.v2.fixtures import ZoneFixture class TestRecordset(BaseDesignateTest): def setUp(self): super(TestRecordset, self).setUp() self.ensure_tld_exists('com') self.zone = self.useFixture(ZoneFixture( name=random_zone_name(), email='test@example.com', )).zone name = random_a_recordset_name(self.zone.name) self.recordset = self.useFixture(RecordsetFixture( zone_id=self.zone.id, name=name, records='1.2.3.4', description='An a recordset', type='A', ttl=1234, )).recordset self.assertEqual(self.recordset.name, name) self.assertEqual(self.recordset.records, '1.2.3.4') self.assertEqual(self.recordset.description, 'An a recordset') self.assertEqual(self.recordset.type, 'A') self.assertEqual(self.recordset.ttl, '1234') def test_recordset_list(self): rsets = self.clients.recordset_list(self.zone.id) self.assertGreater(len(rsets), 0) def test_recordset_create_and_show(self): rset = self.clients.recordset_show(self.zone.id, self.recordset.id) self.assertTrue(hasattr(self.recordset, 'action')) self.assertTrue(hasattr(rset, 'action')) self.assertEqual(self.recordset.created_at, rset.created_at) self.assertEqual(self.recordset.description, rset.description) self.assertEqual(self.recordset.id, rset.id) self.assertEqual(self.recordset.name, rset.name) self.assertEqual(self.recordset.records, rset.records) self.assertEqual(self.recordset.status, rset.status) self.assertEqual(self.recordset.ttl, rset.ttl) self.assertEqual(self.recordset.type, rset.type) self.assertEqual(self.recordset.updated_at, rset.updated_at) self.assertEqual(self.recordset.version, rset.version) self.assertEqual(self.recordset.zone_id, self.zone.id) def test_recordset_delete(self): rset = self.clients.recordset_delete(self.zone.id, self.recordset.id) self.assertEqual(rset.action, 'DELETE') self.assertEqual(rset.status, 'PENDING') def test_recordset_set(self): rset = self.clients.recordset_set( self.zone.id, self.recordset.id, records='2.3.4.5', ttl=2345, description='Updated description', ) self.assertEqual(rset.records, '2.3.4.5') self.assertEqual(rset.ttl, '2345') self.assertEqual(rset.description, 'Updated description') def test_recordset_set_clear_ttl_and_description(self): rset = self.clients.recordset_set( self.zone.id, self.recordset.id, no_description=True, no_ttl=True, ) self.assertEqual(rset.description, 'None') self.assertEqual(rset.ttl, 'None') class TestRecordsetNegative(BaseDesignateTest): def test_invalid_option_on_recordset_create(self): cmd = 'recordset create de47d30b-41c5-4e38-b2c5-e0b908e19ec7 ' \ 'aaa.desig.com. --type A --records 1.2.3.4 ' \ '--invalid "not valid"' self.assertRaises(CommandFailed, self.clients.openstack, cmd) def test_invalid_recordset_command(self): cmd = 'recordset hopefullynotvalid' self.assertRaises(CommandFailed, self.clients.openstack, cmd) python-designateclient-2.9.0/designateclient/functionaltests/v2/fixtures.py0000666000175100017510000001757713232475203027414 0ustar zuulzuul00000000000000""" Copyright 2015 Rackspace 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 __future__ import absolute_import from __future__ import print_function import sys import tempfile import traceback import fixtures from tempest.lib.exceptions import CommandFailed from testtools.runtest import MultipleExceptions from designateclient.functionaltests.client import DesignateCLI class BaseFixture(fixtures.Fixture): def __init__(self, user='default', *args, **kwargs): """args/kwargs are forwarded to a create method on DesignateCLI""" super(BaseFixture, self).__init__() self.args = args self.kwargs = kwargs self.client = DesignateCLI.as_user(user) def setUp(self): # Sometimes, exceptions are raised in _setUp methods on fixtures. # testtools pushes the exception into a MultipleExceptions object along # with an artificial SetupError, which produces bad error messages. # This just logs those stack traces to stderr for easier debugging. try: super(BaseFixture, self).setUp() except MultipleExceptions as e: for i, exc_info in enumerate(e.args): print('--- printing MultipleExceptions traceback {} of {} ---' .format(i + 1, len(e.args)), file=sys.stderr) traceback.print_exception(*exc_info) raise class ZoneFixture(BaseFixture): """See DesignateCLI.zone_create for __init__ args""" def _setUp(self): super(ZoneFixture, self)._setUp() self.zone = self.client.zone_create(*self.args, **self.kwargs) self.addCleanup(self.cleanup_zone, self.client, self.zone.id) @classmethod def cleanup_zone(cls, client, zone_id): try: client.zone_delete(zone_id) except CommandFailed: pass class TransferRequestFixture(BaseFixture): """See DesignateCLI.zone_transfer_request_create for __init__ args""" def __init__(self, zone, user='default', target_user='alt', *args, **kwargs): super(TransferRequestFixture, self).__init__(user, *args, **kwargs) self.zone = zone self.target_client = DesignateCLI.as_user(target_user) # the client has a bug such that it requires --target-project-id. # when this bug is fixed, please remove this self.kwargs['target_project_id'] = self.target_client.project_id def _setUp(self): super(TransferRequestFixture, self)._setUp() self.transfer_request = self.client.zone_transfer_request_create( zone_id=self.zone.id, *self.args, **self.kwargs ) self.addCleanup(self.cleanup_transfer_request, self.client, self.transfer_request.id) self.addCleanup(ZoneFixture.cleanup_zone, self.client, self.zone.id) self.addCleanup(ZoneFixture.cleanup_zone, self.target_client, self.zone.id) @classmethod def cleanup_transfer_request(cls, client, transfer_request_id): try: client.zone_transfer_request_delete(transfer_request_id) except CommandFailed: pass class ExportFixture(BaseFixture): """See DesignateCLI.zone_export_create for __init__ args""" def __init__(self, zone, user='default', *args, **kwargs): super(ExportFixture, self).__init__(user, *args, **kwargs) self.zone = zone def _setUp(self): super(ExportFixture, self)._setUp() self.zone_export = self.client.zone_export_create( zone_id=self.zone.id, *self.args, **self.kwargs ) self.addCleanup(self.cleanup_zone_export, self.client, self.zone_export.id) self.addCleanup(ZoneFixture.cleanup_zone, self.client, self.zone.id) @classmethod def cleanup_zone_export(cls, client, zone_export_id): try: client.zone_export_delete(zone_export_id) except CommandFailed: pass class ImportFixture(BaseFixture): """See DesignateCLI.zone_import_create for __init__ args""" def __init__(self, zone_file_contents, user='default', *args, **kwargs): super(ImportFixture, self).__init__(user, *args, **kwargs) self.zone_file_contents = zone_file_contents def _setUp(self): super(ImportFixture, self)._setUp() with tempfile.NamedTemporaryFile() as f: f.write(self.zone_file_contents) f.flush() self.zone_import = self.client.zone_import_create( zone_file_path=f.name, *self.args, **self.kwargs ) self.addCleanup(self.cleanup_zone_import, self.client, self.zone_import.id) self.addCleanup(ZoneFixture.cleanup_zone, self.client, self.zone_import.zone_id) @classmethod def cleanup_zone_import(cls, client, zone_import_id): try: client.zone_import_delete(zone_import_id) except CommandFailed: pass class RecordsetFixture(BaseFixture): """See DesignateCLI.recordset_create for __init__ args""" def _setUp(self): super(RecordsetFixture, self)._setUp() self.recordset = self.client.recordset_create( *self.args, **self.kwargs) self.addCleanup(self.cleanup_recordset, self.client, self.recordset.zone_id, self.recordset.id) @classmethod def cleanup_recordset(cls, client, zone_id, recordset_id): try: client.recordset_delete(zone_id, recordset_id) except CommandFailed: pass class TLDFixture(BaseFixture): """See DesignateCLI.tld_create for __init__ args""" def __init__(self, user='admin', *args, **kwargs): super(TLDFixture, self).__init__(user=user, *args, **kwargs) def _setUp(self): super(TLDFixture, self)._setUp() self.tld = self.client.tld_create(*self.args, **self.kwargs) self.addCleanup(self.cleanup_tld, self.client, self.tld.id) @classmethod def cleanup_tld(cls, client, tld_id): try: client.tld_delete(tld_id) except CommandFailed: pass class TSIGKeyFixture(BaseFixture): """See DesignateCLI.tsigkey_create for __init__ args""" def __init__(self, user='admin', *args, **kwargs): super(TSIGKeyFixture, self).__init__(user=user, *args, **kwargs) def _setUp(self): super(TSIGKeyFixture, self)._setUp() self.tsigkey = self.client.tsigkey_create(*self.args, **self.kwargs) self.addCleanup(self.cleanup_tsigkey(self.client, self.tsigkey.id)) @classmethod def cleanup_tsigkey(cls, client, tsigkey_id): try: client.tsigkey_delete(tsigkey_id) except CommandFailed: pass class BlacklistFixture(BaseFixture): """See DesignateCLI.zone_blacklist_create for __init__ args""" def __init__(self, user='admin', *args, **kwargs): super(BlacklistFixture, self).__init__(user=user, *args, **kwargs) def _setUp(self): super(BlacklistFixture, self)._setUp() self.blacklist = self.client.zone_blacklist_create(*self.args, **self.kwargs) self.addCleanup(self.cleanup_blacklist, self.client, self.blacklist.id) @classmethod def cleanup_blacklist(cls, client, blacklist_id): try: client.zone_blacklist_delete(blacklist_id) except CommandFailed: pass python-designateclient-2.9.0/designateclient/functionaltests/v2/__init__.py0000666000175100017510000000000013232475203027247 0ustar zuulzuul00000000000000python-designateclient-2.9.0/designateclient/functionaltests/models.py0000666000175100017510000000642413232475203026464 0ustar zuulzuul00000000000000""" Copyright 2015 Rackspace 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 six from tempest.lib.cli import output_parser class Model(object): def __str__(self): return str(self.__dict__) class FieldValueModel(Model): """This converts cli output from messy lists/dicts to neat attributes.""" def __init__(self, out): """This parses output with fields and values like: +----------------+------------------------------+ | Field | Value | +----------------+------------------------------+ | action | CREATE | | created_at | 2015-08-20T17:22:17.000000 | | description | None | +----------------+------------------------------+ These are then accessible as: model.action model.created_at model.description """ table = output_parser.table(out) # Because the output_parser handles Values with multiple lines # in additional Field/Value pairs with Field name '', the following # code is necessary to aggregate Values. # # The list of Field/Value pairs is in-order, so we can append Value # continuation to the previously seen Field, with a newline separator. value_lines = [] prev_field = None for field, value in table['values']: if field == '': value_lines.append(value) setattr(self, prev_field, '\n'.join(value_lines)) else: setattr(self, field, value) prev_field = field value_lines = [value] class ListEntryModel(Model): def __init__(self, fields, values): for k, v in six.moves.zip(fields, values): setattr(self, k, v) class ListModel(Model, list): def __init__(self, out): """This parses an output table with any number of headers, and any number of entries: +--------------------------------------+----------+---------+ | id | name | type | +--------------------------------------+----------+---------+ | e658a875-1024-4f88-a347-e5b244ec5a10 | aaa.com. | PRIMARY | +--------------------------------------+----------+---------+ | 98d1fb5f-2954-448e-988e-6f1df0f24c52 | bbb.com. | PRIMARY | +--------------------------------------+----------+---------+ These are then accessible as: model[0].name == 'aaa.com.' model[1].name == 'bbb.com.' """ table = output_parser.table(out) for entry in table['values']: self.append(ListEntryModel(table['headers'], entry)) python-designateclient-2.9.0/designateclient/functionaltests/datagen.py0000666000175100017510000000337513232475203026606 0ustar zuulzuul00000000000000""" Copyright 2015 Rackspace 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 random import string def random_digits(n=8): return "".join([random.choice(string.digits) for _ in range(n)]) def random_tld(name='testtld'): return "{0}{1}".format(name, random_digits()) def random_tsigkey_name(name='testtsig'): return "{0}{1}".format(name, random_digits()) def random_tsigkey_secret(name='test-secret'): return "{0}-{1}".format(name, random_digits(254 - len(name))) def random_zone_name(name='testdomain', tld='com'): return "{0}{1}.{2}.".format(name, random_digits(), tld) def random_a_recordset_name(zone_name, recordset_name='testrecord'): return "{0}{1}.{2}".format(recordset_name, random_digits(), zone_name) def random_blacklist(name='testblacklist'): return '{0}{1}'.format(name, random_digits()) def random_zone_file(name='testzoneimport'): return "$ORIGIN {0}{1}.com.\n" \ "$TTL 300\n" \ "{0}{1}.com. 300 IN SOA ns.{0}{1}.com. " \ "nsadmin.{0}{1}.com. 42 42 42 42 42\n" \ "{0}{1}.com. 300 IN NS ns.{0}{1}.com.\n" \ "{0}{1}.com. 300 IN MX 10 mail.{0}{1}.com.\n" \ "ns.{0}{1}.com. 300 IN A 10.0.0.1\n" \ "mail.{0}{1}.com. 300 IN A 10.0.0.2\n".format(name, random_digits()) python-designateclient-2.9.0/designateclient/functionaltests/config.py0000666000175100017510000000405713232475203026446 0ustar zuulzuul00000000000000""" Copyright 2015 Rackspace 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 oslo_config import cfg cfg.CONF.register_group(cfg.OptGroup( name='identity', title="Configuration for Keystone auth" )) cfg.CONF.register_group(cfg.OptGroup( name='designateclient', title="Configuration for the Designate client" )) cfg.CONF.register_opts([ cfg.StrOpt('uri', help="The Keystone v2 endpoint"), cfg.StrOpt('uri_v3', help="The Keystone v3 endpoint"), cfg.StrOpt('auth_version', default='v2'), cfg.StrOpt('region', default='RegionOne'), cfg.StrOpt('username'), cfg.StrOpt('tenant_name'), cfg.StrOpt('password', secret=True), cfg.StrOpt('domain_name'), cfg.StrOpt('alt_username'), cfg.StrOpt('alt_tenant_name'), cfg.StrOpt('alt_password', secret=True), cfg.StrOpt('alt_domain_name'), cfg.StrOpt('admin_username'), cfg.StrOpt('admin_tenant_name'), cfg.StrOpt('admin_password', secret=True), cfg.StrOpt('admin_domain_name'), cfg.StrOpt("override_endpoint", help="use this url instead of the url in the service catalog"), cfg.StrOpt("override_token", help="with the override endpoint, pass this token to the api"), ], group='identity') cfg.CONF.register_opts([ cfg.StrOpt('directory', help='the directory containing the client executable'), ], group='designateclient') def find_config_file(): return os.environ.get( 'TEMPEST_CONFIG', '/opt/stack/tempest/etc/tempest.conf') def read_config(): cfg.CONF(args=[], default_config_files=[find_config_file()]) python-designateclient-2.9.0/designateclient/functionaltests/__init__.py0000666000175100017510000000016713232475203026736 0ustar zuulzuul00000000000000import logging logging.basicConfig( filename='functional-tests.log', filemode='w', level=logging.DEBUG, ) python-designateclient-2.9.0/designateclient/functionaltests/base.py0000666000175100017510000000301713232475203026106 0ustar zuulzuul00000000000000""" Copyright 2015 Rackspace 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 tempest.lib.cli import base from tempest.lib.exceptions import CommandFailed from designateclient.functionaltests import client from designateclient.functionaltests import config class BaseDesignateTest(base.ClientTestBase): def _get_clients(self): config.read_config() return client.DesignateCLI.as_user('default') def ensure_tld_exists(self, tld): try: self.clients.as_user('admin').tld_create(tld) except CommandFailed: pass def _is_entity_in_list(self, entity, entity_list): """Determines if the given entity exists in the given list. Uses the id for comparison. Certain entities (e.g. zone import, export) cannot be made comparable in a list of CLI output results, because the fields in a list command can be different from those in a show command. """ return any([entity_record.id == entity.id for entity_record in entity_list]) python-designateclient-2.9.0/designateclient/cli/0000775000175100017510000000000013232475552022150 5ustar zuulzuul00000000000000python-designateclient-2.9.0/designateclient/cli/reports.py0000666000175100017510000000415713232475203024222 0ustar zuulzuul00000000000000# Copyright 2013 Hewlett-Packard Development Company, L.P. All Rights Reserved. # # Author: Patrick Galbraith # # 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 designateclient.cli import base class DomainCountCommand(base.GetCommand): """Get counts for total domains""" def execute(self, parsed_args): return self.client.reports.count_domains() class RecordCountCommand(base.GetCommand): """Get counts for total records""" def execute(self, parsed_args): return self.client.reports.count_records() class TenantCountCommand(base.GetCommand): """Get counts for total tenants""" def execute(self, parsed_args): return self.client.reports.count_tenants() class CountsCommand(base.GetCommand): """Get count totals for all tenants, domains and records""" def execute(self, parsed_args): return self.client.reports.count_all() class TenantsCommand(base.ListCommand): """Get list of tenants and domain count for each""" columns = ['domain_count', 'id'] def execute(self, parsed_args): return self.client.reports.tenants_all() class TenantCommand(base.ListCommand): """Get a list of domains for given tenant""" columns = ['domain'] def get_parser(self, prog_name): parser = super(TenantCommand, self).get_parser(prog_name) parser.add_argument('--report-tenant-id', help="The tenant_id being reported on.", required=True) return parser def execute(self, parsed_args): return self.client.reports.tenant_domains(parsed_args.report_tenant_id) python-designateclient-2.9.0/designateclient/cli/quotas.py0000666000175100017510000000534113232475203024034 0ustar zuulzuul00000000000000# Copyright 2014 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 logging from designateclient.cli import base LOG = logging.getLogger(__name__) class GetQuotaCommand(base.GetCommand): """Get Quota""" def get_parser(self, prog_name): parser = super(GetQuotaCommand, self).get_parser(prog_name) parser.add_argument('tenant_id', help="Tenant ID") return parser def execute(self, parsed_args): return self.client.quotas.get(parsed_args.tenant_id) class UpdateQuotaCommand(base.UpdateCommand): """Update Quota""" def get_parser(self, prog_name): parser = super(UpdateQuotaCommand, self).get_parser(prog_name) parser.add_argument('tenant_id', help="Tenant ID.") parser.add_argument('--domains', help="Allowed domains.", type=int) parser.add_argument('--domain-recordsets', help="Allowed domain records.", type=int) parser.add_argument('--recordset-records', help="Allowed recordset records.", type=int) parser.add_argument('--domain-records', help="Allowed domain records.", type=int) parser.add_argument('--api-export-size', help="Allowed zone export recordsets.", type=int) return parser def execute(self, parsed_args): # TODO(kiall): API needs updating.. this get is silly quota = self.client.quotas.get(parsed_args.tenant_id) for key, old in quota.items(): new = getattr(parsed_args, key) if new is not None and new != old: quota[key] = new return self.client.quotas.update(parsed_args.tenant_id, quota) class ResetQuotaCommand(base.DeleteCommand): """Reset Quota""" def get_parser(self, prog_name): parser = super(ResetQuotaCommand, self).get_parser(prog_name) parser.add_argument('tenant_id', help="Tenant ID.") return parser def execute(self, parsed_args): self.client.quotas.reset(parsed_args.tenant_id) python-designateclient-2.9.0/designateclient/cli/domains.py0000666000175100017510000001062413232475203024152 0ustar zuulzuul00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # 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 logging from designateclient.cli import base from designateclient.v1.domains import Domain LOG = logging.getLogger(__name__) class ListDomainsCommand(base.ListCommand): """List Domains""" columns = ['id', 'name', 'serial'] def execute(self, parsed_args): return self.client.domains.list() class GetDomainCommand(base.GetCommand): """Get Domain""" def get_parser(self, prog_name): parser = super(GetDomainCommand, self).get_parser(prog_name) parser.add_argument('id', help="Domain ID or name.") return parser def execute(self, parsed_args): id = self.find_resourceid_by_name_or_id('domains', parsed_args.id) return self.client.domains.get(id) class CreateDomainCommand(base.CreateCommand): """Create Domain""" def get_parser(self, prog_name): parser = super(CreateDomainCommand, self).get_parser(prog_name) parser.add_argument('--name', help="Domain name.", required=True) parser.add_argument('--email', help="Domain email.", required=True) parser.add_argument('--ttl', type=int, help="Time to live (seconds).") parser.add_argument('--description', help="Description.") return parser def execute(self, parsed_args): domain = Domain( name=parsed_args.name, email=parsed_args.email, ) if parsed_args.description: domain.description = parsed_args.description if parsed_args.ttl is not None: domain.ttl = parsed_args.ttl return self.client.domains.create(domain) class UpdateDomainCommand(base.UpdateCommand): """Update Domain""" def get_parser(self, prog_name): parser = super(UpdateDomainCommand, self).get_parser(prog_name) parser.add_argument('id', help="Domain ID or name.") parser.add_argument('--name', help="Domain name.") parser.add_argument('--email', help="Domain email.") parser.add_argument('--ttl', type=int, help="Time to live (seconds).") description_group = parser.add_mutually_exclusive_group() description_group.add_argument('--description', help="Description.") description_group.add_argument('--no-description', action='store_true') return parser def execute(self, parsed_args): # TODO(kiall): API needs updating.. this get is silly id = self.find_resourceid_by_name_or_id('domains', parsed_args.id) domain = self.client.domains.get(id) if parsed_args.name: domain.name = parsed_args.name if parsed_args.email: domain.email = parsed_args.email if parsed_args.ttl is not None: domain.ttl = parsed_args.ttl if parsed_args.no_description: domain.description = None elif parsed_args.description: domain.description = parsed_args.description return self.client.domains.update(domain) class DeleteDomainCommand(base.DeleteCommand): """Delete Domain""" def get_parser(self, prog_name): parser = super(DeleteDomainCommand, self).get_parser(prog_name) parser.add_argument('id', help="Domain ID or name.") return parser def execute(self, parsed_args): id = self.find_resourceid_by_name_or_id('domains', parsed_args.id) return self.client.domains.delete(id) class ListDomainServersCommand(base.ListCommand): """List Domain Servers""" columns = ['name'] def get_parser(self, prog_name): parser = super(ListDomainServersCommand, self).get_parser(prog_name) parser.add_argument('id', help="Domain ID or name.") return parser def execute(self, parsed_args): id = self.find_resourceid_by_name_or_id('domains', parsed_args.id) return self.client.domains.list_domain_servers(id) python-designateclient-2.9.0/designateclient/cli/servers.py0000666000175100017510000000516013232475203024210 0ustar zuulzuul00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # 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 logging from designateclient.cli import base from designateclient.v1.servers import Server LOG = logging.getLogger(__name__) class ListServersCommand(base.ListCommand): """List Servers""" columns = ['id', 'name'] def execute(self, parsed_args): return self.client.servers.list() class GetServerCommand(base.GetCommand): """Get Server""" def get_parser(self, prog_name): parser = super(GetServerCommand, self).get_parser(prog_name) parser.add_argument('id', help="Server ID.") return parser def execute(self, parsed_args): return self.client.servers.get(parsed_args.id) class CreateServerCommand(base.CreateCommand): """Create Server""" def get_parser(self, prog_name): parser = super(CreateServerCommand, self).get_parser(prog_name) parser.add_argument('--name', help="Server name.", required=True) return parser def execute(self, parsed_args): server = Server( name=parsed_args.name, ) return self.client.servers.create(server) class UpdateServerCommand(base.UpdateCommand): """Update Server""" def get_parser(self, prog_name): parser = super(UpdateServerCommand, self).get_parser(prog_name) parser.add_argument('id', help="Server ID.") parser.add_argument('--name', help="Server name.") return parser def execute(self, parsed_args): # TODO(kiall): API needs updating.. this get is silly server = self.client.servers.get(parsed_args.id) if parsed_args.name: server.name = parsed_args.name return self.client.servers.update(server) class DeleteServerCommand(base.DeleteCommand): """Delete Server""" def get_parser(self, prog_name): parser = super(DeleteServerCommand, self).get_parser(prog_name) parser.add_argument('id', help="Server ID.") return parser def execute(self, parsed_args): return self.client.servers.delete(parsed_args.id) python-designateclient-2.9.0/designateclient/cli/diagnostics.py0000666000175100017510000000237213232475203025030 0ustar zuulzuul00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # 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 logging from designateclient.cli import base LOG = logging.getLogger(__name__) class PingCommand(base.GetCommand): """Ping a service on a given host""" def get_parser(self, prog_name): parser = super(PingCommand, self).get_parser(prog_name) parser.add_argument('--service', help="Service name (e.g. central)", required=True) parser.add_argument('--host', help="Hostname", required=True) return parser def execute(self, parsed_args): return self.client.diagnostics.ping(parsed_args.service, parsed_args.host) python-designateclient-2.9.0/designateclient/cli/touch.py0000666000175100017510000000215113232475203023636 0ustar zuulzuul00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # 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 logging from designateclient.cli import base LOG = logging.getLogger(__name__) class TouchDomainCommand(base.DeleteCommand): """Touch a single Domain""" def get_parser(self, prog_name): parser = super(TouchDomainCommand, self).get_parser(prog_name) parser.add_argument('domain_id', help="Domain ID") return parser def execute(self, parsed_args): self.client.touch.domain(parsed_args.domain_id) LOG.info('Domain touched successfully') python-designateclient-2.9.0/designateclient/cli/records.py0000666000175100017510000001470513232475203024165 0ustar zuulzuul00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # 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 logging from designateclient.cli import base from designateclient.v1.records import Record LOG = logging.getLogger(__name__) class ListRecordsCommand(base.ListCommand): """List Records""" columns = ['id', 'type', 'name', 'data'] def get_parser(self, prog_name): parser = super(ListRecordsCommand, self).get_parser(prog_name) parser.add_argument('domain_id', help="Domain ID or name.") return parser def execute(self, parsed_args): domain_id = self.find_resourceid_by_name_or_id( 'domains', parsed_args.domain_id) return self.client.records.list(domain_id) class GetRecordCommand(base.GetCommand): """Get Record""" def get_parser(self, prog_name): parser = super(GetRecordCommand, self).get_parser(prog_name) parser.add_argument('domain_id', help="Domain ID or name.") parser.add_argument('id', help="Record ID.") return parser def execute(self, parsed_args): domain_id = self.find_resourceid_by_name_or_id( 'domains', parsed_args.domain_id) return self.client.records.get(domain_id, parsed_args.id) class CreateRecordCommand(base.CreateCommand): """Create Record""" def get_parser(self, prog_name): parser = super(CreateRecordCommand, self).get_parser(prog_name) parser.add_argument('domain_id', help="Domain ID or name.") parser.add_argument( '--name', help="Record (relative|absolute) name.", required=True) parser.add_argument('--type', help="Record type.", required=True) parser.add_argument('--data', help="Record data.", required=True) parser.add_argument('--ttl', type=int, help="Record TTL.") parser.add_argument('--priority', type=int, help="Record priority.") parser.add_argument('--description', help="Description.") return parser def execute(self, parsed_args): domain_id = self.find_resourceid_by_name_or_id( 'domains', parsed_args.domain_id) if not parsed_args.name.endswith('.'): # Relative name? domain_name = self.client.domains.get(domain_id)['name'] absolute = parsed_args.name + '.' relative = absolute + domain_name if absolute.endswith('.' + domain_name): # Relative name or absolute name missing final period? msg = ('"%s" is a relative name but looks like an absolute ' 'name, use --name "%s" or "%s"' % (parsed_args.name, absolute, relative)) raise ValueError(msg) parsed_args.name = relative record = Record( name=parsed_args.name, type=parsed_args.type, data=parsed_args.data, ) if parsed_args.ttl is not None: record.ttl = parsed_args.ttl if parsed_args.priority is not None: record.priority = parsed_args.priority if parsed_args.description: record.description = parsed_args.description return self.client.records.create(domain_id, record) class UpdateRecordCommand(base.UpdateCommand): """Update Record""" def get_parser(self, prog_name): parser = super(UpdateRecordCommand, self).get_parser(prog_name) parser.add_argument('domain_id', help="Domain ID or name.") parser.add_argument('id', help="Record ID.") parser.add_argument('--name', help="Record name.") parser.add_argument('--type', help="Record type.") parser.add_argument('--data', help="Record data.") description_group = parser.add_mutually_exclusive_group() description_group.add_argument('--description', help="Description.") description_group.add_argument('--no-description', action='store_true') ttl_group = parser.add_mutually_exclusive_group() ttl_group.add_argument('--ttl', type=int, help="Record time to live (seconds).") ttl_group.add_argument('--no-ttl', action='store_true') priotity_group = parser.add_mutually_exclusive_group() priotity_group.add_argument('--priority', type=int, help="Record priority.") priotity_group.add_argument('--no-priority', action='store_true') return parser def execute(self, parsed_args): # TODO(kiall): API needs updating.. this get is silly record = self.client.records.get(parsed_args.domain_id, parsed_args.id) if parsed_args.name: record.name = parsed_args.name if parsed_args.type: record.type = parsed_args.type if parsed_args.data: record.data = parsed_args.data if parsed_args.no_ttl: record.ttl = None elif parsed_args.ttl is not None: record.ttl = parsed_args.ttl if parsed_args.no_priority: record.priority = None elif parsed_args.priority is not None: record.priority = parsed_args.priority if parsed_args.no_description: record.description = None elif parsed_args.description: record.description = parsed_args.description domain_id = self.find_resourceid_by_name_or_id( 'domains', parsed_args.domain_id) return self.client.records.update(domain_id, record) class DeleteRecordCommand(base.DeleteCommand): """Delete Record""" def get_parser(self, prog_name): parser = super(DeleteRecordCommand, self).get_parser(prog_name) parser.add_argument('domain_id', help="Domain ID or name.") parser.add_argument('id', help="Record ID.") return parser def execute(self, parsed_args): domain_id = self.find_resourceid_by_name_or_id( 'domains', parsed_args.domain_id) return self.client.records.delete(domain_id, parsed_args.id) python-designateclient-2.9.0/designateclient/cli/sync.py0000666000175100017510000000353413232475203023476 0ustar zuulzuul00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # 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 logging from designateclient.cli import base LOG = logging.getLogger(__name__) class SyncAllCommand(base.DeleteCommand): """Sync Everything""" def execute(self, parsed_args): self.client.sync.sync_all() LOG.info('Synchronization of all domains scheduled') class SyncDomainCommand(base.DeleteCommand): """Sync a single Domain""" def get_parser(self, prog_name): parser = super(SyncDomainCommand, self).get_parser(prog_name) parser.add_argument('domain_id', help="Domain ID") return parser def execute(self, parsed_args): self.client.sync.sync_domain(parsed_args.domain_id) LOG.info('Synchronization of domain scheduled') class SyncRecordCommand(base.DeleteCommand): """Sync a single Record""" def get_parser(self, prog_name): parser = super(SyncRecordCommand, self).get_parser(prog_name) parser.add_argument('domain_id', help="Domain ID") parser.add_argument('record_id', help="Record ID") return parser def execute(self, parsed_args): self.client.sync.sync_record(parsed_args.domain_id, parsed_args.record_id) LOG.info('Synchronization of record scheduled') python-designateclient-2.9.0/designateclient/cli/__init__.py0000666000175100017510000000000013232475203024242 0ustar zuulzuul00000000000000python-designateclient-2.9.0/designateclient/cli/base.py0000666000175100017510000001137013232475203023431 0ustar zuulzuul00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # 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 abc import warnings from keystoneauth1 import exceptions as ks_exceptions from osc_lib.command import command import six from designateclient import exceptions from designateclient import utils from designateclient.v1 import Client @six.add_metaclass(abc.ABCMeta) class Command(command.Command): def run(self, parsed_args): warnings.simplefilter('once', category=DeprecationWarning) warnings.warn( 'The "designate" CLI is being deprecated in favour of the ' '"openstack" CLI plugin. All designate API v2 commands are ' 'implemented there. When the v1 API is removed this CLI will ' 'stop functioning', DeprecationWarning) warnings.resetwarnings() warnings.simplefilter('ignore', category=DeprecationWarning) self.client = Client( region_name=self.app.options.os_region_name, service_type=self.app.options.os_service_type, endpoint_type=self.app.options.os_endpoint_type, session=self.app.session, all_tenants=self.app.options.all_tenants, edit_managed=self.app.options.edit_managed, endpoint=self.app.options.os_endpoint) warnings.resetwarnings() try: return super(Command, self).run(parsed_args) except exceptions.RemoteError as e: columns = ['Code', 'Type'] values = [e.code, e.type] if e.message: columns.append('Message') values.append(e.message) if e.errors: columns.append('Errors') values.append(e.errors) self.error_output(parsed_args, columns, values) except ks_exceptions.EndpointNotFound as e: self.app.log.error('No endpoint was found. You must provide a ' 'username or user id via --os-username, ' '--os-user-id, env[OS_USERNAME] or ' 'env[OS_USER_ID]') return 1 def error_output(self, parsed_args, column_names, data): self.formatter.emit_one(column_names, data, self.app.stdout, parsed_args) self.app.log.error('The requested action did not complete ' 'successfully') @abc.abstractmethod def execute(self, parsed_args): """ Execute something, this is since we overload self.take_action() in order to format the data This method __NEEDS__ to be overloaded! :param parsed_args: The parsed args that are given by take_action() """ def post_execute(self, data): """ Format the results locally if needed, by default we just return data :param data: Whatever is returned by self.execute() """ return data def take_action(self, parsed_args): results = self.execute(parsed_args) return self.post_execute(results) def find_resourceid_by_name_or_id(self, resource_plural, name_or_id): resource_client = getattr(self.client, resource_plural) return utils.find_resourceid_by_name_or_id(resource_client, name_or_id) class ListCommand(Command, command.Lister): columns = None def post_execute(self, results): if len(results) > 0: columns = self.columns or utils.get_columns(results) data = [utils.get_item_properties(i, columns) for i in results] return columns, data else: return [], () class GetCommand(Command, command.ShowOne): def post_execute(self, results): return list(six.iterkeys(results)), list(six.itervalues(results)) class CreateCommand(Command, command.ShowOne): def post_execute(self, results): return list(six.iterkeys(results)), list(six.itervalues(results)) class UpdateCommand(Command, command.ShowOne): def post_execute(self, results): return list(six.iterkeys(results)), list(six.itervalues(results)) class DeleteCommand(Command, command.ShowOne): def post_execute(self, results): return [], [] python-designateclient-2.9.0/designateclient/shell.py0000666000175100017510000002447213232475203023066 0ustar zuulzuul00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # 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 logging import os import traceback from cliff.app import App from cliff.commandmanager import CommandManager from designateclient import utils from designateclient.version import version_info as version def env(*vars, **kwargs): """Search for the first defined of possibly many env vars Returns the first environment variable defined in vars, or returns the default defined in kwargs. """ for v in vars: value = os.environ.get(v) if value: return value return kwargs.get('default', '') class DesignateShell(App): CONSOLE_MESSAGE_FORMAT = '%(levelname)s: %(message)s' DEFAULT_VERBOSE_LEVEL = 0 def __init__(self): super(DesignateShell, self).__init__( description='Designate Client', version=version.version_string(), command_manager=CommandManager('designateclient.cli'), ) self.log = logging.getLogger(__name__) def build_option_parser(self, description, version): parser = super(DesignateShell, self).build_option_parser( description, version) parser.add_argument('--os-username', default=env('OS_USERNAME'), help='Name used for authentication with the ' 'OpenStack Identity service. ' 'Defaults to env[OS_USERNAME].') parser.add_argument('--os-user-id', default=env('OS_USER_ID'), help='User ID used for authentication with the ' 'OpenStack Identity service. ' 'Defaults to env[OS_USER_ID].') parser.add_argument('--os-user-domain-id', default=env('OS_USER_DOMAIN_ID'), help='Defaults to env[OS_USER_DOMAIN_ID].') parser.add_argument('--os-user-domain-name', default=env('OS_USER_DOMAIN_NAME'), help='Defaults to env[OS_USER_DOMAIN_NAME].') parser.add_argument('--os-password', default=env('OS_PASSWORD'), help='Password used for authentication with the ' 'OpenStack Identity service. ' 'Defaults to env[OS_PASSWORD].') parser.add_argument('--os-tenant-name', default=env('OS_TENANT_NAME'), help='Tenant to request authorization on. ' 'Defaults to env[OS_TENANT_NAME].') parser.add_argument('--os-tenant-id', default=env('OS_TENANT_ID'), help='Tenant to request authorization on. ' 'Defaults to env[OS_TENANT_ID].') parser.add_argument('--os-project-name', default=env('OS_PROJECT_NAME'), help='Project to request authorization on. ' 'Defaults to env[OS_PROJECT_NAME].') parser.add_argument('--os-domain-name', default=env('OS_DOMAIN_NAME'), help='Project to request authorization on. ' 'Defaults to env[OS_DOMAIN_NAME].') parser.add_argument('--os-domain-id', default=env('OS_DOMAIN_ID'), help='Defaults to env[OS_DOMAIN_ID].') parser.add_argument('--os-project-id', default=env('OS_PROJECT_ID'), help='Project to request authorization on. ' 'Defaults to env[OS_PROJECT_ID].') parser.add_argument('--os-project-domain-id', default=env('OS_PROJECT_DOMAIN_ID'), help='Defaults to env[OS_PROJECT_DOMAIN_ID].') parser.add_argument('--os-project-domain-name', default=env('OS_PROJECT_DOMAIN_NAME'), help='Defaults to env[OS_PROJECT_DOMAIN_NAME].') parser.add_argument('--os-auth-url', default=env('OS_AUTH_URL'), help='Specify the Identity endpoint to use for ' 'authentication. ' 'Defaults to env[OS_AUTH_URL].') parser.add_argument('--os-region-name', default=env('OS_REGION_NAME'), help='Specify the region to use. ' 'Defaults to env[OS_REGION_NAME].') parser.add_argument('--os-token', default=env('OS_SERVICE_TOKEN'), help='Specify an existing token to use instead of ' 'retrieving one via authentication (e.g. ' 'with username & password). ' 'Defaults to env[OS_SERVICE_TOKEN].') parser.add_argument('--os-endpoint', default=env('OS_DNS_ENDPOINT', 'OS_SERVICE_ENDPOINT'), help='Specify an endpoint to use instead of ' 'retrieving one from the service catalog ' '(via authentication). ' 'Defaults to env[OS_DNS_ENDPOINT].') parser.add_argument('--os-endpoint-type', default=env('OS_ENDPOINT_TYPE', default='publicURL'), help='Defaults to env[OS_ENDPOINT_TYPE].') parser.add_argument('--os-service-type', default=env('OS_DNS_SERVICE_TYPE', default='dns'), help=("Defaults to env[OS_DNS_SERVICE_TYPE], or " "'dns'.")) parser.add_argument('--os-cacert', default=env('OS_CACERT'), help=('CA certificate bundle file. Defaults to ' 'env[OS_CACERT].')) parser.add_argument('--insecure', action='store_true', help="Explicitly allow 'insecure' SSL requests.") parser.add_argument('--all-tenants', action='store_true', help="Allows to list all domains from all " "tenants.") parser.add_argument('--edit-managed', action='store_true', help='Allows to edit records that are marked as ' 'managed.') return parser def configure_logging(self): """Configure logging for the app Cliff sets some defaults we don't want so re-work it a bit """ if self.options.debug: # --debug forces verbose_level 3 # Set this here so cliff.app.configure_logging() can work self.options.verbose_level = 3 super(DesignateShell, self).configure_logging() root_logger = logging.getLogger('') # Requests logs some stuff at INFO that we don't want # unless we have DEBUG requests_log = logging.getLogger("requests") requests_log.setLevel(logging.ERROR) # Other modules we don't want DEBUG output for so # don't reset them below iso8601_log = logging.getLogger("iso8601") iso8601_log.setLevel(logging.ERROR) # Set logging to the requested level self.dump_stack_trace = False if self.options.verbose_level == 0: # --quiet root_logger.setLevel(logging.ERROR) elif self.options.verbose_level == 1: # This is the default case, no --debug, --verbose or --quiet root_logger.setLevel(logging.WARNING) elif self.options.verbose_level == 2: # One --verbose root_logger.setLevel(logging.INFO) elif self.options.verbose_level >= 3: # Two or more --verbose root_logger.setLevel(logging.DEBUG) requests_log.setLevel(logging.DEBUG) if self.options.debug: # --debug forces traceback self.dump_stack_trace = True def initialize_app(self, argv): super(DesignateShell, self).initialize_app(argv) self.session = utils.get_session( auth_url=self.options.os_auth_url, endpoint=self.options.os_endpoint, domain_id=self.options.os_domain_id, domain_name=self.options.os_domain_name, project_id=self.options.os_project_id or self.options.os_tenant_id, project_name=(self.options.os_project_name or self.options.os_tenant_name), project_domain_name=self.options.os_project_domain_name, project_domain_id=self.options.os_project_domain_id, username=self.options.os_username, user_id=self.options.os_user_id, password=self.options.os_password, user_domain_id=self.options.os_user_domain_id, user_domain_name=self.options.os_user_domain_name, token=self.options.os_token, insecure=self.options.insecure, cacert=self.options.os_cacert ) def run(self, argv): try: return super(DesignateShell, self).run(argv) except Exception as e: if not logging.getLogger('').handlers: logging.basicConfig() if self.dump_stack_trace: self.log.error(traceback.format_exc(e)) else: self.log.error('Exception raised: ' + str(e)) return 1 python-designateclient-2.9.0/designateclient/tests/0000775000175100017510000000000013232475552022543 5ustar zuulzuul00000000000000python-designateclient-2.9.0/designateclient/tests/test_exceptions.py0000666000175100017510000000447013232475203026335 0ustar zuulzuul00000000000000# Copyright 2015 Rackspace Inc. # # Author: James Li # # 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 designateclient import exceptions from designateclient.tests import base class RemoteErrorTestCase(base.TestCase): response_dict = { 'message': None, 'code': 500, 'type': None, 'errors': None, 'request_id': 1234 } def test_get_error_message(self): expected_msg = 'something wrong' self.response_dict['message'] = expected_msg remote_err = exceptions.RemoteError(**self.response_dict) self.assertEqual(expected_msg, remote_err.message) def test_get_error_message_with_errors(self): expected_msg = "u'nodot.com' is not a 'domainname'" errors = {"errors": [ {"path": ["name"], "message": expected_msg, "validator": "format", "validator_value": "domainname"} ] } self.response_dict['message'] = None self.response_dict['errors'] = errors remote_err = exceptions.RemoteError(**self.response_dict) self.assertEqual(expected_msg, remote_err.message) def test_get_error_message_with_type(self): expected_msg = 'invalid_object' self.response_dict['message'] = None self.response_dict['errors'] = None self.response_dict['type'] = expected_msg remote_err = exceptions.RemoteError(**self.response_dict) self.assertEqual(expected_msg, remote_err.message) def test_get_error_message_with_unknown_response(self): expected_msg = 'invalid_object' self.response_dict['message'] = expected_msg self.response_dict['unknown'] = 'fake' remote_err = exceptions.RemoteError(**self.response_dict) self.assertEqual(expected_msg, remote_err.message) python-designateclient-2.9.0/designateclient/tests/test_v1/0000775000175100017510000000000013232475552024130 5ustar zuulzuul00000000000000python-designateclient-2.9.0/designateclient/tests/test_v1/test_sync.py0000666000175100017510000000310513232475203026507 0ustar zuulzuul00000000000000# Copyright 2015 NEC Corporation. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import mock from mock import patch from designateclient.tests import test_v1 from designateclient.v1 import sync class TestSync(test_v1.APIV1TestCase, test_v1.CrudMixin): @patch.object(sync.SyncController, "sync_all") def test_sync_all(self, sync_all): self.client.sync.sync_all() self.client.sync.sync_all.assert_called_with() @patch.object(sync.SyncController, "sync_domain") def test_sync_domain(self, sync_domain): args = mock.MagicMock() args.tenant_id = "1234" self.client.sync.sync_domain(args.tenant_id) self.client.sync.sync_domain.assert_called_with("1234") @patch.object(sync.SyncController, "sync_record") def test_sync_record(self, sync_record): args = mock.MagicMock() args.tenant_id = "1234" args.record_id = "uuid" self.client.sync.sync_record(args.tenant_id, args.record_id) self.client.sync.sync_record.assert_called_with("1234", "uuid") python-designateclient-2.9.0/designateclient/tests/test_v1/test_records.py0000666000175100017510000001655613232475203027212 0ustar zuulzuul00000000000000# Copyright 2015 NEC Corporation. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import uuid from designateclient.tests import test_v1 from designateclient import utils from designateclient import warlock Record = warlock.model_factory(utils.load_schema('v1', 'record')) DOMAIN = { "id": str(uuid.uuid4()), "name": "example.com." } class TestRecords(test_v1.APIV1TestCase, test_v1.CrudMixin): RESOURCE = 'records' def new_ref(self, **kwargs): ref = super(TestRecords, self).new_ref(**kwargs) ref.setdefault("name", uuid.uuid4().hex) ref.setdefault("type", "A") ref.setdefault("data", "10.0.0.1") return ref def test_create_record(self): ref = self.new_ref(id="2e32e609-3a4f-45ba-bdef-e50eacd345ad") parts = ["domains", DOMAIN["id"], self.RESOURCE] self.stub_url("POST", parts=parts, json=ref) values = ref.copy() del values["id"] self.client.records.create(DOMAIN['id'], Record(values)) self.assertRequestBodyIs(json=values) def test_create_AAAA_record(self): ref = self.new_ref(id="11112222-3333-4444-5555-666677778888", type="AAAA", data="2001:db8:0:1234:0:5678:9:12") parts = ["domains", DOMAIN["id"], self.RESOURCE] self.stub_url("POST", parts=parts, json=ref) values = ref.copy() del values["id"] self.client.records.create(DOMAIN['id'], Record(values)) self.assertRequestBodyIs(json=values) def test_create_MX_record(self): ref = self.new_ref(id="11112222-3333-4444-5555-666677778989", type="MX", data="mail.example.com.", priority=10) parts = ["domains", DOMAIN["id"], self.RESOURCE] self.stub_url("POST", parts=parts, json=ref) values = ref.copy() del values["id"] self.client.records.create(DOMAIN['id'], Record(values)) self.assertRequestBodyIs(json=values) def test_create_CNAME_record(self): ref = self.new_ref(id="11112222-3333-4444-5555-666677778890", type="CNAME", data="example.com.") parts = ["domains", DOMAIN["id"], self.RESOURCE] self.stub_url("POST", parts=parts, json=ref) values = ref.copy() del values["id"] self.client.records.create(DOMAIN['id'], Record(values)) self.assertRequestBodyIs(json=values) def test_create_TXT_record(self): ref = self.new_ref(id="11112222-3333-4444-5555-666677778889", type="TXT", data="This is a TXT record") parts = ["domains", DOMAIN["id"], self.RESOURCE] self.stub_url("POST", parts=parts, json=ref) values = ref.copy() del values["id"] self.client.records.create(DOMAIN['id'], Record(values)) self.assertRequestBodyIs(json=values) def test_create_SRV_record(self): ref = self.new_ref(id="11112222-3333-4444-5555-666677778888", type="SRV", data="0 5060 sip.example.com.", priority=30) parts = ["domains", DOMAIN["id"], self.RESOURCE] self.stub_url("POST", parts=parts, json=ref) values = ref.copy() del values["id"] self.client.records.create(DOMAIN['id'], Record(values)) self.assertRequestBodyIs(json=values) def test_create_NS_record(self): ref = self.new_ref(id="11112222-3333-4444-5555-666677779999", type="NS", data="ns1.example.com.") parts = ["domains", DOMAIN["id"], self.RESOURCE] self.stub_url("POST", parts=parts, json=ref) values = ref.copy() del values["id"] self.client.records.create(DOMAIN['id'], Record(values)) self.assertRequestBodyIs(json=values) def test_create_PTR_record(self): ref = self.new_ref(id="11112222-3333-4444-5555-666677778891", type="PTR", data="www.example.com.") parts = ["domains", DOMAIN["id"], self.RESOURCE] self.stub_url("POST", parts=parts, json=ref) values = ref.copy() del values["id"] self.client.records.create(DOMAIN['id'], Record(values)) self.assertRequestBodyIs(json=values) def test_create_SPF_record(self): ref = self.new_ref(id="11112222-3333-4444-5555-666677778899", type="SPF", data="v=spf1 +mx a:colo.example.com/28 -all") parts = ["domains", DOMAIN["id"], self.RESOURCE] self.stub_url("POST", parts=parts, json=ref) values = ref.copy() del values["id"] self.client.records.create(DOMAIN['id'], Record(values)) self.assertRequestBodyIs(json=values) def test_create_SSHFP_record(self): ref = self.new_ref(id="11112222-3333-4444-5555-666677778888", type="SSHFP", data="2 1 6c3c958af43d953f91f40e0d84157f4fe7b4a898") parts = ["domains", DOMAIN["id"], self.RESOURCE] self.stub_url("POST", parts=parts, json=ref) values = ref.copy() del values["id"] self.client.records.create(DOMAIN['id'], Record(values)) self.assertRequestBodyIs(json=values) def test_get(self): ref = self.new_ref(id="2e32e609-3a4f-45ba-bdef-e50eacd345ad") parts = ["domains", DOMAIN["id"], self.RESOURCE] self.stub_entity("GET", entity=ref, id=ref["id"], parts=parts) response = self.client.records.get(DOMAIN["id"], ref["id"]) self.assertEqual(ref, response) def test_list(self): items = [ self.new_ref(id="2e32e609-3a4f-45ba-bdef-e50eacd345ad"), self.new_ref(id="11112222-3333-4444-5555-666677778888") ] parts = ["domains", DOMAIN["id"], self.RESOURCE] self.stub_url("GET", parts=parts, json={"records": items}) listed = self.client.records.list(DOMAIN["id"]) self.assertList(items, listed) self.assertQueryStringIs("") def test_update(self): ref = self.new_ref(id="2e32e609-3a4f-45ba-bdef-e50eacd345ad", type="A", data="192.0.2.5") parts = ["domains", DOMAIN["id"], self.RESOURCE] self.stub_entity("PUT", entity=ref, id=ref["id"], parts=parts) values = ref.copy() del values["id"] self.client.records.update(DOMAIN["id"], Record(ref)) def test_delete(self): ref = self.new_ref() parts = ["domains", DOMAIN["id"], self.RESOURCE] self.stub_entity("DELETE", id=ref["id"], parts=parts) self.client.records.delete(DOMAIN["id"], ref["id"]) self.assertRequestBodyIs(None) python-designateclient-2.9.0/designateclient/tests/test_v1/test_servers.py0000666000175100017510000000603213232475203027226 0ustar zuulzuul00000000000000# Copyright 2015 NEC Corporation. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import uuid import mock from mock import patch from designateclient.tests import test_v1 from designateclient.v1 import servers class TestServers(test_v1.APIV1TestCase, test_v1.CrudMixin): RESOURCE = 'servers' def new_ref(self, **kwargs): ref = super(TestServers, self).new_ref(**kwargs) ref.setdefault("name", uuid.uuid4().hex) return ref def test_list(self): items = [ self.new_ref(name="ns1.example.org.", id="89acac79-38e7-497d-807c-a011e1310438"), self.new_ref(name="ns2.example.org.", id="89acac79-38e7-497d-807c-a011e1310435") ] self.stub_url("GET", parts=[self.RESOURCE], json={"servers": items}) listed = self.client.servers.list() self.assertList(items, listed) self.assertQueryStringIs("") def test_get(self): ref = self.new_ref(name="ns1.example.org.", id="89acac79-38e7-497d-807c-a011e1310438") self.stub_entity("GET", entity=ref, id=ref["id"]) response = self.client.servers.get(ref["id"]) self.assertEqual(ref, response) def test_create(self): ref = {"id": "89acac79-38e7-497d-807c-a011e1310438", "name": "ns1.example.org."} self.stub_url("POST", parts=[self.RESOURCE], json=ref) values = ref.copy() del values["id"] self.client.servers.create({"name": "ns1.example.org."}) self.assertRequestBodyIs(json=values) def test_create_with_name_too_long(self): ref = {"id": "89acac79-38e7-497d-807c-a011e1310438", "name": "ns1." + "foo" * 85 + ".org."} self.stub_url("POST", parts=[self.RESOURCE], json=ref) values = ref.copy() del values["id"] self.assertRaises(ValueError, self.client.servers.create, {"name": "ns1.example.org."}) @patch.object(servers.ServersController, "update") def test_update(self, server_update): ref = self.new_ref() self.stub_entity("PUT", entity=ref, id=ref["id"]) mock_server = mock.MagicMock() self.client.servers.update(mock_server) self.client.servers.update.assert_called_with(mock_server) def test_delete(self): ref = self.new_ref() self.stub_entity("DELETE", id=ref["id"]) self.client.servers.delete(ref["id"]) self.assertRequestBodyIs(None) python-designateclient-2.9.0/designateclient/tests/test_v1/test_client.py0000666000175100017510000001030013232475203027004 0ustar zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # # Author: Kiall Mac Innes # # 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 designateclient.tests import test_v1 from designateclient import utils from designateclient import v1 from keystoneauth1 import session as keystone_session class TestClient(test_v1.APIV1TestCase): def test_all_tenants(self): # Create a client with the all_tenants flag set to True client = v1.Client(all_tenants=True) # Verify this has been picked up self.assertTrue(client.all_tenants) def test_all_tenants_not_supplied(self): # Create a client without supplying any all_tenants flag client = v1.Client() # Verify all_tenants is False self.assertFalse(client.all_tenants) self.assertIsNotNone(client.all_tenants) def test_all_tenants_through_session(self): # Create a session with the all_tenants flag set to True session = utils.get_session( auth_url='Anything', endpoint='Anything', domain_id='Anything', domain_name='Anything', project_id='Anything', project_name='Anything', project_domain_name='Anything', project_domain_id='Anything', username='Anything', user_id='Anything', password='Anything', user_domain_id='Anything', user_domain_name='Anything', token=None, insecure=False, cacert=None, all_tenants=True) # Create a client using the pre-created session client = v1.Client(session=session) # Verify the all_tenants flag has been picked up self.assertTrue(client.all_tenants) def test_edit_managed(self): # Create a client with the edit_managed flag set to True client = v1.Client(edit_managed=True) # Verify this has been picked up self.assertTrue(client.edit_managed) def test_edit_managed_not_supplied(self): # Create a client without supplying any edit_managed flag client = v1.Client() # Verify edit_managed is False self.assertFalse(client.edit_managed) self.assertIsNotNone(client.edit_managed) def test_edit_managed_through_session(self): # Create a session with the edit_managed flag set to True session = utils.get_session( auth_url='Anything', endpoint='Anything', domain_id='Anything', domain_name='Anything', project_id='Anything', project_name='Anything', project_domain_name='Anything', project_domain_id='Anything', username='Anything', user_id='Anything', password='Anything', user_domain_id='Anything', user_domain_name='Anything', token=None, insecure=False, cacert=None, edit_managed=True) # Create a client using the pre-created session client = v1.Client(session=session) # Verify the edit_managed flag has been picked up self.assertTrue(client.edit_managed) def test_timeout_new_session(self): client = v1.Client( auth_url="http://127.0.0.1:22/", timeout=1, ) assert client.session.timeout == 1 def test_timeout_override_session_timeout(self): # The adapter timeout should override the session timeout session = keystone_session.Session(timeout=10) client = v1.Client( auth_url="http://127.0.0.1:22/", session=session, timeout=2, ) self.assertEqual(2, client.session.timeout) python-designateclient-2.9.0/designateclient/tests/test_v1/test_domain.py0000666000175100017510000001421013232475203027001 0ustar zuulzuul00000000000000# Copyright 2015 NEC Corporation. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import uuid from mock import patch from designateclient.tests import test_v1 from designateclient import utils from designateclient.v1 import domains from designateclient import warlock Domain = warlock.model_factory(utils.load_schema('v1', 'domain')) class TestDomain(test_v1.APIV1TestCase, test_v1.CrudMixin): RESOURCE = 'domains' def new_ref(self, **kwargs): ref = super(TestDomain, self).new_ref(**kwargs) ref.setdefault("name", uuid.uuid4().hex) ref.setdefault("email", "abc@example.com.") ref.setdefault("ttl", 3600) return ref def test_create(self): ref = {"id": "89acac79-38e7-497d-807c-a011e1310438", "name": "domain1.com.", "email": "nsadmin@example.org", "ttl": 60} self.stub_url("POST", parts=[self.RESOURCE], json=ref) values = ref.copy() del values["id"] response = self.client.domains.create(values["name"]) self.assertEqual(ref['id'], response['id']) def test_create_with_description(self): ref = {"id": "89acac79-38e7-497d-807c-a011e1310438", "name": "domain1.com.", "email": "nsadmin@example.org", "ttl": 60, "description": "fully qualified domain"} self.stub_url("POST", parts=[self.RESOURCE], json=ref) values = ref.copy() del values["id"] response = self.client.domains.create(values["name"]) self.assertEqual(ref['id'], response['id']) def test_create_with_description_too_long(self): ref = {"id": "89acac79-38e7-497d-807c-a011e1310438", "name": "domain1.com.", "email": "nsadmin@example.org", "ttl": 60, "description": "d" * 161} self.stub_url("POST", parts=[self.RESOURCE], json=ref) values = ref.copy() del values["id"] self.assertRaises(ValueError, self.client.domains.create, values["name"]) def test_create_with_zero_ttl(self): ref = {"id": "89acac79-38e7-497d-807c-a011e1310438", "name": "domain1.com.", "email": "nsadmin@example.org", "ttl": 0} self.stub_url("POST", parts=[self.RESOURCE], json=ref) values = ref.copy() del values["id"] self.assertRaises(ValueError, self.client.domains.create, values["name"]) def test_create_with_negative_ttl(self): ref = {"id": "89acac79-38e7-497d-807c-a011e1310438", "name": "domain1.com.", "email": "nsadmin@example.org", "ttl": -1} self.stub_url("POST", parts=[self.RESOURCE], json=ref) values = ref.copy() del values["id"] self.assertRaises(ValueError, self.client.domains.create, values["name"]) def test_create_with_no_ttl(self): ref = {"id": "89acac79-38e7-497d-807c-a011e1310438", "name": "domain1.com.", "email": "nsadmin@example.org", "ttl": ""} self.stub_url("POST", parts=[self.RESOURCE], json=ref) values = ref.copy() del values["id"] self.assertRaises(ValueError, self.client.domains.create, values["name"]) def test_create_with_name_too_long(self): ref = {"id": "89acac79-38e7-497d-807c-a011e1310438", "name": "domain" + "a" * 255 + ".com.", "email": "nsadmin@example.org", "ttl": 60} self.stub_url("POST", parts=[self.RESOURCE], json=ref) values = ref.copy() del values["id"] self.assertRaises(ValueError, self.client.domains.create, values["name"]) def test_list(self): items = [ self.new_ref(email="abc@example.org", id="89acac79-38e7-497d-807c-a011e1310438"), self.new_ref(email="root@example.org", id="89acac79-38e7-497d-807c-a011e1310435") ] self.stub_url("GET", parts=[self.RESOURCE], json={"domains": items}) listed = self.client.domains.list() self.assertList(items, listed) self.assertQueryStringIs("") def test_get(self): ref = self.new_ref(email="abc@example.org", id="89acac79-38e7-497d-807c-a011e1310438") self.stub_entity("GET", entity=ref, id=ref["id"]) response = self.client.domains.get(ref["id"]) self.assertEqual(ref, response) def test_delete(self): ref = self.new_ref(email="abc@example.org", id="89acac79-38e7-497d-807c-a011e1310438") self.stub_entity("DELETE", entity=ref, id=ref["id"]) self.client.domains.delete(ref["id"]) self.assertRequestBodyIs(None) def test_update(self): ref = self.new_ref(id="89acac79-38e7-497d-807c-a011e1310438") self.stub_entity("PUT", entity=ref, id=ref["id"]) values = ref.copy() self.client.domains.update(Domain(values)) @patch.object(domains.DomainsController, "list_domain_servers") def test_list_domain_servers(self, domains_get): domains_get.return_value = [{"id": "foo", "name": "ns1.example.com."}] ref = [{ "id": "foo", "name": "ns1.example.com.", }] parts = ["domains", "foo", "servers"] self.stub_url("GET", parts=parts, json={"servers": ref}) response = self.client.domains.list_domain_servers("foo") self.assertEqual(ref, response) python-designateclient-2.9.0/designateclient/tests/test_v1/test_reports.py0000666000175100017510000000425413232475203027237 0ustar zuulzuul00000000000000# Copyright 2015 NEC Corporation. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import mock from mock import patch from designateclient.tests import test_v1 from designateclient.v1 import reports class TestReports(test_v1.APIV1TestCase, test_v1.CrudMixin): @patch.object(reports.ReportsController, "count_all") def test_count_all(self, count_all): self.client.reports.count_all() self.client.reports.count_all.assert_called_with() @patch.object(reports.ReportsController, "count_domains") def test_count_domain(self, count_domains): self.client.reports.count_domains() self.client.reports.count_domains.assert_called_once_with() @patch.object(reports.ReportsController, "count_tenants") def test_count_tenants(self, count_tenants): self.client.reports.count_tenants() self.client.reports.count_tenants.assert_called_once_with() @patch.object(reports.ReportsController, "count_records") def test_count_records(self, count_records): self.client.reports.count_records() self.client.reports.count_records.assert_called_once_with() @patch.object(reports.ReportsController, "tenants_all") def test_tenants_all(self, tenants_all): self.client.reports.tenants_all() self.client.reports.tenants_all.assert_called_once_with() @patch.object(reports.ReportsController, "tenant_domains") def test_tenant_domains(self, tenant_domains): args = mock.MagicMock() args.other_tenant_id = "uuid" self.client.reports.tenant_domains(args.other_tenant_id) self.client.reports.tenant_domains.assert_called_once_with("uuid") python-designateclient-2.9.0/designateclient/tests/test_v1/test_quotas.py0000666000175100017510000000346013232475203027053 0ustar zuulzuul00000000000000# Copyright 2015 NEC Corporation. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import mock from mock import patch from designateclient.tests import test_v1 from designateclient.v1 import quotas class TestQuota(test_v1.APIV1TestCase, test_v1.CrudMixin): @patch.object(quotas.QuotasController, "get") def test_get(self, quota_get): QUOTA = {"domains": 10, "recordset_records": 20, "domain_records": 500, "domain_recordsets": 500} quota_get.return_value = QUOTA response = self.client.quotas.get("foo") self.assertEqual(QUOTA, response) @patch.object(quotas.QuotasController, "update") def test_update(self, quota_update): args = mock.MagicMock() args.tenant_id = "1234" args.value = {"domains": 1000} self.client.quotas.update(args.tenant_id, args.value) self.client.quotas.update.assert_called_with(args.tenant_id, args.value) @patch.object(quotas.QuotasController, "reset") def test_reset(self, quota_reset): args = mock.MagicMock() args.tenant_id = "1234" self.client.quotas.reset(args.tenant_id) self.client.quotas.reset.assert_called_with("1234") python-designateclient-2.9.0/designateclient/tests/test_v1/test_diagnostics.py0000666000175100017510000000215713232475203030050 0ustar zuulzuul00000000000000# Copyright 2015 NEC Corporation. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import mock from mock import patch from designateclient.tests import test_v1 from designateclient.v1 import diagnostics class TestDiagnostics(test_v1.APIV1TestCase, test_v1.CrudMixin): @patch.object(diagnostics.DiagnosticsController, "ping") def test_ping(self, ping): args = mock.MagicMock() args.service = "foo" args.host = "host1" self.client.diagnostics.ping(args.host, args.service) self.client.diagnostics.ping.assert_called_with("host1", "foo") python-designateclient-2.9.0/designateclient/tests/test_v1/test_touch.py0000666000175100017510000000205313232475203026656 0ustar zuulzuul00000000000000# Copyright 2015 NEC Corporation. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import mock from mock import patch from designateclient.tests import test_v1 from designateclient.v1 import touch class TestTouch(test_v1.APIV1TestCase, test_v1.CrudMixin): @patch.object(touch.TouchController, "domain") def test_domain(self, domain): args = mock.MagicMock() args.domain_id = "1234" self.client.touch.domain(args.domain_id) self.client.touch.domain.assert_called_with("1234") python-designateclient-2.9.0/designateclient/tests/test_v1/__init__.py0000666000175100017510000000274513232475203026244 0ustar zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # # Author: Kiall Mac Innes # # 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 uuid from designateclient.tests import base class CrudMixin(object): path_prefix = None def new_ref(self, **kwargs): kwargs.setdefault('id', uuid.uuid4().hex) return kwargs def stub_entity(self, method, parts=None, entity=None, id=None, **kwargs): if entity: kwargs['json'] = entity if not parts: parts = [self.RESOURCE] if self.path_prefix: parts.insert(0, self.path_prefix) if id: if not parts: parts = [] parts.append(id) self.stub_url(method, parts=parts, **kwargs) def assertList(self, expected, actual): self.assertEqual(len(expected), len(actual)) for i in expected: self.assertIn(i, actual) class APIV1TestCase(base.APITestCase): VERSION = "1" python-designateclient-2.9.0/designateclient/tests/v2/0000775000175100017510000000000013232475552023072 5ustar zuulzuul00000000000000python-designateclient-2.9.0/designateclient/tests/v2/test_timeout.py0000666000175100017510000000746113232475203026174 0ustar zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # # Author: Federico Ceratto # # 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 keystoneauth1.identity import generic from keystoneauth1 import session as keystone_session from mock import Mock from designateclient.tests import v2 from designateclient.v2.client import Client def create_session(timeout=None): auth = generic.Password(auth_url='', username='', password='', tenant_name='') return keystone_session.Session(auth=auth, timeout=timeout) class TestTimeout(v2.APIV2TestCase, v2.CrudMixin): def setUp(self): super(TestTimeout, self).setUp() # Mock methods in KeyStone's Session self._saved_methods = ( keystone_session.Session.get_auth_headers, keystone_session.Session.get_endpoint, keystone_session.Session._send_request, ) resp = Mock() resp.text = '' resp.status_code = 200 keystone_session.Session.get_auth_headers = Mock( return_value=[] ) keystone_session.Session.get_endpoint = Mock( return_value='foo' ) keystone_session.Session._send_request = Mock( return_value=resp, ) self.mock_send_request = keystone_session.Session._send_request def tearDown(self): super(TestTimeout, self).tearDown() ( keystone_session.Session.get_auth_headers, keystone_session.Session.get_endpoint, keystone_session.Session._send_request, ) = self._saved_methods def _call_request_and_check_timeout(self, client, timeout): """call the mocked _send_request() and check if the timeout was set """ client.limits.get() self.assertTrue(self.mock_send_request.called) kw = self.mock_send_request.call_args[1] if timeout is None: self.assertNotIn('timeout', kw) else: self.assertEqual(timeout, kw['timeout']) def test_no_timeout(self): session = create_session(timeout=None) client = Client(session=session) self.assertIsNone(session.timeout) self.assertIsNone(client.session.timeout) self._call_request_and_check_timeout(client, None) def test_timeout_in_session(self): session = create_session(timeout=1) client = Client(session=session) self.assertEqual(1, session.timeout) self.assertIsNone(client.session.timeout) self._call_request_and_check_timeout(client, 1) def test_timeout_override_session_timeout(self): # The adapter timeout should override the session timeout session = create_session(timeout=10) self.assertEqual(10, session.timeout) client = Client(session=session, timeout=2) self.assertEqual(2, client.session.timeout) self._call_request_and_check_timeout(client, 2) def test_timeout_update(self): session = create_session(timeout=1) client = Client(session=session) self.assertEqual(1, session.timeout) self.assertIsNone(client.session.timeout) self._call_request_and_check_timeout(client, 1) session.timeout = 2 self.assertEqual(2, session.timeout) self._call_request_and_check_timeout(client, 2) python-designateclient-2.9.0/designateclient/tests/v2/test_blacklists.py0000666000175100017510000000474613232475203026644 0ustar zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 uuid from designateclient.tests import v2 class TestBlacklists(v2.APIV2TestCase, v2.CrudMixin): RESOURCE = 'blacklists' def new_ref(self, **kwargs): ref = super(TestBlacklists, self).new_ref(**kwargs) ref.setdefault("pattern", uuid.uuid4().hex) return ref def test_create(self): ref = self.new_ref() self.stub_url("POST", parts=[self.RESOURCE], json=ref) values = ref.copy() del values["id"] self.client.blacklists.create(**values) self.assertRequestBodyIs(json=values) def test_create_with_description(self): ref = self.new_ref(description="My Blacklist") self.stub_url("POST", parts=[self.RESOURCE], json=ref) values = ref.copy() del values["id"] self.client.blacklists.create(**values) self.assertRequestBodyIs(json=values) def test_get(self): ref = self.new_ref() self.stub_entity("GET", entity=ref, id=ref["id"]) response = self.client.blacklists.get(ref["id"]) self.assertEqual(ref, response) def test_list(self): items = [ self.new_ref(), self.new_ref() ] self.stub_url("GET", parts=[self.RESOURCE], json={"blacklists": items}) listed = self.client.blacklists.list() self.assertList(items, listed) self.assertQueryStringIs("") def test_update(self): ref = self.new_ref() self.stub_entity("PATCH", entity=ref, id=ref["id"]) values = ref.copy() del values["id"] self.client.blacklists.update(ref["id"], values) self.assertRequestBodyIs(json=values) def test_delete(self): ref = self.new_ref() self.stub_entity("DELETE", id=ref["id"]) self.client.blacklists.delete(ref["id"]) self.assertRequestBodyIs(None) python-designateclient-2.9.0/designateclient/tests/v2/test_tlds.py0000666000175100017510000000563113232475203025451 0ustar zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 uuid from designateclient.tests import v2 class TestTlds(v2.APIV2TestCase, v2.CrudMixin): RESOURCE = 'tlds' def new_ref(self, **kwargs): ref = super(TestTlds, self).new_ref(**kwargs) ref.setdefault("name", uuid.uuid4().hex) return ref def test_create(self): ref = self.new_ref() self.stub_url("POST", parts=[self.RESOURCE], json=ref) values = ref.copy() del values["id"] self.client.tlds.create(**values) self.assertRequestBodyIs(json=values) def test_create_with_description(self): ref = self.new_ref(description="My TLD") self.stub_url("POST", parts=[self.RESOURCE], json=ref) values = ref.copy() del values["id"] self.client.tlds.create(**values) self.assertRequestBodyIs(json=values) def test_get(self): ref = self.new_ref() self.stub_entity("GET", entity=ref, id=ref["id"]) response = self.client.tlds.get(ref["id"]) self.assertEqual(ref, response) def test_get_by_name(self): ref = self.new_ref(name="www") self.stub_entity("GET", entity=ref, id=ref["id"]) self.stub_url("GET", parts=[self.RESOURCE], json={"tlds": [ref]}) response = self.client.tlds.get(ref['name']) self.assertEqual("GET", self.requests.request_history[0].method) self.assertEqual( "http://127.0.0.1:9001/v2/tlds?name=www", self.requests.request_history[0].url) self.assertEqual(ref, response) def test_list(self): items = [ self.new_ref(), self.new_ref() ] self.stub_url("GET", parts=[self.RESOURCE], json={"tlds": items}) listed = self.client.tlds.list() self.assertList(items, listed) self.assertQueryStringIs("") def test_update(self): ref = self.new_ref() self.stub_entity("PATCH", entity=ref, id=ref["id"]) values = ref.copy() del values["id"] self.client.tlds.update(ref["id"], values) self.assertRequestBodyIs(json=values) def test_delete(self): ref = self.new_ref() self.stub_entity("DELETE", id=ref["id"]) self.client.tlds.delete(ref["id"]) self.assertRequestBodyIs(None) python-designateclient-2.9.0/designateclient/tests/v2/test_zones.py0000666000175100017510000002676713232475203025656 0ustar zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 time import uuid from designateclient.tests import v2 class TestZones(v2.APIV2TestCase, v2.CrudMixin): RESOURCE = 'zones' def new_ref(self, **kwargs): ref = super(TestZones, self).new_ref(**kwargs) ref.setdefault("name", uuid.uuid4().hex) ref.setdefault("type", "PRIMARY") return ref def test_create_with_description(self): ref = self.new_ref(email="root@example.com", description="Foo") self.stub_url("POST", parts=[self.RESOURCE], json=ref) values = ref.copy() del values["id"] self.client.zones.create( values["name"], email=values["email"], description=values["description"]) self.assertRequestBodyIs(json=values) def test_create_primary(self): ref = self.new_ref(email="root@example.com") self.stub_url("POST", parts=[self.RESOURCE], json=ref) values = ref.copy() del values["id"] self.client.zones.create( values["name"], email=values["email"]) self.assertRequestBodyIs(json=values) def test_create_primary_with_ttl(self): ref = self.new_ref(email="root@example.com", ttl=60) self.stub_url("POST", parts=[self.RESOURCE], json=ref) values = ref.copy() del values["id"] self.client.zones.create( values["name"], email=values["email"], ttl=values["ttl"]) self.assertRequestBodyIs(json=values) def test_create_secondary(self): ref = self.new_ref(type="SECONDARY", masters=["10.0.0.1"]) self.stub_url("POST", parts=[self.RESOURCE], json=ref) values = ref.copy() del values["id"] self.client.zones.create( values["name"], type_=values["type"], masters=values["masters"]) self.assertRequestBodyIs(json=values) def test_get(self): ref = self.new_ref() self.stub_entity("GET", entity=ref, id=ref["id"]) response = self.client.zones.get(ref["id"]) self.assertEqual(ref, response) def test_list(self): items = [ self.new_ref(), self.new_ref() ] self.stub_url("GET", parts=[self.RESOURCE], json={"zones": items}) listed = self.client.zones.list() self.assertList(items, listed) self.assertQueryStringIs("") def test_update(self): ref = self.new_ref() self.stub_entity("PATCH", entity=ref, id=ref["id"]) values = ref.copy() del values["id"] self.client.zones.update(ref["id"], values) self.assertRequestBodyIs(json=values) def test_delete(self): ref = self.new_ref() self.stub_entity("DELETE", id=ref["id"]) self.client.zones.delete(ref["id"]) self.assertRequestBodyIs(None) def test_task_abandon(self): ref = self.new_ref() parts = [self.RESOURCE, ref["id"], "tasks", "abandon"] self.stub_url("POST", parts=parts) self.client.zones.abandon(ref["id"]) self.assertRequestBodyIs(None) def test_task_axfr(self): ref = self.new_ref() parts = [self.RESOURCE, ref["id"], "tasks", "xfr"] self.stub_url("POST", parts=parts) self.client.zones.axfr(ref["id"]) self.assertRequestBodyIs(None) class TestZoneTransfers(v2.APIV2TestCase, v2.CrudMixin): def test_create_request(self): zone = "098bee04-fe30-4a83-8ccd-e0c496755816" project = "123" ref = { "target_project_id": project } parts = ["zones", zone, "tasks", "transfer_requests"] self.stub_url('POST', parts=parts, json=ref) self.client.zone_transfers.create_request(zone, project) self.assertRequestBodyIs(json=ref) def test_create_request_with_description(self): zone = "098bee04-fe30-4a83-8ccd-e0c496755816" project = "123" ref = { "target_project_id": project, "description": "My Foo" } parts = ["zones", zone, "tasks", "transfer_requests"] self.stub_url('POST', parts=parts, json=ref) self.client.zone_transfers.create_request( zone, project, ref["description"]) self.assertRequestBodyIs(json=ref) def test_get_request(self): transfer = "098bee04-fe30-4a83-8ccd-e0c496755816" project = "098bee04-fe30-4a83-8ccd-e0c496755817" ref = { "target_project_id": project } parts = ["zones", "tasks", "transfer_requests", transfer] self.stub_url('GET', parts=parts, json=ref) self.client.zone_transfers.get_request(transfer) self.assertRequestBodyIs("") def test_list_request(self): project = "098bee04-fe30-4a83-8ccd-e0c496755817" ref = [{ "target_project_id": project }] parts = ["zones", "tasks", "transfer_requests"] self.stub_url('GET', parts=parts, json={"transfer_requests": ref}) self.client.zone_transfers.list_requests() self.assertRequestBodyIs("") def test_update_request(self): transfer = "098bee04-fe30-4a83-8ccd-e0c496755816" project = "098bee04-fe30-4a83-8ccd-e0c496755817" ref = { "target_project_id": project } parts = ["zones", "tasks", "transfer_requests", transfer] self.stub_url('PATCH', parts=parts, json=ref) self.client.zone_transfers.update_request(transfer, ref) self.assertRequestBodyIs(json=ref) def test_delete_request(self): transfer = "098bee04-fe30-4a83-8ccd-e0c496755816" parts = ["zones", "tasks", "transfer_requests", transfer] self.stub_url('DELETE', parts=parts) self.client.zone_transfers.delete_request(transfer) self.assertRequestBodyIs("") def test_accept_request(self): transfer = "098bee04-fe30-4a83-8ccd-e0c496755816" key = "foo123" ref = { "status": "COMPLETE" } parts = ["zones", "tasks", "transfer_accepts"] self.stub_url('POST', parts=parts, json=ref) request = { "key": key, "zone_transfer_request_id": transfer } self.client.zone_transfers.accept_request(transfer, key) self.assertRequestBodyIs(json=request) def test_get_accept(self): accept_id = "098bee04-fe30-4a83-8ccd-e0c496755816" ref = { "status": "COMPLETE" } parts = ["zones", "tasks", "transfer_accepts", accept_id] self.stub_url('GET', parts=parts, json=ref) response = self.client.zone_transfers.get_accept(accept_id) self.assertEqual(ref, response) def test_list_accepts(self): accept_id = "098bee04-fe30-4a83-8ccd-e0c496755816" ref = { "id": accept_id, "status": "COMPLETE" } parts = ["zones", "tasks", "transfer_accepts"] self.stub_url('GET', parts=parts, json={"transfer_accepts": ref}) self.client.zone_transfers.list_accepts() self.assertRequestBodyIs("") class TestZoneExports(v2.APIV2TestCase, v2.CrudMixin): def new_ref(self, **kwargs): ref = super(TestZoneExports, self).new_ref(**kwargs) ref.setdefault("zone_id", uuid.uuid4().hex) ref.setdefault("created_at", time.strftime("%c")) ref.setdefault("updated_at", time.strftime("%c")) ref.setdefault("status", 'PENDING') ref.setdefault("version", '1') return ref def test_create_export(self): zone = uuid.uuid4().hex ref = {} parts = ["zones", zone, "tasks", "export"] self.stub_url('POST', parts=parts, json=ref) self.client.zone_exports.create(zone) self.assertRequestBodyIs(json=ref) def test_get_export(self): ref = self.new_ref() parts = ["zones", "tasks", "exports", ref["id"]] self.stub_url('GET', parts=parts, json=ref) self.stub_entity("GET", parts=parts, entity=ref, id=ref["id"]) response = self.client.zone_exports.get_export_record(ref["id"]) self.assertEqual(ref, response) def test_list_exports(self): items = [ self.new_ref(), self.new_ref() ] parts = ["zones", "tasks", "exports"] self.stub_url('GET', parts=parts, json={"exports": items}) listed = self.client.zone_exports.list() self.assertList(items, listed["exports"]) self.assertQueryStringIs("") def test_delete_export(self): ref = self.new_ref() parts = ["zones", "tasks", "exports", ref["id"]] self.stub_url('DELETE', parts=parts, json=ref) self.stub_entity("DELETE", parts=parts, id=ref["id"]) self.client.zone_exports.delete(ref["id"]) self.assertRequestBodyIs(None) def test_get_export_file(self): ref = self.new_ref() parts = ["zones", "tasks", "exports", ref["id"], "export"] self.stub_url('GET', parts=parts, json=ref) self.stub_entity("GET", parts=parts, entity=ref, id=ref["id"]) response = self.client.zone_exports.get_export(ref["id"]) self.assertEqual(ref, response) class TestZoneImports(v2.APIV2TestCase, v2.CrudMixin): def new_ref(self, **kwargs): ref = super(TestZoneImports, self).new_ref(**kwargs) ref.setdefault("zone_id", uuid.uuid4().hex) ref.setdefault("created_at", time.strftime("%c")) ref.setdefault("updated_at", time.strftime("%c")) ref.setdefault("status", 'PENDING') ref.setdefault("message", 'Importing...') ref.setdefault("version", '1') return ref def test_create_import(self): zonefile = '$ORIGIN example.com' parts = ["zones", "tasks", "imports"] self.stub_url('POST', parts=parts, json=zonefile) self.client.zone_imports.create(zonefile) self.assertRequestBodyIs(body=zonefile) def test_get_import(self): ref = self.new_ref() parts = ["zones", "tasks", "imports", ref["id"]] self.stub_url('GET', parts=parts, json=ref) self.stub_entity("GET", parts=parts, entity=ref, id=ref["id"]) response = self.client.zone_imports.get_import_record(ref["id"]) self.assertEqual(ref, response) def test_list_imports(self): items = [ self.new_ref(), self.new_ref() ] parts = ["zones", "tasks", "imports"] self.stub_url('GET', parts=parts, json={"imports": items}) listed = self.client.zone_imports.list() self.assertList(items, listed["imports"]) self.assertQueryStringIs("") def test_delete_import(self): ref = self.new_ref() parts = ["zones", "tasks", "imports", ref["id"]] self.stub_url('DELETE', parts=parts, json=ref) self.stub_entity("DELETE", parts=parts, id=ref["id"]) self.client.zone_imports.delete(ref["id"]) self.assertRequestBodyIs(None) python-designateclient-2.9.0/designateclient/tests/v2/test_tsigkeys.py0000666000175100017510000000550013232475203026340 0ustar zuulzuul00000000000000# Copyright 2017 SAP SE # # Author: Rudolf Vriend # # 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 uuid from designateclient.tests import v2 class TestTSIGKeys(v2.APIV2TestCase, v2.CrudMixin): RESOURCE = 'tsigkeys' def new_ref(self, **kwargs): ref = super(TestTSIGKeys, self).new_ref(**kwargs) ref.setdefault("name", uuid.uuid4().hex) ref.setdefault("algorithm", "hmac-sha256") ref.setdefault("secret", uuid.uuid4().hex) ref.setdefault("scope", "POOL") ref.setdefault("resource_id", uuid.uuid4().hex) return ref def test_create(self): ref = self.new_ref() self.stub_url("POST", parts=[self.RESOURCE], json=ref) values = ref.copy() del values["id"] self.client.tsigkeys.create(**values) self.assertRequestBodyIs(json=values) def test_get(self): ref = self.new_ref() self.stub_entity("GET", entity=ref, id=ref["id"]) response = self.client.tsigkeys.get(ref["id"]) self.assertEqual(ref, response) def test_get_by_name(self): ref = self.new_ref(name="www") self.stub_entity("GET", entity=ref, id=ref["id"]) self.stub_url("GET", parts=[self.RESOURCE], json={"tsigkeys": [ref]}) response = self.client.tsigkeys.get(ref['name']) self.assertEqual("GET", self.requests.request_history[0].method) self.assertEqual( "http://127.0.0.1:9001/v2/tsigkeys?name=www", self.requests.request_history[0].url) self.assertEqual(ref, response) def test_list(self): items = [ self.new_ref(), self.new_ref() ] self.stub_url("GET", parts=[self.RESOURCE], json={"tsigkeys": items}) listed = self.client.tsigkeys.list() self.assertList(items, listed) self.assertQueryStringIs("") def test_update(self): ref = self.new_ref() self.stub_entity("PATCH", entity=ref, id=ref["id"]) values = ref.copy() del values["id"] self.client.tsigkeys.update(ref["id"], values) self.assertRequestBodyIs(json=values) def test_delete(self): ref = self.new_ref() self.stub_entity("DELETE", id=ref["id"]) self.client.tsigkeys.delete(ref["id"]) self.assertRequestBodyIs(None) python-designateclient-2.9.0/designateclient/tests/v2/test_client.py0000666000175100017510000000304613232475203025757 0ustar zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # # Author: Federico Ceratto # # 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 keystoneauth1 import adapter from keystoneauth1 import session as keystone_session from designateclient.tests.base import TestCase from designateclient.v2.client import Client class TestClient(TestCase): def test_init(self): self.assertRaises(ValueError, Client) def test_init_with_session(self): session = keystone_session.Session() adapted = adapter.Adapter(session=session) client = Client(session=adapted) assert client.session def test_init_with_session_timeout(self): session = keystone_session.Session() client = Client( session=session, timeout=1) assert client.session.timeout == 1 def test_init_with_auth(self): session = keystone_session.Session() client = Client( auth='http://127.0.0.1:22/', session=session) assert client.session.auth python-designateclient-2.9.0/designateclient/tests/v2/test_nameservers.py0000666000175100017510000000234113232475203027030 0ustar zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 mock import patch from designateclient.tests import v2 from designateclient.v2 import zones class TestLimits(v2.APIV2TestCase, v2.CrudMixin): @patch.object(zones.ZoneController, "list") def test_get(self, zones_get): zones_get.return_value = [{"id": "foo"}] ref = [{ "hostname": "ns1.example.com.", "priority": 1 }] parts = ["zones", "foo", "nameservers"] self.stub_url("GET", parts=parts, json={"nameservers": ref}) response = self.client.nameservers.list("foo") self.assertEqual(ref, response) python-designateclient-2.9.0/designateclient/tests/v2/test_limits.py0000666000175100017510000000165513232475203026006 0ustar zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 designateclient.tests import v2 class TestLimits(v2.APIV2TestCase, v2.CrudMixin): def test_get(self): ref = {"max_zones": "foo"} self.stub_url("GET", parts=["limits"], json=ref) limits = self.client.limits.get() self.assertEqual(ref, limits) python-designateclient-2.9.0/designateclient/tests/v2/test_recordsets.py0000666000175100017510000001563513232475203026665 0ustar zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 uuid from mock import patch import testtools from designateclient import exceptions from designateclient.tests import v2 from designateclient.v2 import zones ZONE = { "id": str(uuid.uuid4()), "name": "example.com." } class TestRecordSets(v2.APIV2TestCase, v2.CrudMixin): RESOURCE = 'recordsets' def new_ref(self, **kwargs): ref = super(TestRecordSets, self).new_ref(**kwargs) ref.setdefault("name", uuid.uuid4().hex) ref.setdefault("type", "A") ref.setdefault("records", ["10.0.0.1"]) return ref def test_create_absolute_with_zone_dict(self): ref = self.new_ref() parts = ["zones", ZONE["id"], self.RESOURCE] self.stub_url("POST", parts=parts, json=ref) values = ref.copy() del values["id"] self.client.recordsets.create( ZONE, "%s.%s" % (values["name"], ZONE["name"]), values["type"], values["records"]) values["name"] = "%s.%s" % (ref["name"], ZONE["name"]) self.assertRequestBodyIs(json=values) @patch.object(zones.ZoneController, "get") def test_create_absolute_with_zone_name(self, zone_get): ref = self.new_ref() zone_get.return_value = ZONE parts = ["zones", ZONE["id"], self.RESOURCE] self.stub_url("POST", parts=parts, json=ref) values = ref.copy() del values["id"] self.client.recordsets.create( ZONE["name"], "%s.%s" % (values["name"], ZONE["name"]), values["type"], values["records"]) values["name"] = "%s.%s" % (ref["name"], ZONE["name"]) self.assertRequestBodyIs(json=values) @patch.object(zones.ZoneController, "get") def test_create_non_absolute_with_zone_name(self, zone_get): ref = self.new_ref() zone_get.return_value = ZONE parts = ["zones", ZONE["id"], self.RESOURCE] self.stub_url("POST", parts=parts, json=ref) values = ref.copy() del values["id"] self.client.recordsets.create( ZONE["name"], values["name"], values["type"], values["records"]) values["name"] = "%s.%s" % (ref["name"], ZONE["name"]) self.assertRequestBodyIs(json=values) @patch.object(zones.ZoneController, "list") def test_create_non_absolute_with_zone_name_non_unique(self, zone_list): zone_list.return_value = [ 1, 2 ] ref = self.new_ref() values = ref.copy() del values["id"] with testtools.ExpectedException(exceptions.NoUniqueMatch): self.client.recordsets.create( ZONE["name"], "%s.%s" % (values["name"], ZONE["name"]), values["type"], values["records"]) def test_create_absolute_with_zone_id(self): ref = self.new_ref() parts = ["zones", ZONE["id"], self.RESOURCE] self.stub_url("POST", parts=parts, json=ref) values = ref.copy() del values["id"] self.client.recordsets.create( ZONE["id"], "%s.%s" % (values["name"], ZONE["name"]), values["type"], values["records"]) values["name"] = "%s.%s" % (ref["name"], ZONE["name"]) self.assertRequestBodyIs(json=values) @patch.object(zones.ZoneController, "get") def test_create_non_absolute_with_zone_id(self, zone_get): ref = self.new_ref() zone_get.return_value = ZONE parts = ["zones", ZONE["id"], self.RESOURCE] self.stub_url("POST", parts=parts, json=ref) values = ref.copy() del values["id"] self.client.recordsets.create( ZONE["id"], values["name"], values["type"], values["records"]) values["name"] = "%s.%s" % (ref["name"], ZONE["name"]) self.assertRequestBodyIs(json=values) def test_create_with_description(self): ref = self.new_ref(description="Foo") parts = ["zones", ZONE["id"], self.RESOURCE] self.stub_url("POST", parts=parts, json=ref) values = ref.copy() del values["id"] self.client.recordsets.create( ZONE["id"], "%s.%s" % (values["name"], ZONE["name"]), values["type"], values["records"], description=values["description"]) values["name"] = "%s.%s" % (ref["name"], ZONE["name"]) self.assertRequestBodyIs(json=values) def test_create_with_ttl(self): ref = self.new_ref(ttl=60) parts = ["zones", ZONE["id"], self.RESOURCE] self.stub_url("POST", parts=parts, json=ref) values = ref.copy() del values["id"] self.client.recordsets.create( ZONE["id"], "%s.%s" % (values["name"], ZONE["name"]), values["type"], values["records"], ttl=values["ttl"]) values["name"] = "%s.%s" % (ref["name"], ZONE["name"]) self.assertRequestBodyIs(json=values) def test_get(self): ref = self.new_ref() parts = ["zones", ZONE["id"], self.RESOURCE] self.stub_entity("GET", entity=ref, id=ref["id"], parts=parts) response = self.client.recordsets.get(ZONE["id"], ref["id"]) self.assertEqual(ref, response) def test_list(self): items = [ self.new_ref(), self.new_ref() ] parts = ["zones", ZONE["id"], self.RESOURCE] self.stub_url("GET", parts=parts, json={"recordsets": items}) listed = self.client.recordsets.list(ZONE["id"]) self.assertList(items, listed) self.assertQueryStringIs("") def test_update(self): ref = self.new_ref() parts = ["zones", ZONE["id"], self.RESOURCE] self.stub_entity("PUT", entity=ref, id=ref["id"], parts=parts) values = ref.copy() del values["id"] self.client.recordsets.update(ZONE["id"], ref["id"], values) self.assertRequestBodyIs(json=values) def test_delete(self): ref = self.new_ref() parts = ["zones", ZONE["id"], self.RESOURCE] self.stub_entity("DELETE", id=ref["id"], parts=parts) self.client.recordsets.delete(ZONE["id"], ref["id"]) self.assertRequestBodyIs(None) python-designateclient-2.9.0/designateclient/tests/v2/test_service_statuses.py0000666000175100017510000000274213232475203030076 0ustar zuulzuul00000000000000# Copyright 2016 Hewlett Packard Enterprise Development Company LP # # Author: Endre Karlson # # 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 designateclient.tests import v2 class TestServiceStatuses(v2.APIV2TestCase, v2.CrudMixin): RESOURCE = 'service_statuses' def new_ref(self, **kwargs): ref = super(TestServiceStatuses, self).new_ref(**kwargs) ref["name"] = "foo" return ref def test_get(self): ref = self.new_ref() self.stub_entity("GET", entity=ref, id=ref["id"]) response = self.client.service_statuses.get(ref["id"]) self.assertEqual(ref, response) def test_list(self): items = [ self.new_ref(), self.new_ref() ] self.stub_url("GET", parts=[self.RESOURCE], json={"service_statuses": items}) listed = self.client.service_statuses.list() self.assertList(items, listed) self.assertQueryStringIs("") python-designateclient-2.9.0/designateclient/tests/v2/__init__.py0000666000175100017510000000275313232475203025205 0ustar zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 uuid from designateclient.tests import base class CrudMixin(object): path_prefix = None def new_ref(self, **kwargs): kwargs.setdefault('id', uuid.uuid4().hex) return kwargs def stub_entity(self, method, parts=None, entity=None, id=None, **kwargs): if entity: kwargs['json'] = entity if not parts: parts = [self.RESOURCE] if self.path_prefix: parts.insert(0, self.path_prefix) if id: if not parts: parts = [] parts.append(id) self.stub_url(method, parts=parts, **kwargs) def assertList(self, expected, actual): self.assertEqual(len(expected), len(actual)) for i in expected: self.assertIn(i, actual) class APIV2TestCase(base.APITestCase): VERSION = "2" python-designateclient-2.9.0/designateclient/tests/v2/test_reverse.py0000666000175100017510000000344413232475203026156 0ustar zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # # Author: Endre Karlson # # 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 uuid from designateclient.tests import v2 FIP_ID = '%s:%s' % (str(uuid.uuid4()), "RegionOne") class TestFloatingIP(v2.APIV2TestCase, v2.CrudMixin): def test_set(self): name = "foo.com." ref = { "ptrdname": name, "description": "foo" } parts = ["reverse", "floatingips", FIP_ID] self.stub_url("PATCH", parts=parts, json=ref) self.client.floatingips.set(FIP_ID, name, "foo") def test_list(self): ref = [ {"ptrdname": "foo.com."} ] self.stub_url("GET", parts=["reverse", "floatingips"], json={"floatingips": ref}) self.client.floatingips.list() def test_get(self): ref = { "ptrdname": "foo.com." } parts = ["reverse", "floatingips", FIP_ID] self.stub_url("GET", parts=parts, json=ref) self.client.floatingips.get(FIP_ID) def test_unset(self): parts = ["reverse", "floatingips", FIP_ID] self.stub_url("PATCH", parts=parts, json={"ptdrname": None}) self.client.floatingips.unset(FIP_ID) self.assertRequestBodyIs(None) python-designateclient-2.9.0/designateclient/tests/test_designateclient.py0000666000175100017510000000152213232475203027311 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. """ test_designateclient ---------------------------------- Tests for `designateclient` module. """ import designateclient from designateclient.tests import base class ClientTestCase(base.TestCase): def test_module_version(self): self.assertTrue(hasattr(designateclient, '__version__')) python-designateclient-2.9.0/designateclient/tests/test_utils.py0000666000175100017510000000626013232475203025313 0ustar zuulzuul00000000000000# Copyright (c) 2015 Thales Services SAS # 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 uuid import mock from designateclient import exceptions from designateclient.tests import base from designateclient import utils LIST_MOCK_RESPONSE = [ {'id': '13579bdf-0000-0000-abcd-000000000001', 'name': 'abcd'}, {'id': '13579bdf-0000-0000-baba-000000000001', 'name': 'baba'}, {'id': '13579bdf-0000-0000-baba-000000000002', 'name': 'baba'}, ] class UtilsTestCase(base.TestCase): def _find_resourceid_by_name_or_id(self, name_or_id, by_name=False): resource_client = mock.Mock() resource_client.list.return_value = LIST_MOCK_RESPONSE resourceid = utils.find_resourceid_by_name_or_id( resource_client, name_or_id) self.assertEqual(by_name, resource_client.list.called) return resourceid def test_find_resourceid_with_hyphen_uuid(self): expected = str(uuid.uuid4()) observed = self._find_resourceid_by_name_or_id(expected) self.assertEqual(expected, observed) def test_find_resourceid_with_nonhyphen_uuid(self): expected = str(uuid.uuid4()) fakeid = expected.replace('-', '') observed = self._find_resourceid_by_name_or_id(fakeid) self.assertEqual(expected, observed) def test_find_resourceid_with_unique_resource(self): observed = self._find_resourceid_by_name_or_id('abcd', by_name=True) self.assertEqual('13579bdf-0000-0000-abcd-000000000001', observed) def test_find_resourceid_with_nonexistent_resource(self): self.assertRaises(exceptions.ResourceNotFound, self._find_resourceid_by_name_or_id, 'taz', by_name=True) def test_find_resourceid_with_multiple_resources(self): self.assertRaises(exceptions.NoUniqueMatch, self._find_resourceid_by_name_or_id, 'baba', by_name=True) def test_load_schema(self): schema = utils.load_schema('v1', 'domain') self.assertIsInstance(schema, dict) def test_load_schema_missing(self): self.assertRaises(exceptions.ResourceNotFound, utils.load_schema, 'v1', 'missing') def test_resource_string_empty_param(self): self.assertRaises(ValueError, utils.resource_string) def test_resource_string(self): name = ['schemas', 'v1', 'domain.json'] resource_string = utils.resource_string(*name) self.assertIsNotNone(resource_string) def test_resource_string_missing(self): name = ['schemas', 'v1', 'missing'] self.assertRaises(exceptions.ResourceNotFound, utils.resource_string, *name) python-designateclient-2.9.0/designateclient/tests/__init__.py0000666000175100017510000000000013232475203024635 0ustar zuulzuul00000000000000python-designateclient-2.9.0/designateclient/tests/base.py0000666000175100017510000001243413232475203024026 0ustar zuulzuul00000000000000# Copyright 2010-2011 OpenStack Foundation # Copyright (c) 2015 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 as json_ import os import fixtures from keystoneauth1 import session as keystone_session from oslotest import base as test from requests_mock.contrib import fixture as req_fixture import six from six.moves.urllib import parse as urlparse from designateclient import client from designateclient.utils import AdapterWithTimeout _TRUE_VALUES = ('True', 'true', '1', 'yes') class TestCase(test.BaseTestCase): """Test case base class for all unit tests.""" def setUp(self): """Run before each test method to initialize test environment.""" super(TestCase, self).setUp() test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0) try: test_timeout = int(test_timeout) except ValueError: # If timeout value is invalid do not set a timeout. test_timeout = 0 if test_timeout > 0: self.useFixture(fixtures.Timeout(test_timeout, gentle=True)) self.useFixture(fixtures.NestedTempfile()) self.useFixture(fixtures.TempHomeDir()) if os.environ.get('OS_STDOUT_CAPTURE') in _TRUE_VALUES: stdout = self.useFixture(fixtures.StringStream('stdout')).stream self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout)) if os.environ.get('OS_STDERR_CAPTURE') in _TRUE_VALUES: stderr = self.useFixture(fixtures.StringStream('stderr')).stream self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr)) self.log_fixture = self.useFixture(fixtures.FakeLogger()) class APITestCase(TestCase): """Test case base class for all unit tests.""" TEST_URL = "http://127.0.0.1:9001/" VERSION = None def setUp(self): """Run before each test method to initialize test environment.""" super(TestCase, self).setUp() self.log_fixture = self.useFixture(fixtures.FakeLogger()) self.requests = self.useFixture(req_fixture.Fixture()) self.client = self.get_client() def get_base(self, base_url=None): if not base_url: base_url = '%sv%s' % (self.TEST_URL, self.VERSION) return base_url def stub_url(self, method, parts=None, base_url=None, json=None, **kwargs): base_url = self.get_base(base_url) if json: kwargs['text'] = json_.dumps(json) headers = kwargs.setdefault('headers', {}) headers['Content-Type'] = 'application/json' if parts: url = '/'.join([p.strip('/') for p in [base_url] + parts]) else: url = base_url url = url.replace("/?", "?") self.requests.register_uri(method, url, **kwargs) def get_client(self, version=None, session=None): version = version or self.VERSION session = session or keystone_session.Session() adapted = AdapterWithTimeout( session=session, endpoint_override=self.get_base()) return client.Client(version, session=adapted) def assertRequestBodyIs(self, body=None, json=None): last_request_body = self.requests.last_request.body if json: val = json_.loads(last_request_body) self.assertEqual(json, val) elif body: self.assertEqual(body, last_request_body) def assertQueryStringIs(self, qs=''): """Verify the QueryString matches what is expected. The qs parameter should be of the format \'foo=bar&abc=xyz\' """ expected = urlparse.parse_qs(qs, keep_blank_values=True) parts = urlparse.urlparse(self.requests.last_request.url) querystring = urlparse.parse_qs(parts.query, keep_blank_values=True) self.assertEqual(expected, querystring) def assertQueryStringContains(self, **kwargs): """Verify the query string contains the expected parameters. This method is used to verify that the query string for the most recent request made contains all the parameters provided as ``kwargs``, and that the value of each parameter contains the value for the kwarg. If the value for the kwarg is an empty string (''), then all that's verified is that the parameter is present. """ parts = urlparse.urlparse(self.requests.last_request.url) qs = urlparse.parse_qs(parts.query, keep_blank_values=True) for k, v in six.iteritems(kwargs): self.assertIn(k, qs) self.assertIn(v, qs[k]) def assertRequestHeaderEqual(self, name, val): """Verify that the last request made contains a header and its value The request must have already been made. """ headers = self.requests.last_request.headers self.assertEqual(val, headers.get(name)) python-designateclient-2.9.0/designateclient/__init__.py0000666000175100017510000000130713232475203023506 0ustar zuulzuul00000000000000# Copyright 2017 Huawei, Inc. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # from designateclient import version __version__ = version.version_info.version_string() python-designateclient-2.9.0/releasenotes/0000775000175100017510000000000013232475552020730 5ustar zuulzuul00000000000000python-designateclient-2.9.0/releasenotes/notes/0000775000175100017510000000000013232475552022060 5ustar zuulzuul00000000000000python-designateclient-2.9.0/releasenotes/notes/quota-commands-7ff037bddae95771.yaml0000666000175100017510000000040513232475203030175 0ustar zuulzuul00000000000000--- features: - added openstack dns quota command + list + set + reset sub commands All sub commands can be scoped to a project using --project-id If the --project-id does not match the current project id it will set X-Auth-All-Projects:True python-designateclient-2.9.0/releasenotes/notes/.placeholder0000666000175100017510000000000013232475203024324 0ustar zuulzuul00000000000000python-designateclient-2.9.0/releasenotes/source/0000775000175100017510000000000013232475552022230 5ustar zuulzuul00000000000000python-designateclient-2.9.0/releasenotes/source/newton.rst0000666000175100017510000000023213232475203024264 0ustar zuulzuul00000000000000=================================== Newton Series Release Notes =================================== .. release-notes:: :branch: origin/stable/newton python-designateclient-2.9.0/releasenotes/source/pike.rst0000666000175100017510000000021713232475203023705 0ustar zuulzuul00000000000000=================================== Pike Series Release Notes =================================== .. release-notes:: :branch: stable/pike python-designateclient-2.9.0/releasenotes/source/_templates/0000775000175100017510000000000013232475552024365 5ustar zuulzuul00000000000000python-designateclient-2.9.0/releasenotes/source/_templates/.placeholder0000666000175100017510000000000013232475203026631 0ustar zuulzuul00000000000000python-designateclient-2.9.0/releasenotes/source/conf.py0000666000175100017510000002176313232475203023533 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. # Designate Release Notes documentation build configuration file, created by # sphinx-quickstart on Tue Nov 3 17:40:50 2015. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # sys.path.insert(0, os.path.abspath('.')) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'openstackdocstheme', 'reno.sphinxext', ] # openstackdocstheme options repository_name = 'openstack/python-designateclient' bug_project = 'python-designateclient' bug_tag = '' html_last_updated_fmt = '%Y-%m-%d %H:%M' html_theme = 'openstackdocs' # 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'Designate Client Release Notes' copyright = u'2015, Designate Developers' # Release notes are version independent. # The full version, including alpha/beta/rc tags. release = '' # The short X.Y version. version = '' # 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 = 'default' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. # html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". # html_title = None # A shorter title for the navigation bar. Default is the same as html_title. # html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. # html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. # html_extra_path = [] # If 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 = 'DesignateClientReleaseNotesdoc' # -- 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', 'DesignateClientReleaseNotes.tex', u'Designate Client Release Notes ' u'Documentation', u'Designate 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', 'designateclientreleasenotes', u'Designate Client Release Notes ' u'Documentation', [u'Designate 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', 'DesignateClientReleaseNotes', u'Designate Client Release Notes ' u'Documentation', u'Designate Developers', 'DesignateClientReleaseNotes', '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/'] python-designateclient-2.9.0/releasenotes/source/ocata.rst0000666000175100017510000000023013232475203024037 0ustar zuulzuul00000000000000=================================== Ocata Series Release Notes =================================== .. release-notes:: :branch: origin/stable/ocata python-designateclient-2.9.0/releasenotes/source/unreleased.rst0000666000175100017510000000015713232475203025107 0ustar zuulzuul00000000000000============================== Current Series Release Notes ============================== .. release-notes::python-designateclient-2.9.0/releasenotes/source/index.rst0000666000175100017510000000025213232475203024063 0ustar zuulzuul00000000000000================================ Designate Client Release Notes ================================ .. toctree:: :maxdepth: 1 unreleased pike ocata newton python-designateclient-2.9.0/releasenotes/source/_static/0000775000175100017510000000000013232475552023656 5ustar zuulzuul00000000000000python-designateclient-2.9.0/releasenotes/source/_static/.placeholder0000666000175100017510000000000013232475203026122 0ustar zuulzuul00000000000000python-designateclient-2.9.0/tools/0000775000175100017510000000000013232475552017377 5ustar zuulzuul00000000000000python-designateclient-2.9.0/tools/pretty_tox.sh0000777000175100017510000000026513232475203022155 0ustar zuulzuul00000000000000#! /bin/sh TESTRARGS=$1 exec 3>&1 status=$(exec 4>&1 >&3; ( python setup.py testr --slowest --testr-args="--subunit $TESTRARGS"; echo $? >&4 ) | subunit-trace -f) && exit $status python-designateclient-2.9.0/AUTHORS0000664000175100017510000000604413232475551017312 0ustar zuulzuul00000000000000Alex Monk Alok Jani Andreas Jaeger Andreas Jaeger Andreas Jaeger Andrew F. Ly Andrew Spiers Atsushi SAKAI Ben Nemec Betsy Luzader Brian DeHamer Cao Xuan Hoang Cedric Brandily Chaozhe.Chen Christian Berendt Clenimar Filemon Davide Guerri Deepak Dirk Mueller Doug Hellmann Dougal Matthews Endre Karlson Endre Karlson Endre Karlson Eric Wehrmeister Federico Ceratto Flavio Percoco Graham Hayes Graham Hayes Graham Hayes Graham Hayes Hangdong Zhang James Li Janonymous Jens Harbott Jeremy Stanley Joe Gordon Jordan Cazamias KATO Tomoyuki Kiall Mac Innes Kiall Mac Innes Kiall Mac Innes Lakshmi N Sampath Marcus Furlong Monty Taylor Ondřej Nový OpenStack Release Bot Patrick Galbraith Paul Glass Pavel Kirpichyov Pradeep Kumar Singh Rahman Syed Reddy A, Penchal (pr8721) Rudolf Vriend Rui Chen Sascha Peilicke Sascha Peilicke Satyanarayana Patibandla Shane Wang Shuquan Huang Simon McCartney Stephen Finucane Swapnil Kulkarni (coolsvap) Tang Chen TerryHowe Tim Simmons Tony Breeds Tony Xu Venkata Mahesh Jonnalagadda Zuul abhishekkekane algerwang ashish-kumar-gupta ghanshyam howardlee lingyongxu ricolin ricolin rjrjr sonu.kumar venkatamahesh python-designateclient-2.9.0/bin/0000775000175100017510000000000013232475552017007 5ustar zuulzuul00000000000000python-designateclient-2.9.0/bin/designate0000777000175100017510000000140013232475203020666 0ustar zuulzuul00000000000000#!/usr/bin/env python # Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # 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 from designateclient.shell import DesignateShell shell = DesignateShell() sys.exit(shell.run(sys.argv[1:])) python-designateclient-2.9.0/test-requirements.txt0000666000175100017510000000111313232475203022467 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 already pins down pep8, pyflakes and flake8 hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0 coverage!=4.4,>=4.0 # Apache-2.0 mock>=2.0.0 # BSD oslo.config>=5.1.0 # Apache-2.0 oslotest>=3.2.0 # Apache-2.0 python-subunit>=1.0.0 # Apache-2.0/BSD requests-mock>=1.1.0 # Apache-2.0 testrepository>=0.0.18 # Apache-2.0/BSD reno>=2.5.0 # Apache-2.0 tempest>=17.1.0 # Apache-2.0 python-designateclient-2.9.0/doc/0000775000175100017510000000000013232475552017004 5ustar zuulzuul00000000000000python-designateclient-2.9.0/doc/examples/0000775000175100017510000000000013232475552020622 5ustar zuulzuul00000000000000python-designateclient-2.9.0/doc/examples/recordset_create.py0000666000175100017510000000241313232475203024504 0ustar zuulzuul00000000000000from __future__ import print_function import logging from designateclient.v2 import client from designateclient import exceptions from designateclient import shell from keystoneauth1.identity import generic from keystoneauth1 import session as keystone_session logging.basicConfig(level='DEBUG') """ Example script to create or get a domain and add some records to it. """ auth = generic.Password( auth_url=shell.env('OS_AUTH_URL'), username=shell.env('OS_USERNAME'), password=shell.env('OS_PASSWORD'), project_name=shell.env('OS_PROJECT_NAME'), project_domain_id='default', user_domain_id='default') session = keystone_session.Session(auth=auth) client = client.Client(session=session) try: zone = client.zones.create('i.io.', email='i@i.io') except exceptions.RemoteError: zone = dict([(z['name'], z) for z in client.zones.list()])['i.io.'] print("Recordset list...") for rs in client.recordsets.list(zone['id']): print(rs) # Here's an example of just passing "www" as the record name vs "www.i.io." records = ["10.0.0.1"] rs = client.recordsets.create(zone['id'], 'www', 'A', records) # Here we're replacing the records with new ones records = ["10.0.0.1", "10.0.0.5"] client.recordsets.update(zone['id'], rs['id'], {'records': records}) python-designateclient-2.9.0/doc/examples/zone_list_nameservers.py0000666000175100017510000000135713232475203025615 0ustar zuulzuul00000000000000import logging import uuid from designateclient.v2 import client from designateclient import shell from designateclient import utils from keystoneauth1.identity import generic from keystoneauth1 import session as keystone_session logging.basicConfig(level='DEBUG') auth = generic.Password( auth_url=shell.env('OS_AUTH_URL'), username=shell.env('OS_USERNAME'), password=shell.env('OS_PASSWORD'), project_name=shell.env('OS_PROJECT_NAME'), project_domain_id='default', user_domain_id='default') session = keystone_session.Session(auth=auth) client = client.Client(session=session) zone = client.zones.create( 'primary-%s.io.' % str(uuid.uuid4()), 'PRIMARY', 'root@x.com') client.nameservers.list(zone['id']) python-designateclient-2.9.0/doc/examples/zone_list_paging.py0000666000175100017510000000161613232475203024526 0ustar zuulzuul00000000000000from __future__ import print_function import logging from keystoneauth1.identity import generic from keystoneauth1 import session as keystone_session from designateclient import shell from designateclient.v2 import client logging.basicConfig(level='DEBUG') auth = generic.Password( auth_url=shell.env('OS_AUTH_URL'), username=shell.env('OS_USERNAME'), password=shell.env('OS_PASSWORD'), project_name=shell.env('OS_PROJECT_NAME'), project_domain_id='default', user_domain_id='default') session = keystone_session.Session(auth=auth, timeout=10) client = client.Client(session=session) pages = [] fetch = 1 while fetch: kw = {'limit': 3} if pages: # marker is the latest page with the last item. kw['marker'] = pages[-1][-1]['id'] page = client.zones.list(**kw) if not page: break pages.append(page) for page in pages: print(page) python-designateclient-2.9.0/doc/examples/zone_create_primary.py0000666000175100017510000000152313232475203025231 0ustar zuulzuul00000000000000from __future__ import print_function import logging from designateclient import exceptions from designateclient import shell from designateclient.v2 import client from keystoneauth1.identity import generic from keystoneauth1 import session as keystone_session logging.basicConfig(level='DEBUG') auth = generic.Password( auth_url=shell.env('OS_AUTH_URL'), username=shell.env('OS_USERNAME'), password=shell.env('OS_PASSWORD'), project_name=shell.env('OS_PROJECT_NAME'), project_domain_id='default', user_domain_id='default') session = keystone_session.Session(auth=auth) client = client.Client(session=session) try: zone = client.zones.create('i.io.', email='i@i.io') except exceptions.RemoteError: zone = dict([(z['name'], z) for z in client.zones.list()])['i.io.'] print(client.recordsets.list(zone['id'])) python-designateclient-2.9.0/doc/examples/recordset_crud.py0000666000175100017510000000356313232475203024205 0ustar zuulzuul00000000000000import logging from designateclient.v2 import client from designateclient import exceptions from designateclient import shell from keystoneauth1.identity import generic from keystoneauth1 import session as keystone_session logging.basicConfig(level='DEBUG') auth = generic.Password( auth_url=shell.env('OS_AUTH_URL'), username=shell.env('OS_USERNAME'), password=shell.env('OS_PASSWORD'), project_name=shell.env('OS_PROJECT_NAME'), project_domain_id='default', user_domain_id='default') session = keystone_session.Session(auth=auth) client = client.Client(session=session) try: zone = dict([(z['name'], z) for z in client.zones.list()])['i.io.'] client.zones.delete(zone['id']) except exceptions.NotFound: pass zone = client.zones.create(name='i.io.', email='i@i.io') # Clean all recordsets first in this zone (for sanity sake) for rrset in client.recordsets.list(zone['id']): if rrset['type'] in ('NS', 'SOA'): continue client.recordsets.delete(zone['id'], rrset['id']) # Make some A records www = client.recordsets.create( zone['id'], 'www.%s' % zone['name'], 'A', ['10.0.0.1']) values = { 'records': ['10.0.1.1', '10.0.0.2'] } client.recordsets.update(zone['id'], www['id'], values) cname = client.recordsets.create( zone['id'], 'my-site.%s' % zone['name'], 'CNAME', [www['name']]) # Now let's do some Mailserver examples # First create the A record mail1 = client.recordsets.create( zone['id'], 'mail1.' + zone['name'], 'A', ["10.0.0.11"]) mail2 = client.recordsets.create( zone['id'], 'mail2.' + zone['name'], 'A', ["10.0.0.12"]) # Create the MX records - it will be 1 recordset with multiple records pointing # to the A records we created above mx_rrset = client.recordsets.create( zone['id'], zone['name'], 'MX', ['0 ' + mail1['name'], '5 ' + mail2['name']]) print(zone['id']) python-designateclient-2.9.0/doc/examples/zone_create_secondary.py0000666000175100017510000000203713232475203025536 0ustar zuulzuul00000000000000import logging import uuid from keystoneauth1.identity import generic from keystoneauth1 import session as keystone_session from designateclient import exceptions from designateclient import shell from designateclient.v2 import client logging.basicConfig(level='DEBUG') auth = generic.Password( auth_url=shell.env('OS_AUTH_URL'), username=shell.env('OS_USERNAME'), password=shell.env('OS_PASSWORD'), project_name=shell.env('OS_PROJECT_NAME'), project_domain_id='default', user_domain_id='default') session = keystone_session.Session(auth=auth) client = client.Client(session=session) # Primary Zone primary = client.zones.create( 'primary-%s.io.' % str(uuid.uuid4()), 'PRIMARY', 'root@x.com') # Secondary Zone slave = client.zones.create( 'secondary-%s.io.' % str(uuid.uuid4()), 'SECONDARY', masters=["127.0.1.1"]) # Try updating Masters for the Secondary new_slave = client.zones.update( slave['id'], {"masters": ["10.0.0.1", "10.0.0.10"]} ) # List all Zones zones = client.zones.list() python-designateclient-2.9.0/doc/requirements.txt0000666000175100017510000000042613232475203022265 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. sphinx!=1.6.6,>=1.6.2 # BSD openstackdocstheme>=1.18.1 # Apache-2.0 python-designateclient-2.9.0/doc/source/0000775000175100017510000000000013232475552020304 5ustar zuulzuul00000000000000python-designateclient-2.9.0/doc/source/user/0000775000175100017510000000000013232475552021262 5ustar zuulzuul00000000000000python-designateclient-2.9.0/doc/source/user/shell-examples.rst0000666000175100017510000001733713232475203024745 0ustar zuulzuul00000000000000==================================== Designate Command Line Tool Examples ==================================== .. warning:: This page refers to command that use the V1 API, which is currently disabled, and will be removed in a future release Using the client against your dev environment --------------------------------------------- Typically the designate client talks to Keystone (or a Keystone like service) via the OS_AUTH_URL setting & retrives the designate endpoint from the returned service catalog. Using ``--os-endpoint`` or ``OS_ENDPOINT`` you can specify the end point directly, this is useful if you want to point the client at a test environment that's running without a full Keystone service. .. code-block:: shell-session $ designate --os-endpoint http://127.0.0.1:9001/v1 server-create --name ns.example.com. +------------+--------------------------------------+ | Field | Value | +------------+--------------------------------------+ | id | 3dee78df-c6b8-4fbd-8e89-3186c1a4734f | | created_at | 2015-11-04T08:47:12.000000 | | updated_at | None | | name | ns.example.com. | +------------+--------------------------------------+ $ designate --os-endpoint http://127.0.0.1:9001/v1 domain-create --name example.net. --email me@example.org +-------------+--------------------------------------+ | Field | Value | +-------------+--------------------------------------+ | description | None | | created_at | 2015-11-04T08:49:53.000000 | | updated_at | None | | email | me@example.org | | ttl | 3600 | | serial | 1446626993 | | id | f98c3d91-f514-4956-a955-20eefb413a64 | | name | example.net. | +-------------+--------------------------------------+ $ designate --os-endpoint http://127.0.0.1:9001/v1 record-create --name myhost.example.net. --type A --data 1.2.3.4 f98c3d91-f514-4956-a955-20eefb413a64 (domain_id) +-------------+--------------------------------------+ | Field | Value | +-------------+--------------------------------------+ | description | None | | type | A | | created_at | 2015-11-04T08:52:41.000000 | | updated_at | None | | domain_id | f98c3d91-f514-4956-a955-20eefb413a64 | | priority | None | | ttl | None | | data | 1.2.3.4 | | id | b5a74471-8062-4395-be70-968805a0d832 | | name | myhost.example.net. | +-------------+--------------------------------------+ $ designate domain-list +--------------------------------------+--------------+------------+ | id | name | serial | +--------------------------------------+--------------+------------+ | 88c14ecf-b034-424c-b081-ca42494dcdf9 | example.com. | 1462372104 | +--------------------------------------+--------------+------------+ $ designate domain-update --email example@example.com 88c14ecf-b034-424c-b081-ca42494dcdf9 (domain_id) +-------------+---------------------------------------+ | Field | Value | +-------------+---------------------------------------+ | description | None | | created_at | 2016-05-04T14:28:24.000000 | | updated_at | 2016-05-04T14:29:48.000000 | | email | example@example.com | | ttl | 3600 | | serial | 1462372188 | | id | 88c14ecf-b034-424c-b081-ca42494dcdf9 | | name | example.com. | +-------------+---------------------------------------+ $ designate domain-delete 88c14ecf-b034-424c-b081-ca42494dcdf9 (domain_id) $ designate record-list 66584cdd-f7a6-4f0e-acf0-3dd5ad04830d (domain_id) +--------------------------------------+------+-----------------------+-----------------------------------------------------------------+ | id | type | name | data | +--------------------------------------+------+-----------------------+-----------------------------------------------------------------+ | fdfab9c3-51c0-42b9-b500-7779ef917915 | SOA | example.com. | ns1.example.org. pr8721.att.com. 1462372695 3600 600 86400 3600 | | 242a16e8-8455-4b4d-af7f-45de1074aa04 | NS | example.com. | xyz.com. | | 8dc14df7-3651-49df-8c83-0d71954c6152 | NS | example.com. | ns1.example.org. | | 7e80531d-bd65-49bc-a316-a6a06cd7fe26 | A | example1.example.com. | 198.51.100.1 | +--------------------------------------+------+-----------------------+-----------------------------------------------------------------+ $ designate record-update --name example1.example.com. --type A --data 198.5.100.2 --ttl 3600 66584cdd-f7a6-4f0e-acf0-3dd5ad04830d (domain-id) 7e80531d-bd65-49bc-a316-a6a06cd7fe26 (record_id) +-------------+--------------------------------------+ | Field | Value | +-------------+--------------------------------------+ | description | None | | type | A | | created_at | 2016-05-04T14:38:15.000000 | | updated_at | 2016-05-04T16:12:05.000000 | | domain_id | 66584cdd-f7a6-4f0e-acf0-3dd5ad04830d | | priority | None | | ttl | 3600 | | data | 198.5.100.2 | | id | 7e80531d-bd65-49bc-a316-a6a06cd7fe26 | | name | example1.example.com. | +-------------+--------------------------------------+ $ designate record-delete 66584cdd-f7a6-4f0e-acf0-3dd5ad04830d (domain-id) 7e80531d-bd65-49bc-a316-a6a06cd7fe26 (record_id) $ designate quota-get 70a4596c9974429db5fb6fe240ab87b9 (tenant_id) +-------------------+-------+ | Field | Value | +-------------------+-------+ | domains | 10 | | domain_recordsets | 500 | | recordset_records | 20 | | domain_records | 500 | +-------------------+-------+ $ designate quota-update --domains 50 --domain-recordsets 1000 --recordset-records 40 --domain-records 1000 70a4596c9974429db5fb6fe240ab87b9 (tenant_id) +-------------------+-------+ | Field | Value | +-------------------+-------+ | domains | 50 | | domain_recordsets | 1000 | | recordset_records | 40 | | domain_records | 1000 | +-------------------+-------+ $ designate quota-get 70a4596c9974429db5fb6fe240ab87b9 (tenant_id) +-------------------+-------+ | Field | Value | +-------------------+-------+ | domains | 10 | | domain_recordsets | 500 | | recordset_records | 20 | | domain_records | 500 | +-------------------+-------+ python-designateclient-2.9.0/doc/source/user/shell.rst0000666000175100017510000002702513232475203023124 0ustar zuulzuul00000000000000.. _shell: ========================================================= Designate Command Line Tool (compatible with v1 API only) ========================================================= .. warning:: This page refers to command that use the V1 API, which is currently disabled, and will be removed in a future release The python-designateclient package comes with a command line tool (installed as :program:`designate`), this can be used to access a Designate API without having to manipulate JSON by hand, it can also produce the output in a variety of formats (JSON, CSV) and allow you to select columns to be displayed. Credentials ----------- As with any OpenStack utility, :program:`designate` requires certain information to talk to the REST API, username, password, auth url (from where the other required endpoints are retrieved once you are authenticated). To provide your access credentials (username, password, tenant name or tenant id) you can pass them on the command line with the ``--os-username``, ``--os-password``, ``--os-tenant-name`` or ``--os-tenant-id`` params, but it's easier to just set them as environment variables:: export OS_USERNAME=openstack export OS_PASSWORD=yadayada export OS_TENANT_NAME=myproject export OS_TENANT_ID=123456789 You will also need to define the authentication url with ``--os-auth-url`` or set is as an environment variable as well:: export OS_AUTH_URL=https://example.com:5000/v2.0/ Since Keystone can return multiple regions in the Service Catalog, you can specify the one you want with ``--os-region-name`` (or ``export OS_REGION_NAME``). It defaults to the first in the list returned. Using the command line tool --------------------------- With enough details now in the environment, you can use the designate client to create a domain and populate it with some records: .. code-block:: shell-session $ designate domain-create --name example.com. --email admin@example.com +-------------+--------------------------------------+ | Field | Value | +-------------+--------------------------------------+ | description | None | | created_at | 2013-09-19T11:45:25.295355 | | updated_at | None | | email | admin@example.com | | ttl | 3600 | | serial | 1379591125 | | id | eacbe2a5-95f1-4a9f-89f5-b9c58009b163 | | name | example.com. | +-------------+--------------------------------------+ Now that the domain has been created, we can start adding records. You'll note that the name (www.example.com) has a trailing ``.``, as per the DNS standard, we didn't set a TTL and we had to specify the parent zone/domain by domain_id ``eacbe2a5-95f1-4a9f-89f5-b9c58009b163``. .. code-block:: shell-session $ designate record-create eacbe2a5-95f1-4a9f-89f5-b9c58009b163 --name www.example.com. --type A --data 1.2.3.4 +-------------+--------------------------------------+ | Field | Value | +-------------+--------------------------------------+ | name | www.example.com. | | data | 1.2.3.4 | | created_at | 2013-09-19T13:44:42.295428 | | updated_at | None | | id | 147f6082-8466-4951-8d13-37a10e92b11e | | priority | None | | ttl | None | | type | A | | domain_id | eacbe2a5-95f1-4a9f-89f5-b9c58009b163 | | description | None | +-------------+--------------------------------------+ subcommands ----------- We've already seen the ``domain-create`` and ``record-create`` subcommands, here the full list of subcommands: ======================= ====================================================== =============== subcommand Notes Admin Required ======================= ====================================================== =============== complete print bash completion command diagnostics-ping Ping a service on a given host domain-create Create Domain domain-delete Delete Domain domain-get Get Domain domain-list List Domains domain-servers-list List Domain Servers domain-update Update Domain help print detailed help for another command quota-get Get Quota quota-reset Reset Quota quota-update Update Quota record-create Create Record record-delete Delete Record record-get Get Record record-list List Records record-update Update Record report-count-all Get count totals for all tenants, domains and records report-count-domains Get counts for total domains report-count-records Get counts for total records report-count-tenants Get counts for total tenants report-tenant-domains Get a list of domains for given tenant report-tenants-all Get list of tenants and domain count for each server-create Create Server server-delete Delete Server server-get Get Server server-list List Servers server-update Update Server sync-all Sync Everything sync-domain Sync a single Domain sync-record Sync a single Record touch-domain Touch a single Domain ======================= ====================================================== =============== Builtin designate documentation ------------------------------- You'll find complete documentation on the shell by running ``designate --help``: usage: designate [--version] [-v] [--log-file LOG_FILE] [-q] [-h] [--debug] [--os-username OS_USERNAME] [--os-user-id OS_USER_ID] [--os-user-domain-id OS_USER_DOMAIN_ID] [--os-user-domain-name OS_USER_DOMAIN_NAME] [--os-password OS_PASSWORD] [--os-tenant-name OS_TENANT_NAME] [--os-tenant-id OS_TENANT_ID] [--os-project-name OS_PROJECT_NAME] [--os-domain-name OS_DOMAIN_NAME] [--os-domain-id OS_DOMAIN_ID] [--os-project-id OS_PROJECT_ID] [--os-project-domain-id OS_PROJECT_DOMAIN_ID] [--os-project-domain-name OS_PROJECT_DOMAIN_NAME] [--os-auth-url OS_AUTH_URL] [--os-region-name OS_REGION_NAME] [--os-token OS_TOKEN] [--os-endpoint OS_ENDPOINT] [--os-endpoint-type OS_ENDPOINT_TYPE] [--os-service-type OS_SERVICE_TYPE] [--os-cacert OS_CACERT] [--insecure] [--all-tenants] [--edit-managed] Designate Client optional arguments: --version show program's version number and exit -v, --verbose Increase verbosity of output. Can be repeated. --log-file LOG_FILE Specify a file to log output. Disabled by default. -q, --quiet Suppress output except warnings and errors. -h, --help Show this help message and exit. --debug Show tracebacks on errors. --os-username OS_USERNAME Name used for authentication with the OpenStack Identity service. Defaults to env[OS_USERNAME]. --os-user-id OS_USER_ID User ID used for authentication with the OpenStack Identity service. Defaults to env[OS_USER_ID]. --os-user-domain-id OS_USER_DOMAIN_ID Defaults to env[OS_USER_DOMAIN_ID]. --os-user-domain-name OS_USER_DOMAIN_NAME Defaults to env[OS_USER_DOMAIN_NAME]. --os-password OS_PASSWORD Password used for authentication with the OpenStack Identity service. Defaults to env[OS_PASSWORD]. --os-tenant-name OS_TENANT_NAME Tenant to request authorization on. Defaults to env[OS_TENANT_NAME]. --os-tenant-id OS_TENANT_ID Tenant to request authorization on. Defaults to env[OS_TENANT_ID]. --os-project-name OS_PROJECT_NAME Project to request authorization on. Defaults to env[OS_PROJECT_NAME]. --os-domain-name OS_DOMAIN_NAME Project to request authorization on. Defaults to env[OS_DOMAIN_NAME]. --os-domain-id OS_DOMAIN_ID Defaults to env[OS_DOMAIN_ID]. --os-project-id OS_PROJECT_ID Project to request authorization on. Defaults to env[OS_PROJECT_ID]. --os-project-domain-id OS_PROJECT_DOMAIN_ID Defaults to env[OS_PROJECT_DOMAIN_ID]. --os-project-domain-name OS_PROJECT_DOMAIN_NAME Defaults to env[OS_PROJECT_DOMAIN_NAME]. --os-auth-url OS_AUTH_URL Specify the Identity endpoint to use for authentication. Defaults to env[OS_AUTH_URL]. --os-region-name OS_REGION_NAME Specify the region to use. Defaults to env[OS_REGION_NAME]. --os-token OS_TOKEN Specify an existing token to use instead of retrieving one via authentication (e.g. with username & password). Defaults to env[OS_SERVICE_TOKEN]. --os-endpoint OS_ENDPOINT Specify an endpoint to use instead of retrieving one from the service catalog (via authentication). Defaults to env[OS_DNS_ENDPOINT]. --os-endpoint-type OS_ENDPOINT_TYPE Defaults to env[OS_ENDPOINT_TYPE]. --os-service-type OS_SERVICE_TYPE Defaults to env[OS_DNS_SERVICE_TYPE], or 'dns'. --os-cacert OS_CACERT CA certificate bundle file. Defaults to env[OS_CACERT]. --insecure Explicitly allow 'insecure' SSL requests. --all-tenants Allows to list all domains from all tenants. --edit-managed Allows to edit records that are marked as managed. Commands: complete print bash completion command diagnostics-ping Ping a service on a given host domain-create Create Domain domain-delete Delete Domain domain-get Get Domain domain-list List Domains domain-servers-list List Domain Servers domain-update Update Domain help print detailed help for another command quota-get Get Quota quota-reset Reset Quota quota-update Update Quota record-create Create Record record-delete Delete Record record-get Get Record record-list List Records record-update Update Record report-count-all Get count totals for all tenants, domains and records report-count-domains Get counts for total domains report-count-records Get counts for total records report-count-tenants Get counts for total tenants report-tenant-domains Get a list of domains for given tenant report-tenants-all Get list of tenants and domain count for each server-create Create Server server-delete Delete Server server-get Get Server server-list List Servers server-update Update Server sync-all Sync Everything sync-domain Sync a single Domain sync-record Sync a single Record touch-domain Touch a single Domain python-designateclient-2.9.0/doc/source/user/bindings.rst0000666000175100017510000003147113232475203023612 0ustar zuulzuul00000000000000.. _bindings: =========================== Python Bindings - v1 and v2 =========================== The python-designateclient package comes with python bindings for both versions of the Designate API: v1 and v2. These can be used to interact with the Designate API from any python program. Introduction - Bindings v2 ========================== To view examples of usage please checkout the *doc/examples* folder, basic usage is: .. code-block:: python #!/usr/bin/env python from designateclient.v2 import client from designateclient import shell from keystoneauth1.identity import generic from keystoneauth1 import session as keystone_session auth = generic.Password( auth_url=shell.env('OS_AUTH_URL'), username=shell.env('OS_USERNAME'), password=shell.env('OS_PASSWORD'), project_name=shell.env('OS_PROJECT_NAME'), project_domain_id='default', user_domain_id='default') session = keystone_session.Session(auth=auth) client = client.Client(session=session) zone = client.zones.create('i.io.', email='i@i.io') rs = client.recordsets.create(zone['id'], 'www', 'A', ['10.0.0.1']) Introduction ============ Below is a simple example of how to instantiate and perform basic tasks using the bindings. .. code-block:: python #!/usr/bin/env python from __future__ import print_function from designateclient.v1 import Client # Create an instance of the client, providing the necessary credentials client = Client( auth_url="https://example.com:5000/v3/", username="openstack", password="yadayada", project_name="myproject", project_domain_id='default', user_domain_id='default') # Fetch a list of the domains this user/tenant has access to domains = client.domains.list() # Iterate the list, printing some useful information for domain in domains: print("Domain ID: %s, Name: %s" % (domain.id, domain.name)) And the output this program might produce: .. code-block:: console $ python /tmp/example.py Domain ID: 467f97b4-f074-4839-ae85-1a61fccfb83d, Name: example-one.com. Domain ID: 6d3bf479-8a93-47ae-8c65-3dff8dba1b0d, Name: example-two.com. Authentication ============== Designate supports either Keystone authentication, or no authentication at all. Keystone Authentication ----------------------- Below is a sample of standard authentication with keystone using keystoneauth Sessions. For more information on keystoneauth API, see `Using Sessions`_. .. _Using Sessions: https://docs.openstack.org/keystoneauth/latest/using-sessions.html .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client from keystoneauth1.identity import generic from keystoneauth1 import session as keystone_session # Create an authentication plugin providing the necessary credentials auth = generic.Password( auth_url="https://example.com:5000/v3/", username="openstack", password="yadayada", project_name="myproject", project_domain_id='default', user_domain_id='default' ) session = keystone_session.Session(auth=auth) # Create an instance of the client, providing a keystoneauth Session client = Client(session=session) Below is a sample of standard authentication with keystone, but also explicitly providing the endpoint to use: .. note:: This is useful when a development Designate instances authenticates against a production Keystone. .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client from keystoneauth1.identity import generic from keystoneauth1 import session as keystone_session # Create an authentication plugin providing the necessary credentials auth = generic.Password( auth_url="https://example.com:5000/v3/", username="openstack", password="yadayada", project_name="myproject", project_domain_id='default', user_domain_id='default') session = keystone_session.Session(auth=auth) # Create an instance of the client, providing a keystoneauth Session client = Client( session=session, endpoint="https://127.0.0.1:9001/v1/") No Authentication ----------------- Below is a sample of interaction with a non authenticated designate: .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client, providing the endpoint directly client = Client( endpoint="https://127.0.0.1:9001/v1/" ) Working with Domains ==================== The Domain Object ----------------- Object Properties: ======================= ======================================================= Property Description ======================= ======================================================= id Domain ID name Domain Name (e.g. example.com.) email Domain Responsible Person Email (e.g. fred@example.com) ttl Default TTL for records serial Domain Server Number created_at Date and time this domain was created at updated_at Date and time this domain was last updated description Domain Description ======================= ======================================================= Listing Domains --------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) # List All Domains domains = client.domains.list() Fetching a Domain by ID ----------------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) domain_id = 'fb505f10-25df-11e3-8224-0800200c9a66' # Fetch the domain domain = client.domains.get(domain_id) Creating a Domain ----------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client from designateclient.v1.domains import Domain # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) # Create a new Domain object domain = Domain(name="example.com.", email="fred@example.com") # Send the Create Domain API call domain = client.domains.create(domain) Updating a Domain ----------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) domain_id = 'fb505f10-25df-11e3-8224-0800200c9a66' # Fetch the domain domain = client.domains.get(domain_id) # Update a value on the Domain domain.ttl = 300 # Send the Update Domain API call domain = client.domains.update(domain) Deleting a Domain ----------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) domain_id = 'fb505f10-25df-11e3-8224-0800200c9a66' # Fetch the domain domains = client.domains.delete(domain_id) Working with Records ==================== The Record Object ----------------- Object Properties: ======================= ======================================================= Property Description ======================= ======================================================= id Record ID domain_id Domain ID name Record Name (e.g. example.com.) type Record Type (e.g. A, AAAA, CNAME, MX, SRV etc) data Record Data (e.g. 127.0.0.1) priority Rercord Priority (Valid only for MX and SRV records) ttl Record TTL created_at Date and time this record was created at updated_at Date and time this record was last updated description Record Description ======================= ======================================================= Listing Records --------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) domain_id = 'fb505f10-25df-11e3-8224-0800200c9a66' # List All Records records = client.records.list(domain_id) Fetching a Record by ID ----------------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) domain_id = 'fb505f10-25df-11e3-8224-0800200c9a66' record_id = 'bd3e8520-25e0-11e3-8224-0800200c9a66' # Fetch the record records = client.records.get(domain_id, record_id) Creating a Record ----------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client from designateclient.v1.records import Record # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) domain_id = 'fb505f10-25df-11e3-8224-0800200c9a66' # Create a new Record object record = Record(name="www.example.com.", type="A", data="127.0.0.1") # Send the Create Record API call record = client.records.create(domain_id, record) Updating a Record ----------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) domain_id = 'fb505f10-25df-11e3-8224-0800200c9a66' record_id = 'bd3e8520-25e0-11e3-8224-0800200c9a66' # Fetch the record record = client.records.get(record_id) # Update a value on the Record record.ttl = 300 # Send the Update Record API call record = client.records.update(domain_id, record) Deleting a Record ----------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) domain_id = 'fb505f10-25df-11e3-8224-0800200c9a66' record_id = 'bd3e8520-25e0-11e3-8224-0800200c9a66' # Fetch the record records = client.records.delete(domain_id, record_id) Working with Servers ==================== The Server Object ----------------- Object Properties: ======================= ======================================================= Property Description ======================= ======================================================= id Server ID name Server Name (e.g. example.com.) created_at Date and time this server was created at updated_at Date and time this server was last updated ======================= ======================================================= Listing Servers --------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) # List All Servers servers = client.servers.list() Fetching a Server by ID ----------------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) server_id = 'fb505f10-25df-11e3-8224-0800200c9a66' # Fetch the server server = client.servers.get(server_id) Creating a Server ----------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client from designateclient.v1.servers import Server # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) # Create a new Server object server = Server(name="ns1.example.com.") # Send the Create Server API call server = client.servers.create(server) Updating a Server ----------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) server_id = 'fb505f10-25df-11e3-8224-0800200c9a66' # Fetch the server server = client.servers.get(server_id) # Update a value on the Server server.name = "ns2.example.com" # Send the Update Server API call server = client.servers.update(server) Deleting a Server ----------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) server_id = 'fb505f10-25df-11e3-8224-0800200c9a66' # Fetch the server servers = client.servers.delete(server_id) python-designateclient-2.9.0/doc/source/user/index.rst0000666000175100017510000000023613232475203023117 0ustar zuulzuul00000000000000============================== Using python-designateclient ============================== .. toctree:: bindings shell-v2 shell shell-examples python-designateclient-2.9.0/doc/source/user/shell-v2.rst0000666000175100017510000005575213232475203023461 0ustar zuulzuul00000000000000.. _shell-v2: =========================== OpenStack CLI (v2 API only) =========================== The python-designateclient package comes with a plugin for the openstack command line tool (installed as :program:`openstack`). This can be used to access a Designate API without having to manipulate JSON by hand, it can also produce the output in a variety of formats (JSON, CSV) and allow you to select columns to be displayed. Installation ------------ Both *python-openstackclient* and *python-designateclient* must be installed: :: $ pip install python-openstackclient python-designateclient Configuration ------------- :program:`openstack` requires certain information to talk to the REST API. An in-depth explanation is covered in the `OpenStack Client configuration documentation`_. To get started, all you usually need are the following variables: :: OS_AUTH_VERSION=3 OS_IDENTITY_API_VERSION=3 OS_AUTH_URL=http://127.0.0.1:5000/v3 OS_PROJECT_NAME=demo OS_USERNAME=demo OS_TENANT_NAME=demo OS_PASSWORD=password Using the Command Line Tool --------------------------- With enough details now in the environment, you can use the :program:`openstack` to create a zone and populate it with some records: .. code-block:: shell-session $ openstack zone create --email admin@example.com example.com. +----------------+--------------------------------------+ | Field | Value | +----------------+--------------------------------------+ | action | CREATE | | created_at | 2016-04-19T17:44:04.000000 | | description | None | | email | admin@example.com | | id | 388814ef-3c5d-415e-a866-5b1d13d78dae | | masters | | | name | example.com. | | pool_id | 794ccc2c-d751-44fe-b57f-8894c9f5c842 | | project_id | 123456 | | serial | 1461087844 | | status | PENDING | | transferred_at | None | | ttl | 3600 | | type | PRIMARY | | updated_at | None | | version | 1 | +----------------+--------------------------------------+ Now that the zone has been created, we can start adding records. You'll note that the zone name (example.com) has a trailing ``.``, as per the DNS standard, and we didn't set a TTL. .. code-block:: shell-session $ openstack recordset create --type A --records 192.0.2.20 example.com. www +-------------+--------------------------------------+ | Field | Value | +-------------+--------------------------------------+ | action | CREATE | | created_at | 2016-04-19T17:51:12.000000 | | description | None | | id | 180d3574-3c29-4ea2-b6ff-df904bd3f126 | | name | www.example.com. | | records | 192.0.2.20 | | status | PENDING | | ttl | None | | type | A | | updated_at | None | | version | 1 | | zone_id | 388814ef-3c5d-415e-a866-5b1d13d78dae | +-------------+--------------------------------------+ Designate-specific Subcommands ------------------------------ Aside from the ``zone create`` and ``recordset create`` subcommands, this is the full list of subcommands that enable Designate V2 support: ============================ ====================================================== =============== subcommand Notes Admin Required ============================ ====================================================== =============== zone create Create new zone zone list List zones zone show Show zone details zone set Set zone properties zone delete Delete zone recordset create Create new recordset recordset list List recordsets recordset list all List all recordsets in all zones recordset show Show recordset details recordset set Set recordset properties recordset delete Delete recordset ptr record list List floatingip ptr records ptr record show Show floatingip ptr record details ptr record set Set floatingip ptr record ptr record unset Unset floatingip ptr record zone export create Export a Zone zone export list List Zone Exports zone export show Show a Zone Export zone export delete Delete a Zone Export zone export showfile Show the zone file for the Zone Export zone import create Import a Zone from a file on the filesystem zone import list List Zone Imports zone import show Show a Zone Import zone import delete Delete a Zone Import zone transfer request create Create new zone transfer request zone transfer request list List Zone Transfer Requests zone transfer request show Show Zone Transfer Request Details zone transfer request set Set a Zone Transfer Request zone transfer request delete Delete a Zone Transfer Request zone transfer accept request Accept a Zone Transfer Request zone transfer accept list List Zone Transfer Accepts zone transfer accept show Show Zone Transfer Accept zone abandon Abandon a zone Yes zone axfr AXFR a zone zone blacklist create Create new blacklist Yes zone blacklist list List blacklists Yes zone blacklist show Show blacklist details Yes zone blacklist set Set blacklist properties Yes zone blacklist delete Delete blacklist Yes tld create Create new tld Yes tld list List tlds Yes tld show Show tld details Yes tld set Set tld properties Yes tld delete Delete tld Yes ============================ ====================================================== =============== Built-in Designate Documentation -------------------------------- You'll find complete documentation on the shell by running: ``openstack --help`` For a specific command, you can execute: ``openstack subcommand help`` Examples -------- Because command output would make this document long, much of it will be omitted from some examples. Working with Zones '''''''''''''''''' Create a zone with the following command: .. code-block:: shell-session $ openstack zone create --email admin@example.com example.com. +----------------+--------------------------------------+ | Field | Value | +----------------+--------------------------------------+ | action | CREATE | | created_at | 2016-04-19T17:44:04.000000 | | description | None | | email | admin@example.com | | id | 388814ef-3c5d-415e-a866-5b1d13d78dae | | masters | | | name | example.com. | | pool_id | 794ccc2c-d751-44fe-b57f-8894c9f5c842 | | project_id | 123456 | | serial | 1461087844 | | status | PENDING | | transferred_at | None | | ttl | 3600 | | type | PRIMARY | | updated_at | None | | version | 1 | +----------------+--------------------------------------+ See the new zone in your list of zones with the following command: .. code-block:: shell-session $ openstack zone list Display a specific zone with either of these commands; most zone commands accept either the zone_id or name attribute: .. code-block:: shell-session $ openstack zone show example.com. $ openstack zone show 388814ef-3c5d-415e-a866-5b1d13d78dae Update the zone with this command: .. code-block:: shell-session $ openstack zone set --description "Description" example.com. Delete the zone with this command: .. code-block:: shell-session $ openstack zone delete example.com. Working with Recordsets ''''''''''''''''''''''' Using the zone above, create a recordset with the following command: .. code-block:: shell-session $ openstack recordset create example.com. --type A www --records 192.0.2.20 +-------------+--------------------------------------+ | Field | Value | +-------------+--------------------------------------+ | action | CREATE | | created_at | 2016-04-19T17:51:12.000000 | | description | None | | id | 180d3574-3c29-4ea2-b6ff-df904bd3f126 | | name | www.example.com. | | records | 192.0.2.20 | | status | PENDING | | ttl | None | | type | A | | updated_at | None | | version | 1 | | zone_id | 388814ef-3c5d-415e-a866-5b1d13d78dae | +-------------+--------------------------------------+ Multiple records can be provided for a specific recordset type: .. code-block:: shell-session $ openstack recordset create example.com. --type A www --records 192.0.2.20 192.0.2.21 See the new recordset in the list of recordsets with the following command: .. code-block:: shell-session $ openstack recordset list example.com. Display a specific recordset: .. code-block:: shell-session $ openstack recordset show example.com. www.example.com. Update a specific recordset: .. code-block:: shell-session $ openstack recordset set example.com. www.example.com. --ttl 10000 --records 192.0.2.20 192.0.2.21 Delete a recordset: .. code-block:: shell-session $ openstack recordset delete example.com. www.example.com. Working with PTR Records '''''''''''''''''''''''' Reverse DNS for Neutron Floating IPs can be managed with the "ptr" subcommand. Create a PTR record: .. code-block:: shell-session $ openstack ptr record set RegionOne:5c02c519-4928-4a38-bd10-c748c200912f ftp.example.com. +-------------+------------------------------------------------+ | Field | Value | +-------------+------------------------------------------------+ | action | CREATE | | address | 172.24.4.11 | | description | None | | id | RegionOne:5c02c519-4928-4a38-bd10-c748c200912f | | ptrdname | ftp.example.com. | | status | PENDING | | ttl | 3600 | +-------------+------------------------------------------------+ List all PTR records: .. code-block:: shell-session $ openstack ptr record list Show a PTR record: .. code-block:: shell-session $ openstack ptr record show RegionOne:5c02c519-4928-4a38-bd10-c748c200912f Delete a PTR record: .. code-block:: shell-session $ openstack ptr record delete RegionOne:5c02c519-4928-4a38-bd10-c748c200912f Working with Zone Exports ''''''''''''''''''''''''' Zone exports enable you to save Designate zone information offline. Create a zone export: .. code-block:: shell-session $ openstack zone export create example.com. +------------+--------------------------------------+ | Field | Value | +------------+--------------------------------------+ | created_at | 2016-04-19T20:42:16.000000 | | id | 6d5acb9d-f3d6-4ed4-96e1-03bc0e405bb5 | | location | None | | message | None | | project_id | 123456 | | status | PENDING | | updated_at | None | | version | 1 | | zone_id | 388814ef-3c5d-415e-a866-5b1d13d78dae | +------------+--------------------------------------+ List zone exports: .. code-block:: shell-session $ openstack zone export list Show zone export: .. code-block:: shell-session $ openstack zone export show 6d5acb9d-f3d6-4ed4-96e1-03bc0e405bb5 Show the zone file for the Zone Export: .. code-block:: shell-session $ openstack zone export showfile 6d5acb9d-f3d6-4ed4-96e1-03bc0e405bb5 -f value $ORIGIN example.com. $TTL 3600 example.com. IN NS ns2.exampleprovider.com. example.com. IN NS ns1.exampleprovider.com. example.com. IN SOA ns.exampleprovider.com. admin@example.com 1458678636 7200 300 604800 300 Delete zone export: .. code-block:: shell-session $ openstack zone export delete 6d5acb9d-f3d6-4ed4-96e1-03bc0e405bb5 Working with Zone Imports ''''''''''''''''''''''''' Zone imports enable you to import a zone into Designate from a file on the filesystem. Create a zone import from a file: .. code-block:: shell-session $ openstack zone import create zonefile.txt +------------+--------------------------------------+ | Field | Value | +------------+--------------------------------------+ | created_at | 2016-04-19T20:59:38.000000 | | id | bab6e152-da9f-4dfc-8a59-3f9710fe4894 | | message | None | | project_id | 123456 | | status | PENDING | | updated_at | None | | version | 1 | | zone_id | None | +------------+--------------------------------------+ List zone imports: .. code-block:: shell-session $ openstack zone import list Show zone import: .. code-block:: shell-session $ openstack zone import show 839d8041-1960-4d74-8533-118d52218074 Delete zone import: .. code-block:: shell-session $ openstack zone import delete 839d8041-1960-4d74-8533-118d52218074 Working with Zone Blacklists '''''''''''''''''''''''''''' Blacklisting zone names enables you to block any zone pattern from creation. Create a zone blacklist .. code-block:: shell-session $ openstack zone blacklist create --pattern "^example\.com\.$" --description "This is a blacklisted domain." +-------------+--------------------------------------+ | Field | Value | +-------------+--------------------------------------+ | created_at | 2016-05-10 00:26:07 | | description | This is a blacklisted domain. | | id | 308ecb82-4952-4476-88b4-9db18fc78e10 | | pattern | ^example.com.$ | | updated_at | None | +-------------+--------------------------------------+ List zone blacklist .. code-block:: shell-session $ openstack zone blacklist list Show zone blacklist .. code-block:: shell-session $ openstack zone blacklist show 308ecb82-4952-4476-88b4-9db18fc78e10 Update zone blacklist .. code-block:: shell-session $ openstack zone blacklist set --pattern "^([A-Za-z0-9_\-]+\.)*example\.com\.$" --description "Updated the description" 308ecb82-4952-4476-88b4-9db18fc78e10 Delete a zone blacklist .. code-block:: shell-session $ openstack zone blacklist delete 308ecb82-4952-4476-88b4-9db18fc78e10 Working with Zone Transfers Between Projects '''''''''''''''''''''''''''''''''''''''''''' Zone Transfers enable you to perform the transfer of zone ownership to another project. Create a Zone Transfer Request .. code-block:: shell-session $ openstack zone transfer request create --target-project-id 9cc52dd7649c4aa99fa9db2fb94dabb8 53cdcf82-9e32-4a00-a90d-32d6ec5db7e9 +-------------------+----------------------------------------------------------------------------------------+ | Field | Value | +-------------------+----------------------------------------------------------------------------------------+ | created_at | 2016-05-10 01:39:00 | | description | None | | id | 98ba1d22-c092-4603-891f-8a0ab04f7e57 | | key | J6JCET2C | | links | {u'self': | | | u'http://192.168.11.182:9001/v2/zones/tasks/transfer_requests/98ba1d22-c092-4603-891f- | | | 8a0ab04f7e57'} | | project_id | 10457ad1fe074f4a89bb1e4c0cd83d40 | | status | ACTIVE | | target_project_id | 9cc52dd7649c4aa99fa9db2fb94dabb8 | | updated_at | None | | zone_id | 53cdcf82-9e32-4a00-a90d-32d6ec5db7e9 | | zone_name | example.com. | +-------------------+----------------------------------------------------------------------------------------+ List Zone Transfer Requests .. code-block:: shell-session $ openstack zone transfer request list Show Zone Transfer Request Details .. code-block:: shell-session $ openstack zone transfer request show 98ba1d22-c092-4603-891f-8a0ab04f7e57 Update a Zone Transfer Request .. code-block:: shell-session $ openstack zone transfer request set 98ba1d22-c092-4603-891f-8a0ab04f7e57 --description "demo transfer" Delete a Zone Transfer Request .. code-block:: shell-session $ openstack zone transfer request delete 98ba1d22-c092-4603-891f-8a0ab04f7e57 Accept a Zone Transfer Request .. code-block:: shell-session $ openstack zone transfer accept request --transfer-id 98ba1d22-c092-4603-891f-8a0ab04f7e57 --key J6JCET2C +--------------------------+---------------------------------------------------------------------------------+ | Field | Value | +--------------------------+---------------------------------------------------------------------------------+ | created_at | 2016-05-10 05:02:52 | | id | a8750f50-d7e6-403a-89d2-e209d62ef60e | | key | J6JCET2C | | links | {u'self': | | | u'http://192.168.11.182:9001/v2/zones/tasks/transfer_accepts/a8750f50-d7e6 | | | -403a-89d2-e209d62ef60e', u'zone': | | | u'http://192.168.11.182:9001/v2/zones/53cdcf82-9e32-4a00-a90d-32d6ec5db7e9'} | | project_id | 10457ad1fe074f4a89bb1e4c0cd83d40 | | status | COMPLETE | | updated_at | 2016-05-10 05:02:52 | | zone_id | 53cdcf82-9e32-4a00-a90d-32d6ec5db7e9 | | zone_transfer_request_id | 98ba1d22-c092-4603-891f-8a0ab04f7e57 | +--------------------------+---------------------------------------------------------------------------------+ Show Zone Transfer Accept .. code-block:: shell-session $ openstack zone transfer accept show a8750f50-d7e6-403a-89d2-e209d62ef60e List Zone Transfer Accept .. code-block:: shell-session $ openstack zone transfer accept list Working with Top Level Domains '''''''''''''''''''''''''''''' The tld commands enable you to manage top level domains. Create a TLD .. code-block:: shell-session $ openstack tld create --name com --description "demo TLD" +-------------+--------------------------------------+ | Field | Value | +-------------+--------------------------------------+ | created_at | 2016-05-10 05:21:40 | | description | demo TLD | | id | a7bba387-712b-4b42-9368-4508642c6113 | | name | com | | updated_at | None | +-------------+--------------------------------------+ List TLDs .. code-block:: shell-session $ openstack tld list Show TLD Details .. code-block:: shell-session $ openstack tld show a7bba387-712b-4b42-9368-4508642c6113 Update a TLD .. code-block:: shell-session $ openstack tld set a7bba387-712b-4b42-9368-4508642c6113 --name org --description "TLD description" Delete a TLD .. code-block:: shell-session $ openstack tld delete a7bba387-712b-4b42-9368-4508642c6113 .. _OpenStack Client configuration documentation: https://docs.openstack.org/python-openstackclient/latest/configuration/index.html python-designateclient-2.9.0/doc/source/conf.py0000666000175100017510000000361613232475203021604 0ustar zuulzuul00000000000000# -*- coding: utf-8 -*- # # designateclient documentation build configuration file # -- 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.viewcode', 'openstackdocstheme'] # openstackdocstheme options repository_name = 'openstack/python-designateclient' bug_project = 'python-designateclient' bug_tag = '' html_last_updated_fmt = '%Y-%m-%d %H:%M' html_theme = 'openstackdocs' # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The master toctree document. master_doc = 'index' # General information about the project. project = u'designateclient' copyright = u'2012, Managed I.T. 2013-2014, Hewlett-Packard Development Company, L.P.' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. from designateclient.version import version_info as designateclient_version version = designateclient_version.canonical_version_string() # The full version, including alpha/beta/rc tags. release = designateclient_version.version_string_with_vcs() # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = [] # 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 = ['designateclient'] # -- Options for HTML output --------------------------------------------------- # Output file base name for HTML help builder. htmlhelp_basename = 'designateclientdoc' python-designateclient-2.9.0/doc/source/install/0000775000175100017510000000000013232475552021752 5ustar zuulzuul00000000000000python-designateclient-2.9.0/doc/source/install/index.rst0000666000175100017510000000273113232475203023611 0ustar zuulzuul00000000000000============ Installation ============ Install the client from PyPI ---------------------------- The :program:`python-designateclient` package is published on `PyPI`_ and so can be installed using the pip tool, which will manage installing all python dependencies: .. code-block:: shell-session pip install python-designateclient *Warning: the packages on PyPI may lag behind the git repo in functionality.* Setup the client from source ---------------------------- If you want the latest version, straight from github: .. code-block:: shell-session git clone git@github.com:openstack/python-designateclient.git cd python-designateclient virtualenv .venv . .venv/bin/activate pip install -r requirements.txt -r test-requirements.txt python setup.py install Setup the client in development mode ------------------------------------ Installing in development mode allows your to make changes to the source code & test directly without having to re-run the "python setup.py install" step. You can find out more about `Development Mode`_ .. code-block:: shell-session git clone git@github.com:openstack/python-designateclient.git cd python-designateclient virtualenv .venv . .venv/bin/activate pip install -r requirements.txt -r test-requirements.txt python setup.py develop .. _Development Mode: https://setuptools.readthedocs.io/en/latest/setuptools.html#development-mode .. _PyPI: https://pypi.python.org/pypi/python-designateclient/ python-designateclient-2.9.0/doc/source/reference/0000775000175100017510000000000013232475552022242 5ustar zuulzuul00000000000000python-designateclient-2.9.0/doc/source/reference/index.rst0000666000175100017510000000021013232475203024067 0ustar zuulzuul00000000000000================================== python-designateclient Reference ================================== .. toctree:: api/autoindex python-designateclient-2.9.0/doc/source/contributor/0000775000175100017510000000000013232475552022656 5ustar zuulzuul00000000000000python-designateclient-2.9.0/doc/source/contributor/functional-tests.rst0000666000175100017510000000314613232475203026711 0ustar zuulzuul00000000000000================ Functional Tests ================ The functional tests invoke the client executable to see that it actually works with a running Designate. WARNING: these tests will create and delete zones, recordsets, and other resources in Designate. Installation ------------ .. code-block:: shell-session cd python-designateclient pip install python-openstackclient pip install -r requirements.txt -r test-requirements.txt pip install -e . Configuration ------------- The functional tests look for a variable ``TEMPEST_CONFIG`` which specifies a config file for the test. .. code-block:: shell-session export TEMPEST_CONFIG=tempest.conf The tests will use Keystone to grab the Designate endpoint to test against. They need at least three users (two regular users, and one admin) for all the tests to run. .. code-block:: shell-session [identity] uri = http://localhost:5000/v2.0 uri_v3 = http://localhost:5000/v3 auth_version = v2 region = RegionOne username = demo tenant_name = demo password = password domain_name = Default alt_username = alt_demo alt_tenant_name = alt_demo alt_password = password alt_domain_name = Default admin_username = admin admin_tenant_name = admin admin_password = password admin_domain_name = Default [designateclient] # the directory containing the openstack executable directory=/root/python-designateclient/.venv/bin Running the tests ----------------- The functional tests are run with tox (installed with ``pip install tox``): .. code-block:: shell-session tox -e functional python-designateclient-2.9.0/doc/source/contributor/contributing.rst0000666000175100017510000000147713232475203026123 0ustar zuulzuul00000000000000Contributing ============ Code is hosted `on GitHub`_. Submit bugs to the Designate Client project on `Launchpad`_. Submit code to the openstack/python-designateclient project using `Gerrit`_. .. _on GitHub: https://github.com/openstack/python-designateclient .. _Launchpad: https://launchpad.net/python-designateclient .. _Gerrit: https://docs.openstack.org/infra/manual/developers.html#development-workflow Here's a quick summary: Install the git-review package to make life easier .. code-block:: shell-session pip install git-review Branch, work, & submit: .. code-block:: shell-session # cut a new branch, tracking master git checkout --track -b bug/id origin/master # work work work git add stuff git commit # rebase/squash to a single commit before submitting git rebase -i # submit git-review python-designateclient-2.9.0/doc/source/contributor/index.rst0000666000175100017510000000016113232475203024510 0ustar zuulzuul00000000000000==================== Contributors Guide ==================== .. toctree:: contributing functional-tests python-designateclient-2.9.0/doc/source/cli/0000775000175100017510000000000013232475552021053 5ustar zuulzuul00000000000000python-designateclient-2.9.0/doc/source/cli/index.rst0000666000175100017510000005623413232475203022721 0ustar zuulzuul00000000000000.. ################################################### .. ## WARNING ###################################### .. ############## WARNING ########################## .. ########################## WARNING ############## .. ###################################### WARNING ## .. ################################################### .. ################################################### .. ## .. This file is tool-generated. Do not edit manually. .. http://docs.openstack.org/contributor-guide/ .. doc-tools/cli-reference.html .. ## .. ## WARNING ###################################### .. ############## WARNING ########################## .. ########################## WARNING ############## .. ###################################### WARNING ## .. ################################################### =========================================== DNS service (designate) command-line client =========================================== The designate client is the command-line interface (CLI) for the DNS service (designate) API and its extensions. This chapter documents :command:`designate` version ``2.6.0``. For help on a specific :command:`designate` command, enter: .. code-block:: console $ designate help COMMAND .. _designate_command_usage: designate usage ~~~~~~~~~~~~~~~ .. code-block:: console usage: designate [--version] [-v | -q] [--log-file LOG_FILE] [-h] [--debug] [--os-username OS_USERNAME] [--os-user-id OS_USER_ID] [--os-user-domain-id OS_USER_DOMAIN_ID] [--os-user-domain-name OS_USER_DOMAIN_NAME] [--os-password OS_PASSWORD] [--os-tenant-name OS_TENANT_NAME] [--os-tenant-id OS_TENANT_ID] [--os-project-name OS_PROJECT_NAME] [--os-domain-name OS_DOMAIN_NAME] [--os-domain-id OS_DOMAIN_ID] [--os-project-id OS_PROJECT_ID] [--os-project-domain-id OS_PROJECT_DOMAIN_ID] [--os-project-domain-name OS_PROJECT_DOMAIN_NAME] [--os-auth-url OS_AUTH_URL] [--os-region-name OS_REGION_NAME] [--os-token OS_TOKEN] [--os-endpoint OS_ENDPOINT] [--os-endpoint-type OS_ENDPOINT_TYPE] [--os-service-type OS_SERVICE_TYPE] [--os-cacert OS_CACERT] [--insecure] [--all-tenants] [--edit-managed] .. _designate_command_options: designate optional arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``--version`` show program's version number and exit ``-v, --verbose`` Increase verbosity of output. Can be repeated. ``-q, --quiet`` Suppress output except warnings and errors. ``--log-file LOG_FILE`` Specify a file to log output. Disabled by default. ``-h, --help`` Show help message and exit. ``--debug`` Show tracebacks on errors. ``--os-username OS_USERNAME`` Name used for authentication with the OpenStack Identity service. Defaults to ``env[OS_USERNAME]``. ``--os-user-id OS_USER_ID`` User ID used for authentication with the OpenStack Identity service. Defaults to ``env[OS_USER_ID]``. ``--os-user-domain-id OS_USER_DOMAIN_ID`` Defaults to ``env[OS_USER_DOMAIN_ID]``. ``--os-user-domain-name OS_USER_DOMAIN_NAME`` Defaults to ``env[OS_USER_DOMAIN_NAME]``. ``--os-password OS_PASSWORD`` Password used for authentication with the OpenStack Identity service. Defaults to ``env[OS_PASSWORD]``. ``--os-tenant-name OS_TENANT_NAME`` Tenant to request authorization on. Defaults to ``env[OS_TENANT_NAME]``. ``--os-tenant-id OS_TENANT_ID`` Tenant to request authorization on. Defaults to ``env[OS_TENANT_ID]``. ``--os-project-name OS_PROJECT_NAME`` Project to request authorization on. Defaults to ``env[OS_PROJECT_NAME]``. ``--os-domain-name OS_DOMAIN_NAME`` Project to request authorization on. Defaults to ``env[OS_DOMAIN_NAME]``. ``--os-domain-id OS_DOMAIN_ID`` Defaults to ``env[OS_DOMAIN_ID]``. ``--os-project-id OS_PROJECT_ID`` Project to request authorization on. Defaults to ``env[OS_PROJECT_ID]``. ``--os-project-domain-id OS_PROJECT_DOMAIN_ID`` Defaults to ``env[OS_PROJECT_DOMAIN_ID]``. ``--os-project-domain-name OS_PROJECT_DOMAIN_NAME`` Defaults to ``env[OS_PROJECT_DOMAIN_NAME]``. ``--os-auth-url OS_AUTH_URL`` Specify the Identity endpoint to use for authentication. Defaults to ``env[OS_AUTH_URL]``. ``--os-region-name OS_REGION_NAME`` Specify the region to use. Defaults to ``env[OS_REGION_NAME]``. ``--os-token OS_TOKEN`` Specify an existing token to use instead of retrieving one via authentication (e.g. with username & password). Defaults to ``env[OS_SERVICE_TOKEN]``. ``--os-endpoint OS_ENDPOINT`` Specify an endpoint to use instead of retrieving one from the service catalog (via authentication). Defaults to ``env[OS_DNS_ENDPOINT]``. ``--os-endpoint-type OS_ENDPOINT_TYPE`` Defaults to ``env[OS_ENDPOINT_TYPE]``. ``--os-service-type OS_SERVICE_TYPE`` Defaults to ``env[OS_DNS_SERVICE_TYPE]``, or 'dns'. ``--os-cacert OS_CACERT`` CA certificate bundle file. Defaults to ``env[OS_CACERT]``. ``--insecure`` Explicitly allow 'insecure' SSL requests. ``--all-tenants`` Allows to list all domains from all tenants. ``--edit-managed`` Allows to edit records that are marked as managed. .. _designate_diagnostics-ping: designate diagnostics-ping -------------------------- .. code-block:: console usage: designate diagnostics-ping [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] --service SERVICE --host HOST Ping a service on a given host **Optional arguments:** ``-h, --help`` show this help message and exit ``--service SERVICE`` Service name (e.g. central) ``--host HOST`` Hostname .. _designate_domain-create: designate domain-create ----------------------- .. code-block:: console usage: designate domain-create [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] --name NAME --email EMAIL [--ttl TTL] [--description DESCRIPTION] Create Domain **Optional arguments:** ``-h, --help`` show this help message and exit ``--name NAME`` Domain name. ``--email EMAIL`` Domain email. ``--ttl TTL`` Time to live (seconds). ``--description DESCRIPTION`` Description. .. _designate_domain-delete: designate domain-delete ----------------------- .. code-block:: console usage: designate domain-delete [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] id Delete Domain **Positional arguments:** ``id`` Domain ID or name. **Optional arguments:** ``-h, --help`` show this help message and exit .. _designate_domain-get: designate domain-get -------------------- .. code-block:: console usage: designate domain-get [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] id Get Domain **Positional arguments:** ``id`` Domain ID or name. **Optional arguments:** ``-h, --help`` show this help message and exit .. _designate_domain-list: designate domain-list --------------------- .. code-block:: console usage: designate domain-list [-h] [-f {csv,html,json,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--quote {all,minimal,none,nonnumeric}] List Domains **Optional arguments:** ``-h, --help`` show this help message and exit .. _designate_domain-servers-list: designate domain-servers-list ----------------------------- .. code-block:: console usage: designate domain-servers-list [-h] [-f {csv,html,json,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--quote {all,minimal,none,nonnumeric}] id List Domain Servers **Positional arguments:** ``id`` Domain ID or name. **Optional arguments:** ``-h, --help`` show this help message and exit .. _designate_domain-update: designate domain-update ----------------------- .. code-block:: console usage: designate domain-update [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] [--name NAME] [--email EMAIL] [--ttl TTL] [--description DESCRIPTION | --no-description] id Update Domain **Positional arguments:** ``id`` Domain ID or name. **Optional arguments:** ``-h, --help`` show this help message and exit ``--name NAME`` Domain name. ``--email EMAIL`` Domain email. ``--ttl TTL`` Time to live (seconds). ``--description DESCRIPTION`` Description. ``--no-description`` .. _designate_quota-get: designate quota-get ------------------- .. code-block:: console usage: designate quota-get [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] tenant_id Get Quota **Positional arguments:** ``tenant_id`` Tenant ID **Optional arguments:** ``-h, --help`` show this help message and exit .. _designate_quota-reset: designate quota-reset --------------------- .. code-block:: console usage: designate quota-reset [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] tenant_id Reset Quota **Positional arguments:** ``tenant_id`` Tenant ID. **Optional arguments:** ``-h, --help`` show this help message and exit .. _designate_quota-update: designate quota-update ---------------------- .. code-block:: console usage: designate quota-update [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] [--domains DOMAINS] [--domain-recordsets DOMAIN_RECORDSETS] [--recordset-records RECORDSET_RECORDS] [--domain-records DOMAIN_RECORDS] [--api-export-size API_EXPORT_SIZE] tenant_id Update Quota **Positional arguments:** ``tenant_id`` Tenant ID. **Optional arguments:** ``-h, --help`` show this help message and exit ``--domains DOMAINS`` Allowed domains. ``--domain-recordsets DOMAIN_RECORDSETS`` Allowed domain records. ``--recordset-records RECORDSET_RECORDS`` Allowed recordset records. ``--domain-records DOMAIN_RECORDS`` Allowed domain records. ``--api-export-size API_EXPORT_SIZE`` Allowed zone export recordsets. .. _designate_record-create: designate record-create ----------------------- .. code-block:: console usage: designate record-create [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] --name NAME --type TYPE --data DATA [--ttl TTL] [--priority PRIORITY] [--description DESCRIPTION] domain_id Create Record **Positional arguments:** ``domain_id`` Domain ID or name. **Optional arguments:** ``-h, --help`` show this help message and exit ``--name NAME`` Record (relative|absolute) name. ``--type TYPE`` Record type. ``--data DATA`` Record data. ``--ttl TTL`` Record TTL. ``--priority PRIORITY`` Record priority. ``--description DESCRIPTION`` Description. .. _designate_record-delete: designate record-delete ----------------------- .. code-block:: console usage: designate record-delete [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] domain_id id Delete Record **Positional arguments:** ``domain_id`` Domain ID or name. ``id`` Record ID. **Optional arguments:** ``-h, --help`` show this help message and exit .. _designate_record-get: designate record-get -------------------- .. code-block:: console usage: designate record-get [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] domain_id id Get Record **Positional arguments:** ``domain_id`` Domain ID or name. ``id`` Record ID. **Optional arguments:** ``-h, --help`` show this help message and exit .. _designate_record-list: designate record-list --------------------- .. code-block:: console usage: designate record-list [-h] [-f {csv,html,json,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--quote {all,minimal,none,nonnumeric}] domain_id List Records **Positional arguments:** ``domain_id`` Domain ID or name. **Optional arguments:** ``-h, --help`` show this help message and exit .. _designate_record-update: designate record-update ----------------------- .. code-block:: console usage: designate record-update [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] [--name NAME] [--type TYPE] [--data DATA] [--description DESCRIPTION | --no-description] [--ttl TTL | --no-ttl] [--priority PRIORITY | --no-priority] domain_id id Update Record **Positional arguments:** ``domain_id`` Domain ID or name. ``id`` Record ID. **Optional arguments:** ``-h, --help`` show this help message and exit ``--name NAME`` Record name. ``--type TYPE`` Record type. ``--data DATA`` Record data. ``--description DESCRIPTION`` Description. ``--no-description`` ``--ttl TTL`` Record time to live (seconds). ``--no-ttl`` ``--priority PRIORITY`` Record priority. ``--no-priority`` .. _designate_report-count-all: designate report-count-all -------------------------- .. code-block:: console usage: designate report-count-all [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] Get count totals for all tenants, domains and records **Optional arguments:** ``-h, --help`` show this help message and exit .. _designate_report-count-domains: designate report-count-domains ------------------------------ .. code-block:: console usage: designate report-count-domains [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] Get counts for total domains **Optional arguments:** ``-h, --help`` show this help message and exit .. _designate_report-count-records: designate report-count-records ------------------------------ .. code-block:: console usage: designate report-count-records [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] Get counts for total records **Optional arguments:** ``-h, --help`` show this help message and exit .. _designate_report-count-tenants: designate report-count-tenants ------------------------------ .. code-block:: console usage: designate report-count-tenants [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] Get counts for total tenants **Optional arguments:** ``-h, --help`` show this help message and exit .. _designate_report-tenant-domains: designate report-tenant-domains ------------------------------- .. code-block:: console usage: designate report-tenant-domains [-h] [-f {csv,html,json,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--quote {all,minimal,none,nonnumeric}] --report-tenant-id REPORT_TENANT_ID Get a list of domains for given tenant **Optional arguments:** ``-h, --help`` show this help message and exit ``--report-tenant-id REPORT_TENANT_ID`` The tenant_id being reported on. .. _designate_report-tenants-all: designate report-tenants-all ---------------------------- .. code-block:: console usage: designate report-tenants-all [-h] [-f {csv,html,json,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--quote {all,minimal,none,nonnumeric}] Get list of tenants and domain count for each **Optional arguments:** ``-h, --help`` show this help message and exit .. _designate_server-create: designate server-create ----------------------- .. code-block:: console usage: designate server-create [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] --name NAME Create Server **Optional arguments:** ``-h, --help`` show this help message and exit ``--name NAME`` Server name. .. _designate_server-delete: designate server-delete ----------------------- .. code-block:: console usage: designate server-delete [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] id Delete Server **Positional arguments:** ``id`` Server ID. **Optional arguments:** ``-h, --help`` show this help message and exit .. _designate_server-get: designate server-get -------------------- .. code-block:: console usage: designate server-get [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] id Get Server **Positional arguments:** ``id`` Server ID. **Optional arguments:** ``-h, --help`` show this help message and exit .. _designate_server-list: designate server-list --------------------- .. code-block:: console usage: designate server-list [-h] [-f {csv,html,json,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--quote {all,minimal,none,nonnumeric}] List Servers **Optional arguments:** ``-h, --help`` show this help message and exit .. _designate_server-update: designate server-update ----------------------- .. code-block:: console usage: designate server-update [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] [--name NAME] id Update Server **Positional arguments:** ``id`` Server ID. **Optional arguments:** ``-h, --help`` show this help message and exit ``--name NAME`` Server name. .. _designate_sync-all: designate sync-all ------------------ .. code-block:: console usage: designate sync-all [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] Sync Everything **Optional arguments:** ``-h, --help`` show this help message and exit .. _designate_sync-domain: designate sync-domain --------------------- .. code-block:: console usage: designate sync-domain [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] domain_id Sync a single Domain **Positional arguments:** ``domain_id`` Domain ID **Optional arguments:** ``-h, --help`` show this help message and exit .. _designate_sync-record: designate sync-record --------------------- .. code-block:: console usage: designate sync-record [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] domain_id record_id Sync a single Record **Positional arguments:** ``domain_id`` Domain ID ``record_id`` Record ID **Optional arguments:** ``-h, --help`` show this help message and exit .. _designate_touch-domain: designate touch-domain ---------------------- .. code-block:: console usage: designate touch-domain [-h] [-f {html,json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--print-empty] [--noindent] [--prefix PREFIX] domain_id Touch a single Domain **Positional arguments:** ``domain_id`` Domain ID **Optional arguments:** ``-h, --help`` show this help message and exit python-designateclient-2.9.0/doc/source/index.rst0000666000175100017510000000201213232475203022133 0ustar zuulzuul00000000000000====================== python-designateclient ====================== python-designateclient provides python bindings and command line tools for both Designate v1 and v2 APIs. The :ref:`Python API bindings ` are provided by the :program:`designateclient` module. There are two separate command line interfaces to work with the two API versions: v2: the designate plugin for the :program:`openstack` command line tool. More information can be found on the :ref:`designate v2 command line tool page `. v1: the :program:`designate` command line tool. More information can be found on the :ref:`designate v1 command line tool page `. You'll need credentials for an OpenStack cloud that implements the Designate API in order to use the client. .. toctree:: :maxdepth: 1 install/index user/index cli/index contributor/index reference/index .. rubric:: Indices and tables * :ref:`genindex` * :ref:`modindex` * :ref:`search` .. _Cloud DNS: http://www.hpcloud.com/products-services/dns