From 2c4701236abcae0acadaf2eea0a1069569af0e84 Mon Sep 17 00:00:00 2001 From: Tony Breeds Date: Tue, 12 Sep 2017 16:02:12 -0600 Subject: [PATCH] Retire Packaging Deb project repos This commit is part of a series to retire the Packaging Deb project. Step 2 is to remove all content from the project repos, replacing it with a README notification where to find ongoing work, and how to recover the repo if needed at some future point (as in https://docs.openstack.org/infra/manual/drivers.html#retiring-a-project). Change-Id: I59dd6c58e15d7d0b5b12bbc892aadfdc662305c3 --- .gitignore | 53 - .gitreview | 4 - CONTRIBUTING.rst | 16 - LICENSE | 175 -- README | 14 + README.rst | 100 - doc/source/class_reference.rst | 7 - doc/source/cli/cli_usage_with_keycloak.rst | 2 - doc/source/cli/cli_usage_with_openstack.rst | 36 - doc/source/cli/cli_usage_without_auth.rst | 42 - doc/source/conf.py | 111 - doc/source/index.rst | 40 - functional_creds.conf.sample | 12 - functionaltests/post_test_hook.sh | 26 - functionaltests/resources/v2/action_v2.yaml | 20 - .../resources/v2/action_v2_tags.yaml | 13 - functionaltests/resources/v2/wb_v2.yaml | 14 - .../resources/v2/wb_with_tags_v2.yaml | 15 - functionaltests/resources/v2/wf_delay_v2.yaml | 20 - .../resources/v2/wf_single_v2.yaml | 11 - functionaltests/resources/v2/wf_v2.yaml | 28 - .../resources/v2/wf_wrapping_wf_v2.yaml | 8 - functionaltests/run_tests.sh | 58 - mistralclient/__init__.py | 19 - mistralclient/api/__init__.py | 0 mistralclient/api/base.py | 164 -- mistralclient/api/client.py | 26 - mistralclient/api/httpclient.py | 203 -- mistralclient/api/v2/__init__.py | 0 mistralclient/api/v2/action_executions.py | 87 - mistralclient/api/v2/actions.py | 123 - mistralclient/api/v2/client.py | 82 - mistralclient/api/v2/cron_triggers.py | 68 - mistralclient/api/v2/environments.py | 85 - mistralclient/api/v2/event_triggers.py | 61 - mistralclient/api/v2/executions.py | 110 - mistralclient/api/v2/members.py | 76 - mistralclient/api/v2/services.py | 26 - mistralclient/api/v2/tasks.py | 79 - mistralclient/api/v2/workbooks.py | 92 - mistralclient/api/v2/workflows.py | 128 -- mistralclient/auth/__init__.py | 37 - mistralclient/auth/auth_types.py | 21 - mistralclient/auth/keycloak.py | 170 -- mistralclient/auth/keystone.py | 146 -- mistralclient/commands/__init__.py | 0 mistralclient/commands/v2/__init__.py | 0 .../commands/v2/action_executions.py | 338 --- mistralclient/commands/v2/actions.py | 255 --- mistralclient/commands/v2/base.py | 85 - mistralclient/commands/v2/cron_triggers.py | 216 -- mistralclient/commands/v2/environments.py | 186 -- mistralclient/commands/v2/event_triggers.py | 167 -- mistralclient/commands/v2/executions.py | 338 --- mistralclient/commands/v2/members.py | 235 -- mistralclient/commands/v2/services.py | 37 - mistralclient/commands/v2/tasks.py | 222 -- mistralclient/commands/v2/workbooks.py | 194 -- mistralclient/commands/v2/workflows.py | 247 -- mistralclient/exceptions.py | 40 - mistralclient/i18n.py | 22 - mistralclient/osc/__init__.py | 0 mistralclient/osc/plugin.py | 62 - mistralclient/shell.py | 709 ------ mistralclient/tests/__init__.py | 0 mistralclient/tests/functional/__init__.py | 0 .../tests/functional/cli/__init__.py | 0 mistralclient/tests/functional/cli/base.py | 148 -- .../tests/functional/cli/v2/__init__.py | 0 .../tests/functional/cli/v2/base_v2.py | 279 --- .../cli/v2/cli_multi_tenancy_tests.py | 488 ---- .../tests/functional/cli/v2/cli_tests_v2.py | 2040 ----------------- mistralclient/tests/unit/__init__.py | 0 mistralclient/tests/unit/base.py | 39 - mistralclient/tests/unit/base_shell_test.py | 47 - .../tests/unit/resources/action_v2.yaml | 10 - mistralclient/tests/unit/resources/ctx.json | 7 - .../tests/unit/resources/env_v2.json | 8 - .../tests/unit/resources/env_v2.yaml | 7 - mistralclient/tests/unit/resources/wb_v2.yaml | 21 - mistralclient/tests/unit/resources/wf_v2.yaml | 10 - mistralclient/tests/unit/test_client.py | 276 --- mistralclient/tests/unit/test_httpclient.py | 276 --- mistralclient/tests/unit/test_shell.py | 136 -- mistralclient/tests/unit/test_utils.py | 65 - mistralclient/tests/unit/v2/__init__.py | 0 mistralclient/tests/unit/v2/base.py | 37 - .../tests/unit/v2/test_action_executions.py | 114 - mistralclient/tests/unit/v2/test_actions.py | 269 --- .../tests/unit/v2/test_cli_action_execs.py | 228 -- .../tests/unit/v2/test_cli_actions.py | 199 -- .../tests/unit/v2/test_cli_bash_completion.py | 23 - .../tests/unit/v2/test_cli_cron_triggers.py | 178 -- .../tests/unit/v2/test_cli_environments.py | 125 - .../tests/unit/v2/test_cli_event_triggers.py | 100 - .../tests/unit/v2/test_cli_executions.py | 289 --- .../tests/unit/v2/test_cli_members.py | 102 - .../tests/unit/v2/test_cli_services.py | 37 - mistralclient/tests/unit/v2/test_cli_tasks.py | 128 -- .../tests/unit/v2/test_cli_workbooks.py | 119 - .../tests/unit/v2/test_cli_workflows.py | 201 -- .../tests/unit/v2/test_environments.py | 173 -- .../tests/unit/v2/test_executions.py | 221 -- mistralclient/tests/unit/v2/test_members.py | 96 - mistralclient/tests/unit/v2/test_services.py | 41 - mistralclient/tests/unit/v2/test_tasks.py | 117 - mistralclient/tests/unit/v2/test_workbooks.py | 251 -- mistralclient/tests/unit/v2/test_workflows.py | 187 -- mistralclient/utils.py | 89 - releasenotes/notes/.placeholder | 0 .../fix-region-name-2031ff4b83b6308e.yaml | 6 - ...-default-limit-value-7e293d843d6d85ac.yaml | 7 - releasenotes/source/_static/.placeholder | 0 releasenotes/source/_templates/.placeholder | 0 releasenotes/source/conf.py | 273 --- releasenotes/source/index.rst | 14 - releasenotes/source/liberty.rst | 6 - releasenotes/source/mitaka.rst | 6 - releasenotes/source/newton.rst | 6 - releasenotes/source/ocata.rst | 6 - releasenotes/source/unreleased.rst | 5 - requirements.txt | 13 - run_functional_tests.sh | 50 - setup.cfg | 129 -- setup.py | 29 - test-requirements.txt | 14 - tools/config/generate_sample.sh | 99 - tools/mistral.bash_completion | 25 - tools/run_pep8 | 3 - tools/tox_install.sh | 56 - tools/update_env_deps | 16 - tox.ini | 54 - 132 files changed, 14 insertions(+), 13965 deletions(-) delete mode 100644 .gitignore delete mode 100644 .gitreview delete mode 100644 CONTRIBUTING.rst delete mode 100644 LICENSE create mode 100644 README delete mode 100644 README.rst delete mode 100644 doc/source/class_reference.rst delete mode 100644 doc/source/cli/cli_usage_with_keycloak.rst delete mode 100644 doc/source/cli/cli_usage_with_openstack.rst delete mode 100644 doc/source/cli/cli_usage_without_auth.rst delete mode 100644 doc/source/conf.py delete mode 100644 doc/source/index.rst delete mode 100644 functional_creds.conf.sample delete mode 100755 functionaltests/post_test_hook.sh delete mode 100644 functionaltests/resources/v2/action_v2.yaml delete mode 100644 functionaltests/resources/v2/action_v2_tags.yaml delete mode 100644 functionaltests/resources/v2/wb_v2.yaml delete mode 100644 functionaltests/resources/v2/wb_with_tags_v2.yaml delete mode 100644 functionaltests/resources/v2/wf_delay_v2.yaml delete mode 100644 functionaltests/resources/v2/wf_single_v2.yaml delete mode 100644 functionaltests/resources/v2/wf_v2.yaml delete mode 100644 functionaltests/resources/v2/wf_wrapping_wf_v2.yaml delete mode 100755 functionaltests/run_tests.sh delete mode 100644 mistralclient/__init__.py delete mode 100644 mistralclient/api/__init__.py delete mode 100644 mistralclient/api/base.py delete mode 100644 mistralclient/api/client.py delete mode 100644 mistralclient/api/httpclient.py delete mode 100644 mistralclient/api/v2/__init__.py delete mode 100644 mistralclient/api/v2/action_executions.py delete mode 100644 mistralclient/api/v2/actions.py delete mode 100644 mistralclient/api/v2/client.py delete mode 100644 mistralclient/api/v2/cron_triggers.py delete mode 100644 mistralclient/api/v2/environments.py delete mode 100644 mistralclient/api/v2/event_triggers.py delete mode 100644 mistralclient/api/v2/executions.py delete mode 100644 mistralclient/api/v2/members.py delete mode 100644 mistralclient/api/v2/services.py delete mode 100644 mistralclient/api/v2/tasks.py delete mode 100644 mistralclient/api/v2/workbooks.py delete mode 100644 mistralclient/api/v2/workflows.py delete mode 100644 mistralclient/auth/__init__.py delete mode 100644 mistralclient/auth/auth_types.py delete mode 100644 mistralclient/auth/keycloak.py delete mode 100644 mistralclient/auth/keystone.py delete mode 100644 mistralclient/commands/__init__.py delete mode 100644 mistralclient/commands/v2/__init__.py delete mode 100644 mistralclient/commands/v2/action_executions.py delete mode 100644 mistralclient/commands/v2/actions.py delete mode 100644 mistralclient/commands/v2/base.py delete mode 100644 mistralclient/commands/v2/cron_triggers.py delete mode 100644 mistralclient/commands/v2/environments.py delete mode 100644 mistralclient/commands/v2/event_triggers.py delete mode 100644 mistralclient/commands/v2/executions.py delete mode 100644 mistralclient/commands/v2/members.py delete mode 100644 mistralclient/commands/v2/services.py delete mode 100644 mistralclient/commands/v2/tasks.py delete mode 100644 mistralclient/commands/v2/workbooks.py delete mode 100644 mistralclient/commands/v2/workflows.py delete mode 100644 mistralclient/exceptions.py delete mode 100644 mistralclient/i18n.py delete mode 100644 mistralclient/osc/__init__.py delete mode 100644 mistralclient/osc/plugin.py delete mode 100644 mistralclient/shell.py delete mode 100644 mistralclient/tests/__init__.py delete mode 100644 mistralclient/tests/functional/__init__.py delete mode 100644 mistralclient/tests/functional/cli/__init__.py delete mode 100644 mistralclient/tests/functional/cli/base.py delete mode 100644 mistralclient/tests/functional/cli/v2/__init__.py delete mode 100644 mistralclient/tests/functional/cli/v2/base_v2.py delete mode 100644 mistralclient/tests/functional/cli/v2/cli_multi_tenancy_tests.py delete mode 100644 mistralclient/tests/functional/cli/v2/cli_tests_v2.py delete mode 100644 mistralclient/tests/unit/__init__.py delete mode 100644 mistralclient/tests/unit/base.py delete mode 100644 mistralclient/tests/unit/base_shell_test.py delete mode 100644 mistralclient/tests/unit/resources/action_v2.yaml delete mode 100644 mistralclient/tests/unit/resources/ctx.json delete mode 100644 mistralclient/tests/unit/resources/env_v2.json delete mode 100644 mistralclient/tests/unit/resources/env_v2.yaml delete mode 100644 mistralclient/tests/unit/resources/wb_v2.yaml delete mode 100644 mistralclient/tests/unit/resources/wf_v2.yaml delete mode 100644 mistralclient/tests/unit/test_client.py delete mode 100644 mistralclient/tests/unit/test_httpclient.py delete mode 100644 mistralclient/tests/unit/test_shell.py delete mode 100644 mistralclient/tests/unit/test_utils.py delete mode 100644 mistralclient/tests/unit/v2/__init__.py delete mode 100644 mistralclient/tests/unit/v2/base.py delete mode 100644 mistralclient/tests/unit/v2/test_action_executions.py delete mode 100644 mistralclient/tests/unit/v2/test_actions.py delete mode 100644 mistralclient/tests/unit/v2/test_cli_action_execs.py delete mode 100644 mistralclient/tests/unit/v2/test_cli_actions.py delete mode 100644 mistralclient/tests/unit/v2/test_cli_bash_completion.py delete mode 100644 mistralclient/tests/unit/v2/test_cli_cron_triggers.py delete mode 100644 mistralclient/tests/unit/v2/test_cli_environments.py delete mode 100644 mistralclient/tests/unit/v2/test_cli_event_triggers.py delete mode 100644 mistralclient/tests/unit/v2/test_cli_executions.py delete mode 100644 mistralclient/tests/unit/v2/test_cli_members.py delete mode 100644 mistralclient/tests/unit/v2/test_cli_services.py delete mode 100644 mistralclient/tests/unit/v2/test_cli_tasks.py delete mode 100644 mistralclient/tests/unit/v2/test_cli_workbooks.py delete mode 100644 mistralclient/tests/unit/v2/test_cli_workflows.py delete mode 100644 mistralclient/tests/unit/v2/test_environments.py delete mode 100644 mistralclient/tests/unit/v2/test_executions.py delete mode 100644 mistralclient/tests/unit/v2/test_members.py delete mode 100644 mistralclient/tests/unit/v2/test_services.py delete mode 100644 mistralclient/tests/unit/v2/test_tasks.py delete mode 100644 mistralclient/tests/unit/v2/test_workbooks.py delete mode 100644 mistralclient/tests/unit/v2/test_workflows.py delete mode 100644 mistralclient/utils.py delete mode 100644 releasenotes/notes/.placeholder delete mode 100644 releasenotes/notes/fix-region-name-2031ff4b83b6308e.yaml delete mode 100644 releasenotes/notes/set-default-limit-value-7e293d843d6d85ac.yaml delete mode 100644 releasenotes/source/_static/.placeholder delete mode 100644 releasenotes/source/_templates/.placeholder delete mode 100644 releasenotes/source/conf.py delete mode 100644 releasenotes/source/index.rst delete mode 100644 releasenotes/source/liberty.rst delete mode 100644 releasenotes/source/mitaka.rst delete mode 100644 releasenotes/source/newton.rst delete mode 100644 releasenotes/source/ocata.rst delete mode 100644 releasenotes/source/unreleased.rst delete mode 100644 requirements.txt delete mode 100755 run_functional_tests.sh delete mode 100644 setup.cfg delete mode 100644 setup.py delete mode 100644 test-requirements.txt delete mode 100755 tools/config/generate_sample.sh delete mode 100644 tools/mistral.bash_completion delete mode 100755 tools/run_pep8 delete mode 100755 tools/tox_install.sh delete mode 100755 tools/update_env_deps delete mode 100644 tox.ini diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 2ffeaf3..0000000 --- a/.gitignore +++ /dev/null @@ -1,53 +0,0 @@ -*.py[cod] -*.sqlite - -# C extensions -*.so - -# Packages -*.egg* -dist -build -.venv -.eggs -eggs -parts -bin -var -sdist -develop-eggs -.installed.cfg -lib -lib64 - -# Installer logs -pip-log.txt - -# Unit test / coverage reports -.coverage -cover/* -.tox -nosetests.xml -functional_creds.conf -AUTHORS -ChangeLog - -# Translations -*.mo - -# Mr Developer -.mr.developer.cfg -.project -.pydevproject -.idea -.DS_Store -etc/mistral.conf - -#swap file -*.swp - -# Files created by releasenotes build -releasenotes/build - -# Files created by doc build -doc/source/api diff --git a/.gitreview b/.gitreview deleted file mode 100644 index 4aabac1..0000000 --- a/.gitreview +++ /dev/null @@ -1,4 +0,0 @@ -[gerrit] -host=review.openstack.org -port=29418 -project=openstack/python-mistralclient.git diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst deleted file mode 100644 index 78350dc..0000000 --- a/CONTRIBUTING.rst +++ /dev/null @@ -1,16 +0,0 @@ -If 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-mistralclient diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 67db858..0000000 --- a/LICENSE +++ /dev/null @@ -1,175 +0,0 @@ - - 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. diff --git a/README b/README new file mode 100644 index 0000000..8fcd2b2 --- /dev/null +++ b/README @@ -0,0 +1,14 @@ +This project is no longer maintained. + +The contents of this repository are still available in the Git +source code management system. To see the contents of this +repository before it reached its end of life, please check out the +previous commit with "git checkout HEAD^1". + +For ongoing work on maintaining OpenStack packages in the Debian +distribution, please see the Debian OpenStack packaging team at +https://wiki.debian.org/OpenStack/. + +For any further questions, please email +openstack-dev@lists.openstack.org or join #openstack-dev on +Freenode. diff --git a/README.rst b/README.rst deleted file mode 100644 index 36178c9..0000000 --- a/README.rst +++ /dev/null @@ -1,100 +0,0 @@ -======================== -Team and repository tags -======================== - -.. image:: https://governance.openstack.org/badges/python-mistralclient.svg - :target: https://governance.openstack.org/reference/tags/index.html - -Mistral -======= - -.. image:: https://img.shields.io/pypi/v/python-mistralclient.svg - :target: https://pypi.python.org/pypi/python-mistralclient/ - :alt: Latest Version - -.. image:: https://img.shields.io/pypi/dm/python-mistralclient.svg - :target: https://pypi.python.org/pypi/python-mistralclient/ - :alt: Downloads - -Mistral is a workflow service. Most business processes consist of multiple -distinct interconnected steps that need to be executed in a particular -order in a distributed environment. A user can describe such a process as a set -of tasks and their transitions. After that, it is possible to upload such a -description to Mistral, which will take care of state management, correct -execution order, parallelism, synchronization and high availability. - -Mistral also provides flexible task scheduling so that it can run a process -according to a specified schedule (for example, every Sunday at 4.00pm) instead -of running it immediately. In Mistral terminology such a set of tasks and -relations between them is called a workflow. - -Mistral client -============== - -Python client for Mistral REST API. Includes python library for Mistral API and -Command Line Interface (CLI) library. - -Installation ------------- - -First of all, clone the repo and go to the repo directory: - - $ git clone git://git.openstack.org/openstack/python-mistralclient.git - $ cd python-mistralclient - -Then just run: - - $ pip install -e . - -or - - $ pip install -r requirements.txt - $ python setup.py install - - -Running Mistral client ----------------------- - -If Mistral authentication is enabled, provide the information about OpenStack -auth to environment variables. Type: - - $ export OS_AUTH_URL=http://:5000/v2.0 - $ export OS_USERNAME=admin - $ export OS_TENANT_NAME=tenant - $ export OS_PASSWORD=secret - $ export OS_MISTRAL_URL=http://:8989/v2 (optional, by - default URL=http://localhost:8989/v2) - -and in the case that you are authenticating against keystone over https: - - $ export OS_CACERT= - -.. note:: In client, we can use both Keystone auth versions - v2.0 and v3. But - server supports only v3.* - -To make sure Mistral client works, type: - - $ mistral workbook-list - -You can see the list of available commands typing: - - $ mistral --help - -Useful Links -============ - -* `PyPi`_ - package installation -* `Launchpad project`_ - release management -* `Blueprints`_ - feature specifications -* `Bugs`_ - issue tracking -* `Source`_ -* `Specs`_ -* `How to Contribute`_ - -.. _PyPi: https://pypi.python.org/pypi/python-mistralclient -.. _Launchpad project: https://launchpad.net/python-mistralclient -.. _Blueprints: https://blueprints.launchpad.net/python-mistralclient -.. _Bugs: https://bugs.launchpad.net/python-mistralclient -.. _Source: https://git.openstack.org/cgit/openstack/python-mistralclient -.. _How to Contribute: https://docs.openstack.org/infra/manual/developers.html -.. _Specs: https://specs.openstack.org/openstack/mistral-specs/ diff --git a/doc/source/class_reference.rst b/doc/source/class_reference.rst deleted file mode 100644 index 9a681c2..0000000 --- a/doc/source/class_reference.rst +++ /dev/null @@ -1,7 +0,0 @@ -Python Mistral bindings class refrence -====================================== - -.. toctree:: - :maxdepth: 1 - - api/autoindex diff --git a/doc/source/cli/cli_usage_with_keycloak.rst b/doc/source/cli/cli_usage_with_keycloak.rst deleted file mode 100644 index 31ebc55..0000000 --- a/doc/source/cli/cli_usage_with_keycloak.rst +++ /dev/null @@ -1,2 +0,0 @@ -Using Mistral with KeyCloak Server -================================== diff --git a/doc/source/cli/cli_usage_with_openstack.rst b/doc/source/cli/cli_usage_with_openstack.rst deleted file mode 100644 index b1cf84c..0000000 --- a/doc/source/cli/cli_usage_with_openstack.rst +++ /dev/null @@ -1,36 +0,0 @@ -Using Mistral with OpenStack -============================ - -The **mistral** shell utility interacts with OpenStack Mistral API from the -command-line. It supports the features in the OpenStack Mistral API. - -Basic Usage ------------ - -In order to use the CLI, you must provide your OpenStack credentials -(for both user and project), and auth endpoint. Use the corresponding -configuration options (``--os-username``, ``--os-password``, -``--os-project-name``, ``--os-user-domain-id``, ``os-project-domain-id``, and -``--os-auth-url``), but it is easier to set them in environment variables. - -.. code-block:: shell - - $ export OS_AUTH_URL=http://:5000/v2.0 - $ export OS_USERNAME=admin - $ export OS_TENANT_NAME=tenant - $ export OS_PASSWORD=secret - $ export OS_MISTRAL_URL=http://:8989/v2 - -When authenticating against keystone over https: - -.. code-block:: shell - - $ export OS_CACERT= - -Once you've configured your authentication parameters, you can run **mistral** -commands. All commands take the form of:: - - mistral [arguments...] - -Run **mistral --help** to get a full list of all possible commands, and run -**mistral help ** to get detailed help for that command. diff --git a/doc/source/cli/cli_usage_without_auth.rst b/doc/source/cli/cli_usage_without_auth.rst deleted file mode 100644 index b4ef6f8..0000000 --- a/doc/source/cli/cli_usage_without_auth.rst +++ /dev/null @@ -1,42 +0,0 @@ -Using Mistral without Authentication -==================================== - -It is possible to execute a workflow on any arbitrary cloud without additional -configuration on the Mistral server side. If authentication is turned off in -the Mistral server (Pecan's `auth_enable = False` option in `mistral.conf`), -there is no need to set the `keystone_authtoken` section. It is possible to -have Mistral use an external OpenStack cloud even when it isn't deployed in -an OpenStack environment (i.e. no Keystone integration). - -This setup is particularly useful when Mistral is used in standalone mode, -where the Mistral service is not part of the OpenStack cloud and runs -separately. - -To enable this operation, the user can use ``--os-target-username``, -``--os-target-password``, ``--os-target-tenant-id``, -``--os-target-tenant-name``, ``--os-target-auth-token``, -``--os-target-auth-url``, ``--os-target_cacert``, and -``--os-target-region-name`` parameters. - -For example, the user can return the heat stack list with this setup as shown -below: - -.. code-block:: shell - - $ mistral \ - --os-target-auth-url=http://keystone2.example.com:5000/v3 \ - --os-target-username=testuser \ - --os-target-tenant=testtenant \ - --os-target-password="MistralRuleZ" \ - --os-mistral-url=http://mistral.example.com:8989/v2 \ - run-action heat.stacks_list - -The OS-TARGET-* parameters can be set in environment variables as: - -.. code-block:: shell - - $ export OS_TARGET_AUTH_URL=http://keystone2.example.com:5000/v3 - $ export OS_TARGET_USERNAME=admin - $ export OS_TARGET_TENANT_NAME=tenant - $ export OS_TARGET_PASSWORD=secret - $ export OS_TARGET_REGION_NAME=region diff --git a/doc/source/conf.py b/doc/source/conf.py deleted file mode 100644 index 59f8378..0000000 --- a/doc/source/conf.py +++ /dev/null @@ -1,111 +0,0 @@ -# Mistral documentation build configuration file - -import os -import pbr.version -import sys - -on_rtd = os.environ.get('READTHEDOCS', None) == 'True' - -# 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('../../')) -sys.path.insert(0, os.path.abspath('../')) -sys.path.insert(0, os.path.abspath('./')) - -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = [ - 'sphinx.ext.autodoc', - 'openstackdocstheme', -] - -# 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'Mistral Client' -copyright = u'2016, Mistral Contributors' - -# 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. -version_info = pbr.version.VersionInfo('python-mistralclient') -release = version_info.release_string() -version = version_info.version_string() - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = [] - -# 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 = ['mistralclient.'] - - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'openstackdocs' - -# 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' -# Must set this variable to include year, month, day, hours, and minutes. -html_last_updated_fmt = '%Y-%m-%d %H:%M' - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -html_title = 'MistralClient' - -# Custom sidebar templates, maps document names to template names. -html_sidebars = { - 'index': [ - 'sidebarlinks.html', 'localtoc.html', 'searchbox.html', - 'sourcelink.html' - ], - '**': [ - 'localtoc.html', 'relations.html', - 'searchbox.html', 'sourcelink.html' - ] -} - -# Output file base name for HTML help builder. -htmlhelp_basename = 'Mistraldoc' - - -# -- Options for manual page output ------------------------------------------ - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'mistral_client', u'Mistral Client Documentation', - [u'Mistral Contributors'], 1) -] - -# -- Options for openstackdocstheme ------------------------------------------- -repository_name = 'openstack/python-mistralclient' -bug_project = 'python-mistralclient' -bug_tag = '' diff --git a/doc/source/index.rst b/doc/source/index.rst deleted file mode 100644 index dad7824..0000000 --- a/doc/source/index.rst +++ /dev/null @@ -1,40 +0,0 @@ -Python bindings to the OpenStack Workflow API -============================================= - -This is a client for OpenStack Mistral API. There's a Python API -(the :mod:`mistralclient` module), and a command-line script -(installed as :program:`mistral`). - -Using mistralclient -------------------- - -.. toctree:: - :maxdepth: 2 - - cli/cli_usage_with_openstack - cli/cli_usage_with_keycloak - cli/cli_usage_without_auth - class_reference - -For information about using the mistral command-line client, see -`Workflow service command-line client`_. - -.. _Workflow service command-line client: https://docs.openstack.org/mistral/latest/cli/index.html - -Python API Reference --------------------- - -* `REST API Specification`_ - -.. _REST API Specification: https://docs.openstack.org/mistral/latest/api/v2.html - -Contributing ------------- - -Code is hosted `on GitHub`_. Submit bugs to the python-mistralclient project on -`Launchpad`_. Submit code to the openstack/python-mistralclient project -using `Gerrit`_. - -.. _on GitHub: https://github.com/openstack/python-mistralclient -.. _Launchpad: https://launchpad.net/python-mistralclient -.. _Gerrit: https://docs.openstack.org/infra/manual/developers.html#development-workflow diff --git a/functional_creds.conf.sample b/functional_creds.conf.sample deleted file mode 100644 index cb9ae96..0000000 --- a/functional_creds.conf.sample +++ /dev/null @@ -1,12 +0,0 @@ -# Credentials for functional testing -[auth] -uri = http://10.42.0.50:5000/v2.0 - -[admin] -user = admin -tenant = admin -pass = secrete -[demo] -user = demo -tenant = demo -pass = demo_secret \ No newline at end of file diff --git a/functionaltests/post_test_hook.sh b/functionaltests/post_test_hook.sh deleted file mode 100755 index 6c62434..0000000 --- a/functionaltests/post_test_hook.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash -# -# 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 script is executed inside post_test_hook function in devstack gate. - -RETVAL=0 - -sudo chmod -R a+rw /opt/stack/new/ -cd /opt/stack/new/python-mistralclient - -echo "Running CLI python-mistralclient tests" -./functionaltests/run_tests.sh -RETVAL=$? - -exit $RETVAL diff --git a/functionaltests/resources/v2/action_v2.yaml b/functionaltests/resources/v2/action_v2.yaml deleted file mode 100644 index 45384cd..0000000 --- a/functionaltests/resources/v2/action_v2.yaml +++ /dev/null @@ -1,20 +0,0 @@ ---- -version: "2.0" - -greeting: - description: "This action says 'Hello'" - base: std.echo - base-input: - output: 'Hello, <% $.name %>' - input: - - name - output: - string: <% $.output %> - -farewell: - base: std.echo - base-input: - output: 'Bye!' - output: - info: <% $.output %> - diff --git a/functionaltests/resources/v2/action_v2_tags.yaml b/functionaltests/resources/v2/action_v2_tags.yaml deleted file mode 100644 index e7fa4b8..0000000 --- a/functionaltests/resources/v2/action_v2_tags.yaml +++ /dev/null @@ -1,13 +0,0 @@ ---- -version: "2.0" - -greeting: - description: "This action says 'Hello'" - tags: [tag, tag1] - base: std.echo - base-input: - output: 'Hello, <% $.name %>' - input: - - name - output: - string: <% $.output %> diff --git a/functionaltests/resources/v2/wb_v2.yaml b/functionaltests/resources/v2/wb_v2.yaml deleted file mode 100644 index e3d359b..0000000 --- a/functionaltests/resources/v2/wb_v2.yaml +++ /dev/null @@ -1,14 +0,0 @@ ---- -version: '2.0' - -name: wb - -workflows: - wf1: - type: direct - - tasks: - hello: - action: std.echo output="Hello" - publish: - result: <% task(hello).result %> diff --git a/functionaltests/resources/v2/wb_with_tags_v2.yaml b/functionaltests/resources/v2/wb_with_tags_v2.yaml deleted file mode 100644 index 013bcad..0000000 --- a/functionaltests/resources/v2/wb_with_tags_v2.yaml +++ /dev/null @@ -1,15 +0,0 @@ ---- -version: '2.0' - -name: wb -tags: [tag] - -workflows: - wf1: - type: direct - - tasks: - hello: - action: std.echo output="Hello" - publish: - result: <% task(hello).result %> diff --git a/functionaltests/resources/v2/wf_delay_v2.yaml b/functionaltests/resources/v2/wf_delay_v2.yaml deleted file mode 100644 index ad0f29e..0000000 --- a/functionaltests/resources/v2/wf_delay_v2.yaml +++ /dev/null @@ -1,20 +0,0 @@ ---- -version: '2.0' - -wf: - type: direct - tags: [tag] - - tasks: - hello: - action: std.echo output="Hello" - publish: - result: <% task(hello).result %> - wait-after: 1 - on-success: - - task2 - - task2: - action: std.echo output="Task 2" - publish: - task2: <% task(task2).result %> diff --git a/functionaltests/resources/v2/wf_single_v2.yaml b/functionaltests/resources/v2/wf_single_v2.yaml deleted file mode 100644 index aedee3e..0000000 --- a/functionaltests/resources/v2/wf_single_v2.yaml +++ /dev/null @@ -1,11 +0,0 @@ ---- -version: '2.0' - -wf_single: - type: direct - - tasks: - hello: - action: std.echo output="Hello" - publish: - result: <% task(hello).result %> diff --git a/functionaltests/resources/v2/wf_v2.yaml b/functionaltests/resources/v2/wf_v2.yaml deleted file mode 100644 index e32862e..0000000 --- a/functionaltests/resources/v2/wf_v2.yaml +++ /dev/null @@ -1,28 +0,0 @@ ---- -version: '2.0' - -wf: - type: direct - - tasks: - hello: - action: std.echo output="Hello" - wait-before: 5 - publish: - result: <% task(hello).result %> - -wf1: - type: reverse - tags: [tag] - input: - - farewell - - tasks: - addressee: - action: std.echo output="John" - publish: - name: <% task(addressee).result %> - - goodbye: - action: std.echo output="<% $.farewell %>, <% $.name %>" - requires: [addressee] diff --git a/functionaltests/resources/v2/wf_wrapping_wf_v2.yaml b/functionaltests/resources/v2/wf_wrapping_wf_v2.yaml deleted file mode 100644 index 5ac1e37..0000000 --- a/functionaltests/resources/v2/wf_wrapping_wf_v2.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -version: '2.0' - -wrapping_wf: - type: direct - tasks: - hello: - workflow: wf diff --git a/functionaltests/run_tests.sh b/functionaltests/run_tests.sh deleted file mode 100755 index d616d36..0000000 --- a/functionaltests/run_tests.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash -# -# 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. - -# How many seconds to wait for the API to be responding before giving up -API_RESPONDING_TIMEOUT=20 - -if ! timeout ${API_RESPONDING_TIMEOUT} sh -c "until curl --output /dev/null --silent --head --fail http://localhost:8989; do sleep 1; done"; then - echo "Mistral API failed to respond within ${API_RESPONDING_TIMEOUT} seconds" - exit 1 -fi - -echo "Successfully contacted Mistral API" - -export BASE=/opt/stack -export MISTRALCLIENT_DIR="$BASE/new/python-mistralclient" - -# Get demo credentials. -cd ${BASE}/new/devstack -source openrc alt_demo alt_demo - -export OS_ALT_USERNAME=${OS_USERNAME} -export OS_ALT_TENANT_NAME=${OS_TENANT_NAME} -export OS_ALT_PASSWORD=${OS_PASSWORD} - -# Get admin credentials. -source openrc admin admin - -# Store these credentials into the config file. -CREDS_FILE=${MISTRALCLIENT_DIR}/functional_creds.conf -cat < ${CREDS_FILE} -# Credentials for functional testing -[auth] -uri = $OS_AUTH_URL -[admin] -user = $OS_USERNAME -tenant = $OS_TENANT_NAME -pass = $OS_PASSWORD -[demo] -user = $OS_ALT_USERNAME -tenant = $OS_ALT_TENANT_NAME -pass = $OS_ALT_PASSWORD -EOF - -cd $MISTRALCLIENT_DIR - -# Run tests -tox -efunctional -- nosetests -sv mistralclient/tests/functional diff --git a/mistralclient/__init__.py b/mistralclient/__init__.py deleted file mode 100644 index f8f1a43..0000000 --- a/mistralclient/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2014 Rackspace Hosting -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import pbr.version - - -__version__ = pbr.version.VersionInfo( - 'python-mistralclient').version_string() diff --git a/mistralclient/api/__init__.py b/mistralclient/api/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/mistralclient/api/base.py b/mistralclient/api/base.py deleted file mode 100644 index d69f881..0000000 --- a/mistralclient/api/base.py +++ /dev/null @@ -1,164 +0,0 @@ -# Copyright 2013 - Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import copy -import json - - -class Resource(object): - resource_name = 'Something' - defaults = {} - - def __init__(self, manager, data): - self.manager = manager - self._data = data - self._set_defaults() - self._set_attributes() - - def _set_defaults(self): - for k, v in self.defaults.items(): - if k not in self._data: - self._data[k] = v - - def _set_attributes(self): - for k, v in self._data.items(): - try: - setattr(self, k, v) - except AttributeError: - # In this case we already defined the attribute on the class - pass - - def to_dict(self): - return copy.deepcopy(self._data) - - def __str__(self): - vals = ", ".join(["%s='%s'" % (n, v) - for n, v in self._data.items()]) - return "%s [%s]" % (self.resource_name, vals) - - -def _check_items(obj, searches): - try: - return all(getattr(obj, attr) == value for (attr, value) in searches) - except AttributeError: - return False - - -def extract_json(response, response_key): - if response_key is not None: - return get_json(response)[response_key] - else: - return get_json(response) - - -class ResourceManager(object): - resource_class = None - - def __init__(self, http_client): - self.http_client = http_client - - def find(self, **kwargs): - return [i for i in self.list() if _check_items(i, kwargs.items())] - - def _ensure_not_empty(self, **kwargs): - for name, value in kwargs.items(): - if value is None or (isinstance(value, str) and len(value) == 0): - raise APIException( - 400, - '%s is missing field "%s"' % - (self.resource_class.__name__, name) - ) - - def _copy_if_defined(self, data, **kwargs): - for name, value in kwargs.items(): - if value is not None: - data[name] = value - - def _create(self, url, data, response_key=None, dump_json=True): - if dump_json: - data = json.dumps(data) - - resp = self.http_client.post(url, data) - - if resp.status_code != 201: - self._raise_api_exception(resp) - - return self.resource_class(self, extract_json(resp, response_key)) - - def _update(self, url, data, response_key=None, dump_json=True): - if dump_json: - data = json.dumps(data) - - resp = self.http_client.put(url, data) - - if resp.status_code != 200: - self._raise_api_exception(resp) - - return self.resource_class(self, extract_json(resp, response_key)) - - def _list(self, url, response_key=None): - resp = self.http_client.get(url) - - if resp.status_code != 200: - self._raise_api_exception(resp) - - return [self.resource_class(self, resource_data) - for resource_data in extract_json(resp, response_key)] - - def _get(self, url, response_key=None): - resp = self.http_client.get(url) - - if resp.status_code == 200: - return self.resource_class(self, extract_json(resp, response_key)) - else: - self._raise_api_exception(resp) - - def _delete(self, url): - resp = self.http_client.delete(url) - - if resp.status_code != 204: - self._raise_api_exception(resp) - - def _plurify_resource_name(self): - return self.resource_class.resource_name + 's' - - def _raise_api_exception(self, resp): - try: - error_data = (resp.headers.get("Server-Error-Message", None) or - get_json(resp).get("faultstring")) - except ValueError: - error_data = resp.content - raise APIException(error_code=resp.status_code, - error_message=error_data) - - -def get_json(response): - """Gets JSON representation of response. - - This method provided backward compatibility with old versions - of requests library. - """ - json_field_or_function = getattr(response, 'json', None) - - if callable(json_field_or_function): - return response.json() - else: - return json.loads(response.content) - - -class APIException(Exception): - def __init__(self, error_code=None, error_message=None): - super(APIException, self).__init__(error_message) - self.error_code = error_code - self.error_message = error_message diff --git a/mistralclient/api/client.py b/mistralclient/api/client.py deleted file mode 100644 index 378444c..0000000 --- a/mistralclient/api/client.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright 2013 - Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from mistralclient.api.v2 import client as client_v2 - - -def client(auth_type='keystone', **kwargs): - return client_v2.Client(auth_type=auth_type, **kwargs) - - -def determine_client_version(mistral_version): - if mistral_version.find("v2") != -1: - return 2 - - raise RuntimeError("Cannot determine mistral API version") diff --git a/mistralclient/api/httpclient.py b/mistralclient/api/httpclient.py deleted file mode 100644 index f355cca..0000000 --- a/mistralclient/api/httpclient.py +++ /dev/null @@ -1,203 +0,0 @@ -# Copyright 2013 - Mirantis, Inc. -# Copyright 2016 - StackStorm, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import base64 -import copy -import os - -from oslo_utils import importutils -import requests - -import logging - - -AUTH_TOKEN = 'auth_token' -CACERT = 'cacert' -CERT_FILE = 'cert' -CERT_KEY = 'key' -INSECURE = 'insecure' -PROJECT_ID = 'project_id' -USER_ID = 'user_id' -REGION_NAME = 'region_name' - -TARGET_AUTH_TOKEN = 'target_auth_token' -TARGET_AUTH_URI = 'target_auth_url' -TARGET_PROJECT_ID = 'target_project_id' -TARGET_USER_ID = 'target_user_id' -TARGET_INSECURE = 'target_insecure' -TARGET_SERVICE_CATALOG = 'target_service_catalog' -TARGET_REGION_NAME = 'target_region_name' -TARGET_USER_DOMAIN_NAME = 'target_user_domain_name' -TARGET_PROJECT_DOMAIN_NAME = 'target_project_domain_name' - -osprofiler_web = importutils.try_import("osprofiler.web") - -LOG = logging.getLogger(__name__) - - -def log_request(func): - def decorator(self, *args, **kwargs): - resp = func(self, *args, **kwargs) - LOG.debug("HTTP %s %s %d", resp.request.method, resp.url, - resp.status_code) - return resp - return decorator - - -class HTTPClient(object): - def __init__(self, base_url, **kwargs): - self.base_url = base_url - self.session = kwargs.pop('session', None) - self.auth_token = kwargs.get(AUTH_TOKEN) - self.project_id = kwargs.get(PROJECT_ID) - self.user_id = kwargs.get(USER_ID) - self.cacert = kwargs.get(CACERT) - self.insecure = kwargs.get(INSECURE, False) - self.region_name = kwargs.get(REGION_NAME) - self.ssl_options = {} - - self.target_auth_token = kwargs.get(TARGET_AUTH_TOKEN) - self.target_auth_uri = kwargs.get(TARGET_AUTH_URI) - self.target_user_id = kwargs.get(TARGET_USER_ID) - self.target_project_id = kwargs.get(TARGET_PROJECT_ID) - self.target_service_catalog = kwargs.get(TARGET_SERVICE_CATALOG) - self.target_region_name = kwargs.get(TARGET_REGION_NAME) - self.target_insecure = kwargs.get(TARGET_INSECURE) - self.target_user_domain_name = kwargs.get(TARGET_USER_DOMAIN_NAME) - self.target_project_domain_name = kwargs.get( - TARGET_PROJECT_DOMAIN_NAME - ) - - if self.session: - self.crud_provider = self.session - else: - self.crud_provider = requests - - if self.base_url.startswith('https'): - if self.cacert and not os.path.exists(self.cacert): - raise ValueError('Unable to locate cacert file ' - 'at %s.' % self.cacert) - - if self.cacert and self.insecure: - LOG.warning('Client is set to not verify even though ' - 'cacert is provided.') - - # These are already set by the session, so it's not needed - if not self.session: - if self.insecure: - self.ssl_options['verify'] = False - else: - if self.cacert: - self.ssl_options['verify'] = self.cacert - else: - self.ssl_options['verify'] = True - - self.ssl_options['cert'] = ( - kwargs.get(CERT_FILE), - kwargs.get(CERT_KEY) - ) - - @log_request - def get(self, url, headers=None): - options = self._get_request_options('get', headers) - - return self.crud_provider.get(self.base_url + url, **options) - - @log_request - def post(self, url, body, headers=None): - options = self._get_request_options('post', headers) - - return self.crud_provider.post(self.base_url + url, - data=body, **options) - - @log_request - def put(self, url, body, headers=None): - options = self._get_request_options('put', headers) - - return self.crud_provider.put(self.base_url + url, - data=body, **options) - - @log_request - def delete(self, url, headers=None): - options = self._get_request_options('delete', headers) - - return self.crud_provider.delete(self.base_url + url, - **options) - - def _get_request_options(self, method, headers): - headers = self._update_headers(headers) - - if method in ['post', 'put']: - content_type = headers.get('content-type', 'application/json') - headers['content-type'] = content_type - - options = copy.deepcopy(self.ssl_options) - options['headers'] = headers - - return options - - def _update_headers(self, headers): - if not headers: - headers = {} - - if not self.session: - if self.auth_token: - headers['x-auth-token'] = self.auth_token - - if self.project_id: - headers['X-Project-Id'] = self.project_id - - if self.user_id: - headers['X-User-Id'] = self.user_id - - if self.region_name: - headers['X-Region-Name'] = self.region_name - - if self.target_auth_token: - headers['X-Target-Auth-Token'] = self.target_auth_token - - if self.target_auth_uri: - headers['X-Target-Auth-Uri'] = self.target_auth_uri - - if self.target_project_id: - headers['X-Target-Project-Id'] = self.target_project_id - - if self.target_user_id: - headers['X-Target-User-Id'] = self.target_user_id - - if self.target_insecure: - headers['X-Target-Insecure'] = self.target_insecure - - if self.target_region_name: - headers['X-Target-Region-Name'] = self.target_region_name - - if self.target_user_domain_name: - headers['X-Target-User-Domain-Name'] = self.target_user_domain_name - - if self.target_project_domain_name: - h_name = 'X-Target-Project-Domain-Name' - - headers[h_name] = self.target_project_domain_name - - if self.target_service_catalog: - headers['X-Target-Service-Catalog'] = base64.b64encode( - self.target_service_catalog.encode('utf-8') - ) - - if osprofiler_web: - # Add headers for osprofiler. - headers.update(osprofiler_web.get_trace_id_headers()) - - return headers diff --git a/mistralclient/api/v2/__init__.py b/mistralclient/api/v2/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/mistralclient/api/v2/action_executions.py b/mistralclient/api/v2/action_executions.py deleted file mode 100644 index 8dd4c77..0000000 --- a/mistralclient/api/v2/action_executions.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import json - -from mistralclient.api import base - - -class ActionExecution(base.Resource): - resource_name = 'ActionExecution' - - -class ActionExecutionManager(base.ResourceManager): - resource_class = ActionExecution - - def create(self, name, input=None, **params): - self._ensure_not_empty(name=name) - - data = {'name': name} - - if input: - data['input'] = json.dumps(input) - - if params: - data['params'] = json.dumps(params) - - resp = self.http_client.post( - '/action_executions', - json.dumps(data) - ) - - if resp.status_code != 201: - self._raise_api_exception(resp) - - return self.resource_class(self, base.get_json(resp)) - - def update(self, id, state=None, output=None): - self._ensure_not_empty(id=id) - - if not (state or output): - raise base.APIException( - 400, - "Please provide either state or output for action execution." - ) - - data = {} - if state: - data['state'] = state - - if output: - data['output'] = output - - return self._update('/action_executions/%s' % id, data) - - def list(self, task_execution_id=None, limit=None): - url = '/action_executions' - - qparams = {} - - if task_execution_id: - url = '/tasks/%s/action_executions' % task_execution_id - - if limit: - qparams['limit'] = limit - - return self._list(url, response_key='action_executions') - - def get(self, id): - self._ensure_not_empty(id=id) - - return self._get('/action_executions/%s' % id) - - def delete(self, id): - self._ensure_not_empty(id=id) - - self._delete('/action_executions/%s' % id) diff --git a/mistralclient/api/v2/actions.py b/mistralclient/api/v2/actions.py deleted file mode 100644 index 3b7a800..0000000 --- a/mistralclient/api/v2/actions.py +++ /dev/null @@ -1,123 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import six - -from mistralclient.api import base -from mistralclient import utils - -urlparse = six.moves.urllib.parse - - -class Action(base.Resource): - resource_name = 'Action' - - -class ActionManager(base.ResourceManager): - resource_class = Action - - def create(self, definition, scope='private'): - self._ensure_not_empty(definition=definition) - - # If the specified definition is actually a file, read in the - # definition file - definition = utils.get_contents_if_file(definition) - - resp = self.http_client.post( - '/actions?scope=%s' % scope, - definition, - headers={'content-type': 'text/plain'} - ) - - if resp.status_code != 201: - self._raise_api_exception(resp) - - return [self.resource_class(self, resource_data) - for resource_data in base.extract_json(resp, 'actions')] - - def update(self, definition, scope='private', id=None): - self._ensure_not_empty(definition=definition) - - url_pre = ('/actions/%s' % id) if id else '/actions' - - # If the specified definition is actually a file, read in the - # definition file - definition = utils.get_contents_if_file(definition) - - resp = self.http_client.put( - '%s?scope=%s' % (url_pre, scope), - definition, - headers={'content-type': 'text/plain'} - ) - - if resp.status_code != 200: - self._raise_api_exception(resp) - - return [self.resource_class(self, resource_data) - for resource_data in base.extract_json(resp, 'actions')] - - def list(self, marker='', limit=None, sort_keys='', sort_dirs='', - **filters): - qparams = {} - - if marker: - qparams['marker'] = marker - - if limit: - qparams['limit'] = limit - - if sort_keys: - qparams['sort_keys'] = sort_keys - - if sort_dirs: - qparams['sort_dirs'] = sort_dirs - - for name, val in filters.items(): - qparams[name] = val - - query_string = ("?%s" % urlparse.urlencode(list(qparams.items())) - if qparams else "") - - return self._list( - '/actions%s' % query_string, - response_key='actions', - ) - - def get(self, identifier): - self._ensure_not_empty(identifier=identifier) - - return self._get('/actions/%s' % identifier) - - def delete(self, identifier): - self._ensure_not_empty(identifier=identifier) - - self._delete('/actions/%s' % identifier) - - def validate(self, definition): - self._ensure_not_empty(definition=definition) - - # If the specified definition is actually a file, read in the - # definition file - definition = utils.get_contents_if_file(definition) - - resp = self.http_client.post( - '/actions/validate', - definition, - headers={'content-type': 'text/plain'} - ) - - if resp.status_code != 200: - self._raise_api_exception(resp) - - return base.extract_json(resp, None) diff --git a/mistralclient/api/v2/client.py b/mistralclient/api/v2/client.py deleted file mode 100644 index c7dd0f0..0000000 --- a/mistralclient/api/v2/client.py +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# Copyright 2015 - StackStorm, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import copy -import six - -from oslo_utils import importutils - -from mistralclient.api import httpclient -from mistralclient.api.v2 import action_executions -from mistralclient.api.v2 import actions -from mistralclient.api.v2 import cron_triggers -from mistralclient.api.v2 import environments -from mistralclient.api.v2 import event_triggers -from mistralclient.api.v2 import executions -from mistralclient.api.v2 import members -from mistralclient.api.v2 import services -from mistralclient.api.v2 import tasks -from mistralclient.api.v2 import workbooks -from mistralclient.api.v2 import workflows -from mistralclient import auth - - -osprofiler_profiler = importutils.try_import("osprofiler.profiler") - -_DEFAULT_MISTRAL_URL = "http://localhost:8989/v2" - - -class Client(object): - - def __init__(self, auth_type='keystone', **kwargs): - # We get the session at this point, as some instances of session - # objects might have mutexes that can't be deep-copied. - session = kwargs.pop('session', None) - req = copy.deepcopy(kwargs) - mistral_url = req.get('mistral_url') - profile = req.get('profile') - - if mistral_url and not isinstance(mistral_url, six.string_types): - raise RuntimeError('Mistral url should be a string.') - - auth_handler = auth.get_auth_handler(auth_type) - auth_response = auth_handler.authenticate(req, session=session) or {} - - req.update(auth_response) - - mistral_url = auth_response.get('mistral_url') or mistral_url - - if not mistral_url: - mistral_url = _DEFAULT_MISTRAL_URL - - if profile: - osprofiler_profiler.init(profile) - - http_client = httpclient.HTTPClient(mistral_url, session=session, - **req) - - # Create all resource managers. - self.workbooks = workbooks.WorkbookManager(http_client) - self.executions = executions.ExecutionManager(http_client) - self.tasks = tasks.TaskManager(http_client) - self.actions = actions.ActionManager(http_client) - self.workflows = workflows.WorkflowManager(http_client) - self.cron_triggers = cron_triggers.CronTriggerManager(http_client) - self.event_triggers = event_triggers.EventTriggerManager(http_client) - self.environments = environments.EnvironmentManager(http_client) - self.action_executions = action_executions.ActionExecutionManager( - http_client) - self.services = services.ServiceManager(http_client) - self.members = members.MemberManager(http_client) diff --git a/mistralclient/api/v2/cron_triggers.py b/mistralclient/api/v2/cron_triggers.py deleted file mode 100644 index 036b1d1..0000000 --- a/mistralclient/api/v2/cron_triggers.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import json - -from oslo_utils import uuidutils - -from mistralclient.api import base - - -class CronTrigger(base.Resource): - resource_name = 'CronTrigger' - - -class CronTriggerManager(base.ResourceManager): - resource_class = CronTrigger - - def create(self, name, workflow_identifier, workflow_input=None, - workflow_params=None, pattern=None, - first_time=None, count=None): - self._ensure_not_empty( - name=name, - workflow_identifier=workflow_identifier - ) - - data = { - 'name': name, - 'pattern': pattern, - 'first_execution_time': first_time, - 'remaining_executions': count - } - - if uuidutils.is_uuid_like(workflow_identifier): - data.update({'workflow_id': workflow_identifier}) - else: - data.update({'workflow_name': workflow_identifier}) - - if workflow_input: - data.update({'workflow_input': json.dumps(workflow_input)}) - - if workflow_params: - data.update({'workflow_params': json.dumps(workflow_params)}) - - return self._create('/cron_triggers', data) - - def list(self): - return self._list('/cron_triggers', response_key='cron_triggers') - - def get(self, name): - self._ensure_not_empty(name=name) - - return self._get('/cron_triggers/%s' % name) - - def delete(self, name): - self._ensure_not_empty(name=name) - - self._delete('/cron_triggers/%s' % name) diff --git a/mistralclient/api/v2/environments.py b/mistralclient/api/v2/environments.py deleted file mode 100644 index da53d4e..0000000 --- a/mistralclient/api/v2/environments.py +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright 2015 - StackStorm, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import json - -import six - -from mistralclient.api import base -from mistralclient import utils - - -class Environment(base.Resource): - resource_name = 'Environment' - - def _set_attributes(self): - """Override loading of the "variables" attribute from text to dict.""" - for k, v in self._data.items(): - if k == 'variables' and isinstance(v, six.string_types): - v = json.loads(v) - - try: - setattr(self, k, v) - except AttributeError: - # In this case we already defined the attribute on the class - pass - - -class EnvironmentManager(base.ResourceManager): - resource_class = Environment - - def create(self, **kwargs): - # Check to see if the file name or URI is being passed in. If so, - # read it's contents first. - if 'file' in kwargs: - file = kwargs['file'] - kwargs = utils.load_content(utils.get_contents_if_file(file)) - - self._ensure_not_empty(name=kwargs.get('name', None), - variables=kwargs.get('variables', None)) - - # Convert dict to text for the variables attribute. - if isinstance(kwargs['variables'], dict): - kwargs['variables'] = json.dumps(kwargs['variables']) - - return self._create('/environments', kwargs) - - def update(self, **kwargs): - # Check to see if the file name or URI is being passed in. If so, - # read it's contents first. - if 'file' in kwargs: - file = kwargs['file'] - kwargs = utils.load_content(utils.get_contents_if_file(file)) - - name = kwargs.get('name', None) - self._ensure_not_empty(name=name) - - # Convert dict to text for the variables attribute. - if kwargs.get('variables') and isinstance(kwargs['variables'], dict): - kwargs['variables'] = json.dumps(kwargs['variables']) - - return self._update('/environments', kwargs) - - def list(self): - return self._list('/environments', response_key='environments') - - def get(self, name): - self._ensure_not_empty(name=name) - - return self._get('/environments/%s' % name) - - def delete(self, name): - self._ensure_not_empty(name=name) - - self._delete('/environments/%s' % name) diff --git a/mistralclient/api/v2/event_triggers.py b/mistralclient/api/v2/event_triggers.py deleted file mode 100644 index 0eef9f3..0000000 --- a/mistralclient/api/v2/event_triggers.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright 2017, OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import json - -from mistralclient.api import base - - -class EventTrigger(base.Resource): - resource_name = 'EventTrigger' - - -class EventTriggerManager(base.ResourceManager): - resource_class = EventTrigger - - def create(self, name, workflow_id, exchange, topic, event, - workflow_input=None, workflow_params=None): - self._ensure_not_empty( - name=name, - workflow_id=workflow_id - ) - - data = { - 'workflow_id': workflow_id, - 'name': name, - 'exchange': exchange, - 'topic': topic, - 'event': event - } - - if workflow_input: - data.update({'workflow_input': json.dumps(workflow_input)}) - - if workflow_params: - data.update({'workflow_params': json.dumps(workflow_params)}) - - return self._create('/event_triggers', data) - - def list(self): - return self._list('/event_triggers', response_key='event_triggers') - - def get(self, id): - self._ensure_not_empty(id=id) - - return self._get('/event_triggers/%s' % id) - - def delete(self, id): - self._ensure_not_empty(id=id) - - self._delete('/event_triggers/%s' % id) diff --git a/mistralclient/api/v2/executions.py b/mistralclient/api/v2/executions.py deleted file mode 100644 index 137a4e0..0000000 --- a/mistralclient/api/v2/executions.py +++ /dev/null @@ -1,110 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# Copyright 2015 - StackStorm, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import json - -from oslo_utils import uuidutils -import six - -from mistralclient.api import base - - -urlparse = six.moves.urllib.parse - - -class Execution(base.Resource): - resource_name = 'Execution' - - -class ExecutionManager(base.ResourceManager): - resource_class = Execution - - def create(self, workflow_identifier, workflow_input=None, description='', - **params): - self._ensure_not_empty(workflow_identifier=workflow_identifier) - - data = { - 'description': description - } - - if uuidutils.is_uuid_like(workflow_identifier): - data.update({'workflow_id': workflow_identifier}) - else: - data.update({'workflow_name': workflow_identifier}) - - if workflow_input: - if isinstance(workflow_input, six.string_types): - data.update({'input': workflow_input}) - else: - data.update({'input': json.dumps(workflow_input)}) - - if params: - data.update({'params': json.dumps(params)}) - - return self._create('/executions', data) - - def update(self, id, state, description=None, env=None): - data = {} - - if state: - data['state'] = state - - if description: - data['description'] = description - - if env: - data['params'] = {'env': env} - - return self._update('/executions/%s' % id, data) - - def list(self, task=None, marker='', limit=None, sort_keys='', - sort_dirs='', **filters): - qparams = {} - - if task: - qparams['task_execution_id'] = task - - if marker: - qparams['marker'] = marker - - if limit: - qparams['limit'] = limit - - if sort_keys: - qparams['sort_keys'] = sort_keys - - if sort_dirs: - qparams['sort_dirs'] = sort_dirs - - for name, val in filters.items(): - qparams[name] = val - - query_string = ("?%s" % urlparse.urlencode(list(qparams.items())) - if qparams else "") - - return self._list( - '/executions%s' % query_string, - response_key='executions', - ) - - def get(self, id): - self._ensure_not_empty(id=id) - - return self._get('/executions/%s' % id) - - def delete(self, id): - self._ensure_not_empty(id=id) - - self._delete('/executions/%s' % id) diff --git a/mistralclient/api/v2/members.py b/mistralclient/api/v2/members.py deleted file mode 100644 index 6927c40..0000000 --- a/mistralclient/api/v2/members.py +++ /dev/null @@ -1,76 +0,0 @@ -# Copyright 2016 - Catalyst IT Limited -# -# 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 mistralclient.api import base - - -class Member(base.Resource): - resource_name = 'Member' - - -class MemberManager(base.ResourceManager): - resource_class = Member - - def create(self, resource_id, resource_type, member_id): - self._ensure_not_empty( - resource_id=resource_id, - resource_type=resource_type, - member_id=member_id - ) - - data = { - 'member_id': member_id, - } - - url = '/%ss/%s/members' % (resource_type, resource_id) - - return self._create(url, data) - - def update(self, resource_id, resource_type, member_id='', - status='accepted'): - if not member_id: - member_id = self.http_client.project_id - - url = '/%ss/%s/members/%s' % (resource_type, resource_id, member_id) - - return self._update(url, {'status': status}) - - def list(self, resource_id, resource_type): - url = '/%ss/%s/members' % (resource_type, resource_id) - - return self._list(url, response_key='members') - - def get(self, resource_id, resource_type, member_id=None): - self._ensure_not_empty( - resource_id=resource_id, - resource_type=resource_type, - ) - - if not member_id: - member_id = self.http_client.project_id - - url = '/%ss/%s/members/%s' % (resource_type, resource_id, member_id) - - return self._get(url) - - def delete(self, resource_id, resource_type, member_id): - self._ensure_not_empty( - resource_id=resource_id, - resource_type=resource_type, - member_id=member_id - ) - - url = '/%ss/%s/members/%s' % (resource_type, resource_id, member_id) - - self._delete(url) diff --git a/mistralclient/api/v2/services.py b/mistralclient/api/v2/services.py deleted file mode 100644 index 81125d7..0000000 --- a/mistralclient/api/v2/services.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright 2015 Huawei Technologies Co., Ltd. -# -# 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 mistralclient.api import base - - -class Service(base.Resource): - resource_name = 'Service' - - -class ServiceManager(base.ResourceManager): - resource_class = Service - - def list(self): - return self._list('/services', response_key='services') diff --git a/mistralclient/api/v2/tasks.py b/mistralclient/api/v2/tasks.py deleted file mode 100644 index 7a9eae6..0000000 --- a/mistralclient/api/v2/tasks.py +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# Copyright 2015 - StackStorm, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import json -import six - -from mistralclient.api import base - -urlparse = six.moves.urllib.parse - - -class Task(base.Resource): - resource_name = 'Task' - - -class TaskManager(base.ResourceManager): - resource_class = Task - - def list(self, workflow_execution_id=None, marker='', limit=None, - sort_keys='', sort_dirs='', **filters): - url = '/tasks' - - if workflow_execution_id: - url = '/executions/%s/tasks' % workflow_execution_id - - url += '%s' - - qparams = {} - - if marker: - qparams['marker'] = marker - - if limit: - qparams['limit'] = limit - - if sort_keys: - qparams['sort_keys'] = sort_keys - - if sort_dirs: - qparams['sort_dirs'] = sort_dirs - - for name, val in filters.items(): - qparams[name] = val - - query_string = ("?%s" % urlparse.urlencode(list(qparams.items())) - if qparams else "") - - return self._list(url % query_string, response_key='tasks') - - def get(self, id): - self._ensure_not_empty(id=id) - - return self._get('/tasks/%s' % id) - - def rerun(self, task_ex_id, reset=True, env=None): - url = '/tasks/%s' % task_ex_id - - body = { - 'id': task_ex_id, - 'state': 'RUNNING', - 'reset': reset - } - - if env: - body['env'] = json.dumps(env) - - return self._update(url, body) diff --git a/mistralclient/api/v2/workbooks.py b/mistralclient/api/v2/workbooks.py deleted file mode 100644 index 88a5112..0000000 --- a/mistralclient/api/v2/workbooks.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# Copyright 2015 - StackStorm, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from mistralclient.api import base -from mistralclient import utils - - -class Workbook(base.Resource): - resource_name = 'Workbook' - - -class WorkbookManager(base.ResourceManager): - resource_class = Workbook - - def create(self, definition): - self._ensure_not_empty(definition=definition) - - # If the specified definition is actually a file, read in the - # definition file - definition = utils.get_contents_if_file(definition) - - resp = self.http_client.post( - '/workbooks', - definition, - headers={'content-type': 'text/plain'} - ) - - if resp.status_code != 201: - self._raise_api_exception(resp) - - return self.resource_class(self, base.extract_json(resp, None)) - - def update(self, definition): - self._ensure_not_empty(definition=definition) - - # If the specified definition is actually a file, read in the - # definition file - definition = utils.get_contents_if_file(definition) - - resp = self.http_client.put( - '/workbooks', - definition, - headers={'content-type': 'text/plain'} - ) - - if resp.status_code != 200: - self._raise_api_exception(resp) - - return self.resource_class(self, base.extract_json(resp, None)) - - def list(self): - return self._list('/workbooks', response_key='workbooks') - - def get(self, name): - self._ensure_not_empty(name=name) - - return self._get('/workbooks/%s' % name) - - def delete(self, name): - self._ensure_not_empty(name=name) - - self._delete('/workbooks/%s' % name) - - def validate(self, definition): - self._ensure_not_empty(definition=definition) - - # If the specified definition is actually a file, read in the - # definition file - definition = utils.get_contents_if_file(definition) - - resp = self.http_client.post( - '/workbooks/validate', - definition, - headers={'content-type': 'text/plain'} - ) - - if resp.status_code != 200: - self._raise_api_exception(resp) - - return base.extract_json(resp, None) diff --git a/mistralclient/api/v2/workflows.py b/mistralclient/api/v2/workflows.py deleted file mode 100644 index e6bbbef..0000000 --- a/mistralclient/api/v2/workflows.py +++ /dev/null @@ -1,128 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# Copyright 2015 - StackStorm, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import six - -from mistralclient.api import base -from mistralclient import utils - - -urlparse = six.moves.urllib.parse - - -class Workflow(base.Resource): - resource_name = 'Workflow' - - -class WorkflowManager(base.ResourceManager): - resource_class = Workflow - - def create(self, definition, scope='private'): - self._ensure_not_empty(definition=definition) - - # If the specified definition is actually a file, read in the - # definition file - definition = utils.get_contents_if_file(definition) - - resp = self.http_client.post( - '/workflows?scope=%s' % scope, - definition, - headers={'content-type': 'text/plain'} - ) - - if resp.status_code != 201: - self._raise_api_exception(resp) - - return [self.resource_class(self, resource_data) - for resource_data in base.extract_json(resp, 'workflows')] - - def update(self, definition, scope='private', id=None): - self._ensure_not_empty(definition=definition) - - url_pre = ('/workflows/%s' % id) if id else '/workflows' - - # If the specified definition is actually a file, read in the - # definition file - definition = utils.get_contents_if_file(definition) - - resp = self.http_client.put( - '%s?scope=%s' % (url_pre, scope), - definition, - headers={'content-type': 'text/plain'} - ) - - if resp.status_code != 200: - self._raise_api_exception(resp) - - if id: - return self.resource_class(self, base.extract_json(resp, None)) - - return [self.resource_class(self, resource_data) - for resource_data in base.extract_json(resp, 'workflows')] - - def list(self, marker='', limit=None, sort_keys='', sort_dirs='', - **filters): - qparams = {} - - if marker: - qparams['marker'] = marker - - if limit: - qparams['limit'] = limit - - if sort_keys: - qparams['sort_keys'] = sort_keys - - if sort_dirs: - qparams['sort_dirs'] = sort_dirs - - for name, val in filters.items(): - qparams[name] = val - - query_string = ("?%s" % urlparse.urlencode(list(qparams.items())) - if qparams else "") - - return self._list( - '/workflows%s' % query_string, - response_key='workflows', - ) - - def get(self, identifier): - self._ensure_not_empty(identifier=identifier) - - return self._get('/workflows/%s' % identifier) - - def delete(self, identifier): - self._ensure_not_empty(identifier=identifier) - - self._delete('/workflows/%s' % identifier) - - def validate(self, definition): - self._ensure_not_empty(definition=definition) - - # If the specified definition is actually a file, read in the - # definition file - definition = utils.get_contents_if_file(definition) - - resp = self.http_client.post( - '/workflows/validate', - definition, - headers={'content-type': 'text/plain'} - ) - - if resp.status_code != 200: - self._raise_api_exception(resp) - - return base.extract_json(resp, None) diff --git a/mistralclient/auth/__init__.py b/mistralclient/auth/__init__.py deleted file mode 100644 index 85cecd4..0000000 --- a/mistralclient/auth/__init__.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2016 - Brocade Communications Systems, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import abc - -import six -from stevedore import driver - - -def get_auth_handler(auth_type): - mgr = driver.DriverManager( - 'mistralclient.auth', - auth_type, - invoke_on_load=True - ) - - return mgr.driver - - -@six.add_metaclass(abc.ABCMeta) -class AuthHandler(object): - """Abstract base class for an authentication plugin.""" - - @abc.abstractmethod - def authenticate(self, req): - raise NotImplementedError() diff --git a/mistralclient/auth/auth_types.py b/mistralclient/auth/auth_types.py deleted file mode 100644 index 76f5a2e..0000000 --- a/mistralclient/auth/auth_types.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2016 - Nokia Networks -# -# 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 stevedore import extension - -# Valid authentication types. -ALL = extension.ExtensionManager( - namespace='mistralclient.auth', - invoke_on_load=False -).names() diff --git a/mistralclient/auth/keycloak.py b/mistralclient/auth/keycloak.py deleted file mode 100644 index 2f5bc7d..0000000 --- a/mistralclient/auth/keycloak.py +++ /dev/null @@ -1,170 +0,0 @@ -# Copyright 2016 - Nokia Networks -# -# 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 pprint -import requests - -from mistralclient import auth - - -LOG = logging.getLogger(__name__) - - -class KeycloakAuthHandler(auth.AuthHandler): - - def authenticate(self, req, session=None): - """Performs authentication using Keycloak OpenID Protocol. - - :param req: Request dict containing list of parameters required - for Keycloak authentication. - - * auth_url: Base authentication url of KeyCloak server (e.g. - "https://my.keycloak:8443/auth" - * client_id: Client ID (according to OpenID Connect protocol). - * client_secret: Client secret (according to OpenID Connect - protocol). - * realm_name: KeyCloak realm name. - * username: User name (Optional, if None then access_token must be - provided). - * password: Password (Optional). - * access_token: Access token. If passed, username and password are - not used and this method just validates the token and refreshes - it if needed (Optional, if None then username must be - provided). - * cacert: SSL certificate file (Optional). - * insecure: If True, SSL certificate is not verified (Optional). - - :param session: Keystone session object. Not used by this plugin. - - """ - - if not isinstance(req, dict): - raise TypeError('The input "req" is not typeof dict.') - - auth_url = req.get('auth_url') - client_id = req.get('client_id') - client_secret = req.get('client_secret') - realm_name = req.get('realm_name') - username = req.get('username') - password = req.get('password') - access_token = req.get('access_token') - cacert = req.get('cacert') - insecure = req.get('insecure', False) - - if not auth_url: - raise ValueError('Base authentication url is not provided.') - - if not client_id: - raise ValueError('Client ID is not provided.') - - if not client_secret: - raise ValueError('Client secret is not provided.') - - if not realm_name: - raise ValueError('Project(realm) name is not provided.') - - if username and access_token: - raise ValueError( - "User name and access token can't be " - "provided at the same time." - ) - - if not username and not access_token: - raise ValueError( - 'Either user name or access token must be provided.' - ) - - if access_token: - response = self._authenticate_with_token( - auth_url, - client_id, - client_secret, - access_token, - cacert, - insecure - ) - else: - response = self._authenticate_with_password( - auth_url, - client_id, - client_secret, - realm_name, - username, - password, - cacert, - insecure - ) - - response['project_id'] = realm_name - - return response - - def _authenticate_with_token(auth_url, client_id, client_secret, - auth_token, cacert=None, insecure=None): - # TODO(rakhmerov): Implement. - raise NotImplementedError - - def _authenticate_with_password(auth_url, client_id, client_secret, - realm_name, username, password, - cacert=None, insecure=None): - access_token_endpoint = ( - "%s/realms/%s/protocol/openid-connect/token" % - (auth_url, realm_name) - ) - - client_auth = (client_id, client_secret) - - body = { - 'grant_type': 'password', - 'username': username, - 'password': password, - 'scope': 'profile' - } - - resp = requests.post( - access_token_endpoint, - auth=client_auth, - data=body, - verify=not insecure - ) - - try: - resp.raise_for_status() - except Exception as e: - raise Exception("Failed to get access token:\n %s" % str(e)) - - LOG.debug("HTTP response from OIDC provider: %s", - pprint.pformat(resp.json())) - - return resp.json()['access_token'] - - -# An example of using KeyCloak OpenID authentication. -if __name__ == '__main__': - print("Using username/password to get access token from KeyCloak...") - - auth_handler = KeycloakAuthHandler() - - a_token = auth_handler.authenticate( - "https://my.keycloak:8443/auth", - client_id="mistral_client", - client_secret="4a080907-921b-409a-b793-c431609c3a47", - realm_name="mistral", - username="user", - password="secret", - insecure=True - ) - - print("Access token: %s" % a_token) diff --git a/mistralclient/auth/keystone.py b/mistralclient/auth/keystone.py deleted file mode 100644 index 2d6f98f..0000000 --- a/mistralclient/auth/keystone.py +++ /dev/null @@ -1,146 +0,0 @@ -# Copyright 2016 - Nokia Networks -# -# 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 keystoneclient import client -from mistralclient import auth -from oslo_serialization import jsonutils - -import mistralclient.api.httpclient as api - - -class KeystoneAuthHandler(auth.AuthHandler): - - def authenticate(self, req, session=None): - """Performs authentication via Keystone. - - :param req: Request dict containing list of parameters required - for Keystone authentication. - - """ - if not isinstance(req, dict): - raise TypeError('The input "req" is not typeof dict.') - - session = session - mistral_url = req.get('mistral_url') - endpoint_type = req.get('endpoint_type', 'publicURL') - service_type = req.get('service_type', 'workflowv2') - - auth_url = req.get('auth_url') - username = req.get('username') - user_id = req.get('user_id') - api_key = req.get('api_key') - auth_token = req.get('auth_token') - project_name = req.get('project_name') - project_id = req.get('project_id') - region_name = req.get('region_name') - user_domain_name = req.get('user_domain_name', 'Default') - project_domain_name = req.get('project_domain_name', 'Default') - cacert = req.get('cacert') - insecure = req.get('insecure', False) - - target_auth_url = req.get('target_auth_url') - target_username = req.get('target_username') - target_user_id = req.get('target_user_id') - target_api_key = req.get('target_api_key') - target_auth_token = req.get('target_auth_token') - target_project_name = req.get('target_project_name') - target_project_id = req.get('target_project_id') - target_region_name = req.get('target_region_name') - target_user_domain_name = req.get('target_user_domain_name', 'Default') - target_project_domain_name = req.get( - 'target_project_domain_name', - 'Default' - ) - target_cacert = req.get('target_cacert') - target_insecure = req.get('target_insecure') - - if project_name and project_id: - raise RuntimeError( - 'Only project name or project id should be set' - ) - - if username and user_id: - raise RuntimeError( - 'Only user name or user id should be set' - ) - - auth_response = {} - - if session: - keystone = client.Client(session=session) - elif auth_url: - keystone = client.Client( - username=username, - user_id=user_id, - password=api_key, - token=auth_token, - tenant_id=project_id, - tenant_name=project_name, - auth_url=auth_url, - cacert=cacert, - insecure=insecure, - user_domain_name=user_domain_name, - project_domain_name=project_domain_name - ) - keystone.authenticate() - auth_response.update({ - api.AUTH_TOKEN: keystone.auth_token, - api.PROJECT_ID: keystone.project_id, - api.USER_ID: keystone.user_id, - }) - - if session or auth_url: - if not mistral_url: - try: - mistral_url = keystone.service_catalog.url_for( - service_type=service_type, - endpoint_type=endpoint_type, - region_name=region_name - ) - except Exception: - mistral_url = None - - auth_response['mistral_url'] = mistral_url - - if target_auth_url: - target_keystone = client.Client( - username=target_username, - user_id=target_user_id, - password=target_api_key, - token=target_auth_token, - tenant_id=target_project_id, - tenant_name=target_project_name, - project_id=target_project_id, - project_name=target_project_name, - auth_url=target_auth_url, - cacert=target_cacert, - insecure=target_insecure, - region_name=target_region_name, - user_domain_name=target_user_domain_name, - project_domain_name=target_project_domain_name - ) - - target_keystone.authenticate() - - auth_response.update({ - api.TARGET_AUTH_TOKEN: target_keystone.auth_token, - api.TARGET_PROJECT_ID: target_keystone.project_id, - api.TARGET_USER_ID: target_keystone.user_id, - api.TARGET_AUTH_URI: target_auth_url, - api.TARGET_SERVICE_CATALOG: jsonutils.dumps( - target_keystone.auth_ref - ) - }) - - return auth_response diff --git a/mistralclient/commands/__init__.py b/mistralclient/commands/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/mistralclient/commands/v2/__init__.py b/mistralclient/commands/v2/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/mistralclient/commands/v2/action_executions.py b/mistralclient/commands/v2/action_executions.py deleted file mode 100644 index c96efb0..0000000 --- a/mistralclient/commands/v2/action_executions.py +++ /dev/null @@ -1,338 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# Copyright 2016 - Brocade Communications Systems, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import json -import logging - -from osc_lib.command import command - -from mistralclient.commands.v2 import base -from mistralclient import utils - -LOG = logging.getLogger(__name__) - - -def format_list(action_ex=None): - columns = ( - 'ID', - 'Name', - 'Workflow name', - 'Task name', - 'Task ID', - 'State', - 'Accepted', - 'Created at', - 'Updated at' - ) - - if action_ex: - data = ( - action_ex.id, - action_ex.name, - action_ex.workflow_name, - action_ex.task_name if hasattr(action_ex, 'task_name') else None, - action_ex.task_execution_id, - action_ex.state, - action_ex.accepted, - action_ex.created_at, - action_ex.updated_at or '' - ) - else: - data = (tuple('' for _ in range(len(columns))),) - - return columns, data - - -def format(action_ex=None): - columns = ( - 'ID', - 'Name', - 'Workflow name', - 'Task name', - 'Task ID', - 'State', - 'State info', - 'Accepted', - 'Created at', - 'Updated at', - ) - - if action_ex: - data = ( - action_ex.id, - action_ex.name, - action_ex.workflow_name, - action_ex.task_name if hasattr(action_ex, 'task_name') else None, - action_ex.task_execution_id, - action_ex.state, - action_ex.state_info, - action_ex.accepted, - action_ex.created_at, - action_ex.updated_at or '' - ) - else: - data = (tuple('' for _ in range(len(columns))),) - - return columns, data - - -class Create(command.ShowOne): - """Create new Action execution or just run specific action.""" - - def produce_output(self, parsed_args, column_names, data): - if not column_names: - return 0 - - return super(Create, self).produce_output( - parsed_args, - column_names, - data - ) - - def get_parser(self, prog_name): - parser = super(Create, self).get_parser(prog_name) - - parser.add_argument( - 'name', - help='Action name to execute.' - ) - parser.add_argument( - dest='input', - nargs='?', - help='Action input.' - ) - parser.add_argument( - '-s', - '--save-result', - dest='save_result', - action='store_true', - help='Save the result into DB.' - ) - parser.add_argument( - '--run-sync', - dest='run_sync', - action='store_true', - help='Run the action synchronously.' - ) - parser.add_argument( - '-t', - '--target', - dest='target', - help='Action will be executed on executor.' - ) - - return parser - - def take_action(self, parsed_args): - params = {} - - if parsed_args.save_result: - params['save_result'] = parsed_args.save_result - - if parsed_args.run_sync: - params['run_sync'] = parsed_args.run_sync - - if parsed_args.target: - params['target'] = parsed_args.target - - action_input = None - - if parsed_args.input: - action_input = utils.load_json(parsed_args.input) - - mistral_client = self.app.client_manager.workflow_engine - action_ex = mistral_client.action_executions.create( - parsed_args.name, - action_input, - **params - ) - - if not parsed_args.run_sync and parsed_args.save_result: - return format(action_ex) - else: - self.app.stdout.write("%s\n" % action_ex.output) - - return None, None - - -class List(base.MistralLister): - """List all Action executions.""" - - def _get_format_function(self): - return format_list - - def get_parser(self, prog_name): - parser = super(List, self).get_parser(prog_name) - - parser.add_argument( - 'task_execution_id', - nargs='?', - help='Task execution ID.' - ) - parser.add_argument( - '--limit', - type=int, - help='Maximum number of action-executions to return in a single ' - 'result. limit is set to %s by default. Use --limit -1 to ' - 'fetch the full result set.' % base.DEFAULT_LIMIT, - nargs='?' - ) - - return parser - - def _get_resources(self, parsed_args): - if parsed_args.limit is None: - parsed_args.limit = base.DEFAULT_LIMIT - LOG.info("limit is set to %s by default. Set " - "the limit explicitly using \'--limit\', if required. " - "Use \'--limit\' -1 to fetch the full result set.", - base.DEFAULT_LIMIT) - mistral_client = self.app.client_manager.workflow_engine - - return mistral_client.action_executions.list( - parsed_args.task_execution_id, - limit=parsed_args.limit, - ) - - -class Get(command.ShowOne): - """Show specific Action execution.""" - - def get_parser(self, prog_name): - parser = super(Get, self).get_parser(prog_name) - - parser.add_argument('action_execution', help='Action execution ID.') - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - - execution = mistral_client.action_executions.get( - parsed_args.action_execution - ) - - return format(execution) - - -class Update(command.ShowOne): - """Update specific Action execution.""" - - def get_parser(self, prog_name): - parser = super(Update, self).get_parser(prog_name) - - parser.add_argument( - 'id', - help='Action execution ID.') - parser.add_argument( - '--state', - dest='state', - choices=['IDLE', 'RUNNING', 'SUCCESS', 'ERROR', 'CANCELLED'], - help='Action execution state') - parser.add_argument( - '--output', - dest='output', - help='Action execution output') - - return parser - - def take_action(self, parsed_args): - output = None - if parsed_args.output: - output = utils.load_json(parsed_args.output) - - mistral_client = self.app.client_manager.workflow_engine - execution = mistral_client.action_executions.update( - parsed_args.id, - parsed_args.state, - output - ) - - return format(execution) - - -class GetOutput(command.Command): - """Show Action execution output data.""" - - def get_parser(self, prog_name): - parser = super(GetOutput, self).get_parser(prog_name) - parser.add_argument( - 'id', - help='Action execution ID.') - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - output = mistral_client.action_executions.get(parsed_args.id).output - - try: - output = json.loads(output) - output = json.dumps(output, indent=4) + "\n" - except Exception: - LOG.debug("Task result is not JSON.") - - self.app.stdout.write(output or "\n") - - -class GetInput(command.Command): - """Show Action execution input data.""" - - def get_parser(self, prog_name): - parser = super(GetInput, self).get_parser(prog_name) - parser.add_argument( - 'id', - help='Action execution ID.' - ) - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - result = mistral_client.action_executions.get(parsed_args.id).input - - try: - result = json.loads(result) - result = json.dumps(result, indent=4) + "\n" - except Exception: - LOG.debug("Task result is not JSON.") - - self.app.stdout.write(result or "\n") - - -class Delete(command.Command): - """Delete action execution.""" - - def get_parser(self, prog_name): - parser = super(Delete, self).get_parser(prog_name) - - parser.add_argument( - 'action_execution', - nargs='+', - help='Id of action execution identifier(s).' - ) - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - - utils.do_action_on_many( - lambda s: mistral_client.action_executions.delete(s), - parsed_args.action_execution, - "Request to delete action execution %s has been accepted.", - "Unable to delete the specified action execution(s)." - ) diff --git a/mistralclient/commands/v2/actions.py b/mistralclient/commands/v2/actions.py deleted file mode 100644 index 88841aa..0000000 --- a/mistralclient/commands/v2/actions.py +++ /dev/null @@ -1,255 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import argparse - -from osc_lib.command import command - -from mistralclient.commands.v2 import base -from mistralclient import utils - - -def format_list(action=None): - return format(action, lister=True) - - -def format(action=None, lister=False): - columns = ( - 'ID', - 'Name', - 'Is system', - 'Input', - 'Description', - 'Tags', - 'Created at', - 'Updated at' - ) - - if action: - tags = getattr(action, 'tags', None) or [] - input = action.input if not lister else base.cut(action.input) - desc = (action.description if not lister - else base.cut(action.description)) - - data = ( - action.id, - action.name, - action.is_system, - input, - desc, - base.wrap(', '.join(tags)) or '', - action.created_at, - ) - - if hasattr(action, 'updated_at'): - data += (action.updated_at,) - else: - data += (None,) - else: - data = (tuple('' for _ in range(len(columns))),) - - return columns, data - - -class List(base.MistralLister): - """List all actions.""" - - def _get_format_function(self): - return format_list - - def get_parser(self, prog_name): - parser = super(List, self).get_parser(prog_name) - - parser.add_argument( - '--filter', - dest='filters', - action='append', - help='Filters. Can be repeated.' - ) - - return parser - - def _get_resources(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - - return mistral_client.actions.list( - **base.get_filters(parsed_args) - ) - - -class Get(command.ShowOne): - """Show specific action.""" - - def get_parser(self, prog_name): - parser = super(Get, self).get_parser(prog_name) - - parser.add_argument('action', help='Action (name or ID)') - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - action = mistral_client.actions.get(parsed_args.action) - - return format(action) - - -class Create(base.MistralLister): - """Create new action.""" - - def get_parser(self, prog_name): - parser = super(Create, self).get_parser(prog_name) - - parser.add_argument( - 'definition', - type=argparse.FileType('r'), - help='Action definition file' - ) - parser.add_argument( - '--public', - action='store_true', - help='With this flag action will be marked as "public".' - ) - - return parser - - def _validate_parsed_args(self, parsed_args): - if not parsed_args.definition: - raise RuntimeError("Provide action definition file.") - - def _get_format_function(self): - return format_list - - def _get_resources(self, parsed_args): - scope = 'public' if parsed_args.public else 'private' - - mistral_client = self.app.client_manager.workflow_engine - - return mistral_client.actions.create( - parsed_args.definition.read(), - scope=scope - ) - - -class Delete(command.Command): - """Delete action.""" - - def get_parser(self, prog_name): - parser = super(Delete, self).get_parser(prog_name) - - parser.add_argument( - 'action', - nargs='+', - help='Name or ID of action(s).' - ) - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - - utils.do_action_on_many( - lambda s: mistral_client.actions.delete(s), - parsed_args.action, - "Request to delete action %s has been accepted.", - "Unable to delete the specified action(s)." - ) - - -class Update(base.MistralLister): - """Update action.""" - - def get_parser(self, prog_name): - parser = super(Update, self).get_parser(prog_name) - - parser.add_argument( - 'definition', - type=argparse.FileType('r'), - help='Action definition file' - ) - parser.add_argument('--id', help='Action ID.') - parser.add_argument( - '--public', - action='store_true', - help='With this flag action will be marked as "public".' - ) - - return parser - - def _get_format_function(self): - return format_list - - def _get_resources(self, parsed_args): - scope = 'public' if parsed_args.public else 'private' - - mistral_client = self.app.client_manager.workflow_engine - - return mistral_client.actions.update( - parsed_args.definition.read(), - scope=scope, - id=parsed_args.id - ) - - -class GetDefinition(command.Command): - """Show action definition.""" - - def get_parser(self, prog_name): - parser = super(GetDefinition, self).get_parser(prog_name) - - parser.add_argument('name', help='Action name') - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - definition = mistral_client.actions.get(parsed_args.name).definition - - self.app.stdout.write(definition or "\n") - - -class Validate(command.ShowOne): - """Validate action.""" - - def _format(self, result=None): - columns = ('Valid', 'Error') - - if result: - data = (result.get('valid'), result.get('error')) - else: - data = (tuple('' for _ in range(len(columns))),) - - return columns, data - - def get_parser(self, prog_name): - parser = super(Validate, self).get_parser(prog_name) - - parser.add_argument( - 'definition', - type=argparse.FileType('r'), - help='action definition file' - ) - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - - result = mistral_client.actions.validate( - parsed_args.definition.read() - ) - - return self._format(result) diff --git a/mistralclient/commands/v2/base.py b/mistralclient/commands/v2/base.py deleted file mode 100644 index cbfe6da..0000000 --- a/mistralclient/commands/v2/base.py +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import abc -import textwrap - -from osc_lib.command import command -import six - - -DEFAULT_LIMIT = 100 - - -@six.add_metaclass(abc.ABCMeta) -class MistralLister(command.Lister): - @abc.abstractmethod - def _get_format_function(self): - raise NotImplementedError - - @abc.abstractmethod - def _get_resources(self, parsed_args): - """Gets a list of API resources (e.g. using client).""" - raise NotImplementedError - - def _validate_parsed_args(self, parsed_args): - # No-op by default. - pass - - def take_action(self, parsed_args): - self._validate_parsed_args(parsed_args) - - f = self._get_format_function() - - ret = self._get_resources(parsed_args) - if not isinstance(ret, list): - ret = [ret] - - data = [f(r)[1] for r in ret] - - if data: - return f()[0], data - else: - return f() - - -def cut(string, length=25): - if string and len(string) > length: - return "%s..." % string[:length] - else: - return string - - -def wrap(string, width=25): - if string and len(string) > width: - return textwrap.fill(string, width) - else: - return string - - -def get_filters(parsed_args): - filters = {} - - if parsed_args.filters: - for f in parsed_args.filters: - arr = f.split('=') - - if len(arr) != 2: - raise ValueError('Invalid filter: %s' % f) - - filters[arr[0]] = arr[1] - - return filters diff --git a/mistralclient/commands/v2/cron_triggers.py b/mistralclient/commands/v2/cron_triggers.py deleted file mode 100644 index f60c7d3..0000000 --- a/mistralclient/commands/v2/cron_triggers.py +++ /dev/null @@ -1,216 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -import datetime -import time - -from osc_lib.command import command - -from mistralclient.commands.v2 import base -from mistralclient import utils - - -def format_list(trigger=None): - return format(trigger, lister=True) - - -def format(trigger=None, lister=False): - columns = ( - 'Name', - 'Workflow', - 'Params', - 'Pattern', - # TODO(rakhmerov): Uncomment when passwords are handled properly. - # TODO(rakhmerov): Add 'Workflow input' column. - 'Next execution time', - 'Remaining executions', - 'Created at', - 'Updated at' - ) - - if trigger: - # TODO(rakhmerov): Add following here: - # TODO(rakhmerov): wf_input = trigger.workflow_input if not lister - # TODO(rakhmerov:): else base.cut(trigger.workflow_input) - - data = ( - trigger.name, - trigger.workflow_name, - trigger.workflow_params, - trigger.pattern, - # TODO(rakhmerov): Uncomment when passwords are handled properly. - # TODo(rakhmerov): Add 'wf_input' here. - trigger.next_execution_time, - trigger.remaining_executions, - trigger.created_at, - ) - - if hasattr(trigger, 'updated_at'): - data += (trigger.updated_at,) - else: - data += (None,) - else: - data = (tuple('' for _ in range(len(columns))),) - - return columns, data - - -class List(base.MistralLister): - """List all cron triggers.""" - - def _get_format_function(self): - return format_list - - def _get_resources(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - return mistral_client.cron_triggers.list() - - -class Get(command.ShowOne): - """Show specific cron trigger.""" - - def get_parser(self, prog_name): - parser = super(Get, self).get_parser(prog_name) - - parser.add_argument('cron_trigger', help='Cron trigger name') - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - - return format(mistral_client.cron_triggers.get( - parsed_args.cron_trigger - )) - - -class Create(command.ShowOne): - """Create new trigger.""" - - def get_parser(self, prog_name): - parser = super(Create, self).get_parser(prog_name) - - parser.add_argument('name', help='Cron trigger name') - parser.add_argument('workflow_identifier', help='Workflow name or ID') - - parser.add_argument( - 'workflow_input', - nargs='?', - help='Workflow input' - ) - - parser.add_argument( - '--params', - help='Workflow params', - ) - - parser.add_argument( - '--pattern', - type=str, - help='Cron trigger pattern', - metavar='<* * * * *>' - ) - parser.add_argument( - '--first-time', - type=str, - default=None, - help=("Date and time of the first execution. Time is treated as " - "local time unless --utc is also specified"), - metavar='' - ) - parser.add_argument( - '--count', - type=int, - help="Number of wanted executions", - metavar='' - ) - parser.add_argument( - '--utc', - action='store_true', - help="All times specified should be treated as UTC" - ) - - return parser - - @staticmethod - def _get_file_content_or_dict(string): - if string: - return utils.load_json(string) - else: - return {} - - @staticmethod - def _convert_time_string_to_utc(time_string): - datetime_format = '%Y-%m-%d %H:%M' - - the_time = time_string - if the_time: - the_time = datetime.datetime.strptime( - the_time, datetime_format) - - is_dst = time.daylight and time.localtime().tm_isdst > 0 - utc_offset = - (time.altzone if is_dst else time.timezone) - - the_time = (the_time - datetime.timedelta( - 0, utc_offset)).strftime(datetime_format) - - return the_time - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - - wf_input = self._get_file_content_or_dict(parsed_args.workflow_input) - wf_params = self._get_file_content_or_dict(parsed_args.params) - - first_time = parsed_args.first_time - if not parsed_args.utc: - first_time = self._convert_time_string_to_utc( - parsed_args.first_time) - - trigger = mistral_client.cron_triggers.create( - parsed_args.name, - parsed_args.workflow_identifier, - wf_input, - wf_params, - parsed_args.pattern, - first_time, - parsed_args.count - ) - - return format(trigger) - - -class Delete(command.Command): - """Delete trigger.""" - - def get_parser(self, prog_name): - parser = super(Delete, self).get_parser(prog_name) - - parser.add_argument( - 'cron_trigger', - nargs='+', help='Name of cron trigger(s).' - ) - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - - utils.do_action_on_many( - lambda s: mistral_client.cron_triggers.delete(s), - parsed_args.cron_trigger, - "Request to delete cron trigger %s has been accepted.", - "Unable to delete the specified cron trigger(s)." - ) diff --git a/mistralclient/commands/v2/environments.py b/mistralclient/commands/v2/environments.py deleted file mode 100644 index 6912fac..0000000 --- a/mistralclient/commands/v2/environments.py +++ /dev/null @@ -1,186 +0,0 @@ -# Copyright 2015 - StackStorm, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import argparse -import json - -from osc_lib.command import command - -from mistralclient.commands.v2 import base -from mistralclient import utils - - -def format_list(environment=None): - columns = ( - 'Name', - 'Description', - 'Scope', - 'Created at', - 'Updated at' - ) - - if environment: - data = ( - environment.name, - environment.description, - environment.scope, - environment.created_at, - ) - - if hasattr(environment, 'updated_at'): - data += (environment.updated_at or '',) - else: - data += (None,) - - else: - data = (tuple('' for _ in range(len(columns))),) - - return columns, data - - -def format(environment=None): - columns = ( - 'Name', - 'Description', - 'Variables', - 'Scope', - 'Created at', - 'Updated at' - ) - - if environment: - data = (environment.name,) - - if hasattr(environment, 'description'): - data += (environment.description or '',) - else: - data += (None,) - - data += ( - json.dumps(environment.variables, indent=4), - environment.scope, - environment.created_at, - ) - - if hasattr(environment, 'updated_at'): - data += (environment.updated_at or '',) - else: - data += (None,) - - else: - data = (tuple('' for _ in range(len(columns))),) - - return columns, data - - -class List(base.MistralLister): - """List all environments.""" - - def _get_format_function(self): - return format_list - - def _get_resources(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - return mistral_client.environments.list() - - -class Get(command.ShowOne): - """Show specific environment.""" - - def get_parser(self, prog_name): - parser = super(Get, self).get_parser(prog_name) - - parser.add_argument( - 'environment', - help='Environment name' - ) - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - environment = mistral_client.environments.get(parsed_args.environment) - - return format(environment) - - -class Create(command.ShowOne): - """Create new environment.""" - - def get_parser(self, prog_name): - parser = super(Create, self).get_parser(prog_name) - - parser.add_argument( - 'file', - type=argparse.FileType('r'), - help='Environment configuration file in JSON or YAML' - ) - - return parser - - def take_action(self, parsed_args): - data = utils.load_content(parsed_args.file.read()) - - mistral_client = self.app.client_manager.workflow_engine - environment = mistral_client.environments.create(**data) - - return format(environment) - - -class Delete(command.Command): - """Delete environment.""" - - def get_parser(self, prog_name): - parser = super(Delete, self).get_parser(prog_name) - - parser.add_argument( - 'environment', - nargs='+', - help='Name of environment(s).' - ) - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - - utils.do_action_on_many( - lambda s: mistral_client.environments.delete(s), - parsed_args.environment, - "Request to delete environment %s has been accepted.", - "Unable to delete the specified environment(s)." - ) - - -class Update(command.ShowOne): - """Update environment.""" - - def get_parser(self, prog_name): - parser = super(Update, self).get_parser(prog_name) - - parser.add_argument( - 'file', - type=argparse.FileType('r'), - help='Environment configuration file in JSON or YAML' - ) - - return parser - - def take_action(self, parsed_args): - data = utils.load_content(parsed_args.file.read()) - - mistral_client = self.app.client_manager.workflow_engine - environment = mistral_client.environments.update(**data) - - return format(environment) diff --git a/mistralclient/commands/v2/event_triggers.py b/mistralclient/commands/v2/event_triggers.py deleted file mode 100644 index 22101ed..0000000 --- a/mistralclient/commands/v2/event_triggers.py +++ /dev/null @@ -1,167 +0,0 @@ -# Copyright 2017, OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -from osc_lib.command import command - -from mistralclient.commands.v2 import base -from mistralclient import utils - - -def format_list(trigger=None): - return format(trigger, lister=True) - - -def format(trigger=None, lister=False): - columns = ( - 'ID', - 'Name', - 'Workflow ID', - 'Params', - 'Exchange', - 'Topic', - 'Event', - 'Created at', - 'Updated at' - ) - - if trigger: - data = ( - trigger.id, - trigger.name, - trigger.workflow_id, - trigger.workflow_params, - trigger.exchange, - trigger.topic, - trigger.event, - trigger.created_at, - ) - - if hasattr(trigger, 'updated_at'): - data += (trigger.updated_at,) - else: - data += (None,) - else: - data = (tuple('' for _ in range(len(columns))),) - - return columns, data - - -class List(base.MistralLister): - """List all event triggers.""" - - def _get_format_function(self): - return format_list - - def _get_resources(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - return mistral_client.event_triggers.list() - - -class Get(command.ShowOne): - """Show specific event trigger.""" - - def get_parser(self, prog_name): - parser = super(Get, self).get_parser(prog_name) - - parser.add_argument('event_trigger', help='Event trigger ID') - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - - return format(mistral_client.event_triggers.get( - parsed_args.event_trigger - )) - - -class Create(command.ShowOne): - """Create new trigger.""" - - def get_parser(self, prog_name): - parser = super(Create, self).get_parser(prog_name) - - parser.add_argument('name', help='Event trigger name') - parser.add_argument('workflow_id', help='Workflow ID') - - parser.add_argument('exchange', - type=str, - help='Event trigger exchange') - - parser.add_argument('topic', - type=str, - help='Event trigger topic') - - parser.add_argument('event', - type=str, - help='Event trigger event name') - - parser.add_argument('workflow_input', - nargs='?', - help='Workflow input') - - parser.add_argument('--params', - help='Workflow params') - - return parser - - @staticmethod - def _get_json_string_or_dict(string): - if string: - return utils.load_json(string) - else: - return {} - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - - wf_input = self._get_json_string_or_dict(parsed_args.workflow_input) - wf_params = self._get_json_string_or_dict(parsed_args.params) - - trigger = mistral_client.event_triggers.create( - parsed_args.name, - parsed_args.workflow_id, - parsed_args.exchange, - parsed_args.topic, - parsed_args.event, - wf_input, - wf_params, - ) - - return format(trigger) - - -class Delete(command.Command): - """Delete trigger.""" - - def get_parser(self, prog_name): - parser = super(Delete, self).get_parser(prog_name) - - parser.add_argument( - 'event_trigger_id', - nargs='+', help='ID of event trigger(s).' - ) - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - - utils.do_action_on_many( - lambda s: mistral_client.event_triggers.delete(s), - parsed_args.event_trigger_id, - "Request to delete event trigger %s has been accepted.", - "Unable to delete the specified event trigger(s)." - ) diff --git a/mistralclient/commands/v2/executions.py b/mistralclient/commands/v2/executions.py deleted file mode 100644 index a3c8568..0000000 --- a/mistralclient/commands/v2/executions.py +++ /dev/null @@ -1,338 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# Copyright 2015 - StackStorm, Inc. -# Copyright 2016 - Brocade Communications Systems, Inc. -# -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import json -import logging -import os.path - -from osc_lib.command import command - -from mistralclient.commands.v2 import base -from mistralclient import utils - -LOG = logging.getLogger(__name__) - - -def format_list(execution=None): - return format(execution, lister=True) - - -def format(execution=None, lister=False): - columns = ( - 'ID', - 'Workflow ID', - 'Workflow name', - 'Description', - 'Task Execution ID', - 'State', - 'State info', - 'Created at', - 'Updated at' - ) - # TODO(nmakhotkin) Add parent task id when it's implemented in API. - - if execution: - state_info = (execution.state_info if not lister - else base.cut(execution.state_info)) - - data = ( - execution.id, - execution.workflow_id, - execution.workflow_name, - execution.description, - execution.task_execution_id or '', - execution.state, - state_info, - execution.created_at, - execution.updated_at or '' - ) - else: - data = (tuple('' for _ in range(len(columns))),) - - return columns, data - - -class List(base.MistralLister): - """List all executions.""" - - def _get_format_function(self): - return format_list - - def get_parser(self, parsed_args): - parser = super(List, self).get_parser(parsed_args) - parser.add_argument( - '--task', - nargs='?', - help="Parent task execution ID associated with workflow " - "execution list.", - ) - parser.add_argument( - '--marker', - type=str, - help='The last execution uuid of the previous page, displays list ' - 'of executions after "marker".', - default='', - nargs='?' - ) - parser.add_argument( - '--limit', - type=int, - help='Maximum number of executions to return in a single result. ' - 'limit is set to %s by default. Use --limit -1 to fetch the ' - 'full result set.' % base.DEFAULT_LIMIT, - nargs='?' - ) - parser.add_argument( - '--sort_keys', - help='Comma-separated list of sort keys to sort results by. ' - 'Default: created_at. ' - 'Example: mistral execution-list --sort_keys=id,description', - default='created_at', - nargs='?' - ) - parser.add_argument( - '--sort_dirs', - help='Comma-separated list of sort directions. Default: asc. ' - 'Example: mistral execution-list --sort_keys=id,description ' - '--sort_dirs=asc,desc', - default='asc', - nargs='?' - ) - parser.add_argument( - '--filter', - dest='filters', - action='append', - help='Filters. Can be repeated.' - ) - - return parser - - def _get_resources(self, parsed_args): - if parsed_args.limit is None: - parsed_args.limit = base.DEFAULT_LIMIT - LOG.info("limit is set to %s by default. Set " - "the limit explicitly using \'--limit\', if required. " - "Use \'--limit\' -1 to fetch the full result set.", - base.DEFAULT_LIMIT) - mistral_client = self.app.client_manager.workflow_engine - - return mistral_client.executions.list( - task=parsed_args.task, - marker=parsed_args.marker, - limit=parsed_args.limit, - sort_keys=parsed_args.sort_keys, - sort_dirs=parsed_args.sort_dirs, - **base.get_filters(parsed_args) - ) - - -class Get(command.ShowOne): - """Show specific execution.""" - - def get_parser(self, prog_name): - parser = super(Get, self).get_parser(prog_name) - - parser.add_argument('execution', help='Execution identifier') - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - execution = mistral_client.executions.get(parsed_args.execution) - - return format(execution) - - -class Create(command.ShowOne): - """Create new execution.""" - - def get_parser(self, prog_name): - parser = super(Create, self).get_parser(prog_name) - - parser.add_argument( - 'workflow_identifier', - help='Workflow ID or name. Workflow name will be deprecated since ' - 'Mitaka.' - ) - parser.add_argument( - 'workflow_input', - nargs='?', - help='Workflow input' - ) - parser.add_argument( - 'params', - nargs='?', - help='Workflow additional parameters' - ) - parser.add_argument( - '-d', - '--description', - dest='description', - default='', - help='Execution description' - ) - - return parser - - def take_action(self, parsed_args): - if parsed_args.workflow_input: - wf_input = utils.load_json(parsed_args.workflow_input) - else: - wf_input = {} - - if parsed_args.params: - params = utils.load_json(parsed_args.params) - else: - params = {} - - mistral_client = self.app.client_manager.workflow_engine - - execution = mistral_client.executions.create( - parsed_args.workflow_identifier, - wf_input, - parsed_args.description, - **params - ) - - return format(execution) - - -class Delete(command.Command): - """Delete execution.""" - - def get_parser(self, prog_name): - parser = super(Delete, self).get_parser(prog_name) - - parser.add_argument( - 'execution', - nargs='+', - help='Id of execution identifier(s).' - ) - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - - utils.do_action_on_many( - lambda s: mistral_client.executions.delete(s), - parsed_args.execution, - "Request to delete execution %s has been accepted.", - "Unable to delete the specified execution(s)." - ) - - -class Update(command.ShowOne): - """Update execution.""" - - def get_parser(self, prog_name): - parser = super(Update, self).get_parser(prog_name) - - parser.add_argument( - 'id', - help='Execution identifier' - ) - - parser.add_argument( - '-s', - '--state', - dest='state', - choices=['RUNNING', 'PAUSED', 'SUCCESS', 'ERROR', 'CANCELLED'], - help='Execution state' - ) - - parser.add_argument( - '-e', - '--env', - dest='env', - help='Environment variables' - ) - - parser.add_argument( - '-d', - '--description', - dest='description', - help='Execution description' - ) - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - - env = ( - utils.load_file(parsed_args.env) - if parsed_args.env and os.path.isfile(parsed_args.env) - else utils.load_content(parsed_args.env) - ) - - execution = mistral_client.executions.update( - parsed_args.id, - parsed_args.state, - description=parsed_args.description, - env=env - ) - - return format(execution) - - -class GetInput(command.Command): - """Show execution input data.""" - - def get_parser(self, prog_name): - parser = super(GetInput, self).get_parser(prog_name) - - parser.add_argument('id', help='Execution ID') - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - ex_input = mistral_client.executions.get(parsed_args.id).input - - try: - ex_input = json.loads(ex_input) - ex_input = json.dumps(ex_input, indent=4) + "\n" - except Exception: - LOG.debug("Execution input is not JSON.") - - self.app.stdout.write(ex_input or "\n") - - -class GetOutput(command.Command): - """Show execution output data.""" - - def get_parser(self, prog_name): - parser = super(GetOutput, self).get_parser(prog_name) - - parser.add_argument('id', help='Execution ID') - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - output = mistral_client.executions.get(parsed_args.id).output - - try: - output = json.loads(output) - output = json.dumps(output, indent=4) + "\n" - except Exception: - LOG.debug("Execution output is not JSON.") - - self.app.stdout.write(output or "\n") diff --git a/mistralclient/commands/v2/members.py b/mistralclient/commands/v2/members.py deleted file mode 100644 index 24bc4d6..0000000 --- a/mistralclient/commands/v2/members.py +++ /dev/null @@ -1,235 +0,0 @@ -# Copyright 2016 - Catalyst IT Limited -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -from osc_lib.command import command - -from mistralclient.commands.v2 import base -from mistralclient import exceptions - - -def format_list(member=None): - return format(member, lister=True) - - -def format(member=None, lister=False): - columns = ( - 'Resource ID', - 'Resource Type', - 'Resource Owner', - 'Member ID', - 'Status', - 'Created at', - 'Updated at' - ) - - if member: - data = ( - member.resource_id, - member.resource_type, - member.project_id, - member.member_id, - member.status, - member.created_at, - ) - - if hasattr(member, 'updated_at'): - data += (member.updated_at,) - else: - data += (None,) - else: - data = (tuple('' for _ in range(len(columns))),) - - return columns, data - - -class List(base.MistralLister): - """List all members.""" - - def _get_format_function(self): - return format_list - - def get_parser(self, parsed_args): - parser = super(List, self).get_parser(parsed_args) - - parser.add_argument( - 'resource_id', - help='Resource id to be shared.' - ) - parser.add_argument( - 'resource_type', - help='Resource type.' - ) - - return parser - - def _get_resources(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - return mistral_client.members.list( - parsed_args.resource_id, - parsed_args.resource_type - ) - - -class Get(command.ShowOne): - """Show specific member information.""" - - def get_parser(self, prog_name): - parser = super(Get, self).get_parser(prog_name) - - parser.add_argument( - 'resource', - help='Resource ID to be shared.' - ) - parser.add_argument( - 'resource_type', - help='Resource type.' - ) - parser.add_argument( - '-m', - '--member-id', - default='', - help='Project ID to whom the resource is shared to. No need to ' - 'provide this param if you are the resource member.' - ) - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - member = mistral_client.members.get( - parsed_args.resource, - parsed_args.resource_type, - parsed_args.member_id, - ) - - return format(member) - - -class Create(command.ShowOne): - """Shares a resource to another tenant.""" - - def get_parser(self, prog_name): - parser = super(Create, self).get_parser(prog_name) - - parser.add_argument( - 'resource_id', - help='Resource ID to be shared.' - ) - parser.add_argument( - 'resource_type', - help='Resource type.' - ) - parser.add_argument( - 'member_id', - help='Project ID to whom the resource is shared to.' - ) - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - member = mistral_client.members.create( - parsed_args.resource_id, - parsed_args.resource_type, - parsed_args.member_id, - ) - - return format(member) - - -class Delete(command.Command): - """Delete a resource sharing relationship.""" - - def get_parser(self, prog_name): - parser = super(Delete, self).get_parser(prog_name) - - parser.add_argument( - 'resource', - help='Resource ID to be shared.' - ) - parser.add_argument( - 'resource_type', - help='Resource type.' - ) - parser.add_argument( - 'member_id', - help='Project ID to whom the resource is shared to.' - ) - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - - try: - mistral_client.members.delete( - parsed_args.resource, - parsed_args.resource_type, - parsed_args.member_id, - ) - - print( - "Request to delete %s member %s has been accepted." % - (parsed_args.resource_type, parsed_args.member_id) - ) - except Exception as e: - print(e) - - error_msg = "Unable to delete the specified member." - raise exceptions.MistralClientException(error_msg) - - -class Update(command.ShowOne): - """Update resource sharing status.""" - - def get_parser(self, prog_name): - parser = super(Update, self).get_parser(prog_name) - - parser.add_argument( - 'resource_id', - help='Resource ID to be shared.' - ) - parser.add_argument( - 'resource_type', - help='Resource type.' - ) - parser.add_argument( - '-m', - '--member-id', - default='', - help='Project ID to whom the resource is shared to. No need to ' - 'provide this param if you are the resource member.' - ) - parser.add_argument( - '-s', - '--status', - default='accepted', - choices=['pending', 'accepted', 'rejected'], - help='status of the sharing.' - ) - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - - member = mistral_client.members.update( - parsed_args.resource_id, - parsed_args.resource_type, - parsed_args.member_id, - status=parsed_args.status - ) - - return format(member) diff --git a/mistralclient/commands/v2/services.py b/mistralclient/commands/v2/services.py deleted file mode 100644 index 81624ca..0000000 --- a/mistralclient/commands/v2/services.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2015 Huawei Technologies Co., Ltd. -# -# 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 mistralclient.commands.v2 import base - - -def format_list(service=None): - columns = ('Name', 'Type') - - if service: - data = (service.name, service.type) - else: - data = (tuple('' for _ in range(len(columns))),) - - return columns, data - - -class List(base.MistralLister): - """List all services.""" - - def _get_format_function(self): - return format_list - - def _get_resources(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - return mistral_client.services.list() diff --git a/mistralclient/commands/v2/tasks.py b/mistralclient/commands/v2/tasks.py deleted file mode 100644 index 396d3e8..0000000 --- a/mistralclient/commands/v2/tasks.py +++ /dev/null @@ -1,222 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# Copyright 2015 - StackStorm, Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import json -import logging -import os.path - -from osc_lib.command import command - -from mistralclient.commands.v2 import base -from mistralclient import utils - -LOG = logging.getLogger(__name__) - - -def format_list(task=None): - return format(task, lister=True) - - -def format(task=None, lister=False): - columns = ( - 'ID', - 'Name', - 'Workflow name', - 'Execution ID', - 'State', - 'State info', - 'Created at', - 'Updated at' - ) - - if task: - state_info = (task.state_info if not lister - else base.cut(task.state_info)) - - data = ( - task.id, - task.name, - task.workflow_name, - task.workflow_execution_id, - task.state, - state_info, - task.created_at, - task.updated_at or '' - ) - else: - data = (tuple('' for _ in range(len(columns))),) - - return columns, data - - -class List(base.MistralLister): - """List all tasks.""" - - def get_parser(self, prog_name): - parser = super(List, self).get_parser(prog_name) - - parser.add_argument( - 'workflow_execution', - nargs='?', - help='Workflow execution ID associated with list of Tasks.' - ) - parser.add_argument( - '--filter', - dest='filters', - action='append', - help='Filters. Can be repeated.' - ) - parser.add_argument( - '--limit', - type=int, - help='Maximum number of tasks to return in a single result. ' - 'limit is set to %s by default. Use --limit -1 to fetch the ' - 'full result set.' % base.DEFAULT_LIMIT, - nargs='?' - ) - - return parser - - def _get_format_function(self): - return format_list - - def _get_resources(self, parsed_args): - if parsed_args.limit is None: - parsed_args.limit = base.DEFAULT_LIMIT - LOG.info("limit is set to %s by default. Set " - "the limit explicitly using \'--limit\', if required. " - "Use \'--limit\' -1 to fetch the full result set.", - base.DEFAULT_LIMIT) - mistral_client = self.app.client_manager.workflow_engine - - return mistral_client.tasks.list( - parsed_args.workflow_execution, - limit=parsed_args.limit, - **base.get_filters(parsed_args) - ) - - -class Get(command.ShowOne): - """Show specific task.""" - - def get_parser(self, prog_name): - parser = super(Get, self).get_parser(prog_name) - - parser.add_argument('task', help='Task identifier') - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - execution = mistral_client.tasks.get(parsed_args.task) - - return format(execution) - - -class GetResult(command.Command): - """Show task output data.""" - - def get_parser(self, prog_name): - parser = super(GetResult, self).get_parser(prog_name) - parser.add_argument( - 'id', - help='Task ID') - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - result = mistral_client.tasks.get(parsed_args.id).result - - try: - result = json.loads(result) - result = json.dumps(result, indent=4) + "\n" - except Exception: - LOG.debug("Task result is not JSON.") - - self.app.stdout.write(result or "\n") - - -class GetPublished(command.Command): - """Show task published variables.""" - - def get_parser(self, prog_name): - parser = super(GetPublished, self).get_parser(prog_name) - parser.add_argument( - 'id', - help='Task ID') - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - result = mistral_client.tasks.get(parsed_args.id).published - - try: - result = json.loads(result) - result = json.dumps(result, indent=4) + "\n" - except Exception: - LOG.debug("Task result is not JSON.") - - self.app.stdout.write(result or "\n") - - -class Rerun(command.ShowOne): - """Rerun an existing task.""" - - def get_parser(self, prog_name): - parser = super(Rerun, self).get_parser(prog_name) - - parser.add_argument( - 'id', - help='Task identifier' - ) - - parser.add_argument( - '--resume', - action='store_true', - dest='resume', - default=False, - help=('rerun only failed or unstarted action ' - 'executions for with-items task') - ) - - parser.add_argument( - '-e', - '--env', - dest='env', - help='Environment variables' - ) - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - - env = ( - utils.load_file(parsed_args.env) - if parsed_args.env and os.path.isfile(parsed_args.env) - else utils.load_content(parsed_args.env) - ) - - execution = mistral_client.tasks.rerun( - parsed_args.id, - reset=(not parsed_args.resume), - env=env - ) - - return format(execution) diff --git a/mistralclient/commands/v2/workbooks.py b/mistralclient/commands/v2/workbooks.py deleted file mode 100644 index 3d17bb7..0000000 --- a/mistralclient/commands/v2/workbooks.py +++ /dev/null @@ -1,194 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# Copyright 2015 - StackStorm, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import argparse - -from osc_lib.command import command - -from mistralclient.commands.v2 import base -from mistralclient import utils - - -def format(workbook=None): - columns = ( - 'Name', - 'Tags', - 'Created at', - 'Updated at' - ) - - if workbook: - data = ( - workbook.name, - base.wrap(', '.join(workbook.tags or '')) or '', - workbook.created_at, - ) - - if hasattr(workbook, 'updated_at'): - data += (workbook.updated_at,) - else: - data += (None,) - - else: - data = (tuple('' for _ in range(len(columns))),) - - return columns, data - - -class List(base.MistralLister): - """List all workbooks.""" - - def _get_format_function(self): - return format - - def _get_resources(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - return mistral_client.workbooks.list() - - -class Get(command.ShowOne): - """Show specific workbook.""" - - def get_parser(self, prog_name): - parser = super(Get, self).get_parser(prog_name) - - parser.add_argument( - 'workbook', - help='Workbook name' - ) - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - workbook = mistral_client.workbooks.get(parsed_args.workbook) - - return format(workbook) - - -class Create(command.ShowOne): - """Create new workbook.""" - - def get_parser(self, prog_name): - parser = super(Create, self).get_parser(prog_name) - - parser.add_argument( - 'definition', - type=argparse.FileType('r'), - help='Workbook definition file' - ) - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - workbook = mistral_client.workbooks.create( - parsed_args.definition.read() - ) - - return format(workbook) - - -class Delete(command.Command): - """Delete workbook.""" - - def get_parser(self, prog_name): - parser = super(Delete, self).get_parser(prog_name) - - parser.add_argument('workbook', nargs='+', help='Name of workbook(s).') - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - utils.do_action_on_many( - lambda s: mistral_client.workbooks.delete(s), - parsed_args.workbook, - "Request to delete workbook %s has been accepted.", - "Unable to delete the specified workbook(s)." - ) - - -class Update(command.ShowOne): - """Update workbook.""" - - def get_parser(self, prog_name): - parser = super(Update, self).get_parser(prog_name) - - parser.add_argument( - 'definition', - type=argparse.FileType('r'), - help='Workbook definition file' - ) - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - workbook = mistral_client.workbooks.update( - parsed_args.definition.read() - ) - - return format(workbook) - - -class GetDefinition(command.Command): - """Show workbook definition.""" - - def get_parser(self, prog_name): - parser = super(GetDefinition, self).get_parser(prog_name) - - parser.add_argument('name', help='Workbook name') - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - definition = mistral_client.workbooks.get(parsed_args.name).definition - - self.app.stdout.write(definition or "\n") - - -class Validate(command.ShowOne): - """Validate workbook.""" - - def _format(self, result=None): - columns = ('Valid', 'Error') - - if result: - data = (result.get('valid'), result.get('error'),) - else: - data = (tuple('' for _ in range(len(columns))),) - - return columns, data - - def get_parser(self, prog_name): - parser = super(Validate, self).get_parser(prog_name) - - parser.add_argument( - 'definition', - type=argparse.FileType('r'), - help='Workbook definition file' - ) - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - result = mistral_client.workbooks.validate( - parsed_args.definition.read() - ) - - return self._format(result) diff --git a/mistralclient/commands/v2/workflows.py b/mistralclient/commands/v2/workflows.py deleted file mode 100644 index 07fb071..0000000 --- a/mistralclient/commands/v2/workflows.py +++ /dev/null @@ -1,247 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# Copyright 2015 - StackStorm, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import argparse - -from cliff import command -from cliff import show - -from mistralclient.commands.v2 import base -from mistralclient import utils - - -def format_list(workflow=None): - return format(workflow, lister=True) - - -def format(workflow=None, lister=False): - columns = ( - 'ID', - 'Name', - 'Project ID', - 'Tags', - 'Input', - 'Created at', - 'Updated at' - ) - - if workflow: - tags = getattr(workflow, 'tags', None) or [] - - data = ( - workflow.id, - workflow.name, - workflow.project_id, - base.wrap(', '.join(tags)) or '', - workflow.input if not lister else base.cut(workflow.input), - workflow.created_at - ) - - if hasattr(workflow, 'updated_at'): - data += (workflow.updated_at,) - else: - data += (None,) - else: - data = (tuple('' for _ in range(len(columns))),) - - return columns, data - - -class List(base.MistralLister): - """List all workflows.""" - - def _get_format_function(self): - return format_list - - def get_parser(self, prog_name): - parser = super(List, self).get_parser(prog_name) - - parser.add_argument( - '--filter', - dest='filters', - action='append', - help='Filters. Can be repeated.' - ) - - return parser - - def _get_resources(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - - return mistral_client.workflows.list( - **base.get_filters(parsed_args) - ) - - -class Get(show.ShowOne): - """Show specific workflow.""" - - def get_parser(self, prog_name): - parser = super(Get, self).get_parser(prog_name) - - parser.add_argument('workflow', help='Workflow ID or name.') - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - wf = mistral_client.workflows.get(parsed_args.workflow) - - return format(wf) - - -class Create(base.MistralLister): - """Create new workflow.""" - - def get_parser(self, prog_name): - parser = super(Create, self).get_parser(prog_name) - - parser.add_argument( - 'definition', - type=argparse.FileType('r'), - help='Workflow definition file.' - ) - parser.add_argument( - '--public', - action='store_true', - help='With this flag workflow will be marked as "public".' - ) - - return parser - - def _get_format_function(self): - return format_list - - def _validate_parsed_args(self, parsed_args): - if not parsed_args.definition: - raise RuntimeError("You must provide path to workflow " - "definition file.") - - def _get_resources(self, parsed_args): - scope = 'public' if parsed_args.public else 'private' - mistral_client = self.app.client_manager.workflow_engine - - return mistral_client.workflows.create( - parsed_args.definition.read(), - scope=scope - ) - - -class Delete(command.Command): - """Delete workflow.""" - - def get_parser(self, prog_name): - parser = super(Delete, self).get_parser(prog_name) - - parser.add_argument( - 'workflow', - nargs='+', - help='Name or ID of workflow(s).' - ) - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - utils.do_action_on_many( - lambda s: mistral_client.workflows.delete(s), - parsed_args.workflow, - "Request to delete workflow %s has been accepted.", - "Unable to delete the specified workflow(s)." - ) - - -class Update(base.MistralLister): - """Update workflow.""" - - def get_parser(self, prog_name): - parser = super(Update, self).get_parser(prog_name) - - parser.add_argument( - 'definition', - type=argparse.FileType('r'), - help='Workflow definition' - ) - parser.add_argument('--id', help='Workflow ID.') - parser.add_argument( - '--public', - action='store_true', - help='With this flag workflow will be marked as "public".' - ) - - return parser - - def _get_format_function(self): - return format_list - - def _get_resources(self, parsed_args): - scope = 'public' if parsed_args.public else 'private' - mistral_client = self.app.client_manager.workflow_engine - - return mistral_client.workflows.update( - parsed_args.definition.read(), - scope=scope, - id=parsed_args.id - ) - - -class GetDefinition(command.Command): - """Show workflow definition.""" - - def get_parser(self, prog_name): - parser = super(GetDefinition, self).get_parser(prog_name) - - parser.add_argument('identifier', help='Workflow ID or name.') - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - wf = mistral_client.workflows.get(parsed_args.identifier) - - self.app.stdout.write(wf.definition or "\n") - - -class Validate(show.ShowOne): - """Validate workflow.""" - - def _format(self, result=None): - columns = ('Valid', 'Error') - - if result: - data = (result.get('valid'), result.get('error'),) - else: - data = (tuple('' for _ in range(len(columns))),) - - return columns, data - - def get_parser(self, prog_name): - parser = super(Validate, self).get_parser(prog_name) - - parser.add_argument( - 'definition', - type=argparse.FileType('r'), - help='Workflow definition file' - ) - - return parser - - def take_action(self, parsed_args): - mistral_client = self.app.client_manager.workflow_engine - result = mistral_client.workflows.validate( - parsed_args.definition.read() - ) - - return self._format(result) diff --git a/mistralclient/exceptions.py b/mistralclient/exceptions.py deleted file mode 100644 index 84701f7..0000000 --- a/mistralclient/exceptions.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2013 - Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -class MistralClientException(Exception): - """Base Exception for Mistral client - - To correctly use this class, inherit from it and define - a 'message' and 'code' properties. - """ - message = "An unknown exception occurred" - code = "UNKNOWN_EXCEPTION" - - def __str__(self): - return self.message - - def __init__(self, message=message): - self.message = message - super(MistralClientException, self).__init__( - '%s: %s' % (self.code, self.message)) - - -class IllegalArgumentException(MistralClientException): - message = "IllegalArgumentException occurred" - code = "ILLEGAL_ARGUMENT_EXCEPTION" - - def __init__(self, message=None): - if message: - self.message = message diff --git a/mistralclient/i18n.py b/mistralclient/i18n.py deleted file mode 100644 index ee79f8e..0000000 --- a/mistralclient/i18n.py +++ /dev/null @@ -1,22 +0,0 @@ -# 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. - -"""oslo.i18n integration module. -See https://docs.openstack.org/oslo.i18n/latest/user/usage.html -""" - -import oslo_i18n - -_translators = oslo_i18n.TranslatorFactory(domain='mistralclient') - -# The primary translation function using the well-known name "_" -_ = _translators.primary diff --git a/mistralclient/osc/__init__.py b/mistralclient/osc/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/mistralclient/osc/plugin.py b/mistralclient/osc/plugin.py deleted file mode 100644 index f1869b4..0000000 --- a/mistralclient/osc/plugin.py +++ /dev/null @@ -1,62 +0,0 @@ -# -# 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 Workflow service.""" - -import logging - -from osc_lib import utils - -LOG = logging.getLogger(__name__) - -DEFAULT_WORKFLOW_API_VERSION = '2' -API_VERSION_OPTION = 'os_workflow_api_version' -API_NAME = 'workflow_engine' -API_VERSIONS = { - '2': 'mistralclient.api.v2.client.Client', -} - - -def make_client(instance): - """Returns a workflow_engine service client.""" - version = instance._api_version[API_NAME] - workflow_client = utils.get_client_class( - API_NAME, - version, - API_VERSIONS) - - LOG.debug('Instantiating workflow engine client: %s', workflow_client) - - mistral_url = instance.get_endpoint_for_service_type( - 'workflowv2', - interface='publicURL' - ) - - client = workflow_client(mistral_url=mistral_url, session=instance.session) - - return client - - -def build_option_parser(parser): - """Hook to add global options.""" - parser.add_argument( - '--os-workflow-api-version', - metavar='', - default=utils.env( - 'OS_WORKFLOW_API_VERSION', - default=DEFAULT_WORKFLOW_API_VERSION), - help='Workflow API version, default=' + - DEFAULT_WORKFLOW_API_VERSION + - ' (Env: OS_WORKFLOW_API_VERSION)') - - return parser diff --git a/mistralclient/shell.py b/mistralclient/shell.py deleted file mode 100644 index 02353a2..0000000 --- a/mistralclient/shell.py +++ /dev/null @@ -1,709 +0,0 @@ -# Copyright 2015 - StackStorm, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Command-line interface to the Mistral APIs -""" - -import argparse -import logging -import os -import sys - -from cliff import app -from cliff import commandmanager -from osc_lib.command import command - -from mistralclient.api import client -from mistralclient.auth import auth_types -import mistralclient.commands.v2.action_executions -import mistralclient.commands.v2.actions -import mistralclient.commands.v2.cron_triggers -import mistralclient.commands.v2.environments -import mistralclient.commands.v2.event_triggers -import mistralclient.commands.v2.executions -import mistralclient.commands.v2.members -import mistralclient.commands.v2.services -import mistralclient.commands.v2.tasks -import mistralclient.commands.v2.workbooks -import mistralclient.commands.v2.workflows -from mistralclient import exceptions as exe - - -def env(*args, **kwargs): - """Returns the first environment variable set. - - If all are empty, defaults to '' or keyword arg `default`. - """ - for arg in args: - value = os.environ.get(arg) - if value: - return value - return kwargs.get('default', '') - - -class OpenStackHelpFormatter(argparse.HelpFormatter): - - def __init__(self, prog, indent_increment=2, max_help_position=32, - width=None): - super(OpenStackHelpFormatter, self).__init__( - prog, - indent_increment, - max_help_position, - width - ) - - def start_section(self, heading): - # Title-case the headings. - heading = '%s%s' % (heading[0].upper(), heading[1:]) - super(OpenStackHelpFormatter, self).start_section(heading) - - -class HelpAction(argparse.Action): - """Custom help action. - - Provide a custom action so the -h and --help options - to the main app will print a list of the commands. - - The commands are determined by checking the CommandManager - instance, passed in as the "default" value for the action. - - """ - - def __call__(self, parser, namespace, values, option_string=None): - outputs = [] - max_len = 0 - app = self.default - parser.print_help(app.stdout) - app.stdout.write('\nCommands for API v2 :\n') - - for name, ep in sorted(app.command_manager): - factory = ep.load() - cmd = factory(self, None) - one_liner = cmd.get_description().split('\n')[0] - outputs.append((name, one_liner)) - max_len = max(len(name), max_len) - - for (name, one_liner) in outputs: - app.stdout.write(' %s %s\n' % (name.ljust(max_len), one_liner)) - - sys.exit(0) - - -class BashCompletionCommand(command.Command): - """Prints all of the commands and options for bash-completion.""" - - def take_action(self, parsed_args): - commands = set() - options = set() - - for option, _action in self.app.parser._option_string_actions.items(): - options.add(option) - - for command_name, _cmd in self.app.command_manager: - commands.add(command_name) - - print(' '.join(commands | options)) - - -class MistralShell(app.App): - - def __init__(self): - super(MistralShell, self).__init__( - description=__doc__.strip(), - version=mistralclient.__version__, - command_manager=commandmanager.CommandManager('mistral.cli'), - ) - - # Set v2 commands by default - self._set_shell_commands(self._get_commands_v2()) - - def configure_logging(self): - log_lvl = logging.DEBUG if self.options.debug else logging.WARNING - logging.basicConfig( - format="%(levelname)s (%(module)s) %(message)s", - level=log_lvl - ) - logging.getLogger('iso8601').setLevel(logging.WARNING) - - if self.options.verbose_level <= 1: - logging.getLogger('requests').setLevel(logging.WARNING) - - def build_option_parser(self, description, version, - argparse_kwargs=None): - """Return an argparse option parser for this application. - - Subclasses may override this method to extend - the parser with more global options. - - :param description: full description of the application - :paramtype description: str - :param version: version number for the application - :paramtype version: str - :param argparse_kwargs: extra keyword argument passed to the - ArgumentParser constructor - :paramtype extra_kwargs: dict - """ - argparse_kwargs = argparse_kwargs or {} - - parser = argparse.ArgumentParser( - description=description, - add_help=False, - formatter_class=OpenStackHelpFormatter, - **argparse_kwargs - ) - - parser.add_argument( - '--version', - action='version', - version='%(prog)s {0}'.format(version), - help='Show program\'s version number and exit.' - ) - - parser.add_argument( - '-v', '--verbose', - action='count', - dest='verbose_level', - default=self.DEFAULT_VERBOSE_LEVEL, - help='Increase verbosity of output. Can be repeated.', - ) - - parser.add_argument( - '--log-file', - action='store', - default=None, - help='Specify a file to log output. Disabled by default.', - ) - - parser.add_argument( - '-q', '--quiet', - action='store_const', - dest='verbose_level', - const=0, - help='Suppress output except warnings and errors.', - ) - - parser.add_argument( - '-h', '--help', - action=HelpAction, - nargs=0, - default=self, # tricky - help="Show this help message and exit.", - ) - - parser.add_argument( - '--debug', - default=False, - action='store_true', - help='Show tracebacks on errors.', - ) - - parser.add_argument( - '--os-mistral-url', - action='store', - dest='mistral_url', - default=env('OS_MISTRAL_URL'), - help='Mistral API host (Env: OS_MISTRAL_URL)' - ) - - parser.add_argument( - '--os-mistral-version', - action='store', - dest='mistral_version', - default=env('OS_MISTRAL_VERSION', default='v2'), - help='Mistral API version (default = v2) (Env: ' - 'OS_MISTRAL_VERSION)' - ) - - parser.add_argument( - '--os-mistral-service-type', - action='store', - dest='service_type', - default=env('OS_MISTRAL_SERVICE_TYPE', default='workflowv2'), - help='Mistral service-type (should be the same name as in ' - 'keystone-endpoint) (default = workflowv2) (Env: ' - 'OS_MISTRAL_SERVICE_TYPE)' - ) - - parser.add_argument( - '--os-mistral-endpoint-type', - action='store', - dest='endpoint_type', - default=env('OS_MISTRAL_ENDPOINT_TYPE', default='publicURL'), - help='Mistral endpoint-type (should be the same name as in ' - 'keystone-endpoint) (default = publicURL) (Env: ' - 'OS_MISTRAL_ENDPOINT_TYPE)' - ) - - parser.add_argument( - '--os-username', - action='store', - dest='username', - default=env('OS_USERNAME'), - help='Authentication username (Env: OS_USERNAME)' - ) - - parser.add_argument( - '--os-password', - action='store', - dest='password', - default=env('OS_PASSWORD'), - help='Authentication password (Env: OS_PASSWORD)' - ) - - parser.add_argument( - '--os-tenant-id', - action='store', - dest='tenant_id', - default=env('OS_TENANT_ID', 'OS_PROJECT_ID'), - help='Authentication tenant identifier (Env: OS_TENANT_ID' - ' or OS_PROJECT_ID)' - ) - - parser.add_argument( - '--os-project-id', - action='store', - dest='project_id', - default=env('OS_TENANT_ID', 'OS_PROJECT_ID'), - help='Authentication project identifier (Env: OS_TENANT_ID' - ' or OS_PROJECT_ID), will use tenant_id if both tenant_id' - ' and project_id are set' - ) - - parser.add_argument( - '--os-tenant-name', - action='store', - dest='tenant_name', - default=env('OS_TENANT_NAME', 'OS_PROJECT_NAME', - default='Default'), - help='Authentication tenant name (Env: OS_TENANT_NAME' - ' or OS_PROJECT_NAME)' - ) - - parser.add_argument( - '--os-project-name', - action='store', - dest='project_name', - default=env('OS_TENANT_NAME', 'OS_PROJECT_NAME', - default='Default'), - help='Authentication project name (Env: OS_TENANT_NAME' - ' or OS_PROJECT_NAME), will use tenant_name if both' - ' tenant_name and project_name are set' - ) - - parser.add_argument( - '--os-auth-token', - action='store', - dest='token', - default=env('OS_AUTH_TOKEN'), - help='Authentication token (Env: OS_AUTH_TOKEN)' - ) - - parser.add_argument( - '--os-project-domain-name', - action='store', - dest='project_domain_name', - default=env('OS_PROJECT_DOMAIN_NAME', default='Default'), - help='Authentication project domain name' - ' (Env: OS_PROJECT_DOMAIN_NAME)' - ) - - parser.add_argument( - '--os-user-domain-name', - action='store', - dest='user_domain_name', - default=env('OS_USER_DOMAIN_NAME', default='Default'), - help='Authentication user domain name' - ' (Env: OS_USER_DOMAIN_NAME)' - ) - - parser.add_argument( - '--os-auth-url', - action='store', - dest='auth_url', - default=env('OS_AUTH_URL'), - help='Authentication URL (Env: OS_AUTH_URL)' - ) - - parser.add_argument( - '--os-cert', - action='store', - dest='os_cert', - default=env('OS_CERT'), - help='Client Certificate (Env: OS_CERT)' - ) - - parser.add_argument( - '--os-key', - action='store', - dest='os_key', - default=env('OS_KEY'), - help='Client Key (Env: OS_KEY)' - ) - - parser.add_argument( - '--os-cacert', - action='store', - dest='os_cacert', - default=env('OS_CACERT'), - help='Authentication CA Certificate (Env: OS_CACERT)' - ) - - parser.add_argument( - '--os-region-name', - action='store', - dest='region_name', - default=env('OS_REGION_NAME'), - help='Region name (Env: OS_REGION_NAME)' - ) - - parser.add_argument( - '--insecure', - action='store_true', - dest='insecure', - default=env('MISTRALCLIENT_INSECURE', default=False), - help='Disables SSL/TLS certificate verification ' - '(Env: MISTRALCLIENT_INSECURE)' - ) - - parser.add_argument( - '--auth-type', - action='store', - dest='auth_type', - default=env('MISTRAL_AUTH_TYPE', default='keystone'), - help='Authentication type. Valid options are: %s.' - ' (Env: MISTRAL_AUTH_TYPE)' % ', '.join(auth_types.ALL) - ) - - parser.add_argument( - '--openid-client-id', - action='store', - dest='client_id', - default=env('OPENID_CLIENT_ID'), - help='Client ID (according to OpenID Connect).' - ' (Env: OPENID_CLIENT_ID)' - ) - - parser.add_argument( - '--openid-client-secret', - action='store', - dest='client_secret', - default=env('OPENID_CLIENT_SECRET'), - help='Client secret (according to OpenID Connect)' - ' (Env: OPENID_CLIENT_SECRET)' - ) - - parser.add_argument( - '--os-target-username', - action='store', - dest='target_username', - default=env('OS_TARGET_USERNAME', default='admin'), - help='Authentication username for target cloud' - ' (Env: OS_TARGET_USERNAME)' - ) - - parser.add_argument( - '--os-target-password', - action='store', - dest='target_password', - default=env('OS_TARGET_PASSWORD'), - help='Authentication password for target cloud' - ' (Env: OS_TARGET_PASSWORD)' - ) - - parser.add_argument( - '--os-target-tenant-id', - action='store', - dest='target_tenant_id', - default=env('OS_TARGET_TENANT_ID'), - help='Authentication tenant identifier for target cloud' - ' (Env: OS_TARGET_TENANT_ID)' - ) - - parser.add_argument( - '--os-target-tenant-name', - action='store', - dest='target_tenant_name', - default=env('OS_TARGET_TENANT_NAME', 'Default'), - help='Authentication tenant name for target cloud' - ' (Env: OS_TARGET_TENANT_NAME)' - ) - - parser.add_argument( - '--os-target-auth-token', - action='store', - dest='target_token', - default=env('OS_TARGET_AUTH_TOKEN'), - help='Authentication token for target cloud' - ' (Env: OS_TARGET_AUTH_TOKEN)' - ) - - parser.add_argument( - '--os-target-auth-url', - action='store', - dest='target_auth_url', - default=env('OS_TARGET_AUTH_URL'), - help='Authentication URL for target cloud' - ' (Env: OS_TARGET_AUTH_URL)' - ) - - parser.add_argument( - '--os-target_cacert', - action='store', - dest='target_cacert', - default=env('OS_TARGET_CACERT'), - help='Authentication CA Certificate for target cloud' - ' (Env: OS_TARGET_CACERT)' - ) - - parser.add_argument( - '--os-target-region-name', - action='store', - dest='target_region_name', - default=env('OS_TARGET_REGION_NAME'), - help='Region name for target cloud' - '(Env: OS_TARGET_REGION_NAME)' - ) - - parser.add_argument( - '--os-target-user-domain-name', - action='store', - dest='target_user_domain_name', - default=env('OS_TARGET_USER_DOMAIN_NAME'), - help='User domain name for target cloud' - '(Env: OS_TARGET_USER_DOMAIN_NAME)' - ) - - parser.add_argument( - '--os-target-project-domain-name', - action='store', - dest='target_project_domain_name', - default=env('OS_TARGET_PROJECT_DOMAIN_NAME'), - help='Project domain name for target cloud' - '(Env: OS_TARGET_PROJECT_DOMAIN_NAME)' - ) - - parser.add_argument( - '--target_insecure', - action='store_true', - dest='target_insecure', - default=env('TARGET_MISTRALCLIENT_INSECURE', default=False), - help='Disables SSL/TLS certificate verification for target cloud ' - '(Env: TARGET_MISTRALCLIENT_INSECURE)' - ) - - parser.add_argument( - '--profile', - dest='profile', - metavar='HMAC_KEY', - default=env('OS_PROFILE'), - help='HMAC key to use for encrypting context data for performance ' - 'profiling of operation. This key should be one of the ' - 'values configured for the osprofiler middleware in mistral, ' - 'it is specified in the profiler section of the mistral ' - 'configuration (i.e. /etc/mistral/mistral.conf). Without the ' - 'key, profiling will not be triggered even if osprofiler is ' - 'enabled on the server side.' - ) - - return parser - - def initialize_app(self, argv): - self._clear_shell_commands() - - ver = client.determine_client_version(self.options.mistral_version) - - self._set_shell_commands(self._get_commands(ver)) - - do_help = ('help' in argv) or ('-h' in argv) or not argv - - # Set default for auth_url if not supplied. The default is not - # set at the parser to support use cases where auth is not enabled. - # An example use case would be a developer's environment. - if not self.options.auth_url: - if self.options.password or self.options.token: - self.options.auth_url = 'http://localhost:35357/v3' - - # bash-completion should not require authentification. - if do_help or ('bash-completion' in argv): - self.options.auth_url = None - - if self.options.auth_url and not self.options.token: - if not self.options.username: - raise exe.IllegalArgumentException( - ("You must provide a username " - "via --os-username env[OS_USERNAME]") - ) - - if not self.options.password: - raise exe.IllegalArgumentException( - ("You must provide a password " - "via --os-password env[OS_PASSWORD]") - ) - - kwargs = { - 'cert': self.options.os_cert, - 'key': self.options.os_key, - 'user_domain_name': self.options.user_domain_name, - 'project_domain_name': self.options.project_domain_name - } - - self.client = client.client( - mistral_url=self.options.mistral_url, - username=self.options.username, - api_key=self.options.password, - project_name=self.options.tenant_name or self.options.project_name, - auth_url=self.options.auth_url, - project_id=self.options.tenant_id or self.options.project_id, - endpoint_type=self.options.endpoint_type, - service_type=self.options.service_type, - region_name=self.options.region_name, - auth_token=self.options.token, - cacert=self.options.os_cacert, - insecure=self.options.insecure, - profile=self.options.profile, - auth_type=self.options.auth_type, - client_id=self.options.client_id, - client_secret=self.options.client_secret, - target_username=self.options.target_username, - target_api_key=self.options.target_password, - target_project_name=self.options.target_tenant_name, - target_auth_url=self.options.target_auth_url, - target_project_id=self.options.target_tenant_id, - target_auth_token=self.options.target_token, - target_cacert=self.options.target_cacert, - target_region_name=self.options.target_region_name, - target_insecure=self.options.target_insecure, - **kwargs - ) - - # Adding client_manager variable to make mistral client work with - # unified OpenStack client. - ClientManager = type( - 'ClientManager', - (object,), - dict(workflow_engine=self.client) - ) - - self.client_manager = ClientManager() - - def _set_shell_commands(self, cmds_dict): - for k, v in cmds_dict.items(): - self.command_manager.add_command(k, v) - - def _clear_shell_commands(self): - exclude_cmds = ['help', 'complete'] - - cmds = self.command_manager.commands.copy() - for k, v in cmds.items(): - if k not in exclude_cmds: - self.command_manager.commands.pop(k) - - def _get_commands(self, version): - if version == 2: - return self._get_commands_v2() - - return {} - - @staticmethod - def _get_commands_v2(): - return { - 'bash-completion': BashCompletionCommand, - 'workbook-list': mistralclient.commands.v2.workbooks.List, - 'workbook-get': mistralclient.commands.v2.workbooks.Get, - 'workbook-create': mistralclient.commands.v2.workbooks.Create, - 'workbook-delete': mistralclient.commands.v2.workbooks.Delete, - 'workbook-update': mistralclient.commands.v2.workbooks.Update, - 'workbook-get-definition': - mistralclient.commands.v2.workbooks.GetDefinition, - 'workbook-validate': mistralclient.commands.v2.workbooks.Validate, - 'workflow-list': mistralclient.commands.v2.workflows.List, - 'workflow-get': mistralclient.commands.v2.workflows.Get, - 'workflow-create': mistralclient.commands.v2.workflows.Create, - 'workflow-delete': mistralclient.commands.v2.workflows.Delete, - 'workflow-update': mistralclient.commands.v2.workflows.Update, - 'workflow-get-definition': - mistralclient.commands.v2.workflows.GetDefinition, - 'workflow-validate': mistralclient.commands.v2.workflows.Validate, - 'environment-create': - mistralclient.commands.v2.environments.Create, - 'environment-delete': - mistralclient.commands.v2.environments.Delete, - 'environment-update': - mistralclient.commands.v2.environments.Update, - 'environment-list': mistralclient.commands.v2.environments.List, - 'environment-get': mistralclient.commands.v2.environments.Get, - 'run-action': mistralclient.commands.v2.action_executions.Create, - 'action-execution-list': - mistralclient.commands.v2.action_executions.List, - 'action-execution-get': - mistralclient.commands.v2.action_executions.Get, - 'action-execution-get-input': - mistralclient.commands.v2.action_executions.GetInput, - 'action-execution-get-output': - mistralclient.commands.v2.action_executions.GetOutput, - 'action-execution-update': - mistralclient.commands.v2.action_executions.Update, - 'action-execution-delete': - mistralclient.commands.v2.action_executions.Delete, - 'execution-create': mistralclient.commands.v2.executions.Create, - 'execution-delete': mistralclient.commands.v2.executions.Delete, - 'execution-update': mistralclient.commands.v2.executions.Update, - 'execution-list': mistralclient.commands.v2.executions.List, - 'execution-get': mistralclient.commands.v2.executions.Get, - 'execution-get-input': - mistralclient.commands.v2.executions.GetInput, - 'execution-get-output': - mistralclient.commands.v2.executions.GetOutput, - 'task-list': mistralclient.commands.v2.tasks.List, - 'task-get': mistralclient.commands.v2.tasks.Get, - 'task-get-published': mistralclient.commands.v2.tasks.GetPublished, - 'task-get-result': mistralclient.commands.v2.tasks.GetResult, - 'task-rerun': mistralclient.commands.v2.tasks.Rerun, - 'action-list': mistralclient.commands.v2.actions.List, - 'action-get': mistralclient.commands.v2.actions.Get, - 'action-create': mistralclient.commands.v2.actions.Create, - 'action-delete': mistralclient.commands.v2.actions.Delete, - 'action-update': mistralclient.commands.v2.actions.Update, - 'action-get-definition': - mistralclient.commands.v2.actions.GetDefinition, - 'action-validate': mistralclient.commands.v2.actions.Validate, - 'cron-trigger-list': mistralclient.commands.v2.cron_triggers.List, - 'cron-trigger-get': mistralclient.commands.v2.cron_triggers.Get, - 'cron-trigger-create': - mistralclient.commands.v2.cron_triggers.Create, - 'cron-trigger-delete': - mistralclient.commands.v2.cron_triggers.Delete, - 'event-trigger-list': - mistralclient.commands.v2.event_triggers.List, - 'event-trigger-get': mistralclient.commands.v2.event_triggers.Get, - 'event-trigger-create': - mistralclient.commands.v2.event_triggers.Create, - 'event-trigger-delete': - mistralclient.commands.v2.event_triggers.Delete, - 'service-list': mistralclient.commands.v2.services.List, - 'member-create': mistralclient.commands.v2.members.Create, - 'member-delete': mistralclient.commands.v2.members.Delete, - 'member-update': mistralclient.commands.v2.members.Update, - 'member-list': mistralclient.commands.v2.members.List, - 'member-get': mistralclient.commands.v2.members.Get, - } - - -def main(argv=sys.argv[1:]): - return MistralShell().run(argv) - - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) diff --git a/mistralclient/tests/__init__.py b/mistralclient/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/mistralclient/tests/functional/__init__.py b/mistralclient/tests/functional/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/mistralclient/tests/functional/cli/__init__.py b/mistralclient/tests/functional/cli/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/mistralclient/tests/functional/cli/base.py b/mistralclient/tests/functional/cli/base.py deleted file mode 100644 index 55df25d..0000000 --- a/mistralclient/tests/functional/cli/base.py +++ /dev/null @@ -1,148 +0,0 @@ -# Copyright (c) 2014 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os - -from six.moves import configparser -from tempest.lib.cli import base - - -CLI_DIR = os.environ.get( - 'OS_MISTRALCLIENT_EXEC_DIR', - os.path.join(os.path.abspath('.'), '.tox/functional/bin') -) -_CREDS_FILE = 'functional_creds.conf' - - -def credentials(group='admin'): - """Retrieves credentials to run functional tests. - - Credentials are either read from the environment or from a config file - ('functional_creds.conf'). Environment variables override those from the - config file. - - The 'functional_creds.conf' file is the clean and new way to use (by - default tox 2.0 does not pass environment variables). - """ - if group == 'admin': - username = os.environ.get('OS_USERNAME') - password = os.environ.get('OS_PASSWORD') - tenant_name = os.environ.get('OS_TENANT_NAME') - else: - username = os.environ.get('OS_ALT_USERNAME') - password = os.environ.get('OS_ALT_PASSWORD') - tenant_name = os.environ.get('OS_ALT_TENANT_NAME') - - auth_url = os.environ.get('OS_AUTH_URL') - - config = configparser.RawConfigParser() - if config.read(_CREDS_FILE): - username = username or config.get(group, 'user') - password = password or config.get(group, 'pass') - tenant_name = tenant_name or config.get(group, 'tenant') - auth_url = auth_url or config.get('auth', 'uri') - - # TODO(ddeja): Default value of OS_AUTH_URL is to provide url to v3 API. - # Since tempest openstack client doesn't properly handle it, we switch - # it back to v2. Once tempest openstack starts to use v3, this can be - # deleted. - # https://github.com/openstack/tempest/blob/master/tempest/lib/cli/base.py#L363 - return { - 'username': username, - 'password': password, - 'tenant_name': tenant_name, - 'auth_url': auth_url.replace('v3', 'v2.0') - } - - -class MistralCLIAuth(base.ClientTestBase): - - _mistral_url = None - - def _get_admin_clients(self): - creds = credentials() - - clients = base.CLIClient( - username=creds['username'], - password=creds['password'], - tenant_name=creds['tenant_name'], - uri=creds['auth_url'], - cli_dir=CLI_DIR - ) - - return clients - - def _get_clients(self): - return self._get_admin_clients() - - def mistral(self, action, flags='', params='', fail_ok=False): - """Executes Mistral command.""" - mistral_url_op = "--os-mistral-url %s" % self._mistral_url - - if 'WITHOUT_AUTH' in os.environ: - return base.execute( - 'mistral %s' % mistral_url_op, - action, - flags, - params, - fail_ok, - merge_stderr=False, - cli_dir='' - ) - else: - return self.clients.cmd_with_auth( - 'mistral %s' % mistral_url_op, - action, - flags, - params, - fail_ok - ) - - def get_project_id(self, project='admin'): - project_name = credentials(project)['tenant_name'] - - admin_clients = self._get_clients() - projects = self.parser.listing( - admin_clients.openstack('project show', params=project_name) - ) - - return [o['Value'] for o in projects if o['Field'] == 'id'][0] - - -class MistralCLIAltAuth(base.ClientTestBase): - - _mistral_url = None - - def _get_alt_clients(self): - creds = credentials('demo') - - clients = base.CLIClient( - username=creds['username'], - password=creds['password'], - tenant_name=creds['tenant_name'], - uri=creds['auth_url'], - cli_dir=CLI_DIR - ) - - return clients - - def _get_clients(self): - return self._get_alt_clients() - - def mistral_alt(self, action, flags='', params='', mode='alt_user'): - """Executes Mistral command for alt_user from alt_tenant.""" - mistral_url_op = "--os-mistral-url %s" % self._mistral_url - - return self.clients.cmd_with_auth( - 'mistral %s' % mistral_url_op, action, flags, params) diff --git a/mistralclient/tests/functional/cli/v2/__init__.py b/mistralclient/tests/functional/cli/v2/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/mistralclient/tests/functional/cli/v2/base_v2.py b/mistralclient/tests/functional/cli/v2/base_v2.py deleted file mode 100644 index 808082b..0000000 --- a/mistralclient/tests/functional/cli/v2/base_v2.py +++ /dev/null @@ -1,279 +0,0 @@ -# Copyright (c) 2014 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os -import time - -from tempest.lib import exceptions - -from mistralclient.tests.functional.cli import base - - -MISTRAL_URL = "http://localhost:8989/v2" - - -class MistralClientTestBase(base.MistralCLIAuth, base.MistralCLIAltAuth): - - _mistral_url = MISTRAL_URL - - @classmethod - def setUpClass(cls): - super(MistralClientTestBase, cls).setUpClass() - - cls.wb_def = os.path.relpath( - 'functionaltests/resources/v2/wb_v2.yaml', os.getcwd() - ) - - cls.wb_with_tags_def = os.path.relpath( - 'functionaltests/resources/v2/wb_with_tags_v2.yaml', os.getcwd() - ) - - cls.wf_def = os.path.relpath( - 'functionaltests/resources/v2/wf_v2.yaml', os.getcwd() - ) - - cls.wf_single_def = os.path.relpath( - 'functionaltests/resources/v2/wf_single_v2.yaml', os.getcwd() - ) - - cls.wf_with_delay_def = os.path.relpath( - 'functionaltests/resources/v2/wf_delay_v2.yaml', os.getcwd() - ) - - cls.wf_wrapping_wf = os.path.relpath( - 'functionaltests/resources/v2/wf_wrapping_wf_v2.yaml', os.getcwd() - ) - - cls.act_def = os.path.relpath( - 'functionaltests/resources/v2/action_v2.yaml', os.getcwd() - ) - - cls.act_tag_def = os.path.relpath( - 'functionaltests/resources/v2/action_v2_tags.yaml', os.getcwd() - ) - - def setUp(self): - super(MistralClientTestBase, self).setUp() - - def get_field_value(self, obj, field): - return [ - o['Value'] for o in obj - if o['Field'] == "{0}".format(field) - ][0] - - def get_item_info(self, get_from, get_by, value): - return [i for i in get_from if i[get_by] == value][0] - - def mistral_admin(self, cmd, params=""): - self.clients = self._get_admin_clients() - - return self.parser.listing( - self.mistral('{0}'.format(cmd), params='{0}'.format(params)) - ) - - def mistral_alt_user(self, cmd, params=""): - self.clients = self._get_alt_clients() - - return self.parser.listing( - self.mistral_alt('{0}'.format(cmd), params='{0}'.format(params)) - ) - - def mistral_cli(self, admin, cmd, params=''): - if admin: - return self.mistral_admin(cmd, params) - else: - return self.mistral_alt_user(cmd, params) - - def workbook_create(self, wb_def, admin=True): - wb = self.mistral_cli( - admin, - 'workbook-create', - params='{0}'.format(wb_def) - ) - - wb_name = self.get_field_value(wb, "Name") - - self.addCleanup( - self.mistral_cli, - admin, - 'workbook-delete', - params=wb_name - ) - - self.addCleanup( - self.mistral_cli, - admin, - 'workflow-delete', - params='wb.wf1' - ) - - return wb - - def workflow_create(self, wf_def, admin=True, scope='private'): - params = '{0}'.format(wf_def) - - if scope == 'public': - params += ' --public' - - wf = self.mistral_cli( - admin, - 'workflow-create', - params=params - ) - - for workflow in wf: - self.addCleanup( - self.mistral_cli, - admin, - 'workflow-delete', - params=workflow['ID'] - ) - - return wf - - def workflow_member_create(self, wf_id): - cmd_param = ( - '%s workflow %s' % (wf_id, self.get_project_id("demo")) - ) - member = self.mistral_admin("member-create", params=cmd_param) - - self.addCleanup( - self.mistral_admin, - 'member-delete', - params=cmd_param - ) - - return member - - def action_create(self, act_def, admin=True, scope='private'): - params = '{0}'.format(act_def) - - if scope == 'public': - params += ' --public' - - acts = self.mistral_cli( - admin, - 'action-create', - params=params - ) - - for action in acts: - self.addCleanup( - self.mistral_cli, - admin, - 'action-delete', - params=action['Name'] - ) - - return acts - - def cron_trigger_create(self, name, wf_name, wf_input, pattern=None, - count=None, first_time=None, admin=True): - optional_params = "" - - if pattern: - optional_params += ' --pattern "{}"'.format(pattern) - if count: - optional_params += ' --count {}'.format(count) - if first_time: - optional_params += ' --first-time "{}"'.format(first_time) - - trigger = self.mistral_cli( - admin, - 'cron-trigger-create', - params='{} {} {} {}'.format(name, wf_name, wf_input, - optional_params)) - - self.addCleanup(self.mistral_cli, - admin, - 'cron-trigger-delete', - params=name) - - return trigger - - def event_trigger_create(self, name, wf_id, exchange, - topic, event, wf_input, admin=True): - - trigger = self.mistral_cli( - admin, - 'event-trigger-create', - params=' '.join((name, wf_id, exchange, topic, event, wf_input))) - ev_tr_id = self.get_field_value(trigger, 'ID') - self.addCleanup(self.mistral_cli, - admin, - 'event-trigger-delete', - params=ev_tr_id) - - return trigger - - def execution_create(self, params, admin=True): - ex = self.mistral_cli(admin, 'execution-create', params=params) - exec_id = self.get_field_value(ex, 'ID') - - self.addCleanup( - self.mistral_cli, - admin, - 'execution-delete', - params=exec_id - ) - - return ex - - def environment_create(self, params, admin=True): - env = self.mistral_cli(admin, 'environment-create', params=params) - env_name = self.get_field_value(env, 'Name') - - self.addCleanup( - self.mistral_cli, - admin, - 'environment-delete', - params=env_name - ) - - return env - - def create_file(self, file_name, file_body=""): - f = open(file_name, 'w') - f.write(file_body) - f.close() - - self.addCleanup(os.remove, file_name) - - def wait_execution_success(self, exec_id, timeout=180): - start_time = time.time() - - ex = self.mistral_admin('execution-get', params=exec_id) - exec_state = self.get_field_value(ex, 'State') - - expected_states = ['SUCCESS', 'RUNNING'] - - while exec_state != 'SUCCESS': - if time.time() - start_time > timeout: - msg = ("Execution exceeds timeout {0} to change state " - "to SUCCESS. Execution: {1}".format(timeout, ex)) - - raise exceptions.TimeoutException(msg) - - ex = self.mistral_admin('execution-get', params=exec_id) - exec_state = self.get_field_value(ex, 'State') - - if exec_state not in expected_states: - msg = ("Execution state %s is not in expected " - "states: %s" % (exec_state, expected_states)) - - raise exceptions.TempestException(msg) - - time.sleep(2) - - return True diff --git a/mistralclient/tests/functional/cli/v2/cli_multi_tenancy_tests.py b/mistralclient/tests/functional/cli/v2/cli_multi_tenancy_tests.py deleted file mode 100644 index 70971e7..0000000 --- a/mistralclient/tests/functional/cli/v2/cli_multi_tenancy_tests.py +++ /dev/null @@ -1,488 +0,0 @@ -# Copyright (c) 2014 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from tempest.lib import exceptions - -from mistralclient.tests.functional.cli.v2 import base_v2 - - -class StandardItemsAvailabilityCLITests(base_v2.MistralClientTestBase): - - def test_std_workflows_availability(self): - wfs = self.mistral_admin("workflow-list") - - self.assertTableStruct( - wfs, - ["Name", "Tags", "Input", "Created at", "Updated at"] - ) - self.assertIn("std.create_instance", - [workflow["Name"] for workflow in wfs]) - - wfs = self.mistral_alt_user("workflow-list") - - self.assertTableStruct( - wfs, - ["Name", "Tags", "Input", "Created at", "Updated at"] - ) - self.assertIn("std.create_instance", - [workflow["Name"] for workflow in wfs]) - - def test_std_actions_availability(self): - acts = self.mistral_admin("action-list") - - self.assertTableStruct( - acts, - ["Name", "Is system", "Input", "Description", - "Tags", "Created at", "Updated at"] - ) - self.assertIn("glance.images_list", - [action["Name"] for action in acts]) - - acts = self.mistral_alt_user("action-list") - - self.assertTableStruct( - acts, - ["Name", "Is system", "Input", "Description", - "Tags", "Created at", "Updated at"] - ) - self.assertIn("glance.images_list", - [action["Name"] for action in acts]) - - -class WorkbookIsolationCLITests(base_v2.MistralClientTestBase): - - def test_workbook_name_uniqueness(self): - self.workbook_create(self.wb_def) - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - "workbook-create", - params="{0}".format(self.wb_def) - ) - - self.workbook_create(self.wb_def, admin=False) - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_alt_user, - "workbook-create", - params="{0}".format(self.wb_def) - ) - - def test_wb_isolation(self): - wb = self.workbook_create(self.wb_def) - wb_name = self.get_field_value(wb, "Name") - wbs = self.mistral_admin("workbook-list") - - self.assertIn(wb_name, [w["Name"] for w in wbs]) - - alt_wbs = self.mistral_alt_user("workbook-list") - - self.assertNotIn(wb_name, [w["Name"] for w in alt_wbs]) - - def test_get_wb_from_another_tenant(self): - wb = self.workbook_create(self.wb_def) - name = self.get_field_value(wb, "Name") - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_alt_user, - "workbook-get", - params=name - ) - - def test_delete_wb_from_another_tenant(self): - wb = self.workbook_create(self.wb_def) - name = self.get_field_value(wb, "Name") - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_alt_user, - "workbook-delete", - params=name - ) - - -class WorkflowIsolationCLITests(base_v2.MistralClientTestBase): - - def test_workflow_name_uniqueness(self): - self.workflow_create(self.wf_def) - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - "workflow-create", - params="{0}".format(self.wf_def) - ) - - self.workflow_create(self.wf_def, admin=False) - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_alt_user, - "workflow-create", - params="{0}".format(self.wf_def) - ) - - def test_wf_isolation(self): - wf = self.workflow_create(self.wf_def) - wfs = self.mistral_admin("workflow-list") - - self.assertIn(wf[0]["Name"], [w["Name"] for w in wfs]) - - alt_wfs = self.mistral_alt_user("workflow-list") - - self.assertNotIn(wf[0]["Name"], [w["Name"] for w in alt_wfs]) - - def test_get_wf_from_another_tenant(self): - wf = self.workflow_create(self.wf_def) - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_alt_user, - "workflow-get", - params=wf[0]["ID"] - ) - - def test_create_public_workflow(self): - wf = self.workflow_create(self.wf_def, scope='public') - - same_wf = self.mistral_alt_user( - "workflow-get", - params=wf[0]["Name"] - ) - - self.assertEqual( - wf[0]["Name"], - self.get_field_value(same_wf, "Name") - ) - - def test_delete_wf_from_another_tenant(self): - wf = self.workflow_create(self.wf_def) - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_alt_user, - "workflow-delete", - params=wf[0]["ID"] - ) - - -class WorkflowSharingCLITests(base_v2.MistralClientTestBase): - def setUp(self): - super(WorkflowSharingCLITests, self).setUp() - - self.wf = self.workflow_create(self.wf_def, admin=True) - - def _update_shared_workflow(self, new_status='accepted'): - member = self.workflow_member_create(self.wf[0]["ID"]) - status = self.get_field_value(member, 'Status') - - self.assertEqual('pending', status) - - cmd_param = '%s workflow --status %s' % (self.wf[0]["ID"], new_status) - member = self.mistral_alt_user("member-update", params=cmd_param) - status = self.get_field_value(member, 'Status') - - self.assertEqual(new_status, status) - - def test_list_accepted_shared_workflow(self): - wfs = self.mistral_alt_user("workflow-list") - - self.assertNotIn(self.wf[0]["ID"], [w["ID"] for w in wfs]) - - self._update_shared_workflow(new_status='accepted') - alt_wfs = self.mistral_alt_user("workflow-list") - - self.assertIn(self.wf[0]["ID"], [w["ID"] for w in alt_wfs]) - self.assertIn( - self.get_project_id("admin"), - [w["Project ID"] for w in alt_wfs] - ) - - def test_list_rejected_shared_workflow(self): - self._update_shared_workflow(new_status='rejected') - alt_wfs = self.mistral_alt_user("workflow-list") - - self.assertNotIn(self.wf[0]["ID"], [w["ID"] for w in alt_wfs]) - - def test_create_execution_using_shared_workflow(self): - self._update_shared_workflow(new_status='accepted') - - execution = self.execution_create(self.wf[0]["ID"], admin=False) - wf_name = self.get_field_value(execution, 'Workflow name') - - self.assertEqual(self.wf[0]["Name"], wf_name) - - def test_create_contrigger_using_shared_workflow(self): - self._update_shared_workflow(new_status='accepted') - - trigger = self.cron_trigger_create( - "test_trigger", - self.wf[0]["ID"], - "{}", - "5 * * * *", - admin=False - ) - wf_name = self.get_field_value(trigger, 'Workflow') - - self.assertEqual(self.wf[0]["Name"], wf_name) - - # Admin project can not delete the shared workflow, because it is used - # in a cron-trigger of another project. - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workflow-delete', - params=self.wf[0]["ID"] - ) - - -class ActionIsolationCLITests(base_v2.MistralClientTestBase): - - def test_actions_name_uniqueness(self): - self.action_create(self.act_def) - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - "action-create", - params="{0}".format(self.act_def) - ) - - self.action_create(self.act_def, admin=False) - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_alt_user, - "action-create", - params="{0}".format(self.act_def) - ) - - def test_action_isolation(self): - act = self.action_create(self.act_def) - acts = self.mistral_admin("action-list") - - self.assertIn(act[0]["Name"], [a["Name"] for a in acts]) - - alt_acts = self.mistral_alt_user("action-list") - - self.assertNotIn(act[0]["Name"], [a["Name"] for a in alt_acts]) - - def test_get_action_from_another_tenant(self): - act = self.action_create(self.act_def) - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_alt_user, - "action-get", - params=act[0]["Name"] - ) - - def test_delete_action_from_another_tenant(self): - act = self.action_create(self.act_def) - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_alt_user, - "action-delete", - params=act[0]["Name"] - ) - - def test_create_public_action(self): - act = self.action_create(self.act_def, scope='public') - - same_act = self.mistral_alt_user( - "action-get", - params=act[0]["Name"] - ) - - self.assertEqual( - act[0]["Name"], - self.get_field_value(same_act, "Name") - ) - - -class CronTriggerIsolationCLITests(base_v2.MistralClientTestBase): - def test_cron_trigger_name_uniqueness(self): - wf = self.workflow_create(self.wf_def) - self.cron_trigger_create( - "admin_trigger", - wf[0]["ID"], - "{}", - "5 * * * *" - ) - - self.assertRaises( - exceptions.CommandFailed, - self.cron_trigger_create, - "admin_trigger", - wf[0]["ID"], - "{}" - "5 * * * *", - ) - - wf = self.workflow_create(self.wf_def, admin=False) - self.cron_trigger_create( - "user_trigger", - wf[0]["ID"], - "{}", - "5 * * * *", - None, - None, - admin=False - ) - - self.assertRaises( - exceptions.CommandFailed, - self.cron_trigger_create, - "user_trigger", - wf[0]["ID"], - "{}", - "5 * * * *", - None, - None, - admin=False - ) - - def test_cron_trigger_isolation(self): - wf = self.workflow_create(self.wf_def) - self.cron_trigger_create( - "trigger", wf[0]["Name"], "{}", "5 * * * *") - - alt_trs = self.mistral_alt_user("cron-trigger-list") - - self.assertNotIn("trigger", [t["Name"] for t in alt_trs]) - - -class ExecutionIsolationCLITests(base_v2.MistralClientTestBase): - - def test_execution_isolation(self): - wf = self.workflow_create(self.wf_def) - ex = self.execution_create(wf[0]["Name"]) - exec_id = self.get_field_value(ex, "ID") - - execs = self.mistral_admin("execution-list") - self.assertIn(exec_id, [e["ID"] for e in execs]) - - alt_execs = self.mistral_alt_user("execution-list") - self.assertNotIn(exec_id, [e["ID"] for e in alt_execs]) - - def test_get_execution_from_another_tenant(self): - wf = self.workflow_create(self.wf_def) - ex = self.execution_create(wf[0]["Name"]) - exec_id = self.get_field_value(ex, "ID") - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_alt_user, - "execution-get", - params=exec_id - ) - - -class EnvironmentIsolationCLITests(base_v2.MistralClientTestBase): - - def setUp(self): - super(EnvironmentIsolationCLITests, self).setUp() - - self.env_file = "env.yaml" - self.create_file("{0}".format(self.env_file), - "name: env\n" - "description: Test env\n" - "variables:\n" - " var: value") - - def test_environment_name_uniqueness(self): - self.environment_create(self.env_file) - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - "environment-create", - params=self.env_file - ) - - self.environment_create(self.env_file, admin=False) - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_alt_user, - "environment-create", - params=self.env_file - ) - - def test_environment_isolation(self): - env = self.environment_create(self.env_file) - env_name = self.get_field_value(env, "Name") - envs = self.mistral_admin("environment-list") - - self.assertIn(env_name, [en["Name"] for en in envs]) - - alt_envs = self.mistral_alt_user("environment-list") - - self.assertNotIn(env_name, [en["Name"] for en in alt_envs]) - - def test_get_env_from_another_tenant(self): - env = self.environment_create(self.env_file) - env_name = self.get_field_value(env, "Name") - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_alt_user, - "environment-get", - params=env_name - ) - - def test_delete_env_from_another_tenant(self): - env = self.environment_create(self.env_file) - env_name = self.get_field_value(env, "Name") - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_alt_user, - "environment-delete", - params=env_name - ) - - -class ActionExecutionIsolationCLITests(base_v2.MistralClientTestBase): - - def test_action_execution_isolation(self): - wf = self.workflow_create(self.wf_def) - wf_exec = self.execution_create(wf[0]["Name"]) - direct_ex_id = self.get_field_value(wf_exec, 'ID') - - self.wait_execution_success(direct_ex_id) - - act_execs = self.mistral_admin("action-execution-list") - self.assertIn(wf[0]["Name"], - [act["Workflow name"] for act in act_execs]) - - alt_act_execs = self.mistral_alt_user("action-execution-list") - self.assertNotIn(wf[0]["Name"], - [act["Workflow name"] for act in alt_act_execs]) - - def test_get_action_execution_from_another_tenant(self): - wf = self.workflow_create(self.wf_def) - ex = self.execution_create(wf[0]["Name"]) - exec_id = self.get_field_value(ex, "ID") - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_alt_user, - "action-execution-get", - params=exec_id - ) diff --git a/mistralclient/tests/functional/cli/v2/cli_tests_v2.py b/mistralclient/tests/functional/cli/v2/cli_tests_v2.py deleted file mode 100644 index 18a384a..0000000 --- a/mistralclient/tests/functional/cli/v2/cli_tests_v2.py +++ /dev/null @@ -1,2040 +0,0 @@ -# Copyright (c) 2014 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from tempest.lib import exceptions - -from mistralclient.tests.functional.cli import base -from mistralclient.tests.functional.cli.v2 import base_v2 - - -MISTRAL_URL = "http://localhost:8989/v2" - - -class SimpleMistralCLITests(base.MistralCLIAuth): - """Basic tests, check '-list', '-help' commands.""" - - _mistral_url = MISTRAL_URL - - @classmethod - def setUpClass(cls): - super(SimpleMistralCLITests, cls).setUpClass() - - def test_workbooks_list(self): - workbooks = self.parser.listing(self.mistral('workbook-list')) - - self.assertTableStruct( - workbooks, - ['Name', 'Tags', 'Created at', 'Updated at'] - ) - - def test_workflow_list(self): - workflows = self.parser.listing(self.mistral('workflow-list')) - - self.assertTableStruct( - workflows, - ['ID', 'Name', 'Tags', 'Input', 'Created at', 'Updated at'] - ) - - def test_executions_list(self): - executions = self.parser.listing(self.mistral('execution-list')) - - self.assertTableStruct( - executions, - ['ID', 'Workflow name', 'Workflow ID', 'State', 'Created at', - 'Updated at'] - ) - - def test_tasks_list(self): - tasks = self.parser.listing(self.mistral('task-list')) - - self.assertTableStruct( - tasks, - ['ID', 'Name', 'Workflow name', 'Execution ID', 'State'] - ) - - def test_cron_trigger_list(self): - triggers = self.parser.listing(self.mistral('cron-trigger-list')) - - self.assertTableStruct( - triggers, - ['Name', 'Workflow', 'Pattern', 'Next execution time', - 'Remaining executions', 'Created at', 'Updated at'] - ) - - def test_event_trigger_list(self): - triggers = self.parser.listing(self.mistral('event-trigger-list')) - - self.assertTableStruct( - triggers, - ['ID', 'Name', 'Workflow ID', 'Exchange', 'Topic', 'Event', - 'Created at', 'Updated at'] - ) - - def test_actions_list(self): - actions = self.parser.listing(self.mistral('action-list')) - - self.assertTableStruct( - actions, - ['Name', 'Is system', 'Input', 'Description', - 'Tags', 'Created at', 'Updated at'] - ) - - def test_environments_list(self): - envs = self.parser.listing(self.mistral('environment-list')) - - self.assertTableStruct( - envs, - ['Name', 'Description', 'Scope', 'Created at', 'Updated at'] - ) - - def test_action_execution_list(self): - act_execs = self.parser.listing(self.mistral('action-execution-list')) - - self.assertTableStruct( - act_execs, - ['ID', 'Name', 'Workflow name', 'State', 'Accepted'] - ) - - def test_action_execution_list_with_limit(self): - act_execs = self.parser.listing( - self.mistral( - 'action-execution-list', - params='--limit 1' - ) - ) - - self.assertEqual(1, len(act_execs)) - - -class WorkbookCLITests(base_v2.MistralClientTestBase): - """Test suite checks commands to work with workbooks.""" - - @classmethod - def setUpClass(cls): - super(WorkbookCLITests, cls).setUpClass() - - def test_workbook_create_delete(self): - wb = self.mistral_admin('workbook-create', params=self.wb_def) - - wb_name = self.get_field_value(wb, "Name") - - self.assertTableStruct(wb, ['Field', 'Value']) - - wbs = self.mistral_admin('workbook-list') - self.assertIn(wb_name, [w['Name'] for w in wbs]) - - wbs = self.mistral_admin('workbook-list') - self.assertIn(wb_name, [w['Name'] for w in wbs]) - - self.mistral_admin('workbook-delete', params=wb_name) - - wbs = self.mistral_admin('workbook-list') - self.assertNotIn(wb_name, [w['Name'] for w in wbs]) - - def test_workbook_create_with_tags(self): - wb = self.workbook_create(self.wb_with_tags_def) - - self.assertIn('tag', self.get_field_value(wb, 'Tags')) - - def test_workbook_update(self): - wb = self.workbook_create(self.wb_def) - - wb_name = self.get_field_value(wb, "Name") - - init_update_at = self.get_field_value(wb, "Updated at") - tags = self.get_field_value(wb, 'Tags') - - self.assertNotIn('tag', tags) - - wb = self.mistral_admin('workbook-update', params=self.wb_def) - - update_at = self.get_field_value(wb, "Updated at") - name = self.get_field_value(wb, 'Name') - tags = self.get_field_value(wb, 'Tags') - - self.assertEqual(wb_name, name) - self.assertNotIn('tag', tags) - self.assertEqual(init_update_at, update_at) - - wb = self.mistral_admin( - 'workbook-update', - params=self.wb_with_tags_def - ) - - self.assertTableStruct(wb, ['Field', 'Value']) - - update_at = self.get_field_value(wb, "Updated at") - name = self.get_field_value(wb, 'Name') - tags = self.get_field_value(wb, 'Tags') - - self.assertEqual(wb_name, name) - self.assertIn('tag', tags) - self.assertNotEqual(init_update_at, update_at) - - def test_workbook_get(self): - created = self.workbook_create(self.wb_with_tags_def) - - wb_name = self.get_field_value(created, "Name") - - fetched = self.mistral_admin('workbook-get', params=wb_name) - - created_wb_name = self.get_field_value(created, 'Name') - fetched_wb_name = self.get_field_value(fetched, 'Name') - - self.assertEqual(created_wb_name, fetched_wb_name) - - created_wb_tag = self.get_field_value(created, 'Tags') - fetched_wb_tag = self.get_field_value(fetched, 'Tags') - - self.assertEqual(created_wb_tag, fetched_wb_tag) - - def test_workbook_get_definition(self): - wb = self.workbook_create(self.wb_def) - - wb_name = self.get_field_value(wb, "Name") - - definition = self.mistral_admin( - 'workbook-get-definition', - params=wb_name - ) - - self.assertNotIn('404 Not Found', definition) - - def test_workbook_validate_with_valid_def(self): - wb = self.mistral_admin('workbook-validate', params=self.wb_def) - - wb_valid = self.get_field_value(wb, 'Valid') - wb_error = self.get_field_value(wb, 'Error') - - self.assertEqual('True', wb_valid) - self.assertEqual('None', wb_error) - - def test_workbook_validate_with_invalid_def(self): - self.create_file('wb.yaml', 'name: wb\n') - - wb = self.mistral_admin('workbook-validate', params='wb.yaml') - - wb_valid = self.get_field_value(wb, 'Valid') - wb_error = self.get_field_value(wb, 'Error') - - self.assertEqual('False', wb_valid) - self.assertNotEqual('None', wb_error) - - -class WorkflowCLITests(base_v2.MistralClientTestBase): - """Test suite checks commands to work with workflows.""" - - @classmethod - def setUpClass(cls): - super(WorkflowCLITests, cls).setUpClass() - - def test_workflow_create_delete(self): - init_wfs = self.mistral_admin('workflow-create', params=self.wf_def) - - wf_names = [wf['Name'] for wf in init_wfs] - - self.assertTableStruct(init_wfs, ['Name', 'Created at', 'Updated at']) - - wfs = self.mistral_admin('workflow-list') - self.assertIn(wf_names[0], [workflow['Name'] for workflow in wfs]) - - for wf_name in wf_names: - self.mistral_admin('workflow-delete', params=wf_name) - - wfs = self.mistral_admin('workflow-list') - for wf in wf_names: - self.assertNotIn(wf, [workflow['Name'] for workflow in wfs]) - - def test_create_wf_with_tags(self): - init_wfs = self.workflow_create(self.wf_def) - wf_name = init_wfs[1]['Name'] - - self.assertTableStruct( - init_wfs, - ['Name', 'Created at', 'Updated at', 'Tags'] - ) - - created_wf_info = self.get_item_info( - get_from=init_wfs, - get_by='Name', - value=wf_name - ) - - self.assertEqual('tag', created_wf_info['Tags']) - - def test_workflow_update(self): - wf = self.workflow_create(self.wf_def) - - wf_name = wf[0]['Name'] - wf_id = wf[0]['ID'] - - created_wf_info = self.get_item_info( - get_from=wf, - get_by='Name', - value=wf_name - ) - - # Update a workflow with definition unchanged. - upd_wf = self.mistral_admin( - 'workflow-update', - params='{0}'.format(self.wf_def) - ) - - self.assertTableStruct(upd_wf, ['Name', 'Created at', 'Updated at']) - - updated_wf_info = self.get_item_info( - get_from=upd_wf, - get_by='Name', - value=wf_name - ) - - self.assertEqual(wf_name, upd_wf[0]['Name']) - self.assertEqual( - created_wf_info['Created at'].split(".")[0], - updated_wf_info['Created at'] - ) - self.assertEqual( - created_wf_info['Updated at'], - updated_wf_info['Updated at'] - ) - - # Update a workflow with definition changed. - upd_wf = self.mistral_admin( - 'workflow-update', - params='{0}'.format(self.wf_with_delay_def) - ) - - self.assertTableStruct(upd_wf, ['Name', 'Created at', 'Updated at']) - - updated_wf_info = self.get_item_info( - get_from=upd_wf, - get_by='Name', - value=wf_name - ) - - self.assertEqual(wf_name, upd_wf[0]['Name']) - self.assertEqual( - created_wf_info['Created at'].split(".")[0], - updated_wf_info['Created at'] - ) - self.assertNotEqual( - created_wf_info['Updated at'], - updated_wf_info['Updated at'] - ) - - # Update a workflow with uuid. - upd_wf = self.mistral_admin( - 'workflow-update', - params='{0} --id {1}'.format(self.wf_with_delay_def, wf_id) - ) - - self.assertTableStruct(upd_wf, ['Name', 'Created at', 'Updated at']) - - updated_wf_info = self.get_item_info( - get_from=upd_wf, - get_by='ID', - value=wf_id - ) - - self.assertEqual(wf_name, upd_wf[0]['Name']) - self.assertEqual( - created_wf_info['Created at'].split(".")[0], - updated_wf_info['Created at'] - ) - self.assertNotEqual( - created_wf_info['Updated at'], - updated_wf_info['Updated at'] - ) - - def test_workflow_update_truncate_input(self): - input_value = "very_long_input_parameter_name_that_should_be_truncated" - - wf_def = """ - version: "2.0" - workflow1: - input: - - {0} - tasks: - task1: - action: std.noop - """.format(input_value) - - self.create_file('wf.yaml', wf_def) - self.workflow_create('wf.yaml') - - updated_wf = self.mistral_admin('workflow-update', params='wf.yaml') - - updated_wf_info = self.get_item_info( - get_from=updated_wf, - get_by='Name', - value='workflow1' - ) - - self.assertEqual(updated_wf_info['Input'][:-3], input_value[:25]) - - def test_workflow_get(self): - created = self.workflow_create(self.wf_def) - - wf_name = created[0]['Name'] - - fetched = self.mistral_admin('workflow-get', params=wf_name) - fetched_wf_name = self.get_field_value(fetched, 'Name') - - self.assertEqual(wf_name, fetched_wf_name) - - def test_workflow_get_with_id(self): - created = self.workflow_create(self.wf_def) - - wf_name = created[0]['Name'] - wf_id = created[0]['ID'] - - fetched = self.mistral_admin('workflow-get', params=wf_id) - fetched_wf_name = self.get_field_value(fetched, 'Name') - - self.assertEqual(wf_name, fetched_wf_name) - - def test_workflow_get_definition(self): - wf = self.workflow_create(self.wf_def) - - wf_name = wf[0]['Name'] - - definition = self.mistral_admin( - 'workflow-get-definition', - params=wf_name - ) - - self.assertNotIn('404 Not Found', definition) - - def test_workflow_validate_with_valid_def(self): - wf = self.mistral_admin('workflow-validate', params=self.wf_def) - - wf_valid = self.get_field_value(wf, 'Valid') - wf_error = self.get_field_value(wf, 'Error') - - self.assertEqual('True', wf_valid) - self.assertEqual('None', wf_error) - - def test_workflow_validate_with_invalid_def(self): - self.create_file('wf.yaml', 'name: wf\n') - - wf = self.mistral_admin('workflow-validate', params='wf.yaml') - - wf_valid = self.get_field_value(wf, 'Valid') - wf_error = self.get_field_value(wf, 'Error') - - self.assertEqual('False', wf_valid) - self.assertNotEqual('None', wf_error) - - def test_workflow_list_with_filter(self): - workflows = self.parser.listing(self.mistral('workflow-list')) - - self.assertTableStruct( - workflows, - ['ID', 'Name', 'Tags', 'Input', 'Created at', 'Updated at'] - ) - - # We know that we have more than one workflow by default. - self.assertGreater(len(workflows), 1) - - # Now let's provide a filter to the list command. - workflows = self.parser.listing( - self.mistral( - 'workflow-list', - params='--filter name=std.create_instance' - ) - ) - - self.assertTableStruct( - workflows, - ['ID', 'Name', 'Tags', 'Input', 'Created at', 'Updated at'] - ) - - self.assertEqual(1, len(workflows)) - - self.assertIn('std.create_instance', workflows[0]['Name']) - - -class ExecutionCLITests(base_v2.MistralClientTestBase): - """Test suite checks commands to work with executions.""" - - @classmethod - def setUpClass(cls): - super(ExecutionCLITests, cls).setUpClass() - - def setUp(self): - super(ExecutionCLITests, self).setUp() - - wfs = self.workflow_create(self.wf_def) - - self.direct_wf = wfs[0] - self.reverse_wf = wfs[1] - - self.create_file('input', '{\n "farewell": "Bye"\n}\n') - self.create_file('task_name', '{\n "task_name": "goodbye"\n}\n') - - def test_execution_create_delete(self): - execution = self.mistral_admin( - 'execution-create', - params='{0} -d "execution test"'.format(self.direct_wf['Name']) - ) - - exec_id = self.get_field_value(execution, 'ID') - - self.assertTableStruct(execution, ['Field', 'Value']) - - wf_name = self.get_field_value(execution, 'Workflow name') - wf_id = self.get_field_value(execution, 'Workflow ID') - created_at = self.get_field_value(execution, 'Created at') - description = self.get_field_value(execution, 'Description') - - self.assertEqual(self.direct_wf['Name'], wf_name) - self.assertIsNotNone(wf_id) - self.assertIsNotNone(created_at) - self.assertEqual("execution test", description) - - execs = self.mistral_admin('execution-list') - - self.assertIn(exec_id, [ex['ID'] for ex in execs]) - self.assertIn(wf_name, [ex['Workflow name'] for ex in execs]) - - self.mistral_admin('execution-delete', params=exec_id) - - def test_execution_create_with_input_and_start_task(self): - execution = self.execution_create( - "%s input task_name" % self.reverse_wf['Name'] - ) - - exec_id = self.get_field_value(execution, 'ID') - - result = self.wait_execution_success(exec_id) - - self.assertTrue(result) - - def test_execution_update(self): - execution = self.execution_create(self.direct_wf['Name']) - - exec_id = self.get_field_value(execution, 'ID') - status = self.get_field_value(execution, 'State') - - self.assertEqual('RUNNING', status) - - # Update execution state. - execution = self.mistral_admin( - 'execution-update', - params='{0} -s PAUSED'.format(exec_id)) - - updated_exec_id = self.get_field_value(execution, 'ID') - status = self.get_field_value(execution, 'State') - - self.assertEqual(exec_id, updated_exec_id) - self.assertEqual('PAUSED', status) - - # Update execution description. - execution = self.mistral_admin( - 'execution-update', - params='{0} -d "execution update test"'.format(exec_id) - ) - - description = self.get_field_value(execution, 'Description') - - self.assertEqual("execution update test", description) - - def test_execution_get(self): - execution = self.execution_create(self.direct_wf['Name']) - - exec_id = self.get_field_value(execution, 'ID') - - execution = self.mistral_admin( - 'execution-get', - params='{0}'.format(exec_id) - ) - - gotten_id = self.get_field_value(execution, 'ID') - wf_name = self.get_field_value(execution, 'Workflow name') - wf_id = self.get_field_value(execution, 'Workflow ID') - - self.assertIsNotNone(wf_id) - self.assertEqual(exec_id, gotten_id) - self.assertEqual(self.direct_wf['Name'], wf_name) - - def test_execution_get_input(self): - execution = self.execution_create(self.direct_wf['Name']) - exec_id = self.get_field_value(execution, 'ID') - - ex_input = self.mistral_admin('execution-get-input', params=exec_id) - - self.assertEqual([], ex_input) - - def test_execution_get_output(self): - execution = self.execution_create(self.direct_wf['Name']) - - exec_id = self.get_field_value(execution, 'ID') - - ex_output = self.mistral_admin('execution-get-output', params=exec_id) - - self.assertEqual([], ex_output) - - def test_executions_list_with_task(self): - wrapping_wf = self.workflow_create(self.wf_wrapping_wf) - decoy = self.execution_create(wrapping_wf[-1]['Name']) - wrapping_wf_ex = self.execution_create(wrapping_wf[-1]['Name']) - - wrapping_wf_ex_id = self.get_field_value(wrapping_wf_ex, 'ID') - - self.assertIsNot(wrapping_wf_ex_id, self.get_field_value(decoy, 'ID')) - - tasks = self.mistral_admin('task-list', params=wrapping_wf_ex_id) - - wrapping_task_id = tasks[-1]['ID'] - - wf_execs = self.mistral_cli( - True, - 'execution-list', - params="--task {}".format(wrapping_task_id) - ) - - self.assertEqual(1, len(wf_execs)) - - wf_exec = wf_execs[0] - - self.assertEqual(wrapping_task_id, wf_exec['Task Execution ID']) - - def test_executions_list_with_pagination(self): - wf_ex1 = self.execution_create( - params='{0} -d "a"'.format(self.direct_wf['Name']) - ) - - wf_ex2 = self.execution_create( - params='{0} -d "b"'.format(self.direct_wf['Name']) - ) - - wf_execs = self.mistral_cli(True, 'execution-list') - - self.assertEqual(2, len(wf_execs)) - - wf_execs = self.mistral_cli( - True, - 'execution-list', - params="--limit 1" - ) - - self.assertEqual(1, len(wf_execs)) - - wf_ex1_id = self.get_field_value(wf_ex1, 'ID') - wf_ex2_id = self.get_field_value(wf_ex2, 'ID') - - wf_execs = self.mistral_cli( - True, - 'execution-list', - params="--marker %s" % wf_ex1_id - ) - - self.assertNotIn(wf_ex1_id, [ex['ID'] for ex in wf_execs]) - self.assertIn(wf_ex2_id, [ex['ID'] for ex in wf_execs]) - - wf_execs = self.mistral_cli( - True, - 'execution-list', - params="--sort_keys Description" - ) - - self.assertIn(wf_ex1_id, [ex['ID'] for ex in wf_execs]) - self.assertIn(wf_ex2_id, [ex['ID'] for ex in wf_execs]) - - wf_ex1_index = -1 - wf_ex2_index = -1 - - for idx, ex in enumerate(wf_execs): - if ex['ID'] == wf_ex1_id: - wf_ex1_index = idx - elif ex['ID'] == wf_ex2_id: - wf_ex2_index = idx - - self.assertLess(wf_ex1_index, wf_ex2_index) - - wf_execs = self.mistral_cli( - True, - 'execution-list', - params="--sort_keys Description --sort_dirs=desc" - ) - - self.assertIn(wf_ex1_id, [ex['ID'] for ex in wf_execs]) - self.assertIn(wf_ex2_id, [ex['ID'] for ex in wf_execs]) - - wf_ex1_index = -1 - wf_ex2_index = -1 - - for idx, ex in enumerate(wf_execs): - if ex['ID'] == wf_ex1_id: - wf_ex1_index = idx - elif ex['ID'] == wf_ex2_id: - wf_ex2_index = idx - - self.assertGreater(wf_ex1_index, wf_ex2_index) - - def test_execution_list_with_filter(self): - wf_ex1 = self.execution_create( - params='{0} -d "a"'.format(self.direct_wf['Name']) - ) - - wf_ex1_id = self.get_field_value(wf_ex1, 'ID') - - self.execution_create( - params='{0} -d "b"'.format(self.direct_wf['Name']) - ) - - # Request a list without filters. - wf_execs = self.mistral_cli(True, 'execution-list') - - self.assertTableStruct( - wf_execs, - ['ID', 'Workflow name', 'Workflow ID', 'State', 'Created at', - 'Updated at'] - ) - - self.assertEqual(2, len(wf_execs)) - - # Now let's provide a filter. - wf_execs = self.mistral_cli( - True, - 'execution-list', - params='--filter description=a' - ) - - self.assertTableStruct( - wf_execs, - ['ID', 'Workflow name', 'Workflow ID', 'State', 'Created at', - 'Updated at'] - ) - - self.assertEqual(1, len(wf_execs)) - - self.assertEqual(wf_ex1_id, wf_execs[0]['ID']) - self.assertEqual('a', wf_execs[0]['Description']) - - -class CronTriggerCLITests(base_v2.MistralClientTestBase): - """Test suite checks commands to work with cron-triggers.""" - - @classmethod - def setUpClass(cls): - super(CronTriggerCLITests, cls).setUpClass() - - def setUp(self): - super(CronTriggerCLITests, self).setUp() - - wf = self.workflow_create(self.wf_def) - - self.wf_name = wf[0]['Name'] - - def test_cron_trigger_create_delete(self): - trigger = self.mistral_admin( - 'cron-trigger-create', - params=('trigger %s {} --pattern "5 * * * *" --count 5' - ' --first-time "4242-12-25 13:37"' % self.wf_name) - ) - - self.assertTableStruct(trigger, ['Field', 'Value']) - - tr_name = self.get_field_value(trigger, 'Name') - wf_name = self.get_field_value(trigger, 'Workflow') - created_at = self.get_field_value(trigger, 'Created at') - remain = self.get_field_value(trigger, 'Remaining executions') - next_time = self.get_field_value(trigger, 'Next execution time') - - self.assertEqual('trigger', tr_name) - self.assertEqual(self.wf_name, wf_name) - self.assertIsNotNone(created_at) - self.assertEqual("4242-12-25 13:37:00", next_time) - self.assertEqual("5", remain) - - triggers = self.mistral_admin('cron-trigger-list') - - self.assertIn(tr_name, [tr['Name'] for tr in triggers]) - self.assertIn(wf_name, [tr['Workflow'] for tr in triggers]) - - self.mistral('cron-trigger-delete', params=tr_name) - - triggers = self.mistral_admin('cron-trigger-list') - - self.assertNotIn(tr_name, [tr['Name'] for tr in triggers]) - - def test_two_cron_triggers_for_one_wf(self): - self.cron_trigger_create('trigger1', self.wf_name, '{}', "5 * * * *") - - self.cron_trigger_create('trigger2', self.wf_name, '{}', "15 * * * *") - - triggers = self.mistral_admin('cron-trigger-list') - - self.assertIn("trigger1", [tr['Name'] for tr in triggers]) - self.assertIn("trigger2", [tr['Name'] for tr in triggers]) - - def test_cron_trigger_get(self): - trigger = self.cron_trigger_create( - 'trigger', - self.wf_name, - '{}', - "5 * * * *" - ) - - self.assertTableStruct(trigger, ['Field', 'Value']) - - fetched_tr = self.mistral_admin( - 'cron-trigger-get', - params='trigger' - ) - - self.assertTableStruct(trigger, ['Field', 'Value']) - - tr_name = self.get_field_value(fetched_tr, 'Name') - wf_name = self.get_field_value(fetched_tr, 'Workflow') - created_at = self.get_field_value(fetched_tr, 'Created at') - - self.assertEqual('trigger', tr_name) - self.assertEqual(self.wf_name, wf_name) - self.assertIsNotNone(created_at) - - -class EventTriggerCLITests(base_v2.MistralClientTestBase): - """Test suite checks commands to work with event-triggers.""" - - @classmethod - def setUpClass(cls): - super(EventTriggerCLITests, cls).setUpClass() - - def setUp(self): - super(EventTriggerCLITests, self).setUp() - - wf = self.workflow_create(self.wf_def) - - self.wf_id = wf[0]['ID'] - - def test_event_trigger_create_delete(self): - trigger = self.mistral_admin( - 'event-trigger-create', - params=('trigger %s dummy_exchange dummy_topic event.dummy {}' % - self.wf_id)) - - self.assertTableStruct(trigger, ['Field', 'Value']) - - tr_id = self.get_field_value(trigger, 'ID') - tr_name = self.get_field_value(trigger, 'Name') - wf_id = self.get_field_value(trigger, 'Workflow ID') - created_at = self.get_field_value(trigger, 'Created at') - - self.assertEqual('trigger', tr_name) - self.assertEqual(self.wf_id, wf_id) - self.assertIsNotNone(created_at) - - triggers = self.mistral_admin('event-trigger-list') - - self.assertIn(tr_name, [tr['Name'] for tr in triggers]) - self.assertIn(wf_id, [tr['Workflow ID'] for tr in triggers]) - - self.mistral('event-trigger-delete', params=tr_id) - - triggers = self.mistral_admin('event-trigger-list') - - self.assertNotIn(tr_name, [tr['Name'] for tr in triggers]) - - def test_two_event_triggers_for_one_wf(self): - self.event_trigger_create('trigger1', - self.wf_id, - 'dummy_exchange', - 'dummy_topic', - 'event.dummy', - '{}') - - self.event_trigger_create('trigger2', - self.wf_id, - 'dummy_exchange', - 'dummy_topic', - 'dummy.event', - '{}') - - triggers = self.mistral_admin('event-trigger-list') - - self.assertIn('trigger1', [tr['Name'] for tr in triggers]) - self.assertIn('trigger2', [tr['Name'] for tr in triggers]) - - def test_event_trigger_get(self): - trigger = self.event_trigger_create('trigger', - self.wf_id, - 'dummy_exchange', - 'dummy_topic', - 'event.dummy.other', - '{}') - - self.assertTableStruct(trigger, ['Field', 'Value']) - - ev_tr_id = self.get_field_value(trigger, 'ID') - fetched_tr = self.mistral_admin('event-trigger-get', params=ev_tr_id) - - self.assertTableStruct(trigger, ['Field', 'Value']) - - tr_name = self.get_field_value(fetched_tr, 'Name') - wf_id = self.get_field_value(fetched_tr, 'Workflow ID') - created_at = self.get_field_value(fetched_tr, 'Created at') - - self.assertEqual('trigger', tr_name) - self.assertEqual(self.wf_id, wf_id) - self.assertIsNotNone(created_at) - - -class TaskCLITests(base_v2.MistralClientTestBase): - """Test suite checks commands to work with tasks.""" - - def setUp(self): - super(TaskCLITests, self).setUp() - - wfs = self.workflow_create(self.wf_def) - - self.direct_wf = wfs[0] - self.reverse_wf = wfs[1] - - self.create_file('input', '{\n "farewell": "Bye"\n}\n') - self.create_file('task_name', '{\n "task_name": "goodbye"\n}\n') - - def test_task_get(self): - wf_ex = self.execution_create(self.direct_wf['Name']) - - wf_ex_id = self.get_field_value(wf_ex, 'ID') - - tasks = self.mistral_admin('task-list', params=wf_ex_id) - - created_task_id = tasks[-1]['ID'] - - fetched_task = self.mistral_admin('task-get', params=created_task_id) - fetched_task_id = self.get_field_value(fetched_task, 'ID') - task_execution_id = self.get_field_value(fetched_task, 'Execution ID') - - self.assertEqual(created_task_id, fetched_task_id) - self.assertEqual(wf_ex_id, task_execution_id) - - def test_task_list_with_filter(self): - wf_exec = self.execution_create( - "%s input task_name" % self.reverse_wf['Name'] - ) - - exec_id = self.get_field_value(wf_exec, 'ID') - - self.assertTrue(self.wait_execution_success(exec_id)) - - # Request task executions without filters. - tasks = self.parser.listing(self.mistral('task-list')) - - self.assertTableStruct( - tasks, - ['ID', 'Name', 'Workflow name', 'Execution ID', 'State'] - ) - - self.assertEqual(2, len(tasks)) - - # Now let's provide a filter. - tasks = self.parser.listing( - self.mistral( - 'task-list', - params='--filter name=goodbye' - ) - ) - - self.assertTableStruct( - tasks, - ['ID', 'Name', 'Workflow name', 'Execution ID', 'State'] - ) - - self.assertEqual(1, len(tasks)) - - self.assertEqual('goodbye', tasks[0]['Name']) - - def test_task_list_with_limit(self): - wf_exec = self.execution_create( - "%s input task_name" % self.reverse_wf['Name'] - ) - - exec_id = self.get_field_value(wf_exec, 'ID') - - self.assertTrue(self.wait_execution_success(exec_id)) - - tasks = self.parser.listing(self.mistral('task-list')) - - tasks = self.parser.listing( - self.mistral( - 'task-list', - params='--limit 1' - ) - ) - - self.assertEqual(1, len(tasks)) - - -class ActionCLITests(base_v2.MistralClientTestBase): - """Test suite checks commands to work with actions.""" - - @classmethod - def setUpClass(cls): - super(ActionCLITests, cls).setUpClass() - - def test_action_create_delete(self): - init_acts = self.mistral_admin('action-create', params=self.act_def) - - self.assertTableStruct( - init_acts, - [ - 'Name', 'Is system', 'Input', 'Description', 'Tags', - 'Created at', 'Updated at' - ] - ) - - self.assertIn('greeting', [action['Name'] for action in init_acts]) - self.assertIn('farewell', [action['Name'] for action in init_acts]) - - action_1 = self.get_item_info( - get_from=init_acts, - get_by='Name', - value='greeting' - ) - action_2 = self.get_item_info( - get_from=init_acts, - get_by='Name', - value='farewell' - ) - - self.assertEqual('', action_1['Tags']) - self.assertEqual('', action_2['Tags']) - - self.assertEqual('False', action_1['Is system']) - self.assertEqual('False', action_2['Is system']) - - self.assertEqual('name', action_1['Input']) - self.assertEqual('None', action_2['Input']) - - acts = self.mistral_admin('action-list') - - self.assertIn(action_1['Name'], [action['Name'] for action in acts]) - self.assertIn(action_2['Name'], [action['Name'] for action in acts]) - - self.mistral_admin( - 'action-delete', - params='{0}'.format(action_1['Name']) - ) - self.mistral_admin( - 'action-delete', - params='{0}'.format(action_2['Name']) - ) - - acts = self.mistral_admin('action-list') - - self.assertNotIn(action_1['Name'], [action['Name'] for action in acts]) - self.assertNotIn(action_2['Name'], [action['Name'] for action in acts]) - - def test_action_update(self): - actions = self.action_create(self.act_def) - - created_action = self.get_item_info( - get_from=actions, - get_by='Name', - value='greeting' - ) - - actions = self.mistral_admin('action-update', params=self.act_def) - - updated_action = self.get_item_info( - get_from=actions, - get_by='Name', - value='greeting' - ) - - self.assertEqual( - created_action['Created at'].split(".")[0], - updated_action['Created at'] - ) - self.assertEqual(created_action['Name'], updated_action['Name']) - self.assertEqual( - created_action['Updated at'], - updated_action['Updated at'] - ) - - actions = self.mistral_admin('action-update', params=self.act_tag_def) - - updated_action = self.get_item_info( - get_from=actions, - get_by='Name', - value='greeting' - ) - - self.assertEqual('tag, tag1', updated_action['Tags']) - self.assertEqual( - created_action['Created at'].split(".")[0], - updated_action['Created at'] - ) - self.assertEqual(created_action['Name'], updated_action['Name']) - self.assertNotEqual( - created_action['Updated at'], - updated_action['Updated at'] - ) - - def test_action_update_with_id(self): - acts = self.action_create(self.act_def) - - created_action = self.get_item_info( - get_from=acts, - get_by='Name', - value='greeting' - ) - - action_id = created_action['ID'] - - params = '{0} --id {1}'.format(self.act_tag_def, action_id) - acts = self.mistral_admin('action-update', params=params) - - updated_action = self.get_item_info( - get_from=acts, - get_by='ID', - value=action_id - ) - - self.assertEqual( - created_action['Created at'].split(".")[0], - updated_action['Created at'] - ) - self.assertEqual(created_action['Name'], updated_action['Name']) - self.assertNotEqual( - created_action['Updated at'], - updated_action['Updated at'] - ) - - def test_action_update_truncate_input(self): - input_value = "very_long_input_parameter_name_that_should_be_truncated" - - act_def = """ - version: "2.0" - action1: - input: - - {0} - base: std.noop - """.format(input_value) - - self.create_file('action.yaml', act_def) - self.action_create('action.yaml') - - updated_act = self.mistral_admin('action-update', params='action.yaml') - - updated_act_info = self.get_item_info( - get_from=updated_act, - get_by='Name', - value='action1' - ) - - self.assertEqual(updated_act_info['Input'][:-3], input_value[:25]) - - def test_action_get_definition(self): - self.action_create(self.act_def) - - definition = self.mistral_admin( - 'action-get-definition', - params='greeting' - ) - - self.assertNotIn('404 Not Found', definition) - - def test_action_get_with_id(self): - created = self.action_create(self.act_def) - - action_name = created[0]['Name'] - action_id = created[0]['ID'] - - fetched = self.mistral_admin('action-get', params=action_id) - fetched_action_name = self.get_field_value(fetched, 'Name') - - self.assertEqual(action_name, fetched_action_name) - - def test_action_list_with_filter(self): - actions = self.parser.listing(self.mistral('action-list')) - - self.assertTableStruct( - actions, - ['Name', 'Is system', 'Input', 'Description', - 'Tags', 'Created at', 'Updated at'] - ) - - # NOTE(rakhmerov): This length isn't really a number of actions. - # The problem is that one entity in a table may be on more than - # one lines depending on their data. For example, for the - # workflows that we use in our tests it works fine and parsing - # algorithm is able to parse entities correctly even if they are - # on multiple lines, but for actions it doesn't. So the only thing - # we can do is only check if unfiltered table is bigger than - # filtered. - # We need to think how to improve it. - unfiltered_len = len(actions) - - self.assertGreater(unfiltered_len, 0) - - # Now let's provide a filter to the list command. - actions = self.parser.listing( - self.mistral( - 'action-list', - params='--filter name=in:std.echo,std.noop' - ) - ) - - self.assertTableStruct( - actions, - ['Name', 'Is system', 'Input', 'Description', - 'Tags', 'Created at', 'Updated at'] - ) - - self.assertGreater(unfiltered_len, len(actions)) - - action_names = [a['Name'] for a in actions] - - self.assertIn('std.echo', action_names) - self.assertIn('std.noop', action_names) - self.assertNotIn('std.ssh', action_names) - - -class EnvironmentCLITests(base_v2.MistralClientTestBase): - """Test suite checks commands to work with environments.""" - - def setUp(self): - super(EnvironmentCLITests, self).setUp() - - self.create_file( - 'env.yaml', - 'name: env\n' - 'description: Test env\n' - 'variables:\n' - ' var: "value"' - ) - - def test_environment_create(self): - env = self.mistral_admin('environment-create', params='env.yaml') - - env_name = self.get_field_value(env, 'Name') - env_desc = self.get_field_value(env, 'Description') - - self.assertTableStruct(env, ['Field', 'Value']) - - envs = self.mistral_admin('environment-list') - - self.assertIn(env_name, [en['Name'] for en in envs]) - self.assertIn(env_desc, [en['Description'] for en in envs]) - - self.mistral_admin('environment-delete', params=env_name) - - envs = self.mistral_admin('environment-list') - - self.assertNotIn(env_name, [en['Name'] for en in envs]) - - def test_environment_create_without_description(self): - self.create_file( - 'env_without_des.yaml', - 'name: env\n' - 'variables:\n' - ' var: "value"' - ) - - env = self.mistral_admin( - 'environment-create', - params='env_without_des.yaml' - ) - - env_name = self.get_field_value(env, 'Name') - env_desc = self.get_field_value(env, 'Description') - - self.assertTableStruct(env, ['Field', 'Value']) - - envs = self.mistral_admin('environment-list') - - self.assertIn(env_name, [en['Name'] for en in envs]) - self.assertIn(env_desc, 'None') - - self.mistral_admin('environment-delete', params='env') - - envs = self.mistral_admin('environment-list') - - self.assertNotIn(env_name, [en['Name'] for en in envs]) - - def test_environment_update(self): - env = self.environment_create('env.yaml') - - env_name = self.get_field_value(env, 'Name') - env_desc = self.get_field_value(env, 'Description') - env_created_at = self.get_field_value(env, 'Created at') - env_updated_at = self.get_field_value(env, 'Updated at') - - self.assertIsNotNone(env_created_at) - self.assertEqual('None', env_updated_at) - - self.create_file( - 'env_upd.yaml', - 'name: env\n' - 'description: Updated env\n' - 'variables:\n' - ' var: "value"' - ) - - env = self.mistral_admin('environment-update', params='env_upd.yaml') - - self.assertTableStruct(env, ['Field', 'Value']) - - updated_env_name = self.get_field_value(env, 'Name') - updated_env_desc = self.get_field_value(env, 'Description') - updated_env_created_at = self.get_field_value(env, 'Created at') - updated_env_updated_at = self.get_field_value(env, 'Updated at') - - self.assertEqual(env_name, updated_env_name) - self.assertNotEqual(env_desc, updated_env_desc) - self.assertEqual('Updated env', updated_env_desc) - self.assertEqual(env_created_at.split('.')[0], updated_env_created_at) - self.assertIsNotNone(updated_env_updated_at) - - def test_environment_get(self): - env = self.environment_create('env.yaml') - - env_name = self.get_field_value(env, 'Name') - env_desc = self.get_field_value(env, 'Description') - - env = self.mistral_admin('environment-get', params=env_name) - - fetched_env_name = self.get_field_value(env, 'Name') - fetched_env_desc = self.get_field_value(env, 'Description') - - self.assertTableStruct(env, ['Field', 'Value']) - self.assertEqual(env_name, fetched_env_name) - self.assertEqual(env_desc, fetched_env_desc) - - -class ActionExecutionCLITests(base_v2.MistralClientTestBase): - """Test suite checks commands to work with action executions.""" - - def setUp(self): - super(ActionExecutionCLITests, self).setUp() - - wfs = self.workflow_create(self.wf_def) - - self.direct_wf = wfs[0] - - direct_wf_exec = self.execution_create(self.direct_wf['Name']) - - self.direct_ex_id = self.get_field_value(direct_wf_exec, 'ID') - - def test_act_execution_get(self): - self.wait_execution_success(self.direct_ex_id) - - task = self.mistral_admin('task-list', params=self.direct_ex_id)[0] - - act_ex_from_list = self.mistral_admin( - 'action-execution-list', - params=task['ID'] - )[0] - - act_ex = self.mistral_admin( - 'action-execution-get', - params=act_ex_from_list['ID'] - ) - - wf_name = self.get_field_value(act_ex, 'Workflow name') - status = self.get_field_value(act_ex, 'State') - - self.assertEqual( - act_ex_from_list['ID'], - self.get_field_value(act_ex, 'ID') - ) - self.assertEqual(self.direct_wf['Name'], wf_name) - self.assertEqual('SUCCESS', status) - - def test_act_execution_create_delete(self): - action_ex = self.mistral_admin( - 'run-action', - params="std.echo '{0}' --save-result".format( - '{"output": "Hello!"}') - ) - - action_ex_id = self.get_field_value(action_ex, 'ID') - - self.assertTableStruct(action_ex, ['Field', 'Value']) - - name = self.get_field_value(action_ex, 'Name') - wf_name = self.get_field_value(action_ex, 'Workflow name') - task_name = self.get_field_value(action_ex, 'Task name') - - self.assertEqual('std.echo', name) - self.assertEqual('None', wf_name) - self.assertEqual('None', task_name) - - action_exs = self.mistral_admin('action-execution-list') - - self.assertIn(action_ex_id, [ex['ID'] for ex in action_exs]) - - self.mistral_admin('action-execution-delete', params=action_ex_id) - - action_exs = self.mistral_admin('action-execution-list') - - self.assertNotIn(action_ex_id, [ex['ID'] for ex in action_exs]) - - -class NegativeCLITests(base_v2.MistralClientTestBase): - """This class contains negative tests.""" - - def test_wb_list_extra_param(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workbook-list', - params='param' - ) - - def test_wb_get_unexist_wb(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workbook-get', - params='wb' - ) - - def test_wb_get_without_param(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workbook-get' - ) - - def test_wb_create_same_name(self): - self.workbook_create(self.wb_def) - - self.assertRaises( - exceptions.CommandFailed, - self.workbook_create, - self.wb_def - ) - - def test_wb_create_with_wrong_path_to_definition(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workbook_create', - 'wb' - ) - - def test_wb_delete_unexist_wb(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workbook-delete', - params='wb' - ) - - def test_wb_update_wrong_path_to_def(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workbook-update', - params='wb' - ) - - def test_wb_update_nonexistant_wb(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workbook-update', - params=self.wb_with_tags_def - ) - - def test_wb_create_empty_def(self): - self.create_file('empty') - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workbook-create', - params='empty' - ) - - def test_wb_update_empty_def(self): - self.create_file('empty') - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workbook-update', - params='empty' - ) - - def test_wb_get_definition_unexist_wb(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workbook-get-definition', - params='wb' - ) - - def test_wb_create_invalid_def(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workbook-create', - params=self.wf_def - ) - - def test_wb_update_invalid_def(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workbook-update', - params=self.wf_def - ) - - def test_wb_update_without_def(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workbook-update' - ) - - def test_wf_list_extra_param(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workflow-list', - params='param' - ) - - def test_wf_get_unexist_wf(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workflow-get', - params='wf' - ) - - def test_wf_get_without_param(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workflow-get' - ) - - def test_wf_create_without_definition(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workflow-create', - params='' - ) - - def test_wf_create_with_wrong_path_to_definition(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workflow-create', - params='wf' - ) - - def test_wf_delete_unexist_wf(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workflow-delete', - params='wf' - ) - - def test_wf_update_unexist_wf(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workflow-update', - params='wf' - ) - - def test_wf_get_definition_unexist_wf(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workflow-get-definition', - params='wf' - ) - - def test_wf_get_definition_missed_param(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workflow-get-definition' - ) - - def test_wf_create_invalid_def(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workflow-create', - params=self.wb_def - ) - - def test_wf_update_invalid_def(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workflow-update', - params=self.wb_def - ) - - def test_wf_create_empty_def(self): - self.create_file('empty') - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workflow-create', - params='empty' - ) - - def test_wf_update_empty_def(self): - self.create_file('empty') - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'workflow-update', - params='empty' - ) - - def test_ex_list_extra_param(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'execution-list', - params='param' - ) - - def test_ex_create_unexist_wf(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'execution-create', - params='wf' - ) - - def test_ex_create_unexist_task(self): - wf = self.workflow_create(self.wf_def) - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'execution-create', - params='%s param {}' % wf[0]['Name'] - ) - - def test_ex_create_with_invalid_input(self): - wf = self.workflow_create(self.wf_def) - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'execution-create', - params="%s input" % wf[0]['Name'] - ) - - def test_ex_get_nonexist_execution(self): - wf = self.workflow_create(self.wf_def) - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'execution-get', - params='%s id' % wf[0]['Name'] - ) - - def test_ex_create_without_wf_name(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'execution-create' - ) - - def test_ex_create_reverse_wf_without_start_task(self): - wf = self.workflow_create(self.wf_def) - - self.create_file('input', '{\n "farewell": "Bye"\n}\n') - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'execution-create ', - params=wf[1]['Name'] - ) - - def test_ex_create_missed_input(self): - self.create_file('empty') - - wf = self.workflow_create(self.wf_def) - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'execution-create empty', - params=wf[1]['Name'] - ) - - def test_ex_update_both_state_and_description(self): - wf = self.workflow_create(self.wf_def) - execution = self.execution_create(params=wf[0]['Name']) - - exec_id = self.get_field_value(execution, 'ID') - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'execution-update', - params='%s -s ERROR -d update' % exec_id - ) - - def test_ex_delete_nonexistent_execution(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'execution-delete', - params='1a2b3c' - ) - - def test_tr_create_without_pattern(self): - wf = self.workflow_create(self.wf_def) - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'cron-trigger-create', - params='tr %s {}' % wf[0]['Name'] - ) - - def test_tr_create_invalid_pattern(self): - wf = self.workflow_create(self.wf_def) - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'cron-trigger-create', - params='tr %s {} --pattern "q"' % wf[0]['Name'] - ) - - def test_tr_create_invalid_pattern_value_out_of_range(self): - wf = self.workflow_create(self.wf_def) - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'cron-trigger-create', - params='tr %s {} --pattern "80 * * * *"' % wf[0]['Name'] - ) - - def test_tr_create_nonexistent_wf(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'cron-trigger-create', - params='tr wb.wf1 {} --pattern "* * * * *"' - ) - - def test_tr_delete_nonexistant_tr(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'cron-trigger-delete', - params='tr' - ) - - def test_tr_get_nonexistant_tr(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'cron-trigger-get', - params='tr' - ) - - def test_tr_create_invalid_count(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'cron-trigger-create', - params='tr wb.wf1 {} --pattern "* * * * *" --count q' - ) - - def test_tr_create_negative_count(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'cron-trigger-create', - params='tr wb.wf1 {} --pattern "* * * * *" --count -1') - - def test_tr_create_invalid_first_date(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'cron-trigger-create', - params='tr wb.wf1 {} --pattern "* * * * *" --first-date "q"' - ) - - def test_tr_create_count_only(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'cron-trigger-create', - params='tr wb.wf1 {} --count 42' - ) - - def test_tr_create_date_and_count_without_pattern(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'cron-trigger-create', - params='tr wb.wf1 {} --count 42 --first-time "4242-12-25 13:37"' - ) - - def test_event_tr_create_missing_argument(self): - wf = self.workflow_create(self.wf_def) - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'event-trigger-create', - params='tr %s exchange topic' % wf[0]['ID'] - ) - - def test_event_tr_create_nonexistent_wf(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'event-trigger-create', - params='456 4307362e-4a4a-4021-aa58-0fab23c9c751 ' - 'exchange topic event {} ' - ) - - def test_event_tr_delete_nonexistent_tr(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'event-trigger-delete', - params='789' - ) - - def test_event_tr_get_nonexistent_tr(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'event-trigger-get', - params='789' - ) - - def test_action_get_nonexistent(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral, - 'action-get', - params='nonexist' - ) - - def test_action_double_creation(self): - self.action_create(self.act_def) - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'action-create', - params='{0}'.format(self.act_def) - ) - - def test_action_create_without_def(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'action-create', - params='' - ) - - def test_action_create_invalid_def(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'action-create', - params='{0}'.format(self.wb_def) - ) - - def test_action_delete_nonexistent_act(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'action-delete', - params='nonexist' - ) - - def test_action_delete_standard_action(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'action-delete', - params='heat.events_get' - ) - - def test_action_get_definition_nonexistent_action(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'action-get-definition', - params='nonexist' - ) - - def test_task_get_nonexistent_task(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'task-get', - params='nonexist' - ) - - def test_env_get_without_param(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'environment-get' - ) - - def test_env_get_nonexistent(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'environment-get', - params='nonexist' - ) - - def test_env_create_same_name(self): - self.create_file( - 'env.yaml', - 'name: env\n' - 'description: Test env\n' - 'variables:\n' - ' var: "value"' - ) - - self.environment_create('env.yaml') - - self.assertRaises( - exceptions.CommandFailed, - self.environment_create, - 'env.yaml' - ) - - def test_env_create_empty(self): - self.create_file('env.yaml') - - self.assertRaises( - exceptions.CommandFailed, - self.environment_create, - 'env.yaml' - ) - - def test_env_create_with_wrong_path_to_definition(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'execution_create', - 'env' - ) - - def test_env_delete_unexist_env(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'environment-delete', - params='env' - ) - - def test_env_update_wrong_path_to_def(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'environment-update', - params='env' - ) - - def test_env_update_empty(self): - self.create_file('env.yaml') - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'environment-update', - params='env' - ) - - def test_env_update_nonexistant_env(self): - self.create_file( - 'env.yaml', - 'name: env' - 'variables:\n var: "value"' - ) - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'environment-update', - params='env.yaml' - ) - - def test_env_create_without_name(self): - self.create_file('env.yaml', 'variables:\n var: "value"') - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'environment-create', - params='env.yaml' - ) - - def test_env_create_without_variables(self): - self.create_file('env.yaml', 'name: env') - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'environment-create', - params='env.yaml' - ) - - def test_action_execution_get_without_params(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'action-execution-get' - ) - - def test_action_execution_get_unexistent_obj(self): - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'action-execution-get', - params='123456' - ) - - def test_action_execution_update(self): - wfs = self.workflow_create(self.wf_def) - direct_wf_exec = self.execution_create(wfs[0]['Name']) - - direct_ex_id = self.get_field_value(direct_wf_exec, 'ID') - - self.assertRaises( - exceptions.CommandFailed, - self.mistral_admin, - 'action-execution-update', - params='%s ERROR' % direct_ex_id - ) diff --git a/mistralclient/tests/unit/__init__.py b/mistralclient/tests/unit/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/mistralclient/tests/unit/base.py b/mistralclient/tests/unit/base.py deleted file mode 100644 index 32a0023..0000000 --- a/mistralclient/tests/unit/base.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2013 - Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import mock -from oslotest import base -from requests_mock.contrib import fixture - - -class BaseClientTest(base.BaseTestCase): - _client = None - - def setUp(self): - super(BaseClientTest, self).setUp() - self.requests_mock = self.useFixture(fixture.Fixture()) - - -class BaseCommandTest(base.BaseTestCase): - def setUp(self): - super(BaseCommandTest, self).setUp() - self.app = mock.Mock() - self.client = self.app.client_manager.workflow_engine - - def call(self, command, app_args=[], prog_name=''): - cmd = command(self.app, app_args) - - parsed_args = cmd.get_parser(prog_name).parse_args(app_args) - - return cmd.take_action(parsed_args) diff --git a/mistralclient/tests/unit/base_shell_test.py b/mistralclient/tests/unit/base_shell_test.py deleted file mode 100644 index c09cdb8..0000000 --- a/mistralclient/tests/unit/base_shell_test.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright 2015 Huawei Technologies Co., Ltd. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys - -from oslotest import base -import six - -from mistralclient import shell - - -class BaseShellTests(base.BaseTestCase): - - def shell(self, argstr): - orig = (sys.stdout, sys.stderr) - clean_env = {} - _old_env, os.environ = os.environ, clean_env.copy() - - try: - sys.stdout = six.moves.cStringIO() - sys.stderr = six.moves.cStringIO() - _shell = shell.MistralShell() - _shell.run(argstr.split()) - except SystemExit: - exc_type, exc_value, exc_traceback = sys.exc_info() - self.assertEqual(0, exc_value.code) - finally: - stdout = sys.stdout.getvalue() - stderr = sys.stderr.getvalue() - sys.stdout.close() - sys.stderr.close() - sys.stdout, sys.stderr = orig - os.environ = _old_env - - return stdout, stderr diff --git a/mistralclient/tests/unit/resources/action_v2.yaml b/mistralclient/tests/unit/resources/action_v2.yaml deleted file mode 100644 index 32360f2..0000000 --- a/mistralclient/tests/unit/resources/action_v2.yaml +++ /dev/null @@ -1,10 +0,0 @@ - ---- -version: 2.0 - -my_action: - base: std.echo - base-input: - output: 'Bye!' - output: - info: <% $.output %> diff --git a/mistralclient/tests/unit/resources/ctx.json b/mistralclient/tests/unit/resources/ctx.json deleted file mode 100644 index ae74753..0000000 --- a/mistralclient/tests/unit/resources/ctx.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "context": { - "server": { - "name": "name" - } - } -} diff --git a/mistralclient/tests/unit/resources/env_v2.json b/mistralclient/tests/unit/resources/env_v2.json deleted file mode 100644 index e494543..0000000 --- a/mistralclient/tests/unit/resources/env_v2.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "env1", - "description": "Test Environment #1", - "scope": "private", - "variables": { - "server": "localhost" - } -} \ No newline at end of file diff --git a/mistralclient/tests/unit/resources/env_v2.yaml b/mistralclient/tests/unit/resources/env_v2.yaml deleted file mode 100644 index f13454e..0000000 --- a/mistralclient/tests/unit/resources/env_v2.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- - -"name": "env1" -"description": "Test Environment #1" -"scope": "private" -"variables": - "server": "localhost" \ No newline at end of file diff --git a/mistralclient/tests/unit/resources/wb_v2.yaml b/mistralclient/tests/unit/resources/wb_v2.yaml deleted file mode 100644 index 344f4cf..0000000 --- a/mistralclient/tests/unit/resources/wb_v2.yaml +++ /dev/null @@ -1,21 +0,0 @@ - ---- -version: 2.0 - -name: wb - -workflows: - wf1: - type: direct - input: - - param1 - - param2 - - tasks: - task1: - action: std.http url="localhost:8989" - on-success: - - test_subsequent - - test_subsequent: - action: std.http url="http://some_url" server_id=1 diff --git a/mistralclient/tests/unit/resources/wf_v2.yaml b/mistralclient/tests/unit/resources/wf_v2.yaml deleted file mode 100644 index c9e30e9..0000000 --- a/mistralclient/tests/unit/resources/wf_v2.yaml +++ /dev/null @@ -1,10 +0,0 @@ - ---- -version: 2.0 - -my_wf: - type: direct - - tasks: - task1: - action: std.echo output="hello, world" diff --git a/mistralclient/tests/unit/test_client.py b/mistralclient/tests/unit/test_client.py deleted file mode 100644 index 7348e88..0000000 --- a/mistralclient/tests/unit/test_client.py +++ /dev/null @@ -1,276 +0,0 @@ -# Copyright 2015 - Huawei Technologies Co., Ltd. -# Copyright 2016 - StackStorm, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import json -import os -import tempfile - -import mock -from oslo_utils import uuidutils -from oslotest import base -import osprofiler.profiler - -from mistralclient.api import client - -AUTH_HTTP_URL_v3 = 'http://localhost:35357/v3' -AUTH_HTTP_URL_v2_0 = 'http://localhost:35357/v2.0' -AUTH_HTTPS_URL = AUTH_HTTP_URL_v3.replace('http', 'https') -MISTRAL_HTTP_URL = 'http://localhost:8989/v2' -MISTRAL_HTTPS_URL = MISTRAL_HTTP_URL.replace('http', 'https') -PROFILER_HMAC_KEY = 'SECRET_HMAC_KEY' - - -class BaseClientTests(base.BaseTestCase): - - @staticmethod - def setup_keystone_mock(keystone_client_mock): - keystone_client_instance = keystone_client_mock.return_value - keystone_client_instance.auth_token = uuidutils.generate_uuid() - keystone_client_instance.project_id = uuidutils.generate_uuid() - keystone_client_instance.user_id = uuidutils.generate_uuid() - keystone_client_instance.auth_ref = str(json.dumps({})) - return keystone_client_instance - - @mock.patch('keystoneclient.client.Client') - def test_mistral_url_from_catalog_v2(self, keystone_client_mock): - keystone_client_instance = self.setup_keystone_mock( - keystone_client_mock - ) - - url_for = mock.Mock(return_value='http://mistral_host:8989/v2') - keystone_client_instance.service_catalog.url_for = url_for - - mistralclient = client.client( - username='mistral', - project_name='mistral', - auth_url=AUTH_HTTP_URL_v2_0, - service_type='workflowv2' - ) - - self.assertEqual( - 'http://mistral_host:8989/v2', - mistralclient.actions.http_client.base_url - ) - - @mock.patch('keystoneclient.client.Client') - def test_mistral_url_from_catalog(self, keystone_client_mock): - keystone_client_instance = self.setup_keystone_mock( - keystone_client_mock - ) - - url_for = mock.Mock(return_value='http://mistral_host:8989/v2') - - keystone_client_instance.service_catalog.url_for = url_for - - mistralclient = client.client( - username='mistral', - project_name='mistral', - auth_url=AUTH_HTTP_URL_v3, - service_type='workflowv2' - ) - - self.assertEqual( - 'http://mistral_host:8989/v2', - mistralclient.actions.http_client.base_url - ) - - @mock.patch('keystoneclient.client.Client') - @mock.patch('mistralclient.api.httpclient.HTTPClient') - def test_mistral_url_default(self, http_client_mock, keystone_client_mock): - keystone_client_instance = self.setup_keystone_mock( - keystone_client_mock - ) - - url_for = mock.Mock(side_effect=Exception) - keystone_client_instance.service_catalog.url_for = url_for - - client.client( - username='mistral', - project_name='mistral', - auth_url=AUTH_HTTP_URL_v3 - ) - - self.assertTrue(http_client_mock.called) - mistral_url_for_http = http_client_mock.call_args[0][0] - kwargs = http_client_mock.call_args[1] - self.assertEqual(MISTRAL_HTTP_URL, mistral_url_for_http) - self.assertEqual( - keystone_client_instance.auth_token, kwargs['auth_token'] - ) - self.assertEqual( - keystone_client_instance.project_id, kwargs['project_id'] - ) - self.assertEqual( - keystone_client_instance.user_id, kwargs['user_id'] - ) - - @mock.patch('keystoneclient.client.Client') - @mock.patch('mistralclient.api.httpclient.HTTPClient') - def test_target_parameters_processed( - self, - http_client_mock, - keystone_client_mock - ): - keystone_client_instance = self.setup_keystone_mock( - keystone_client_mock - ) - - url_for = mock.Mock(return_value='http://mistral_host:8989/v2') - keystone_client_instance.service_catalog.url_for = url_for - - client.client( - target_username='tmistral', - target_project_name='tmistralp', - target_auth_url=AUTH_HTTP_URL_v3, - target_region_name='tregion' - ) - - self.assertTrue(http_client_mock.called) - mistral_url_for_http = http_client_mock.call_args[0][0] - kwargs = http_client_mock.call_args[1] - self.assertEqual(MISTRAL_HTTP_URL, mistral_url_for_http) - - expected_values = { - 'target_project_id': keystone_client_instance.project_id, - 'target_auth_token': keystone_client_instance.auth_token, - 'target_user_id': keystone_client_instance.user_id, - 'target_auth_url': AUTH_HTTP_URL_v3, - 'target_project_name': 'tmistralp', - 'target_username': 'tmistral', - 'target_region_name': 'tregion', - 'target_service_catalog': '"{}"' - } - - for key in expected_values: - self.assertEqual(expected_values[key], kwargs[key]) - - @mock.patch('keystoneclient.client.Client') - @mock.patch('mistralclient.api.httpclient.HTTPClient') - def test_mistral_url_https_insecure(self, http_client_mock, - keystone_client_mock): - keystone_client_instance = self.setup_keystone_mock( # noqa - keystone_client_mock - ) - - expected_args = ( - MISTRAL_HTTPS_URL, - ) - - client.client( - mistral_url=MISTRAL_HTTPS_URL, - username='mistral', - project_name='mistral', - auth_url=AUTH_HTTP_URL_v3, - cacert=None, - insecure=True - ) - - self.assertTrue(http_client_mock.called) - self.assertEqual(http_client_mock.call_args[0], expected_args) - self.assertEqual(http_client_mock.call_args[1]['insecure'], True) - - @mock.patch('keystoneclient.client.Client') - @mock.patch('mistralclient.api.httpclient.HTTPClient') - def test_mistral_url_https_secure(self, http_client_mock, - keystone_client_mock): - fd, cert_path = tempfile.mkstemp(suffix='.pem') - - keystone_client_instance = self.setup_keystone_mock( # noqa - keystone_client_mock - ) - - expected_args = ( - MISTRAL_HTTPS_URL, - ) - - try: - client.client( - mistral_url=MISTRAL_HTTPS_URL, - username='mistral', - project_name='mistral', - auth_url=AUTH_HTTP_URL_v3, - cacert=cert_path, - insecure=False - ) - finally: - os.close(fd) - os.unlink(cert_path) - - self.assertTrue(http_client_mock.called) - self.assertEqual(http_client_mock.call_args[0], expected_args) - self.assertEqual(http_client_mock.call_args[1]['cacert'], cert_path) - - @mock.patch('keystoneclient.client.Client') - def test_mistral_url_https_bad_cacert(self, keystone_client_mock): - keystone_client_instance = self.setup_keystone_mock( # noqa - keystone_client_mock - ) - - self.assertRaises( - ValueError, - client.client, - mistral_url=MISTRAL_HTTPS_URL, - username='mistral', - project_name='mistral', - auth_url=AUTH_HTTP_URL_v3, - cacert='/path/to/foobar', - insecure=False - ) - - @mock.patch('logging.Logger.warning') - @mock.patch('keystoneclient.client.Client') - def test_mistral_url_https_bad_insecure(self, keystone_client_mock, - log_warning_mock): - fd, path = tempfile.mkstemp(suffix='.pem') - - keystone_client_instance = self.setup_keystone_mock( - keystone_client_mock - ) - - try: - client.client( - mistral_url=MISTRAL_HTTPS_URL, - user_id=keystone_client_instance.user_id, - project_id=keystone_client_instance.project_id, - auth_url=AUTH_HTTP_URL_v3, - cacert=path, - insecure=True - ) - finally: - os.close(fd) - os.unlink(path) - - self.assertTrue(log_warning_mock.called) - - @mock.patch('keystoneclient.client.Client') - @mock.patch('mistralclient.api.httpclient.HTTPClient') - def test_mistral_profile_enabled(self, http_client_mock, - keystone_client_mock): - keystone_client_instance = self.setup_keystone_mock( # noqa - keystone_client_mock - ) - - client.client( - username='mistral', - project_name='mistral', - auth_url=AUTH_HTTP_URL_v3, - profile=PROFILER_HMAC_KEY - ) - - self.assertTrue(http_client_mock.called) - - profiler = osprofiler.profiler.get() - - self.assertEqual(profiler.hmac_key, PROFILER_HMAC_KEY) diff --git a/mistralclient/tests/unit/test_httpclient.py b/mistralclient/tests/unit/test_httpclient.py deleted file mode 100644 index dba2768..0000000 --- a/mistralclient/tests/unit/test_httpclient.py +++ /dev/null @@ -1,276 +0,0 @@ -# Copyright 2016 - StackStorm, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import base64 -import copy - -import mock -from six.moves.urllib import parse as urlparse - -from oslo_utils import uuidutils -from osprofiler import _utils as osprofiler_utils -import osprofiler.profiler - -from mistralclient.api import httpclient -from mistralclient.tests.unit import base - -API_BASE_URL = 'http://localhost:8989/v2' -API_URL = '/executions' - -EXPECTED_URL = API_BASE_URL + API_URL - -AUTH_TOKEN = uuidutils.generate_uuid() -PROJECT_ID = uuidutils.generate_uuid() -USER_ID = uuidutils.generate_uuid() -REGION_NAME = 'fake_region' -PROFILER_HMAC_KEY = 'SECRET_HMAC_KEY' -PROFILER_TRACE_ID = uuidutils.generate_uuid() - -EXPECTED_AUTH_HEADERS = { - 'x-auth-token': AUTH_TOKEN, - 'X-Project-Id': PROJECT_ID, - 'X-User-Id': USER_ID, - 'X-Region-Name': REGION_NAME -} - -EXPECTED_REQ_OPTIONS = { - 'headers': EXPECTED_AUTH_HEADERS -} - -EXPECTED_BODY = { - 'k1': 'abc', - 'k2': 123, - 'k3': True -} - - -class HTTPClientTest(base.BaseClientTest): - - def setUp(self): - super(HTTPClientTest, self).setUp() - osprofiler.profiler.init(None) - self.client = httpclient.HTTPClient( - API_BASE_URL, - auth_token=AUTH_TOKEN, - project_id=PROJECT_ID, - user_id=USER_ID, - region_name=REGION_NAME - ) - - def assertExpectedAuthHeaders(self): - headers = self.requests_mock.last_request.headers - - self.assertEqual(AUTH_TOKEN, headers['X-Auth-Token']) - self.assertEqual(PROJECT_ID, headers['X-Project-Id']) - self.assertEqual(USER_ID, headers['X-User-Id']) - - return headers - - def assertExpectedBody(self): - text = self.requests_mock.last_request.text - form = urlparse.parse_qs(text, strict_parsing=True) - - self.assertEqual(len(EXPECTED_BODY), len(form)) - - for k, v in EXPECTED_BODY.items(): - self.assertEqual([str(v)], form[k]) - - return form - - def test_get_request_options(self): - m = self.requests_mock.get(EXPECTED_URL, text='text') - - self.client.get(API_URL) - - self.assertTrue(m.called_once) - self.assertExpectedAuthHeaders() - - @mock.patch.object( - osprofiler.profiler._Profiler, - 'get_base_id', - mock.MagicMock(return_value=PROFILER_TRACE_ID) - ) - @mock.patch.object( - osprofiler.profiler._Profiler, - 'get_id', - mock.MagicMock(return_value=PROFILER_TRACE_ID) - ) - def test_get_request_options_with_profile_enabled(self): - m = self.requests_mock.get(EXPECTED_URL, text='text') - osprofiler.profiler.init(PROFILER_HMAC_KEY) - - data = {'base_id': PROFILER_TRACE_ID, 'parent_id': PROFILER_TRACE_ID} - signed_data = osprofiler_utils.signed_pack(data, PROFILER_HMAC_KEY) - - headers = { - 'X-Trace-Info': signed_data[0], - 'X-Trace-HMAC': signed_data[1] - } - - self.client.get(API_URL) - - self.assertTrue(m.called_once) - headers = self.assertExpectedAuthHeaders() - self.assertEqual(signed_data[0], headers['X-Trace-Info']) - self.assertEqual(signed_data[1], headers['X-Trace-HMAC']) - - def test_get_request_options_with_headers_for_get(self): - m = self.requests_mock.get(EXPECTED_URL, text='text') - target_auth_url = uuidutils.generate_uuid() - target_auth_token = uuidutils.generate_uuid() - target_user_id = 'target_user' - target_project_id = 'target_project' - target_service_catalog = 'this should be there' - target_insecure = 'target insecure' - target_region = 'target region name' - target_user_domain_name = 'target user domain name' - target_project_domain_name = 'target project domain name' - - target_client = httpclient.HTTPClient( - API_BASE_URL, - auth_token=AUTH_TOKEN, - project_id=PROJECT_ID, - user_id=USER_ID, - region_name=REGION_NAME, - target_auth_url=target_auth_url, - target_auth_token=target_auth_token, - target_project_id=target_project_id, - target_user_id=target_user_id, - target_service_catalog=target_service_catalog, - target_region_name=target_region, - target_user_domain_name=target_user_domain_name, - target_project_domain_name=target_project_domain_name, - target_insecure=target_insecure - ) - - target_client.get(API_URL) - - self.assertTrue(m.called_once) - headers = self.assertExpectedAuthHeaders() - self.assertEqual(target_auth_url, headers['X-Target-Auth-Uri']) - self.assertEqual(target_auth_token, headers['X-Target-Auth-Token']) - self.assertEqual(target_user_id, headers['X-Target-User-Id']) - self.assertEqual(target_project_id, headers['X-Target-Project-Id']) - self.assertEqual(target_insecure, headers['X-Target-Insecure']) - self.assertEqual(target_region, headers['X-Target-Region-Name']) - self.assertEqual(target_user_domain_name, - headers['X-Target-User-Domain-Name']) - self.assertEqual(target_project_domain_name, - headers['X-Target-Project-Domain-Name']) - - catalog = base64.b64encode(target_service_catalog.encode('utf-8')) - self.assertEqual(catalog, headers['X-Target-Service-Catalog']) - - def test_get_request_options_with_headers_for_post(self): - m = self.requests_mock.post(EXPECTED_URL, text='text') - headers = {'foo': 'bar'} - - self.client.post(API_URL, EXPECTED_BODY, headers=headers) - - self.assertTrue(m.called_once) - headers = self.assertExpectedAuthHeaders() - self.assertEqual('application/json', headers['Content-Type']) - self.assertEqual('bar', headers['foo']) - self.assertExpectedBody() - - def test_get_request_options_with_headers_for_put(self): - m = self.requests_mock.put(EXPECTED_URL, text='text') - headers = {'foo': 'bar'} - - self.client.put(API_URL, EXPECTED_BODY, headers=headers) - - self.assertTrue(m.called_once) - headers = self.assertExpectedAuthHeaders() - self.assertEqual('application/json', headers['Content-Type']) - self.assertEqual('bar', headers['foo']) - self.assertExpectedBody() - - def test_get_request_options_with_headers_for_delete(self): - m = self.requests_mock.delete(EXPECTED_URL, text='text') - headers = {'foo': 'bar'} - - self.client.delete(API_URL, headers=headers) - - self.assertTrue(m.called_once) - headers = self.assertExpectedAuthHeaders() - self.assertEqual('bar', headers['foo']) - - @mock.patch.object( - httpclient.HTTPClient, - '_get_request_options', - mock.MagicMock(return_value=copy.deepcopy(EXPECTED_REQ_OPTIONS)) - ) - def test_http_get(self): - m = self.requests_mock.get(EXPECTED_URL, text='text') - self.client.get(API_URL) - - httpclient.HTTPClient._get_request_options.assert_called_with( - 'get', - None - ) - self.assertTrue(m.called_once) - self.assertExpectedAuthHeaders() - - @mock.patch.object( - httpclient.HTTPClient, - '_get_request_options', - mock.MagicMock(return_value=copy.deepcopy(EXPECTED_REQ_OPTIONS)) - ) - def test_http_post(self): - m = self.requests_mock.post(EXPECTED_URL, status_code=201, text='text') - self.client.post(API_URL, EXPECTED_BODY) - - httpclient.HTTPClient._get_request_options.assert_called_with( - 'post', - None - ) - - self.assertTrue(m.called_once) - self.assertExpectedAuthHeaders() - self.assertExpectedBody() - - @mock.patch.object( - httpclient.HTTPClient, - '_get_request_options', - mock.MagicMock(return_value=copy.deepcopy(EXPECTED_REQ_OPTIONS)) - ) - def test_http_put(self): - m = self.requests_mock.put(EXPECTED_URL, json={}) - self.client.put(API_URL, EXPECTED_BODY) - - httpclient.HTTPClient._get_request_options.assert_called_with( - 'put', - None - ) - - self.assertTrue(m.called_once) - self.assertExpectedAuthHeaders() - self.assertExpectedBody() - - @mock.patch.object( - httpclient.HTTPClient, - '_get_request_options', - mock.MagicMock(return_value=copy.deepcopy(EXPECTED_REQ_OPTIONS)) - ) - def test_http_delete(self): - m = self.requests_mock.delete(EXPECTED_URL, text='text') - self.client.delete(API_URL) - - httpclient.HTTPClient._get_request_options.assert_called_with( - 'delete', - None - ) - - self.assertTrue(m.called_once) - self.assertExpectedAuthHeaders() diff --git a/mistralclient/tests/unit/test_shell.py b/mistralclient/tests/unit/test_shell.py deleted file mode 100644 index 24e7a36..0000000 --- a/mistralclient/tests/unit/test_shell.py +++ /dev/null @@ -1,136 +0,0 @@ -# Copyright 2015 Huawei Technologies Co., Ltd. -# -# 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 - -import mistralclient.tests.unit.base_shell_test as base - - -class TestShell(base.BaseShellTests): - - @mock.patch('mistralclient.api.client.client') - def test_command_no_mistral_url(self, client_mock): - self.shell( - 'workbook-list' - ) - self.assertTrue(client_mock.called) - params = client_mock.call_args - self.assertEqual('', params[1]['mistral_url']) - - @mock.patch('mistralclient.api.client.client') - def test_command_with_mistral_url(self, client_mock): - self.shell( - '--os-mistral-url=http://localhost:8989/v2 workbook-list' - ) - self.assertTrue(client_mock.called) - params = client_mock.call_args - self.assertEqual('http://localhost:8989/v2', - params[1]['mistral_url']) - - @mock.patch('mistralclient.api.client.determine_client_version') - def test_mistral_version(self, client_mock): - self.shell( - '--os-mistral-version=v1 workbook-list' - ) - self.assertTrue(client_mock.called) - mistral_version = client_mock.call_args - self.assertEqual('v1', mistral_version[0][0]) - - @mock.patch('mistralclient.api.client.determine_client_version') - def test_no_mistral_version(self, client_mock): - self.shell('workbook-list') - self.assertTrue(client_mock.called) - mistral_version = client_mock.call_args - self.assertEqual('v2', mistral_version[0][0]) - - @mock.patch('mistralclient.api.client.client') - def test_service_type(self, client_mock): - self.shell('--os-mistral-service-type=test workbook-list') - self.assertTrue(client_mock.called) - parmters = client_mock.call_args - self.assertEqual('test', parmters[1]['service_type']) - - @mock.patch('mistralclient.api.client.client') - def test_no_service_type(self, client_mock): - self.shell('workbook-list') - self.assertTrue(client_mock.called) - params = client_mock.call_args - self.assertEqual('workflowv2', params[1]['service_type']) - - @mock.patch('mistralclient.api.client.client') - def test_endpoint_type(self, client_mock): - self.shell('--os-mistral-endpoint-type=adminURL workbook-list') - self.assertTrue(client_mock.called) - params = client_mock.call_args - self.assertEqual('adminURL', params[1]['endpoint_type']) - - @mock.patch('mistralclient.api.client.client') - def test_no_endpoint_type(self, client_mock): - self.shell('workbook-list') - self.assertTrue(client_mock.called) - params = client_mock.call_args - self.assertEqual('publicURL', params[1]['endpoint_type']) - - @mock.patch('mistralclient.api.client.client') - def test_auth_url(self, client_mock): - self.shell( - '--os-auth-url=https://127.0.0.1:35357/v3 ' - '--os-username=admin ' - '--os-password=1234 ' - 'workbook-list' - ) - self.assertTrue(client_mock.called) - params = client_mock.call_args - self.assertEqual('https://127.0.0.1:35357/v3', params[1]['auth_url']) - - @mock.patch('mistralclient.api.client.client') - def test_no_auth_url(self, client_mock): - self.shell('workbook-list') - self.assertTrue(client_mock.called) - params = client_mock.call_args - self.assertEqual('', params[1]['auth_url']) - - @mock.patch('mistralclient.api.client.client') - def test_default_auth_url_with_os_password(self, client_mock): - self.shell('--os-username=admin --os-password=1234 workbook-list') - self.assertTrue(client_mock.called) - params = client_mock.call_args - self.assertEqual('http://localhost:35357/v3', params[1]['auth_url']) - - @mock.patch('mistralclient.api.client.client') - def test_default_auth_url_with_os_auth_token(self, client_mock): - self.shell( - '--os-auth-token=abcd1234 ' - 'workbook-list' - ) - self.assertTrue(client_mock.called) - params = client_mock.call_args - self.assertEqual('http://localhost:35357/v3', params[1]['auth_url']) - - @mock.patch('mistralclient.api.client.client') - def test_profile(self, client_mock): - self.shell('--profile=SECRET_HMAC_KEY workbook-list') - self.assertTrue(client_mock.called) - params = client_mock.call_args - self.assertEqual('SECRET_HMAC_KEY', params[1]['profile']) - - @mock.patch('mistralclient.api.client.client') - def test_region_name(self, client_mock): - self.shell('--os-region-name=RegionOne workbook-list') - - self.assertTrue(client_mock.called) - - params = client_mock.call_args - - self.assertEqual('RegionOne', params[1]['region_name']) diff --git a/mistralclient/tests/unit/test_utils.py b/mistralclient/tests/unit/test_utils.py deleted file mode 100644 index 51343d6..0000000 --- a/mistralclient/tests/unit/test_utils.py +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright 2015 - StackStorm, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import json -import os.path -import tempfile -import yaml - -from mistralclient import utils -from oslotest import base - - -ENV_DICT = {'k1': 'abc', 'k2': 123, 'k3': True} -ENV_STR = json.dumps(ENV_DICT) -ENV_YAML = yaml.safe_dump(ENV_DICT, default_flow_style=False) - - -class UtilityTest(base.BaseTestCase): - - def test_load_empty(self): - self.assertDictEqual(dict(), utils.load_content(None)) - self.assertDictEqual(dict(), utils.load_content('')) - self.assertDictEqual(dict(), utils.load_content('{}')) - self.assertListEqual(list(), utils.load_content('[]')) - - def test_load_json_content(self): - self.assertDictEqual(ENV_DICT, utils.load_content(ENV_STR)) - - def test_load_json_file(self): - with tempfile.NamedTemporaryFile() as f: - f.write(ENV_STR.encode('utf-8')) - f.flush() - file_path = os.path.abspath(f.name) - - self.assertDictEqual(ENV_DICT, utils.load_file(file_path)) - - def test_load_yaml_content(self): - self.assertDictEqual(ENV_DICT, utils.load_content(ENV_YAML)) - - def test_load_yaml_file(self): - with tempfile.NamedTemporaryFile() as f: - f.write(ENV_YAML.encode('utf-8')) - f.flush() - file_path = os.path.abspath(f.name) - - self.assertDictEqual(ENV_DICT, utils.load_file(file_path)) - - def test_load_json(self): - with tempfile.NamedTemporaryFile() as f: - f.write(ENV_STR.encode('utf-8')) - f.flush() - self.assertDictEqual(ENV_DICT, utils.load_json(f.name)) - - self.assertDictEqual(ENV_DICT, utils.load_json(ENV_STR)) diff --git a/mistralclient/tests/unit/v2/__init__.py b/mistralclient/tests/unit/v2/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/mistralclient/tests/unit/v2/base.py b/mistralclient/tests/unit/v2/base.py deleted file mode 100644 index ef4f060..0000000 --- a/mistralclient/tests/unit/v2/base.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# Copyright 2015 - StackStorm, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from mistralclient.api.v2 import client -from mistralclient.tests.unit import base - - -class BaseClientV2Test(base.BaseClientTest): - - TEST_URL = 'http://mistral.example.com' - - def setUp(self): - super(BaseClientV2Test, self).setUp() - - self._client = client.Client(project_name="test", - mistral_url=self.TEST_URL) - self.workbooks = self._client.workbooks - self.executions = self._client.executions - self.tasks = self._client.tasks - self.workflows = self._client.workflows - self.environments = self._client.environments - self.action_executions = self._client.action_executions - self.actions = self._client.actions - self.services = self._client.services - self.members = self._client.members diff --git a/mistralclient/tests/unit/v2/test_action_executions.py b/mistralclient/tests/unit/v2/test_action_executions.py deleted file mode 100644 index f47a988..0000000 --- a/mistralclient/tests/unit/v2/test_action_executions.py +++ /dev/null @@ -1,114 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from mistralclient.api.v2 import action_executions -from mistralclient.tests.unit.v2 import base - -# TODO(everyone): later we need additional tests verifying all the errors etc. - -ACTION_EXEC = { - 'id': "1", - 'name': 'my_action_execution', - 'workflow_name': 'my_wf', - 'state': 'RUNNING', -} - - -URL_TEMPLATE = '/action_executions' -URL_TEMPLATE_ID = '/action_executions/%s' - - -class TestActionExecutions(base.BaseClientV2Test): - def test_create(self): - self.requests_mock.post(self.TEST_URL + URL_TEMPLATE, - json=ACTION_EXEC, - status_code=201) - - body = { - 'name': ACTION_EXEC['name'] - } - - action_execution = self.action_executions.create( - 'my_action_execution', - {} - ) - - self.assertIsNotNone(action_execution) - self.assertEqual(action_executions.ActionExecution( - self.action_executions, ACTION_EXEC - ).to_dict(), action_execution.to_dict()) - - self.assertEqual(body, self.requests_mock.last_request.json()) - - def test_update(self): - url = self.TEST_URL + URL_TEMPLATE_ID % ACTION_EXEC['id'] - self.requests_mock.put(url, json=ACTION_EXEC) - - body = { - 'state': ACTION_EXEC['state'] - } - - action_execution = self.action_executions.update( - ACTION_EXEC['id'], - ACTION_EXEC['state'] - ) - - self.assertIsNotNone(action_execution) - - expected = action_executions.ActionExecution( - self.action_executions, - ACTION_EXEC - ).to_dict() - - self.assertEqual( - expected, - action_execution.to_dict() - ) - - self.assertEqual(body, self.requests_mock.last_request.json()) - - def test_list(self): - self.requests_mock.get(self.TEST_URL + URL_TEMPLATE, - json={'action_executions': [ACTION_EXEC]}) - - action_execution_list = self.action_executions.list() - - self.assertEqual(1, len(action_execution_list)) - action_execution = action_execution_list[0] - - expected = action_executions.ActionExecution( - self.action_executions, - ACTION_EXEC - ).to_dict() - - self.assertEqual(expected, action_execution.to_dict()) - - def test_get(self): - url = self.TEST_URL + URL_TEMPLATE_ID % ACTION_EXEC['id'] - self.requests_mock.get(url, json=ACTION_EXEC) - - action_execution = self.action_executions.get(ACTION_EXEC['id']) - - expected = action_executions.ActionExecution( - self.action_executions, - ACTION_EXEC - ).to_dict() - - self.assertEqual(expected, action_execution.to_dict()) - - def test_delete(self): - url = self.TEST_URL + URL_TEMPLATE_ID % ACTION_EXEC['id'] - self.requests_mock.delete(url, status_code=204) - - self.action_executions.delete(ACTION_EXEC['id']) diff --git a/mistralclient/tests/unit/v2/test_actions.py b/mistralclient/tests/unit/v2/test_actions.py deleted file mode 100644 index 8eb4cb3..0000000 --- a/mistralclient/tests/unit/v2/test_actions.py +++ /dev/null @@ -1,269 +0,0 @@ -# Copyright 2015 Huawei Technologies Co., Ltd. -# -# 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 pkg_resources as pkg -from six.moves.urllib import parse -from six.moves.urllib import request - -from mistralclient.api import base as api_base -from mistralclient.api.v2 import actions -from mistralclient.tests.unit.v2 import base - - -ACTION_DEF = """ ---- -version: 2.0 - -my_action: - base: std.echo - base-input: - output: 'Bye!' - output: - info: <% $.output %> -""" - -INVALID_ACTION_DEF = """ ---- -version: 2.0 - -my_action: - base: std.echo - unexpected-property: 'this should fail' - base-input: - output: 'Bye!' - output: - info: <% $.output %> -""" - -ACTION = { - 'id': '123', - 'name': 'my_action', - 'input': '', - 'definition': ACTION_DEF -} - -URL_TEMPLATE = '/actions' -URL_TEMPLATE_SCOPE = '/actions?scope=private' -URL_TEMPLATE_NAME = '/actions/%s' -URL_TEMPLATE_VALIDATE = '/actions/validate' - - -class TestActionsV2(base.BaseClientV2Test): - def test_create(self): - self.requests_mock.post(self.TEST_URL + URL_TEMPLATE, - json={'actions': [ACTION]}, - status_code=201) - - actions = self.actions.create(ACTION_DEF) - - self.assertIsNotNone(actions) - self.assertEqual(ACTION_DEF, actions[0].definition) - - last_request = self.requests_mock.last_request - self.assertEqual('text/plain', last_request.headers['content-type']) - self.assertEqual(ACTION_DEF, last_request.text) - - def test_create_with_file(self): - self.requests_mock.post(self.TEST_URL + URL_TEMPLATE, - json={'actions': [ACTION]}, - status_code=201) - - # The contents of action_v2.yaml must be identical to ACTION_DEF - path = pkg.resource_filename( - 'mistralclient', - 'tests/unit/resources/action_v2.yaml' - ) - - actions = self.actions.create(path) - - self.assertIsNotNone(actions) - self.assertEqual(ACTION_DEF, actions[0].definition) - - last_request = self.requests_mock.last_request - self.assertEqual('text/plain', last_request.headers['content-type']) - self.assertEqual(ACTION_DEF, last_request.text) - - def test_update_with_id(self): - self.requests_mock.put(self.TEST_URL + URL_TEMPLATE_NAME % 123, - json={'actions': [ACTION]}) - - actions = self.actions.update(ACTION_DEF, id=123) - - self.assertIsNotNone(actions) - self.assertEqual(ACTION_DEF, actions[0].definition) - - last_request = self.requests_mock.last_request - - self.assertEqual('scope=private', last_request.query) - self.assertEqual('text/plain', last_request.headers['content-type']) - self.assertEqual(ACTION_DEF, last_request.text) - - def test_update(self): - self.requests_mock.put(self.TEST_URL + URL_TEMPLATE, - json={'actions': [ACTION]}) - - actions = self.actions.update(ACTION_DEF) - - self.assertIsNotNone(actions) - self.assertEqual(ACTION_DEF, actions[0].definition) - - last_request = self.requests_mock.last_request - - self.assertEqual('scope=private', last_request.query) - self.assertEqual('text/plain', last_request.headers['content-type']) - self.assertEqual(ACTION_DEF, last_request.text) - - def test_update_with_file_uri(self): - self.requests_mock.put(self.TEST_URL + URL_TEMPLATE, - json={'actions': [ACTION]}) - - # The contents of action_v2.yaml must be identical to ACTION_DEF - path = pkg.resource_filename( - 'mistralclient', - 'tests/unit/resources/action_v2.yaml' - ) - - # Convert the file path to file URI - uri = parse.urljoin('file:', request.pathname2url(path)) - - actions = self.actions.update(uri) - - self.assertIsNotNone(actions) - self.assertEqual(ACTION_DEF, actions[0].definition) - - last_request = self.requests_mock.last_request - self.assertEqual('scope=private', last_request.query) - self.assertEqual('text/plain', last_request.headers['content-type']) - self.assertEqual(ACTION_DEF, last_request.text) - - def test_list(self): - self.requests_mock.get(self.TEST_URL + URL_TEMPLATE, - json={'actions': [ACTION]}) - - action_list = self.actions.list() - - self.assertEqual(1, len(action_list)) - - action = action_list[0] - - self.assertEqual( - actions.Action(self.actions, ACTION).to_dict(), - action.to_dict() - ) - - def test_list_with_pagination(self): - self.requests_mock.get(self.TEST_URL + URL_TEMPLATE, - json={'actions': [ACTION], - 'next': '/actions?fake'}) - - action_list = self.actions.list( - limit=1, - sort_keys='created_at', - sort_dirs='asc' - ) - - self.assertEqual(1, len(action_list)) - - last_request = self.requests_mock.last_request - - # The url param order is unpredictable. - self.assertEqual(['1'], last_request.qs['limit']) - self.assertEqual(['created_at'], last_request.qs['sort_keys']) - self.assertEqual(['asc'], last_request.qs['sort_dirs']) - - def test_get(self): - self.requests_mock.get(self.TEST_URL + URL_TEMPLATE_NAME % 'action', - json=ACTION) - - action = self.actions.get('action') - - self.assertIsNotNone(action) - self.assertEqual( - actions.Action(self.actions, ACTION).to_dict(), - action.to_dict() - ) - - def test_delete(self): - url = self.TEST_URL + URL_TEMPLATE_NAME % 'action' - m = self.requests_mock.delete(url, status_code=204) - - self.actions.delete('action') - - self.assertEqual(1, m.call_count) - - def test_validate(self): - self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_VALIDATE, - json={'valid': True}) - - result = self.actions.validate(ACTION_DEF) - - self.assertIsNotNone(result) - self.assertIn('valid', result) - self.assertTrue(result['valid']) - - last_request = self.requests_mock.last_request - self.assertEqual(ACTION_DEF, last_request.text) - self.assertEqual('text/plain', last_request.headers['content-type']) - - def test_validate_with_file(self): - self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_VALIDATE, - json={'valid': True}) - - # The contents of action_v2.yaml must be identical to ACTION_DEF - path = pkg.resource_filename( - 'mistralclient', - 'tests/unit/resources/action_v2.yaml' - ) - - result = self.actions.validate(path) - - self.assertIsNotNone(result) - self.assertIn('valid', result) - self.assertTrue(result['valid']) - - last_request = self.requests_mock.last_request - self.assertEqual(ACTION_DEF, last_request.text) - self.assertEqual('text/plain', last_request.headers['content-type']) - - def test_validate_failed(self): - self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_VALIDATE, - json={"valid": False, - "error": "mocked error message"}) - - result = self.actions.validate(INVALID_ACTION_DEF) - - self.assertIsNotNone(result) - self.assertIn('valid', result) - self.assertFalse(result['valid']) - self.assertIn('error', result) - self.assertIn("mocked error message", result['error']) - - last_request = self.requests_mock.last_request - self.assertEqual('text/plain', last_request.headers['content-type']) - - def test_validate_api_failed(self): - self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_VALIDATE, - status_code=500, - json={}) - - self.assertRaises( - api_base.APIException, - self.actions.validate, - ACTION_DEF - ) - - last_request = self.requests_mock.last_request - - self.assertEqual('text/plain', last_request.headers['content-type']) - self.assertEqual(ACTION_DEF, last_request.text) diff --git a/mistralclient/tests/unit/v2/test_cli_action_execs.py b/mistralclient/tests/unit/v2/test_cli_action_execs.py deleted file mode 100644 index 49db348..0000000 --- a/mistralclient/tests/unit/v2/test_cli_action_execs.py +++ /dev/null @@ -1,228 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# Copyright 2016 - Brocade Communications Systems, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import copy -import json -import sys - -from six import StringIO - -import mock - -from mistralclient.api.v2 import action_executions as action_ex -from mistralclient.commands.v2 import action_executions as action_ex_cmd -from mistralclient.tests.unit import base - -ACTION_EX_DICT = { - 'id': '123', - 'name': 'some', - 'workflow_name': 'thing', - 'task_name': 'task1', - 'task_execution_id': "1-2-3-4", - 'state': 'RUNNING', - 'state_info': 'RUNNING somehow.', - 'accepted': True, - 'created_at': '1', - 'updated_at': '1', -} - -ACTION_EX_RESULT = {"test": "is", "passed": "successfully"} -ACTION_EX_INPUT = {"param1": "val1", "param2": 2} - -ACTION_EX_WITH_OUTPUT_DICT = ACTION_EX_DICT.copy() -ACTION_EX_WITH_OUTPUT_DICT.update({'output': json.dumps(ACTION_EX_RESULT)}) - -ACTION_EX_WITH_INPUT_DICT = ACTION_EX_DICT.copy() -ACTION_EX_WITH_INPUT_DICT.update({'input': json.dumps(ACTION_EX_INPUT)}) - -ACTION_EX = action_ex.ActionExecution(mock, ACTION_EX_DICT) -ACTION_EX_WITH_OUTPUT = action_ex.ActionExecution( - mock, - ACTION_EX_WITH_OUTPUT_DICT -) -ACTION_EX_WITH_INPUT = action_ex.ActionExecution( - mock, - ACTION_EX_WITH_INPUT_DICT -) - - -class TestCLIActionExecutions(base.BaseCommandTest): - def test_create(self): - (self.client.action_executions.create. - return_value) = ACTION_EX_WITH_OUTPUT - - self.call( - action_ex_cmd.Create, - app_args=['some', '{"output": "Hello!"}'] - ) - - self.assertDictEqual( - ACTION_EX_RESULT, - json.loads(self.app.stdout.write.call_args[0][0]) - ) - - def test_create_save_result(self): - (self.client.action_executions.create. - return_value) = ACTION_EX_WITH_OUTPUT - - result = self.call( - action_ex_cmd.Create, - app_args=[ - 'some', '{"output": "Hello!"}', '--save-result' - ] - ) - - self.assertEqual( - ('123', 'some', 'thing', 'task1', '1-2-3-4', 'RUNNING', - 'RUNNING somehow.', True, '1', '1'), - result[1] - ) - - def test_create_run_sync(self): - (self.client.action_executions.create. - return_value) = ACTION_EX_WITH_OUTPUT - - self.call( - action_ex_cmd.Create, - app_args=[ - 'some', '{"output": "Hello!"}', '--run-sync' - ] - ) - - self.assertDictEqual( - ACTION_EX_RESULT, - json.loads(self.app.stdout.write.call_args[0][0]) - ) - - def test_create_run_sync_and_save_result(self): - (self.client.action_executions.create. - return_value) = ACTION_EX_WITH_OUTPUT - - self.call( - action_ex_cmd.Create, - app_args=[ - 'some', '{"output": "Hello!"}', '--save-result', '--run-sync' - ] - ) - - self.assertDictEqual( - ACTION_EX_RESULT, - json.loads(self.app.stdout.write.call_args[0][0]) - ) - - def test_update(self): - states = ['IDLE', 'RUNNING', 'SUCCESS', 'ERROR', 'CANCELLED'] - - for state in states: - action_ex_dict = copy.deepcopy(ACTION_EX_DICT) - action_ex_dict['state'] = state - action_ex_dict['state_info'] = 'testing update' - action_ex_obj = action_ex.ActionExecution(mock, action_ex_dict) - self.client.action_executions.update.return_value = action_ex_obj - - result = self.call( - action_ex_cmd.Update, - app_args=['id', '--state', state] - ) - - expected_result = ( - action_ex_dict['id'], - action_ex_dict['name'], - action_ex_dict['workflow_name'], - action_ex_dict['task_name'], - action_ex_dict['task_execution_id'], - action_ex_dict['state'], - action_ex_dict['state_info'], - action_ex_dict['accepted'], - action_ex_dict['created_at'], - action_ex_dict['updated_at'] - ) - - self.assertEqual(expected_result, result[1]) - - def test_update_invalid_state(self): - states = ['PAUSED', 'WAITING', 'DELAYED'] - - # Redirect the stderr so it doesn't show during tox - _stderr = sys.stderr - sys.stderr = StringIO() - - for state in states: - self.assertRaises( - SystemExit, - self.call, - action_ex_cmd.Update, - app_args=['id', '--state', state] - ) - - # Stop the redirection - print(sys.stderr.getvalue()) - sys.stderr = _stderr - - def test_list(self): - self.client.action_executions.list.return_value = [ACTION_EX] - - result = self.call(action_ex_cmd.List) - - self.assertEqual( - [('123', 'some', 'thing', 'task1', '1-2-3-4', 'RUNNING', True, - '1', '1')], - result[1] - ) - - def test_get(self): - self.client.action_executions.get.return_value = ACTION_EX - - result = self.call(action_ex_cmd.Get, app_args=['id']) - - self.assertEqual( - ('123', 'some', 'thing', 'task1', '1-2-3-4', 'RUNNING', - 'RUNNING somehow.', True, '1', '1'), result[1] - ) - - def test_get_output(self): - self.client.action_executions.get.return_value = ACTION_EX_WITH_OUTPUT - - self.call(action_ex_cmd.GetOutput, app_args=['id']) - - self.assertDictEqual( - ACTION_EX_RESULT, - json.loads(self.app.stdout.write.call_args[0][0]) - ) - - def test_get_input(self): - self.client.action_executions.get.return_value = ACTION_EX_WITH_INPUT - - self.call(action_ex_cmd.GetInput, app_args=['id']) - - self.assertDictEqual( - ACTION_EX_INPUT, - json.loads(self.app.stdout.write.call_args[0][0]) - ) - - def test_delete(self): - self.call(action_ex_cmd.Delete, app_args=['id']) - - self.client.action_executions.delete.assert_called_once_with('id') - - def test_delete_with_multi_names(self): - self.call(action_ex_cmd.Delete, app_args=['id1', 'id2']) - - self.assertEqual(2, self.client.action_executions.delete.call_count) - self.assertEqual( - [mock.call('id1'), mock.call('id2')], - self.client.action_executions.delete.call_args_list - ) diff --git a/mistralclient/tests/unit/v2/test_cli_actions.py b/mistralclient/tests/unit/v2/test_cli_actions.py deleted file mode 100644 index b2e4872..0000000 --- a/mistralclient/tests/unit/v2/test_cli_actions.py +++ /dev/null @@ -1,199 +0,0 @@ -# Copyright 2014 Mirantis, Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import mock -import six - -from mistralclient.api.v2 import actions -from mistralclient.commands.v2 import actions as action_cmd -from mistralclient.commands.v2 import base as cmd_base -from mistralclient.tests.unit import base - - -ACTION_DICT = { - 'id': '1234-4567-7894-7895', - 'name': 'a', - 'is_system': True, - 'input': "param1", - 'description': 'My cool action', - 'tags': ['test'], - 'created_at': '1', - 'updated_at': '1' -} - -ACTION_DEF = """ ---- -version: '2.0' - -base: std.echo -base-parameters: - output: "<% $.str1 %><% $.str2 %>" -output: "<% $ %><% $ %>" -""" - -ACTION_WITH_DEF_DICT = ACTION_DICT.copy() -ACTION_WITH_DEF_DICT.update({'definition': ACTION_DEF}) -ACTION = actions.Action(mock, ACTION_DICT) -ACTION_WITH_DEF = actions.Action(mock, ACTION_WITH_DEF_DICT) - - -class TestCLIActionsV2(base.BaseCommandTest): - @mock.patch('argparse.open', create=True) - def test_create(self, mock_open): - self.client.actions.create.return_value = [ACTION] - - result = self.call(action_cmd.Create, app_args=['1.txt']) - - self.assertEqual( - [('1234-4567-7894-7895', 'a', True, "param1", - 'My cool action', 'test', '1', '1')], - result[1] - ) - - @mock.patch('argparse.open', create=True) - def test_create_public(self, mock_open): - self.client.actions.create.return_value = [ACTION] - - result = self.call( - action_cmd.Create, - app_args=['1.txt', '--public'] - ) - - self.assertEqual( - [('1234-4567-7894-7895', 'a', True, "param1", - 'My cool action', 'test', '1', '1')], - result[1] - ) - - self.assertEqual( - 'public', - self.client.actions.create.call_args[1]['scope'] - ) - - @mock.patch('argparse.open', create=True) - def test_create_long_input(self, mock_open): - action_long_input_dict = ACTION_DICT.copy() - long_input = ', '.join( - ['var%s' % i for i in six.moves.xrange(10)] - ) - action_long_input_dict['input'] = long_input - workflow_long_input = actions.Action( - mock.Mock(), - action_long_input_dict - ) - self.client.actions.create.return_value = [workflow_long_input] - - result = self.call(action_cmd.Create, app_args=['1.txt']) - - self.assertEqual( - [('1234-4567-7894-7895', 'a', True, cmd_base.cut(long_input), - 'My cool action', 'test', '1', '1')], - result[1] - ) - - @mock.patch('argparse.open', create=True) - def test_update(self, mock_open): - self.client.actions.update.return_value = [ACTION] - - result = self.call(action_cmd.Update, app_args=['my_action.yaml']) - - self.assertEqual( - [('1234-4567-7894-7895', 'a', True, "param1", - 'My cool action', 'test', '1', '1')], - result[1] - ) - - @mock.patch('argparse.open', create=True) - def test_update_public(self, mock_open): - self.client.actions.update.return_value = [ACTION] - - result = self.call( - action_cmd.Update, - app_args=['my_action.yaml', '--public'] - ) - - self.assertEqual( - [('1234-4567-7894-7895', 'a', True, "param1", - 'My cool action', 'test', '1', '1')], - result[1] - ) - - self.assertEqual( - 'public', - self.client.actions.update.call_args[1]['scope'] - ) - - def test_list(self): - self.client.actions.list.return_value = [ACTION] - - result = self.call(action_cmd.List) - - self.assertEqual( - [('1234-4567-7894-7895', 'a', True, "param1", - 'My cool action', 'test', '1', '1')], - result[1] - ) - - def test_get(self): - self.client.actions.get.return_value = ACTION - - result = self.call(action_cmd.Get, app_args=['name']) - - self.assertEqual( - ('1234-4567-7894-7895', 'a', True, "param1", - 'My cool action', 'test', '1', '1'), - result[1] - ) - - def test_delete(self): - self.call(action_cmd.Delete, app_args=['name']) - - self.client.actions.delete.assert_called_once_with('name') - - def test_delete_with_multi_names(self): - self.call(action_cmd.Delete, app_args=['name1', 'name2']) - - self.assertEqual(2, self.client.actions.delete.call_count) - self.assertEqual( - [mock.call('name1'), mock.call('name2')], - self.client.actions.delete.call_args_list - ) - - def test_get_definition(self): - self.client.actions.get.return_value = ACTION_WITH_DEF - - self.call(action_cmd.GetDefinition, app_args=['name']) - - self.app.stdout.write.assert_called_with(ACTION_DEF) - - @mock.patch('argparse.open', create=True) - def test_validate(self, mock_open): - self.client.actions.validate.return_value = {'valid': True} - - result = self.call(action_cmd.Validate, app_args=['action.yaml']) - - self.assertEqual((True, None), result[1]) - - @mock.patch('argparse.open', create=True) - def test_validate_failed(self, mock_open): - self.client.actions.validate.return_value = { - 'valid': False, - 'error': 'Invalid DSL...' - } - - result = self.call(action_cmd.Validate, app_args=['action.yaml']) - - self.assertEqual((False, 'Invalid DSL...'), result[1]) diff --git a/mistralclient/tests/unit/v2/test_cli_bash_completion.py b/mistralclient/tests/unit/v2/test_cli_bash_completion.py deleted file mode 100644 index c80aea5..0000000 --- a/mistralclient/tests/unit/v2/test_cli_bash_completion.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2015 Huawei Technologies Co., Ltd. -# -# 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 mistralclient.tests.unit.base_shell_test as base - - -class TestCLIBashCompletionV2(base.BaseShellTests): - def test_bash_completion(self): - bash_completion, stderr = self.shell('bash-completion') - - self.assertIn('bash-completion', bash_completion) - self.assertFalse(stderr) diff --git a/mistralclient/tests/unit/v2/test_cli_cron_triggers.py b/mistralclient/tests/unit/v2/test_cli_cron_triggers.py deleted file mode 100644 index 7c15243..0000000 --- a/mistralclient/tests/unit/v2/test_cli_cron_triggers.py +++ /dev/null @@ -1,178 +0,0 @@ -# Copyright 2014 Mirantis, Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import mock - -from mistralclient.api.v2 import cron_triggers -from mistralclient.commands.v2 import cron_triggers as cron_triggers_cmd -from mistralclient.tests.unit import base - - -TRIGGER_DICT = { - 'name': 'my_trigger', - 'workflow_name': 'flow1', - 'workflow_input': {}, - 'workflow_params': {}, - 'pattern': '* * * * *', - 'next_execution_time': '4242-12-20 13:37', - 'remaining_executions': 5, - 'created_at': '1', - 'updated_at': '1' -} - -TRIGGER = cron_triggers.CronTrigger(mock, TRIGGER_DICT) - - -class TestCLITriggersV2(base.BaseCommandTest): - @mock.patch('mistralclient.commands.v2.cron_triggers.Create.' - '_convert_time_string_to_utc') - @mock.patch('argparse.open', create=True) - def test_create(self, mock_open, mock_convert): - self.client.cron_triggers.create.return_value = TRIGGER - mock_open.return_value = mock.MagicMock(spec=open) - - result = self.call( - cron_triggers_cmd.Create, - app_args=['my_trigger', 'flow1', '--pattern', '* * * * *', - '--params', '{}', '--count', '5', '--first-time', - '4242-12-20 13:37', '--utc'] - ) - - mock_convert.assert_not_called() - self.assertEqual( - ( - 'my_trigger', 'flow1', {}, '* * * * *', - '4242-12-20 13:37', 5, '1', '1' - ), - result[1] - ) - - @mock.patch('mistralclient.commands.v2.cron_triggers.Create.' - '_convert_time_string_to_utc') - @mock.patch('argparse.open', create=True) - def test_create_no_utc(self, mock_open, mock_convert): - self.client.cron_triggers.create.return_value = TRIGGER - mock_open.return_value = mock.MagicMock(spec=open) - mock_convert.return_value = '4242-12-20 18:37' - - result = self.call( - cron_triggers_cmd.Create, - app_args=['my_trigger', 'flow1', '--pattern', '* * * * *', - '--params', '{}', '--count', '5', '--first-time', - '4242-12-20 13:37'] - ) - - mock_convert.assert_called_once_with('4242-12-20 13:37') - self.client.cron_triggers.create.assert_called_once_with( - 'my_trigger', 'flow1', {}, {}, '* * * * *', '4242-12-20 18:37', 5) - self.assertEqual( - ( - 'my_trigger', 'flow1', {}, '* * * * *', - '4242-12-20 13:37', 5, '1', '1' - ), - result[1] - ) - - @mock.patch('mistralclient.commands.v2.cron_triggers.time') - def test_convert_time_string_to_utc_from_utc(self, mock_time): - cmd = cron_triggers_cmd.Create(self.app, None) - - mock_time.daylight = 0 - mock_time.altzone = 0 - mock_time.timezone = 0 - mock_localtime = mock.Mock() - mock_localtime.tm_isdst = 0 - mock_time.localtime.return_value = mock_localtime - - utc_value = cmd._convert_time_string_to_utc('4242-12-20 13:37') - - expected_time = '4242-12-20 13:37' - - self.assertEqual(expected_time, utc_value) - - @mock.patch('mistralclient.commands.v2.cron_triggers.time') - def test_convert_time_string_to_utc_from_dst(self, mock_time): - cmd = cron_triggers_cmd.Create(self.app, None) - - mock_time.daylight = 1 - mock_time.altzone = (4 * 60 * 60) - mock_time.timezone = (5 * 60 * 60) - mock_localtime = mock.Mock() - mock_localtime.tm_isdst = 1 - mock_time.localtime.return_value = mock_localtime - - utc_value = cmd._convert_time_string_to_utc('4242-12-20 13:37') - - expected_time = '4242-12-20 17:37' - - self.assertEqual(expected_time, utc_value) - - @mock.patch('mistralclient.commands.v2.cron_triggers.time') - def test_convert_time_string_to_utc_no_dst(self, mock_time): - cmd = cron_triggers_cmd.Create(self.app, None) - - mock_time.daylight = 1 - mock_time.altzone = (4 * 60 * 60) - mock_time.timezone = (5 * 60 * 60) - mock_localtime = mock.Mock() - mock_localtime.tm_isdst = 0 - mock_time.localtime.return_value = mock_localtime - - utc_value = cmd._convert_time_string_to_utc('4242-12-20 13:37') - - expected_time = '4242-12-20 18:37' - - self.assertEqual(expected_time, utc_value) - - def test_list(self): - self.client.cron_triggers.list.return_value = [TRIGGER] - - result = self.call(cron_triggers_cmd.List) - - self.assertEqual( - [( - 'my_trigger', 'flow1', {}, '* * * * *', - '4242-12-20 13:37', 5, '1', '1' - )], - result[1] - ) - - def test_get(self): - self.client.cron_triggers.get.return_value = TRIGGER - - result = self.call(cron_triggers_cmd.Get, app_args=['name']) - - self.assertEqual( - ( - 'my_trigger', 'flow1', {}, '* * * * *', - '4242-12-20 13:37', 5, '1', '1' - ), - result[1] - ) - - def test_delete(self): - self.call(cron_triggers_cmd.Delete, app_args=['name']) - - self.client.cron_triggers.delete.assert_called_once_with('name') - - def test_delete_with_multi_names(self): - self.call(cron_triggers_cmd.Delete, app_args=['name1', 'name2']) - - self.assertEqual(2, self.client.cron_triggers.delete.call_count) - self.assertEqual( - [mock.call('name1'), mock.call('name2')], - self.client.cron_triggers.delete.call_args_list - ) diff --git a/mistralclient/tests/unit/v2/test_cli_environments.py b/mistralclient/tests/unit/v2/test_cli_environments.py deleted file mode 100644 index 4c24618..0000000 --- a/mistralclient/tests/unit/v2/test_cli_environments.py +++ /dev/null @@ -1,125 +0,0 @@ -# Copyright 2015 - StackStorm, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import copy -import datetime -import json -import os -import tempfile - -import mock -import yaml - -from mistralclient.api.v2 import environments -from mistralclient.commands.v2 import environments as environment_cmd -from mistralclient.tests.unit import base - - -ENVIRONMENT_DICT = { - 'name': 'env1', - 'description': 'Test Environment #1', - 'scope': 'private', - 'variables': { - 'server': 'localhost', - 'database': 'test', - 'timeout': 600, - 'verbose': True - }, - 'created_at': str(datetime.datetime.utcnow()), - 'updated_at': str(datetime.datetime.utcnow()) -} - -ENVIRONMENT = environments.Environment(mock, ENVIRONMENT_DICT) -EXPECTED_RESULT = (ENVIRONMENT_DICT['name'], - ENVIRONMENT_DICT['description'], - json.dumps(ENVIRONMENT_DICT['variables'], indent=4), - ENVIRONMENT_DICT['scope'], - ENVIRONMENT_DICT['created_at'], - ENVIRONMENT_DICT['updated_at']) - - -class TestCLIEnvironmentsV2(base.BaseCommandTest): - - def _test_create(self, content): - self.client.environments.create.return_value = ENVIRONMENT - - with tempfile.NamedTemporaryFile() as f: - f.write(content.encode('utf-8')) - f.flush() - file_path = os.path.abspath(f.name) - result = self.call(environment_cmd.Create, app_args=[file_path]) - self.assertEqual(EXPECTED_RESULT, result[1]) - - def test_create_from_json(self): - self._test_create(json.dumps(ENVIRONMENT_DICT, indent=4)) - - def test_create_from_yaml(self): - yml = yaml.dump(ENVIRONMENT_DICT, default_flow_style=False) - self._test_create(yml) - - def _test_update(self, content): - self.client.environments.update.return_value = ENVIRONMENT - - with tempfile.NamedTemporaryFile() as f: - f.write(content.encode('utf-8')) - f.flush() - file_path = os.path.abspath(f.name) - result = self.call(environment_cmd.Update, app_args=[file_path]) - self.assertEqual(EXPECTED_RESULT, result[1]) - - def test_update_from_json(self): - env = copy.deepcopy(ENVIRONMENT_DICT) - del env['created_at'] - del env['updated_at'] - self._test_update(json.dumps(env, indent=4)) - - def test_update_from_yaml(self): - env = copy.deepcopy(ENVIRONMENT_DICT) - del env['created_at'] - del env['updated_at'] - yml = yaml.dump(env, default_flow_style=False) - self._test_update(yml) - - def test_list(self): - self.client.environments.list.return_value = [ENVIRONMENT] - expected = (ENVIRONMENT_DICT['name'], - ENVIRONMENT_DICT['description'], - ENVIRONMENT_DICT['scope'], - ENVIRONMENT_DICT['created_at'], - ENVIRONMENT_DICT['updated_at']) - - result = self.call(environment_cmd.List) - - self.assertListEqual([expected], result[1]) - - def test_get(self): - self.client.environments.get.return_value = ENVIRONMENT - - result = self.call(environment_cmd.Get, app_args=['name']) - - self.assertEqual(EXPECTED_RESULT, result[1]) - - def test_delete(self): - self.call(environment_cmd.Delete, app_args=['name']) - - self.client.environments.delete.assert_called_once_with('name') - - def test_delete_with_multi_names(self): - self.call(environment_cmd.Delete, app_args=['name1', 'name2']) - - self.assertEqual(2, self.client.environments.delete.call_count) - self.assertEqual( - [mock.call('name1'), mock.call('name2')], - self.client.environments.delete.call_args_list - ) diff --git a/mistralclient/tests/unit/v2/test_cli_event_triggers.py b/mistralclient/tests/unit/v2/test_cli_event_triggers.py deleted file mode 100644 index f670c35..0000000 --- a/mistralclient/tests/unit/v2/test_cli_event_triggers.py +++ /dev/null @@ -1,100 +0,0 @@ -# Copyright 2014 Mirantis, Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import mock - -from mistralclient.api.v2 import event_triggers -from mistralclient.commands.v2 import event_triggers as event_triggers_cmd -from mistralclient.tests.unit import base - - -TRIGGER_DICT = { - 'id': '456', - 'name': 'my_trigger', - 'workflow_id': '123e4567-e89b-12d3-a456-426655440000', - 'workflow_input': {}, - 'workflow_params': {}, - 'exchange': 'dummy_exchange', - 'topic': 'dummy_topic', - 'event': 'event.dummy', - 'created_at': '1', - 'updated_at': '1' -} - -TRIGGER = event_triggers.EventTrigger(mock, TRIGGER_DICT) - - -class TestCLITriggersV2(base.BaseCommandTest): - - @mock.patch('argparse.open', create=True) - def test_create(self, mock_open): - self.client.event_triggers.create.return_value = TRIGGER - mock_open.return_value = mock.MagicMock(spec=open) - - result = self.call( - event_triggers_cmd.Create, - app_args=['my_trigger', '123e4567-e89b-12d3-a456-426655440000', - 'dummy_exchange', 'dummy_topic', 'event.dummy', - '--params', '{}'] - ) - - self.assertEqual( - ( - '456', 'my_trigger', '123e4567-e89b-12d3-a456-426655440000', - {}, 'dummy_exchange', 'dummy_topic', 'event.dummy', '1', '1' - ), - result[1] - ) - - def test_list(self): - self.client.event_triggers.list.return_value = [TRIGGER] - - result = self.call(event_triggers_cmd.List) - - self.assertEqual( - [( - '456', 'my_trigger', '123e4567-e89b-12d3-a456-426655440000', - {}, 'dummy_exchange', 'dummy_topic', 'event.dummy', '1', '1' - )], - result[1] - ) - - def test_get(self): - self.client.event_triggers.get.return_value = TRIGGER - - result = self.call(event_triggers_cmd.Get, app_args=['id']) - - self.assertEqual( - ( - '456', 'my_trigger', '123e4567-e89b-12d3-a456-426655440000', - {}, 'dummy_exchange', 'dummy_topic', 'event.dummy', '1', '1' - ), - result[1] - ) - - def test_delete(self): - self.call(event_triggers_cmd.Delete, app_args=['id']) - - self.client.event_triggers.delete.assert_called_once_with('id') - - def test_delete_with_multi_names(self): - self.call(event_triggers_cmd.Delete, app_args=['id1', 'id2']) - - self.assertEqual(2, self.client.event_triggers.delete.call_count) - self.assertEqual( - [mock.call('id1'), mock.call('id2')], - self.client.event_triggers.delete.call_args_list - ) diff --git a/mistralclient/tests/unit/v2/test_cli_executions.py b/mistralclient/tests/unit/v2/test_cli_executions.py deleted file mode 100644 index f65368d..0000000 --- a/mistralclient/tests/unit/v2/test_cli_executions.py +++ /dev/null @@ -1,289 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# Copyright 2015 - StackStorm, Inc. -# Copyright 2016 - Brocade Communications Systems, Inc. -# -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import mock -import pkg_resources as pkg -import six -import sys - -from mistralclient.api.v2 import executions -from mistralclient.commands.v2 import executions as execution_cmd -from mistralclient.tests.unit import base - -EXEC = executions.Execution( - mock, - { - 'id': '123', - 'workflow_id': '123e4567-e89b-12d3-a456-426655440000', - 'workflow_name': 'some', - 'description': '', - 'state': 'RUNNING', - 'state_info': None, - 'created_at': '1', - 'updated_at': '1', - 'task_execution_id': None - } -) - -SUB_WF_EXEC = executions.Execution( - mock, - { - 'id': '456', - 'workflow_id': '123e4567-e89b-12d3-a456-426655440000', - 'workflow_name': 'some_sub_wf', - 'description': '', - 'state': 'RUNNING', - 'state_info': None, - 'created_at': '1', - 'updated_at': '1', - 'task_execution_id': 'abc' - } -) - -EX_RESULT = ( - '123', - '123e4567-e89b-12d3-a456-426655440000', - 'some', - '', - '', - 'RUNNING', - None, - '1', - '1' -) - -SUB_WF_EX_RESULT = ( - '456', - '123e4567-e89b-12d3-a456-426655440000', - 'some_sub_wf', - '', - 'abc', - 'RUNNING', - None, - '1', - '1' -) - - -class TestCLIExecutionsV2(base.BaseCommandTest): - - stdout = six.moves.StringIO() - stderr = six.moves.StringIO() - - def setUp(self): - super(TestCLIExecutionsV2, self).setUp() - - # Redirect stdout and stderr so it doesn't pollute the test result. - sys.stdout = self.stdout - sys.stderr = self.stderr - - def tearDown(self): - super(TestCLIExecutionsV2, self).tearDown() - - # Reset to original stdout and stderr. - sys.stdout = sys.__stdout__ - sys.stderr = sys.__stderr__ - - def test_create_wf_input_string(self): - self.client.executions.create.return_value = EXEC - - result = self.call( - execution_cmd.Create, - app_args=['id', '{ "context": true }'] - ) - - self.assertEqual( - EX_RESULT, - result[1] - ) - - def test_create_wf_input_file(self): - self.client.executions.create.return_value = EXEC - - path = pkg.resource_filename( - 'mistralclient', - 'tests/unit/resources/ctx.json' - ) - - result = self.call( - execution_cmd.Create, - app_args=['id', path] - ) - - self.assertEqual( - EX_RESULT, - result[1] - ) - - def test_create_with_description(self): - self.client.executions.create.return_value = EXEC - - result = self.call( - execution_cmd.Create, - app_args=['id', '{ "context": true }', '-d', ''] - ) - - self.assertEqual( - EX_RESULT, - result[1] - ) - - def test_update_state(self): - states = ['RUNNING', 'SUCCESS', 'PAUSED', 'ERROR', 'CANCELLED'] - - for state in states: - self.client.executions.update.return_value = executions.Execution( - mock, - { - 'id': '123', - 'workflow_id': '123e4567-e89b-12d3-a456-426655440000', - 'workflow_name': 'some', - 'description': '', - 'state': state, - 'state_info': None, - 'created_at': '1', - 'updated_at': '1', - 'task_execution_id': None - } - ) - - ex_result = list(EX_RESULT) - ex_result[5] = state - ex_result = tuple(ex_result) - - result = self.call( - execution_cmd.Update, - app_args=['id', '-s', state] - ) - - self.assertEqual( - ex_result, - result[1] - ) - - def test_update_invalid_state(self): - states = ['IDLE', 'WAITING', 'DELAYED'] - - for state in states: - self.assertRaises( - SystemExit, - self.call, - execution_cmd.Update, - app_args=['id', '-s', state] - ) - - def test_resume_update_env(self): - self.client.executions.update.return_value = EXEC - - result = self.call( - execution_cmd.Update, - app_args=['id', '-s', 'RUNNING', '--env', '{"k1": "foobar"}'] - ) - - self.assertEqual( - EX_RESULT, - result[1] - ) - - def test_update_description(self): - self.client.executions.update.return_value = EXEC - - result = self.call( - execution_cmd.Update, - app_args=['id', '-d', 'foobar'] - ) - - self.assertEqual( - EX_RESULT, - result[1] - ) - - def test_list(self): - self.client.executions.list.return_value = [EXEC, SUB_WF_EXEC] - - result = self.call(execution_cmd.List) - - self.assertEqual( - [EX_RESULT, SUB_WF_EX_RESULT], - result[1] - ) - - def test_list_with_pagination(self): - self.client.executions.list.return_value = [EXEC] - - self.call(execution_cmd.List) - self.client.executions.list.assert_called_once_with( - limit=100, - marker='', - sort_dirs='asc', - sort_keys='created_at', - task=None - ) - - self.call( - execution_cmd.List, - app_args=[ - '--limit', '5', - '--sort_dirs', 'id, Workflow', - '--sort_keys', 'desc', - '--marker', 'abc' - ] - ) - - self.client.executions.list.assert_called_with( - limit=5, - marker='abc', - sort_dirs='id, Workflow', - sort_keys='desc', - task=None - ) - - def test_get(self): - self.client.executions.get.return_value = EXEC - - result = self.call(execution_cmd.Get, app_args=['id']) - - self.assertEqual( - EX_RESULT, - result[1] - ) - - def test_get_sub_wf_ex(self): - self.client.executions.get.return_value = SUB_WF_EXEC - - result = self.call(execution_cmd.Get, app_args=['id']) - - self.assertEqual( - SUB_WF_EX_RESULT, - result[1] - ) - - def test_delete(self): - self.call(execution_cmd.Delete, app_args=['id']) - - self.client.executions.delete.assert_called_once_with('id') - - def test_delete_with_multi_names(self): - self.call(execution_cmd.Delete, app_args=['id1', 'id2']) - - self.assertEqual(2, self.client.executions.delete.call_count) - self.assertEqual( - [mock.call('id1'), mock.call('id2')], - self.client.executions.delete.call_args_list - ) diff --git a/mistralclient/tests/unit/v2/test_cli_members.py b/mistralclient/tests/unit/v2/test_cli_members.py deleted file mode 100644 index f37e120..0000000 --- a/mistralclient/tests/unit/v2/test_cli_members.py +++ /dev/null @@ -1,102 +0,0 @@ -# Copyright 2016 Catalyst IT Limited -# -# 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 mistralclient.api.v2 import members -from mistralclient.commands.v2 import members as member_cmd -from mistralclient.tests.unit import base - -MEMBER_DICT = { - 'id': '123', - 'resource_id': '456', - 'resource_type': 'workflow', - 'project_id': '1111', - 'member_id': '2222', - 'status': 'pending', - 'created_at': '1', - 'updated_at': '1' -} - -MEMBER = members.Member(mock, MEMBER_DICT) - - -class TestCLIWorkflowMembers(base.BaseCommandTest): - def test_create(self): - self.client.members.create.return_value = MEMBER - - result = self.call( - member_cmd.Create, - app_args=[MEMBER_DICT['resource_id'], MEMBER_DICT['resource_type'], - MEMBER_DICT['member_id']] - ) - - self.assertEqual( - ('456', 'workflow', '1111', '2222', 'pending', '1', '1'), - result[1] - ) - - def test_update(self): - self.client.members.update.return_value = MEMBER - - result = self.call( - member_cmd.Update, - app_args=[MEMBER_DICT['resource_id'], MEMBER_DICT['resource_type'], - '-m', MEMBER_DICT['member_id']] - ) - - self.assertEqual( - ('456', 'workflow', '1111', '2222', 'pending', '1', '1'), - result[1] - ) - - def test_list(self): - self.client.members.list.return_value = [MEMBER] - - result = self.call( - member_cmd.List, - app_args=[MEMBER_DICT['resource_id'], MEMBER_DICT['resource_type']] - ) - - self.assertListEqual( - [('456', 'workflow', '1111', '2222', 'pending', '1', '1')], - result[1] - ) - - def test_get(self): - self.client.members.get.return_value = MEMBER - - result = self.call( - member_cmd.Get, - app_args=[MEMBER_DICT['resource_id'], MEMBER_DICT['resource_type'], - '-m', MEMBER_DICT['member_id']] - ) - - self.assertEqual( - ('456', 'workflow', '1111', '2222', 'pending', '1', '1'), - result[1] - ) - - def test_delete(self): - self.call( - member_cmd.Delete, - app_args=[MEMBER_DICT['resource_id'], MEMBER_DICT['resource_type'], - MEMBER_DICT['member_id']] - ) - - self.client.members.delete.assert_called_once_with( - MEMBER_DICT['resource_id'], - MEMBER_DICT['resource_type'], - MEMBER_DICT['member_id'] - ) diff --git a/mistralclient/tests/unit/v2/test_cli_services.py b/mistralclient/tests/unit/v2/test_cli_services.py deleted file mode 100644 index 09e4e86..0000000 --- a/mistralclient/tests/unit/v2/test_cli_services.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2015 Huawei Technologies Co., Ltd. -# -# 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 mistralclient.api.v2 import services -from mistralclient.commands.v2 import services as service_cmd -from mistralclient.tests.unit import base - - -SERVICE_DICT = { - 'name': 'service_name', - 'type': 'service_type', -} - -SERVICE = services.Service(mock, SERVICE_DICT) - - -class TestCLIServicesV2(base.BaseCommandTest): - def test_list(self): - self.client.services.list.return_value = [SERVICE] - expected = (SERVICE_DICT['name'], SERVICE_DICT['type'],) - - result = self.call(service_cmd.List) - - self.assertListEqual([expected], result[1]) diff --git a/mistralclient/tests/unit/v2/test_cli_tasks.py b/mistralclient/tests/unit/v2/test_cli_tasks.py deleted file mode 100644 index 09fedff..0000000 --- a/mistralclient/tests/unit/v2/test_cli_tasks.py +++ /dev/null @@ -1,128 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# Copyright 2015 - StackStorm, Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import json - -import mock - -from mistralclient.api.v2 import tasks -from mistralclient.commands.v2 import tasks as task_cmd -from mistralclient.tests.unit import base - -TASK_DICT = { - 'id': '123', - 'name': 'some', - 'workflow_name': 'thing', - 'workflow_execution_id': '321', - 'state': 'RUNNING', - 'state_info': None, - 'created_at': '1', - 'updated_at': '1', -} - -TASK_RESULT = {"test": "is", "passed": "successfully"} -TASK_PUBLISHED = {"bar1": "val1", "var2": 2} - -TASK_WITH_RESULT_DICT = TASK_DICT.copy() -TASK_WITH_RESULT_DICT.update({'result': json.dumps(TASK_RESULT)}) -TASK_WITH_PUBLISHED_DICT = TASK_DICT.copy() -TASK_WITH_PUBLISHED_DICT.update({'published': json.dumps(TASK_PUBLISHED)}) - -TASK = tasks.Task(mock, TASK_DICT) -TASK_WITH_RESULT = tasks.Task(mock, TASK_WITH_RESULT_DICT) -TASK_WITH_PUBLISHED = tasks.Task(mock, TASK_WITH_PUBLISHED_DICT) - -EXPECTED_TASK_RESULT = ( - '123', 'some', 'thing', '321', 'RUNNING', None, '1', '1' -) - - -class TestCLITasksV2(base.BaseCommandTest): - def test_list(self): - self.client.tasks.list.return_value = [TASK] - - result = self.call(task_cmd.List) - - self.assertEqual([EXPECTED_TASK_RESULT], result[1]) - - def test_list_with_workflow_execution(self): - self.client.tasks.list.return_value = [TASK] - - result = self.call(task_cmd.List, app_args=['workflow_execution']) - - self.assertEqual([EXPECTED_TASK_RESULT], result[1]) - - def test_get(self): - self.client.tasks.get.return_value = TASK - - result = self.call(task_cmd.Get, app_args=['id']) - - self.assertEqual(EXPECTED_TASK_RESULT, result[1]) - - def test_get_result(self): - self.client.tasks.get.return_value = TASK_WITH_RESULT - - self.call(task_cmd.GetResult, app_args=['id']) - - self.assertDictEqual( - TASK_RESULT, - json.loads(self.app.stdout.write.call_args[0][0]) - ) - - def test_get_published(self): - self.client.tasks.get.return_value = TASK_WITH_PUBLISHED - - self.call(task_cmd.GetPublished, app_args=['id']) - - self.assertDictEqual( - TASK_PUBLISHED, - json.loads(self.app.stdout.write.call_args[0][0]) - ) - - def test_rerun(self): - self.client.tasks.rerun.return_value = TASK - - result = self.call(task_cmd.Rerun, app_args=['id']) - - self.assertEqual(EXPECTED_TASK_RESULT, result[1]) - - def test_rerun_no_reset(self): - self.client.tasks.rerun.return_value = TASK - - result = self.call(task_cmd.Rerun, app_args=['id', '--resume']) - - self.assertEqual(EXPECTED_TASK_RESULT, result[1]) - - def test_rerun_update_env(self): - self.client.tasks.rerun.return_value = TASK - - result = self.call( - task_cmd.Rerun, - app_args=['id', '--env', '{"k1": "foobar"}'] - ) - - self.assertEqual(EXPECTED_TASK_RESULT, result[1]) - - def test_rerun_no_reset_update_env(self): - self.client.tasks.rerun.return_value = TASK - - result = self.call( - task_cmd.Rerun, - app_args=['id', '--resume', '--env', '{"k1": "foobar"}'] - ) - - self.assertEqual(EXPECTED_TASK_RESULT, result[1]) diff --git a/mistralclient/tests/unit/v2/test_cli_workbooks.py b/mistralclient/tests/unit/v2/test_cli_workbooks.py deleted file mode 100644 index a789939..0000000 --- a/mistralclient/tests/unit/v2/test_cli_workbooks.py +++ /dev/null @@ -1,119 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# Copyright 2015 - StackStorm, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import mock - -from mistralclient.api.v2 import workbooks -from mistralclient.commands.v2 import workbooks as workbook_cmd -from mistralclient.tests.unit import base - - -WORKBOOK_DICT = { - 'name': 'a', - 'tags': ['a', 'b'], - 'created_at': '1', - 'updated_at': '1' -} - - -WB_DEF = """ ---- -version: '2.0 - -name: wb - -workflows: - wf1: - tasks: - task1: - action: nova.servers_get server="1" -""" - -WB_WITH_DEF_DICT = WORKBOOK_DICT.copy() -WB_WITH_DEF_DICT.update({'definition': WB_DEF}) -WORKBOOK = workbooks.Workbook(mock, WORKBOOK_DICT) -WORKBOOK_WITH_DEF = workbooks.Workbook(mock, WB_WITH_DEF_DICT) - - -class TestCLIWorkbooksV2(base.BaseCommandTest): - @mock.patch('argparse.open', create=True) - def test_create(self, mock_open): - self.client.workbooks.create.return_value = WORKBOOK - - result = self.call(workbook_cmd.Create, app_args=['wb.yaml']) - - self.assertEqual(('a', 'a, b', '1', '1'), result[1]) - - @mock.patch('argparse.open', create=True) - def test_update(self, mock_open): - self.client.workbooks.update.return_value = WORKBOOK - - result = self.call(workbook_cmd.Update, app_args=['definition']) - - self.assertEqual(('a', 'a, b', '1', '1'), result[1]) - - def test_list(self): - self.client.workbooks.list.return_value = [WORKBOOK] - - result = self.call(workbook_cmd.List) - - self.assertEqual([('a', 'a, b', '1', '1')], result[1]) - - def test_get(self): - self.client.workbooks.get.return_value = WORKBOOK - - result = self.call(workbook_cmd.Get, app_args=['name']) - - self.assertEqual(('a', 'a, b', '1', '1'), result[1]) - - def test_delete(self): - self.call(workbook_cmd.Delete, app_args=['name']) - - self.client.workbooks.delete.assert_called_once_with('name') - - def test_delete_with_multi_names(self): - self.call(workbook_cmd.Delete, app_args=['name1', 'name2']) - - self.assertEqual(2, self.client.workbooks.delete.call_count) - self.assertEqual( - [mock.call('name1'), mock.call('name2')], - self.client.workbooks.delete.call_args_list - ) - - def test_get_definition(self): - self.client.workbooks.get.return_value = WORKBOOK_WITH_DEF - - self.call(workbook_cmd.GetDefinition, app_args=['name']) - - self.app.stdout.write.assert_called_with(WB_DEF) - - @mock.patch('argparse.open', create=True) - def test_validate(self, mock_open): - self.client.workbooks.validate.return_value = {'valid': True} - - result = self.call(workbook_cmd.Validate, app_args=['wb.yaml']) - - self.assertEqual((True, None), result[1]) - - @mock.patch('argparse.open', create=True) - def test_validate_failed(self, mock_open): - self.client.workbooks.validate.return_value = { - 'valid': False, - 'error': 'Invalid DSL...' - } - - result = self.call(workbook_cmd.Validate, app_args=['wb.yaml']) - - self.assertEqual((False, 'Invalid DSL...'), result[1]) diff --git a/mistralclient/tests/unit/v2/test_cli_workflows.py b/mistralclient/tests/unit/v2/test_cli_workflows.py deleted file mode 100644 index 38c5fa5..0000000 --- a/mistralclient/tests/unit/v2/test_cli_workflows.py +++ /dev/null @@ -1,201 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# Copyright 2015 - StackStorm, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import mock -import six - -from mistralclient.api.v2 import workflows -from mistralclient.commands.v2 import base as cmd_base -from mistralclient.commands.v2 import workflows as workflow_cmd -from mistralclient.tests.unit import base - - -WORKFLOW_DICT = { - 'id': '1-2-3-4', - 'name': 'a', - 'project_id': '12345', - 'tags': ['a', 'b'], - 'input': 'param', - 'created_at': '1', - 'updated_at': '1' -} - -WF_DEF = """ -version: '2.0' - -flow: - tasks: - task1: - action: nova.servers_get server="1" -""" - -WF_WITH_DEF_DICT = WORKFLOW_DICT.copy() -WF_WITH_DEF_DICT.update({'definition': WF_DEF}) -WORKFLOW = workflows.Workflow(mock, WORKFLOW_DICT) -WORKFLOW_WITH_DEF = workflows.Workflow(mock, WF_WITH_DEF_DICT) - - -class TestCLIWorkflowsV2(base.BaseCommandTest): - @mock.patch('argparse.open', create=True) - def test_create(self, mock_open): - self.client.workflows.create.return_value = [WORKFLOW] - - result = self.call(workflow_cmd.Create, app_args=['1.txt']) - - self.assertEqual( - [('1-2-3-4', 'a', '12345', 'a, b', 'param', '1', '1')], - result[1] - ) - - @mock.patch('argparse.open', create=True) - def test_create_public(self, mock_open): - self.client.workflows.create.return_value = [WORKFLOW] - - result = self.call( - workflow_cmd.Create, - app_args=['1.txt', '--public'] - ) - - self.assertEqual( - [('1-2-3-4', 'a', '12345', 'a, b', 'param', '1', '1')], - result[1] - ) - - self.assertEqual( - 'public', - self.client.workflows.create.call_args[1]['scope'] - ) - - @mock.patch('argparse.open', create=True) - def test_create_long_input(self, mock_open): - wf_long_input_dict = WORKFLOW_DICT.copy() - long_input = ', '.join( - ['var%s' % i for i in six.moves.xrange(10)] - ) - wf_long_input_dict['input'] = long_input - workflow_long_input = workflows.Workflow(mock, wf_long_input_dict) - self.client.workflows.create.return_value = [workflow_long_input] - - result = self.call(workflow_cmd.Create, app_args=['1.txt']) - - self.assertEqual( - [('1-2-3-4', 'a', '12345', 'a, b', cmd_base.cut(long_input), - '1', '1')], - result[1] - ) - - @mock.patch('argparse.open', create=True) - def test_update(self, mock_open): - self.client.workflows.update.return_value = [WORKFLOW] - - result = self.call(workflow_cmd.Update, app_args=['1.txt']) - - self.assertEqual( - [('1-2-3-4', 'a', '12345', 'a, b', 'param', '1', '1')], - result[1] - ) - - @mock.patch('argparse.open', create=True) - def test_update_public(self, mock_open): - self.client.workflows.update.return_value = [WORKFLOW] - - result = self.call( - workflow_cmd.Update, - app_args=['1.txt', '--public'] - ) - - self.assertEqual( - [('1-2-3-4', 'a', '12345', 'a, b', 'param', '1', '1')], - result[1] - ) - - self.assertEqual( - 'public', - self.client.workflows.update.call_args[1]['scope'] - ) - - @mock.patch('argparse.open', create=True) - def test_update_with_id(self, mock_open): - self.client.workflows.update.return_value = WORKFLOW - - result = self.call( - workflow_cmd.Update, - app_args=['1.txt', '--id', '1-2-3-4'] - ) - - self.assertEqual( - [('1-2-3-4', 'a', '12345', 'a, b', 'param', '1', '1')], - result[1] - ) - - def test_list(self): - self.client.workflows.list.return_value = [WORKFLOW] - - result = self.call(workflow_cmd.List) - - self.assertEqual( - [('1-2-3-4', 'a', '12345', 'a, b', 'param', '1', '1')], - result[1] - ) - - def test_get(self): - self.client.workflows.get.return_value = WORKFLOW - - result = self.call(workflow_cmd.Get, app_args=['name']) - - self.assertEqual( - ('1-2-3-4', 'a', '12345', 'a, b', 'param', '1', '1'), - result[1] - ) - - def test_delete(self): - self.call(workflow_cmd.Delete, app_args=['name']) - - self.client.workflows.delete.assert_called_once_with('name') - - def test_delete_with_multi_names(self): - self.call(workflow_cmd.Delete, app_args=['name1', 'name2']) - - self.assertEqual(2, self.client.workflows.delete.call_count) - self.assertEqual( - [mock.call('name1'), mock.call('name2')], - self.client.workflows.delete.call_args_list - ) - - def test_get_definition(self): - self.client.workflows.get.return_value = WORKFLOW_WITH_DEF - - self.call(workflow_cmd.GetDefinition, app_args=['name']) - - self.app.stdout.write.assert_called_with(WF_DEF) - - @mock.patch('argparse.open', create=True) - def test_validate(self, mock_open): - self.client.workflows.validate.return_value = {'valid': True} - - result = self.call(workflow_cmd.Validate, app_args=['wf.yaml']) - - self.assertEqual((True, None), result[1]) - - @mock.patch('argparse.open', create=True) - def test_validate_failed(self, mock_open): - self.client.workflows.validate.return_value = { - 'valid': False, - 'error': 'Invalid DSL...' - } - - result = self.call(workflow_cmd.Validate, app_args=['wf.yaml']) - - self.assertEqual((False, 'Invalid DSL...'), result[1]) diff --git a/mistralclient/tests/unit/v2/test_environments.py b/mistralclient/tests/unit/v2/test_environments.py deleted file mode 100644 index 74168fe..0000000 --- a/mistralclient/tests/unit/v2/test_environments.py +++ /dev/null @@ -1,173 +0,0 @@ -# Copyright 2015 - StackStorm, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import collections -import copy -import json - -import pkg_resources as pkg -from six.moves.urllib import parse -from six.moves.urllib import request - -from mistralclient.api import base as api_base -from mistralclient.api.v2 import environments -from mistralclient.tests.unit.v2 import base -from mistralclient import utils - - -ENVIRONMENT = { - 'name': 'env1', - 'description': 'Test Environment #1', - 'scope': 'private', - 'variables': { - 'server': 'localhost' - } -} - -URL_TEMPLATE = '/environments' -URL_TEMPLATE_NAME = '/environments/%s' - - -class TestEnvironmentsV2(base.BaseClientV2Test): - - def test_create(self): - data = copy.deepcopy(ENVIRONMENT) - - self.requests_mock.post(self.TEST_URL + URL_TEMPLATE, - status_code=201, - json=data) - env = self.environments.create(**data) - - self.assertIsNotNone(env) - - expected_data = copy.deepcopy(data) - expected_data['variables'] = json.dumps(expected_data['variables']) - - self.assertEqual(expected_data, self.requests_mock.last_request.json()) - - def test_create_with_json_file_uri(self): - # The contents of env_v2.json must be equivalent to ENVIRONMENT - path = pkg.resource_filename( - 'mistralclient', - 'tests/unit/resources/env_v2.json' - ) - - # Convert the file path to file URI - uri = parse.urljoin('file:', request.pathname2url(path)) - data = collections.OrderedDict( - utils.load_content( - utils.get_contents_if_file(uri) - ) - ) - - self.requests_mock.post(self.TEST_URL + URL_TEMPLATE, - status_code=201, - json=data) - file_input = {'file': uri} - env = self.environments.create(**file_input) - - self.assertIsNotNone(env) - - expected_data = copy.deepcopy(data) - expected_data['variables'] = json.dumps(expected_data['variables']) - - self.assertEqual(expected_data, self.requests_mock.last_request.json()) - - def test_create_without_name(self): - data = copy.deepcopy(ENVIRONMENT) - data.pop('name') - - e = self.assertRaises(api_base.APIException, - self.environments.create, - **data) - - self.assertEqual(400, e.error_code) - - def test_update(self): - data = copy.deepcopy(ENVIRONMENT) - - self.requests_mock.put(self.TEST_URL + URL_TEMPLATE, json=data) - env = self.environments.update(**data) - - self.assertIsNotNone(env) - - expected_data = copy.deepcopy(data) - expected_data['variables'] = json.dumps(expected_data['variables']) - - self.assertEqual(expected_data, self.requests_mock.last_request.json()) - - def test_update_with_yaml_file(self): - # The contents of env_v2.json must be equivalent to ENVIRONMENT - path = pkg.resource_filename( - 'mistralclient', - 'tests/unit/resources/env_v2.json' - ) - data = collections.OrderedDict( - utils.load_content( - utils.get_contents_if_file(path) - ) - ) - self.requests_mock.put(self.TEST_URL + URL_TEMPLATE, json=data) - - file_input = {'file': path} - env = self.environments.update(**file_input) - - self.assertIsNotNone(env) - - expected_data = copy.deepcopy(data) - expected_data['variables'] = json.dumps(expected_data['variables']) - - self.assertEqual(expected_data, self.requests_mock.last_request.json()) - - def test_update_without_name(self): - data = copy.deepcopy(ENVIRONMENT) - data.pop('name') - - e = self.assertRaises(api_base.APIException, - self.environments.update, - **data) - - self.assertEqual(400, e.error_code) - - def test_list(self): - self.requests_mock.get(self.TEST_URL + URL_TEMPLATE, - json={'environments': [ENVIRONMENT]}) - - environment_list = self.environments.list() - - self.assertEqual(1, len(environment_list)) - - env = environment_list[0] - - self.assertDictEqual( - environments.Environment(self.environments, ENVIRONMENT).to_dict(), - env.to_dict() - ) - - def test_get(self): - self.requests_mock.get(self.TEST_URL + URL_TEMPLATE_NAME % 'env', - json=ENVIRONMENT) - - env = self.environments.get('env') - - self.assertIsNotNone(env) - self.assertDictEqual( - environments.Environment(self.environments, ENVIRONMENT).to_dict(), - env.to_dict() - ) - - def test_delete(self): - self.requests_mock.delete(self.TEST_URL + URL_TEMPLATE_NAME % 'env', - status_code=204) - - self.environments.delete('env') diff --git a/mistralclient/tests/unit/v2/test_executions.py b/mistralclient/tests/unit/v2/test_executions.py deleted file mode 100644 index 77296e3..0000000 --- a/mistralclient/tests/unit/v2/test_executions.py +++ /dev/null @@ -1,221 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# Copyright 2015 - StackStorm, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import json - -from mistralclient.api import base as api_base -from mistralclient.api.v2 import executions -from mistralclient.tests.unit.v2 import base - -# TODO(everyone): Later we need additional tests verifying all the errors etc. - -EXEC = { - 'id': "123", - 'workflow_id': '123e4567-e89b-12d3-a456-426655440000', - 'workflow_name': 'my_wf', - 'description': '', - 'state': 'RUNNING', - 'input': { - "person": { - "first_name": "John", - "last_name": "Doe" - } - } -} - -SUB_WF_EXEC = { - 'id': "456", - 'workflow_id': '123e4567-e89b-12d3-a456-426655440000', - 'workflow_name': 'my_sub_wf', - 'task_execution_id': "abc", - 'description': '', - 'state': 'RUNNING', - 'input': { - "person": { - "first_name": "John", - "last_name": "Doe" - } - } -} - -URL_TEMPLATE = '/executions' -URL_TEMPLATE_ID = '/executions/%s' - - -class TestExecutionsV2(base.BaseClientV2Test): - def test_create(self): - self.requests_mock.post(self.TEST_URL + URL_TEMPLATE, - json=EXEC, - status_code=201) - - body = { - 'workflow_name': EXEC['workflow_name'], - 'description': '', - 'input': json.dumps(EXEC['input']), - } - - ex = self.executions.create( - EXEC['workflow_name'], - EXEC['input'] - ) - - self.assertIsNotNone(ex) - - self.assertDictEqual( - executions.Execution(self.executions, EXEC).to_dict(), - ex.to_dict() - ) - - self.assertDictEqual(body, self.requests_mock.last_request.json()) - - def test_create_with_workflow_id(self): - self.requests_mock.post(self.TEST_URL + URL_TEMPLATE, - json=EXEC, - status_code=201) - - body = { - 'workflow_id': EXEC['workflow_id'], - 'description': '', - 'input': json.dumps(EXEC['input']), - } - - ex = self.executions.create( - EXEC['workflow_id'], - EXEC['input'] - ) - - self.assertIsNotNone(ex) - - self.assertDictEqual( - executions.Execution(self.executions, EXEC).to_dict(), - ex.to_dict() - ) - - self.assertDictEqual(body, self.requests_mock.last_request.json()) - - def test_create_failure1(self): - self.requests_mock.post(self.TEST_URL + URL_TEMPLATE, - json=EXEC, - status_code=201) - self.assertRaises(api_base.APIException, self.executions.create, '') - - def test_update(self): - url = self.TEST_URL + URL_TEMPLATE_ID % EXEC['id'] - self.requests_mock.put(url, json=EXEC) - body = { - 'state': EXEC['state'] - } - - ex = self.executions.update(EXEC['id'], EXEC['state']) - - self.assertIsNotNone(ex) - - self.assertDictEqual( - executions.Execution(self.executions, EXEC).to_dict(), - ex.to_dict() - ) - - self.assertDictEqual(body, self.requests_mock.last_request.json()) - - def test_update_env(self): - url = self.TEST_URL + URL_TEMPLATE_ID % EXEC['id'] - self.requests_mock.put(url, json=EXEC) - body = { - 'state': EXEC['state'], - 'params': { - 'env': {'k1': 'foobar'} - } - } - - ex = self.executions.update( - EXEC['id'], - EXEC['state'], - env={'k1': 'foobar'} - ) - - self.assertIsNotNone(ex) - - self.assertDictEqual( - executions.Execution(self.executions, EXEC).to_dict(), - ex.to_dict() - ) - - self.assertDictEqual(body, self.requests_mock.last_request.json()) - - def test_list(self): - self.requests_mock.get(self.TEST_URL + URL_TEMPLATE, - json={'executions': [EXEC, SUB_WF_EXEC]}) - - execution_list = self.executions.list() - - self.assertEqual(2, len(execution_list)) - - self.assertDictEqual( - executions.Execution(self.executions, EXEC).to_dict(), - execution_list[0].to_dict() - ) - - self.assertDictEqual( - executions.Execution(self.executions, SUB_WF_EXEC).to_dict(), - execution_list[1].to_dict() - ) - - def test_list_with_pagination(self): - self.requests_mock.get(self.TEST_URL + URL_TEMPLATE, - json={'executions': [EXEC], - 'next': '/executions?fake'}) - - execution_list = self.executions.list( - limit=1, - sort_keys='created_at', - sort_dirs='asc' - ) - - self.assertEqual(1, len(execution_list)) - - last_request = self.requests_mock.last_request - - # The url param order is unpredictable. - self.assertEqual(['1'], last_request.qs['limit']) - self.assertEqual(['created_at'], last_request.qs['sort_keys']) - self.assertEqual(['asc'], last_request.qs['sort_dirs']) - - def test_get(self): - url = self.TEST_URL + URL_TEMPLATE_ID % EXEC['id'] - self.requests_mock.get(url, json=EXEC) - - ex = self.executions.get(EXEC['id']) - - self.assertDictEqual( - executions.Execution(self.executions, EXEC).to_dict(), - ex.to_dict() - ) - - def test_get_sub_wf_ex(self): - url = self.TEST_URL + URL_TEMPLATE_ID % SUB_WF_EXEC['id'] - self.requests_mock.get(url, json=SUB_WF_EXEC) - - ex = self.executions.get(SUB_WF_EXEC['id']) - - self.assertDictEqual( - executions.Execution(self.executions, SUB_WF_EXEC).to_dict(), - ex.to_dict() - ) - - def test_delete(self): - url = self.TEST_URL + URL_TEMPLATE_ID % EXEC['id'] - self.requests_mock.delete(url, status_code=204) - - self.executions.delete(EXEC['id']) diff --git a/mistralclient/tests/unit/v2/test_members.py b/mistralclient/tests/unit/v2/test_members.py deleted file mode 100644 index a3245eb..0000000 --- a/mistralclient/tests/unit/v2/test_members.py +++ /dev/null @@ -1,96 +0,0 @@ -# Copyright 2016 Catalyst IT Limited -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import copy - -from mistralclient.tests.unit.v2 import base - -MEMBER = { - 'id': '123', - 'resource_id': '456', - 'resource_type': 'workflow', - 'project_id': 'dc4ffdee54d74028b19b1b90e77aa84f', - 'member_id': '04f61e967fa14cd49950ffe2319317ad', - 'status': 'pending', -} - -WORKFLOW_MEMBERS_URL = '/workflows/%s/members' % (MEMBER['resource_id']) -WORKFLOW_MEMBER_URL = '/workflows/%s/members/%s' % ( - MEMBER['resource_id'], MEMBER['member_id'] -) - - -class TestWorkflowMembers(base.BaseClientV2Test): - def test_create(self): - self.requests_mock.post(self.TEST_URL + WORKFLOW_MEMBERS_URL, - json=MEMBER, - status_code=201) - - mb = self.members.create( - MEMBER['resource_id'], - MEMBER['resource_type'], - MEMBER['member_id'] - ) - - self.assertIsNotNone(mb) - - self.assertDictEqual({'member_id': MEMBER['member_id']}, - self.requests_mock.last_request.json()) - - def test_update(self): - updated_member = copy.copy(MEMBER) - updated_member['status'] = 'accepted' - - self.requests_mock.put(self.TEST_URL + WORKFLOW_MEMBER_URL, - json=updated_member) - - mb = self.members.update( - MEMBER['resource_id'], - MEMBER['resource_type'], - MEMBER['member_id'] - ) - - self.assertIsNotNone(mb) - - self.assertDictEqual({"status": "accepted"}, - self.requests_mock.last_request.json()) - - def test_list(self): - self.requests_mock.get(self.TEST_URL + WORKFLOW_MEMBERS_URL, - json={'members': [MEMBER]}) - - mbs = self.members.list(MEMBER['resource_id'], MEMBER['resource_type']) - - self.assertEqual(1, len(mbs)) - - def test_get(self): - self.requests_mock.get(self.TEST_URL + WORKFLOW_MEMBER_URL, - json=MEMBER) - - mb = self.members.get( - MEMBER['resource_id'], - MEMBER['resource_type'], - MEMBER['member_id'] - ) - - self.assertIsNotNone(mb) - - def test_delete(self): - self.requests_mock.delete(self.TEST_URL + WORKFLOW_MEMBER_URL, - status_code=204) - self.members.delete( - MEMBER['resource_id'], - MEMBER['resource_type'], - MEMBER['member_id'] - ) diff --git a/mistralclient/tests/unit/v2/test_services.py b/mistralclient/tests/unit/v2/test_services.py deleted file mode 100644 index 40b24ab..0000000 --- a/mistralclient/tests/unit/v2/test_services.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 2015 Huawei Technologies Co., Ltd. -# -# 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 mistralclient.api.v2 import services -from mistralclient.tests.unit.v2 import base - - -SERVICE = { - 'name': 'service_name', - 'type': 'service_type', -} - -URL_TEMPLATE = '/services' - - -class TestServicesV2(base.BaseClientV2Test): - def test_list(self): - self.requests_mock.get(self.TEST_URL + URL_TEMPLATE, - json={'services': [SERVICE]}) - - service_list = self.services.list() - - self.assertEqual(1, len(service_list)) - - srv = service_list[0] - - self.assertDictEqual( - services.Service(self.services, SERVICE).to_dict(), - srv.to_dict() - ) diff --git a/mistralclient/tests/unit/v2/test_tasks.py b/mistralclient/tests/unit/v2/test_tasks.py deleted file mode 100644 index 93d9370..0000000 --- a/mistralclient/tests/unit/v2/test_tasks.py +++ /dev/null @@ -1,117 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# Copyright 2015 - StackStorm, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import json - -from mistralclient.api.v2 import tasks -from mistralclient.tests.unit.v2 import base - -# TODO(everyone): later we need additional tests verifying all the errors etc. - -TASK = { - 'id': "1", - 'workflow_execution_id': '123', - 'name': 'my_task', - 'workflow_name': 'my_wf', - 'state': 'RUNNING', - 'tags': ['deployment', 'demo'], - 'result': {'some': 'result'} -} - - -URL_TEMPLATE = '/tasks' -URL_TEMPLATE_ID = '/tasks/%s' - - -class TestTasksV2(base.BaseClientV2Test): - def test_list(self): - self.requests_mock.get(self.TEST_URL + URL_TEMPLATE, - json={'tasks': [TASK]}) - - task_list = self.tasks.list() - - self.assertEqual(1, len(task_list)) - task = task_list[0] - - self.assertEqual( - tasks.Task(self.tasks, TASK).to_dict(), - task.to_dict() - ) - - def test_get(self): - url = self.TEST_URL + URL_TEMPLATE_ID % TASK['id'] - self.requests_mock.get(url, json=TASK) - - task = self.tasks.get(TASK['id']) - - self.assertEqual( - tasks.Task(self.tasks, TASK).to_dict(), - task.to_dict() - ) - - def test_rerun(self): - url = self.TEST_URL + URL_TEMPLATE_ID % TASK['id'] - self.requests_mock.put(url, json=TASK) - - task = self.tasks.rerun(TASK['id']) - - self.assertDictEqual( - tasks.Task(self.tasks, TASK).to_dict(), - task.to_dict() - ) - - body = { - 'reset': True, - 'state': 'RUNNING', - 'id': TASK['id'] - } - self.assertDictEqual(body, self.requests_mock.last_request.json()) - - def test_rerun_no_reset(self): - url = self.TEST_URL + URL_TEMPLATE_ID % TASK['id'] - self.requests_mock.put(url, json=TASK) - - task = self.tasks.rerun(TASK['id'], reset=False) - - self.assertDictEqual( - tasks.Task(self.tasks, TASK).to_dict(), - task.to_dict() - ) - - body = { - 'reset': False, - 'state': 'RUNNING', - 'id': TASK['id'] - } - self.assertDictEqual(body, self.requests_mock.last_request.json()) - - def test_rerun_update_env(self): - url = self.TEST_URL + URL_TEMPLATE_ID % TASK['id'] - self.requests_mock.put(url, json=TASK) - - task = self.tasks.rerun(TASK['id'], env={'k1': 'foobar'}) - - self.assertDictEqual( - tasks.Task(self.tasks, TASK).to_dict(), - task.to_dict() - ) - - body = { - 'reset': True, - 'state': 'RUNNING', - 'id': TASK['id'], - 'env': json.dumps({'k1': 'foobar'}) - } - self.assertDictEqual(body, self.requests_mock.last_request.json()) diff --git a/mistralclient/tests/unit/v2/test_workbooks.py b/mistralclient/tests/unit/v2/test_workbooks.py deleted file mode 100644 index 59a5941..0000000 --- a/mistralclient/tests/unit/v2/test_workbooks.py +++ /dev/null @@ -1,251 +0,0 @@ -# Copyright 2014 - Mirantis, Inc. -# Copyright 2015 - StackStorm, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import pkg_resources as pkg -from six.moves.urllib import parse -from six.moves.urllib import request - -from mistralclient.api import base as api_base -from mistralclient.api.v2 import workbooks -from mistralclient.tests.unit.v2 import base - -# TODO(everyone): later we need additional tests verifying all the errors etc. - - -WB_DEF = """ ---- -version: 2.0 - -name: wb - -workflows: - wf1: - type: direct - input: - - param1 - - param2 - - tasks: - task1: - action: std.http url="localhost:8989" - on-success: - - test_subsequent - - test_subsequent: - action: std.http url="http://some_url" server_id=1 -""" - -INVALID_WB_DEF = """ -version: 2.0 - -name: wb - -workflows: - wf1: - type: direct - tasks: - task1: - action: std.http url="localhost:8989" - workflow: wf2 -""" - -WORKBOOK = {'definition': WB_DEF} - -URL_TEMPLATE = '/workbooks' -URL_TEMPLATE_NAME = '/workbooks/%s' -URL_TEMPLATE_VALIDATE = '/workbooks/validate' - - -class TestWorkbooksV2(base.BaseClientV2Test): - def test_create(self): - self.requests_mock.post(self.TEST_URL + URL_TEMPLATE, - json=WORKBOOK, - status_code=201) - - wb = self.workbooks.create(WB_DEF) - - self.assertIsNotNone(wb) - self.assertEqual(WB_DEF, wb.definition) - - last_request = self.requests_mock.last_request - - self.assertEqual(WB_DEF, last_request.text) - self.assertEqual('text/plain', last_request.headers['content-type']) - - def test_create_with_file_uri(self): - self.requests_mock.post(self.TEST_URL + URL_TEMPLATE, - json=WORKBOOK, - status_code=201) - - # The contents of wb_v2.yaml must be identical to WB_DEF - path = pkg.resource_filename( - 'mistralclient', - 'tests/unit/resources/wb_v2.yaml' - ) - - # Convert the file path to file URI - uri = parse.urljoin('file:', request.pathname2url(path)) - - wb = self.workbooks.create(uri) - - self.assertIsNotNone(wb) - self.assertEqual(WB_DEF, wb.definition) - - last_request = self.requests_mock.last_request - - self.assertEqual(WB_DEF, last_request.text) - self.assertEqual('text/plain', last_request.headers['content-type']) - - def test_update(self): - self.requests_mock.put(self.TEST_URL + URL_TEMPLATE, json=WORKBOOK) - - wb = self.workbooks.update(WB_DEF) - - self.assertIsNotNone(wb) - self.assertEqual(WB_DEF, wb.definition) - - last_request = self.requests_mock.last_request - - self.assertEqual(WB_DEF, last_request.text) - self.assertEqual('text/plain', last_request.headers['content-type']) - - def test_update_with_file(self): - self.requests_mock.put(self.TEST_URL + URL_TEMPLATE, json=WORKBOOK) - - # The contents of wb_v2.yaml must be identical to WB_DEF - path = pkg.resource_filename( - 'mistralclient', - 'tests/unit/resources/wb_v2.yaml' - ) - - wb = self.workbooks.update(path) - - self.assertIsNotNone(wb) - self.assertEqual(WB_DEF, wb.definition) - - last_request = self.requests_mock.last_request - - self.assertEqual(WB_DEF, last_request.text) - self.assertEqual('text/plain', last_request.headers['content-type']) - - def test_list(self): - self.requests_mock.get(self.TEST_URL + URL_TEMPLATE, - json={'workbooks': [WORKBOOK]}) - - workbook_list = self.workbooks.list() - - self.assertEqual(1, len(workbook_list)) - - wb = workbook_list[0] - - self.assertEqual( - workbooks.Workbook(self.workbooks, WORKBOOK).to_dict(), - wb.to_dict() - ) - - def test_get(self): - url = self.TEST_URL + URL_TEMPLATE_NAME % 'wb' - self.requests_mock.get(url, json=WORKBOOK) - - wb = self.workbooks.get('wb') - - self.assertIsNotNone(wb) - self.assertEqual( - workbooks.Workbook(self.workbooks, WORKBOOK).to_dict(), - wb.to_dict() - ) - - def test_delete(self): - url = self.TEST_URL + URL_TEMPLATE_NAME % 'wb' - self.requests_mock.delete(url, status_code=204) - - self.workbooks.delete('wb') - - def test_validate(self): - self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_VALIDATE, - json={'valid': True}) - - result = self.workbooks.validate(WB_DEF) - - self.assertIsNotNone(result) - self.assertIn('valid', result) - self.assertTrue(result['valid']) - - last_request = self.requests_mock.last_request - - self.assertEqual(WB_DEF, last_request.text) - self.assertEqual('text/plain', last_request.headers['content-type']) - - def test_validate_with_file(self): - self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_VALIDATE, - json={'valid': True}) - - # The contents of wb_v2.yaml must be identical to WB_DEF - path = pkg.resource_filename( - 'mistralclient', - 'tests/unit/resources/wb_v2.yaml' - ) - - result = self.workbooks.validate(path) - - self.assertIsNotNone(result) - self.assertIn('valid', result) - self.assertTrue(result['valid']) - - last_request = self.requests_mock.last_request - - self.assertEqual(WB_DEF, last_request.text) - self.assertEqual('text/plain', last_request.headers['content-type']) - - def test_validate_failed(self): - mock_result = { - "valid": False, - "error": "Task properties 'action' and 'workflow' " - "can't be specified both" - } - - self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_VALIDATE, - json=mock_result) - - result = self.workbooks.validate(INVALID_WB_DEF) - - self.assertIsNotNone(result) - self.assertIn('valid', result) - self.assertFalse(result['valid']) - self.assertIn('error', result) - self.assertIn( - "Task properties 'action' and 'workflow' " - "can't be specified both", result['error'] - ) - - last_request = self.requests_mock.last_request - - self.assertEqual(INVALID_WB_DEF, last_request.text) - self.assertEqual('text/plain', last_request.headers['content-type']) - - def test_validate_api_failed(self): - self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_VALIDATE, - status_code=500) - - self.assertRaises( - api_base.APIException, - self.workbooks.validate, - WB_DEF - ) - - last_request = self.requests_mock.last_request - - self.assertEqual(WB_DEF, last_request.text) - self.assertEqual('text/plain', last_request.headers['content-type']) diff --git a/mistralclient/tests/unit/v2/test_workflows.py b/mistralclient/tests/unit/v2/test_workflows.py deleted file mode 100644 index fb5cac7..0000000 --- a/mistralclient/tests/unit/v2/test_workflows.py +++ /dev/null @@ -1,187 +0,0 @@ -# Copyright 2015 Huawei Technologies Co., Ltd. -# -# 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 pkg_resources as pkg -from six.moves.urllib import parse -from six.moves.urllib import request - -from mistralclient.api.v2 import workflows -from mistralclient.tests.unit.v2 import base - - -WF_DEF = """ ---- -version: 2.0 - -my_wf: - type: direct - - tasks: - task1: - action: std.echo output="hello, world" -""" - -WORKFLOW = { - 'id': '123', - 'name': 'my_wf', - 'input': '', - 'definition': WF_DEF -} - -URL_TEMPLATE = '/workflows' -URL_TEMPLATE_SCOPE = '/workflows?scope=private' -URL_TEMPLATE_NAME = '/workflows/%s' - - -class TestWorkflowsV2(base.BaseClientV2Test): - def test_create(self): - self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_SCOPE, - json={'workflows': [WORKFLOW]}, - status_code=201) - - wfs = self.workflows.create(WF_DEF) - - self.assertIsNotNone(wfs) - self.assertEqual(WF_DEF, wfs[0].definition) - - last_request = self.requests_mock.last_request - - self.assertEqual(WF_DEF, last_request.text) - self.assertEqual('text/plain', last_request.headers['content-type']) - - def test_create_with_file(self): - self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_SCOPE, - json={'workflows': [WORKFLOW]}, - status_code=201) - - # The contents of wf_v2.yaml must be identical to WF_DEF - path = pkg.resource_filename( - 'mistralclient', - 'tests/unit/resources/wf_v2.yaml' - ) - - wfs = self.workflows.create(path) - - self.assertIsNotNone(wfs) - self.assertEqual(WF_DEF, wfs[0].definition) - - last_request = self.requests_mock.last_request - - self.assertEqual(WF_DEF, last_request.text) - self.assertEqual('text/plain', last_request.headers['content-type']) - - def test_update(self): - self.requests_mock.put(self.TEST_URL + URL_TEMPLATE_SCOPE, - json={'workflows': [WORKFLOW]}) - - wfs = self.workflows.update(WF_DEF) - - self.assertIsNotNone(wfs) - self.assertEqual(WF_DEF, wfs[0].definition) - - last_request = self.requests_mock.last_request - - self.assertEqual(WF_DEF, last_request.text) - self.assertEqual('text/plain', last_request.headers['content-type']) - - def test_update_with_id(self): - self.requests_mock.put(self.TEST_URL + URL_TEMPLATE_NAME % '123', - json=WORKFLOW) - - wf = self.workflows.update(WF_DEF, id='123') - - self.assertIsNotNone(wf) - self.assertEqual(WF_DEF, wf.definition) - - last_request = self.requests_mock.last_request - - self.assertEqual('scope=private', last_request.query) - self.assertEqual(WF_DEF, last_request.text) - self.assertEqual('text/plain', last_request.headers['content-type']) - - def test_update_with_file_uri(self): - self.requests_mock.put(self.TEST_URL + URL_TEMPLATE_SCOPE, - json={'workflows': [WORKFLOW]}) - - # The contents of wf_v2.yaml must be identical to WF_DEF - path = pkg.resource_filename( - 'mistralclient', - 'tests/unit/resources/wf_v2.yaml' - ) - - # Convert the file path to file URI - uri = parse.urljoin('file:', request.pathname2url(path)) - - wfs = self.workflows.update(uri) - - self.assertIsNotNone(wfs) - self.assertEqual(WF_DEF, wfs[0].definition) - - last_request = self.requests_mock.last_request - - self.assertEqual(WF_DEF, last_request.text) - self.assertEqual('text/plain', last_request.headers['content-type']) - - def test_list(self): - self.requests_mock.get(self.TEST_URL + URL_TEMPLATE, - json={'workflows': [WORKFLOW]}) - - workflows_list = self.workflows.list() - - self.assertEqual(1, len(workflows_list)) - - wf = workflows_list[0] - - self.assertEqual( - workflows.Workflow(self.workflows, WORKFLOW).to_dict(), - wf.to_dict() - ) - - def test_list_with_pagination(self): - self.requests_mock.get(self.TEST_URL + URL_TEMPLATE, - json={'workflows': [WORKFLOW], - 'next': '/workflows?fake'}) - - workflows_list = self.workflows.list( - limit=1, - sort_keys='created_at', - sort_dirs='asc' - ) - - self.assertEqual(1, len(workflows_list)) - - last_request = self.requests_mock.last_request - - # The url param order is unpredictable. - self.assertEqual(['1'], last_request.qs['limit']) - self.assertEqual(['created_at'], last_request.qs['sort_keys']) - self.assertEqual(['asc'], last_request.qs['sort_dirs']) - - def test_get(self): - url = self.TEST_URL + URL_TEMPLATE_NAME % 'wf' - self.requests_mock.get(url, json=WORKFLOW) - - wf = self.workflows.get('wf') - - self.assertIsNotNone(wf) - self.assertEqual( - workflows.Workflow(self.workflows, WORKFLOW).to_dict(), - wf.to_dict() - ) - - def test_delete(self): - url = self.TEST_URL + URL_TEMPLATE_NAME % 'wf' - self.requests_mock.delete(url, status_code=204) - - self.workflows.delete('wf') diff --git a/mistralclient/utils.py b/mistralclient/utils.py deleted file mode 100644 index 4459765..0000000 --- a/mistralclient/utils.py +++ /dev/null @@ -1,89 +0,0 @@ -# Copyright 2015 - Huawei Technologies Co. Ltd -# Copyright 2015 - StackStorm, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import json -import os -import yaml - -from six.moves.urllib import parse -from six.moves.urllib import request - -from mistralclient import exceptions - - -def do_action_on_many(action, resources, success_msg, error_msg): - """Helper to run an action on many resources.""" - failure_flag = False - - for resource in resources: - try: - action(resource) - print(success_msg % resource) - except Exception as e: - failure_flag = True - print(e) - - if failure_flag: - raise exceptions.MistralClientException(error_msg) - - -def load_content(content): - if content is None or content == '': - return dict() - - try: - data = yaml.safe_load(content) - except Exception: - data = json.loads(content) - - return data - - -def load_file(path): - with open(path, 'r') as f: - return load_content(f.read()) - - -def get_contents_if_file(contents_or_file_name): - """Get the contents of a file. - - If the value passed in is a file name or file URI, return the - contents. If not, or there is an error reading the file contents, - return the value passed in as the contents. - - For example, a workflow definition will be returned if either the - workflow definition file name, or file URI are passed in, or the - actual workflow definition itself is passed in. - """ - try: - if parse.urlparse(contents_or_file_name).scheme: - definition_url = contents_or_file_name - else: - path = os.path.abspath(contents_or_file_name) - definition_url = parse.urljoin( - 'file:', - request.pathname2url(path) - ) - return request.urlopen(definition_url).read().decode('utf8') - except Exception: - return contents_or_file_name - - -def load_json(input_string): - try: - with open(input_string) as fh: - return json.load(fh) - except IOError: - return json.loads(input_string) diff --git a/releasenotes/notes/.placeholder b/releasenotes/notes/.placeholder deleted file mode 100644 index e69de29..0000000 diff --git a/releasenotes/notes/fix-region-name-2031ff4b83b6308e.yaml b/releasenotes/notes/fix-region-name-2031ff4b83b6308e.yaml deleted file mode 100644 index 8345bd2..0000000 --- a/releasenotes/notes/fix-region-name-2031ff4b83b6308e.yaml +++ /dev/null @@ -1,6 +0,0 @@ ---- -fixes: - - | - ``--os-region-name`` or ``OS_REGION_NAME`` is fully supported now and will - be passed to Mistral service in order to get OpenStack service client for - the specific region. diff --git a/releasenotes/notes/set-default-limit-value-7e293d843d6d85ac.yaml b/releasenotes/notes/set-default-limit-value-7e293d843d6d85ac.yaml deleted file mode 100644 index 08cb1d3..0000000 --- a/releasenotes/notes/set-default-limit-value-7e293d843d6d85ac.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -critical: - - | - The "--limit" parameter of heavy CLI commands like "task-list" and - "execution-list" and "action-execution-list" is set to "100" by - default to avoid the huge load on server. To fetch the full result - set, user may use "--limit -1". diff --git a/releasenotes/source/_static/.placeholder b/releasenotes/source/_static/.placeholder deleted file mode 100644 index e69de29..0000000 diff --git a/releasenotes/source/_templates/.placeholder b/releasenotes/source/_templates/.placeholder deleted file mode 100644 index e69de29..0000000 diff --git a/releasenotes/source/conf.py b/releasenotes/source/conf.py deleted file mode 100644 index 31ea0dd..0000000 --- a/releasenotes/source/conf.py +++ /dev/null @@ -1,273 +0,0 @@ -# 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. -# -# Mistral documentation build configuration file, created by -# sphinx-quickstart on Fri Nov 1 02:06:28 2013. -# -# 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. - -# import sys, os -import pbr.version - -# 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', -] - -# 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'Mistral Client Release Notes' -copyright = u'2016, Mistral developers' - -# 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. - -mistralclient_version = pbr.version.VersionInfo('python-mistralclient') -# The short X.Y version. -version = mistralclient_version.canonical_version_string() -# The full version, including alpha/beta/rc tags. -release = mistralclient_version.version_string_with_vcs() - -# 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' -# Must set this variable to include year, month, day, hours, and minutes. -html_last_updated_fmt = '%Y-%m-%d %H:%M' - -# 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 = [] - - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'openstackdocs' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -# html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -# html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -# html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -# html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -# html_static_path = ['_static'] - -# 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 = 'MistralreleaseNotesdoc' - - -# -- 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]). -latex_documents = [ - ('index', 'MistralClientReleaseNotes.tex', - u'Mistral Client Release Notes Documentation', - u'Mistral 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', 'mistral_clientreleasenotes', - u'Mistral Client Release Notes Documentation', - [u'Mistral 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', 'MistralClientReleaseNotes', - u'Mistral Client Release Notes Documentation', - u'Mistral developers', 'MistralClientReleaseNotes', - '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' - -# -- Options for Internationalization output ------------------------------ -locale_dirs = ['locale/'] - -# -- Options for openstackdocstheme ------------------------------------------- -repository_name = 'openstack/python-mistralclient' -bug_project = 'python-mistralclient' -bug_tag = '' diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst deleted file mode 100644 index fc9c549..0000000 --- a/releasenotes/source/index.rst +++ /dev/null @@ -1,14 +0,0 @@ -Mistral Client Release Notes -============================ - -Contents -======== - -.. toctree:: - :maxdepth: 2 - - unreleased - ocata - newton - mitaka - liberty diff --git a/releasenotes/source/liberty.rst b/releasenotes/source/liberty.rst deleted file mode 100644 index 67b4cd9..0000000 --- a/releasenotes/source/liberty.rst +++ /dev/null @@ -1,6 +0,0 @@ -============================ -Liberty Series Release Notes -============================ - -.. release-notes:: - :branch: origin/stable/liberty diff --git a/releasenotes/source/mitaka.rst b/releasenotes/source/mitaka.rst deleted file mode 100644 index 05ed3e4..0000000 --- a/releasenotes/source/mitaka.rst +++ /dev/null @@ -1,6 +0,0 @@ -=========================== -Mitaka Series Release Notes -=========================== - -.. release-notes:: - :branch: origin/stable/mitaka diff --git a/releasenotes/source/newton.rst b/releasenotes/source/newton.rst deleted file mode 100644 index a737f9a..0000000 --- a/releasenotes/source/newton.rst +++ /dev/null @@ -1,6 +0,0 @@ -=========================== -Newton Series Release Notes -=========================== - -.. release-notes:: - :branch: origin/stable/newton diff --git a/releasenotes/source/ocata.rst b/releasenotes/source/ocata.rst deleted file mode 100644 index ebe62f4..0000000 --- a/releasenotes/source/ocata.rst +++ /dev/null @@ -1,6 +0,0 @@ -=================================== - Ocata Series Release Notes -=================================== - -.. release-notes:: - :branch: origin/stable/ocata diff --git a/releasenotes/source/unreleased.rst b/releasenotes/source/unreleased.rst deleted file mode 100644 index 875030f..0000000 --- a/releasenotes/source/unreleased.rst +++ /dev/null @@ -1,5 +0,0 @@ -============================ -Current Series Release Notes -============================ - -.. release-notes:: diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 4bb4c29..0000000 --- a/requirements.txt +++ /dev/null @@ -1,13 +0,0 @@ -# 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.8.0 # Apache-2.0 -osc-lib>=1.7.0 # Apache-2.0 -oslo.utils>=3.20.0 # Apache-2.0 -oslo.i18n!=3.15.2,>=2.1.0 # Apache-2.0 -pbr!=2.1.0,>=2.0.0 # Apache-2.0 -python-keystoneclient>=3.8.0 # Apache-2.0 -PyYAML>=3.10.0 # MIT -requests>=2.14.2 # Apache-2.0 -six>=1.9.0 # MIT -stevedore>=1.20.0 # Apache-2.0 diff --git a/run_functional_tests.sh b/run_functional_tests.sh deleted file mode 100755 index 90d9488..0000000 --- a/run_functional_tests.sh +++ /dev/null @@ -1,50 +0,0 @@ -#! /usr/bin/env bash - -ARG=$1 - -export USER_AUTH_SETTING=$(echo $OS_AUTH_URL) - -function pre_hook() { - export WITHOUT_AUTH="True" - IS_TEMPEST=$(pip freeze | grep tempest) - if [ -z "$IS_TEMPEST" ] - then echo "$(tput setaf 4)No such module 'tempest' in the system. Before running this script please install tempest module using : pip install git+http://github.com/openstack/tempest.git$(tput sgr 0)" - fi -} - -function run_tests_by_version() { - export OS_AUTH_URL="" - echo "$(tput setaf 4)Running integration CLI and python-mistralclient tests for v$1$(tput sgr 0)" - export VERSION="v$1" - nosetests -v mistralclient/tests/functional/cli/v$1/ - nosetests -v mistralclient/tests/functional/client/v$1/ - unset VERSION -} - -function run_tests() { - if [ -z "$ARG" ] - then - run_tests_by_version 1 - run_tests_by_version 2 - elif [ "$ARG" == "v1" ] - then - run_tests_by_version 1 - elif [ "$ARG" == "v2" ] - then - run_tests_by_version 2 - fi -} - -function post_hook () { - unset LOCAL_RUN - export OS_AUTH_URL=$USER_AUTH_SETTING - unset USER_AUTH_SETTING -} -#----------main-part---------- - -echo "$(tput setaf 4)Preparation for tests running...$(tput sgr 0)" -pre_hook -echo "$(tput setaf 4)Running tests...$(tput sgr 0)" -run_tests - -post_hook diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 06946c3..0000000 --- a/setup.cfg +++ /dev/null @@ -1,129 +0,0 @@ -[metadata] -name = python-mistralclient -summary = Mistral Client Library -description-file = README.rst -license = Apache Software License -classifiers = - Programming Language :: Python - Programming Language :: Python :: 2 - Programming Language :: Python :: 2.7 - Programming Language :: Python :: 3 - Programming Language :: Python :: 3.5 - Environment :: OpenStack - Intended Audience :: Information Technology - Intended Audience :: System Administrators - License :: OSI Approved :: Apache Software License - Operating System :: POSIX :: Linux -author = OpenStack -author-email = openstack-dev@lists.openstack.org -home-page = https://docs.openstack.org/python-mistralclient/latest/ - -[files] -packages = - mistralclient - -[build_sphinx] -builders = html,man -source-dir = doc/source -build-dir = doc/build -all_files = 1 -warning-is-error = 1 - -[upload_sphinx] -upload-dir = doc/build/html - -[entry_points] -console_scripts = - mistral = mistralclient.shell:main - -openstack.cli.extension = - workflow_engine = mistralclient.osc.plugin - -openstack.workflow_engine.v2 = - workbook_list = mistralclient.commands.v2.workbooks:List - workbook_show = mistralclient.commands.v2.workbooks:Get - workbook_create = mistralclient.commands.v2.workbooks:Create - workbook_delete = mistralclient.commands.v2.workbooks:Delete - workbook_update = mistralclient.commands.v2.workbooks:Update - workbook_definition_show = mistralclient.commands.v2.workbooks:GetDefinition - workbook_validate = mistralclient.commands.v2.workbooks:Validate - - workflow_list = mistralclient.commands.v2.workflows:List - workflow_show = mistralclient.commands.v2.workflows:Get - workflow_create = mistralclient.commands.v2.workflows:Create - workflow_delete = mistralclient.commands.v2.workflows:Delete - workflow_update = mistralclient.commands.v2.workflows:Update - workflow_definition_show = mistralclient.commands.v2.workflows:GetDefinition - workflow_validate = mistralclient.commands.v2.workflows:Validate - - workflow_env_create = mistralclient.commands.v2.environments:Create - workflow_env_delete = mistralclient.commands.v2.environments:Delete - workflow_env_update = mistralclient.commands.v2.environments:Update - workflow_env_list = mistralclient.commands.v2.environments:List - workflow_env_show = mistralclient.commands.v2.environments:Get - - action_execution_run = mistralclient.commands.v2.action_executions:Create - action_execution_list = mistralclient.commands.v2.action_executions:List - action_execution_show = mistralclient.commands.v2.action_executions:Get - action_execution_input_show = mistralclient.commands.v2.action_executions:GetInput - action_execution_output_show = mistralclient.commands.v2.action_executions:GetOutput - action_execution_update = mistralclient.commands.v2.action_executions:Update - action_execution_delete = mistralclient.commands.v2.action_executions:Delete - - workflow_execution_create = mistralclient.commands.v2.executions:Create - workflow_execution_delete = mistralclient.commands.v2.executions:Delete - workflow_execution_update = mistralclient.commands.v2.executions:Update - workflow_execution_list = mistralclient.commands.v2.executions:List - workflow_execution_show = mistralclient.commands.v2.executions:Get - workflow_execution_input_show = mistralclient.commands.v2.executions:GetInput - workflow_execution_output_show = mistralclient.commands.v2.executions:GetOutput - - task_execution_list = mistralclient.commands.v2.tasks:List - task_execution_show = mistralclient.commands.v2.tasks:Get - task_execution_published_show = mistralclient.commands.v2.tasks:GetPublished - task_execution_result_show = mistralclient.commands.v2.tasks:GetResult - task_execution_rerun = mistralclient.commands.v2.tasks:Rerun - - action_definition_list = mistralclient.commands.v2.actions:List - action_definition_show = mistralclient.commands.v2.actions:Get - action_definition_create = mistralclient.commands.v2.actions:Create - action_definition_delete = mistralclient.commands.v2.actions:Delete - action_definition_update = mistralclient.commands.v2.actions:Update - action_definition_definition_show = mistralclient.commands.v2.actions:GetDefinition - - cron_trigger_list = mistralclient.commands.v2.cron_triggers:List - cron_trigger_show = mistralclient.commands.v2.cron_triggers:Get - cron_trigger_create = mistralclient.commands.v2.cron_triggers:Create - cron_trigger_delete = mistralclient.commands.v2.cron_triggers:Delete - - event_trigger_list = mistralclient.commands.v2.event_triggers:List - event_trigger_show = mistralclient.commands.v2.event_triggers:Get - event_trigger_create = mistralclient.commands.v2.event_triggers:Create - event_trigger_delete = mistralclient.commands.v2.event_triggers:Delete - - workflow_engine_service_list = mistralclient.commands.v2.services:List - - resource_member_list = mistralclient.commands.v2.members:List - resource_member_show = mistralclient.commands.v2.members:Get - resource_member_create = mistralclient.commands.v2.members:Create - resource_member_delete = mistralclient.commands.v2.members:Delete - resource_member_update = mistralclient.commands.v2.members:Update - -mistralclient.auth = - # Standard Keystone authentication. - keystone = mistralclient.auth.keystone:KeystoneAuthHandler - - # Authentication using OpenID Connect protocol but specific to KeyCloak - # server regarding multi-tenancy support. KeyCloak has a notion of realm - # used as an analog of Keystone project/tenant. - keycloak-oidc = mistralclient.auth.keycloak:KeycloakAuthHandler - -[nosetests] -cover-package = mistralclient - -[extract_messages] -keywords = _ gettext ngettext l_ lazy_gettext - -[pbr] -autodoc_index_modules = True -warnerrors = True diff --git a/setup.py b/setup.py deleted file mode 100644 index 566d844..0000000 --- a/setup.py +++ /dev/null @@ -1,29 +0,0 @@ -# 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) diff --git a/test-requirements.txt b/test-requirements.txt deleted file mode 100644 index e0d494b..0000000 --- a/test-requirements.txt +++ /dev/null @@ -1,14 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. -hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0 -python-openstackclient!=3.10.0,>=3.3.0 # Apache-2.0 -sphinx>=1.6.2 # BSD -mock>=2.0 # BSD -nose # LGPL -oslotest>=1.10.0 # Apache-2.0 -requests-mock>=1.1 # Apache-2.0 -tempest>=16.1.0 # Apache-2.0 -osprofiler>=1.4.0 # Apache-2.0 -reno!=2.3.1,>=1.8.0 # Apache-2.0 -openstackdocstheme>=1.11.0 # Apache-2.0 diff --git a/tools/config/generate_sample.sh b/tools/config/generate_sample.sh deleted file mode 100755 index 29fb346..0000000 --- a/tools/config/generate_sample.sh +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env bash - -print_hint() { - echo "Try \`${0##*/} --help' for more information." >&2 -} - -PARSED_OPTIONS=$(getopt -n "${0##*/}" -o hb:p:o: \ - --long help,base-dir:,package-name:,output-dir: -- "$@") - -if [ $? != 0 ] ; then print_hint ; exit 1 ; fi - -eval set -- "$PARSED_OPTIONS" - -while true; do - case "$1" in - -h|--help) - echo "${0##*/} [options]" - echo "" - echo "options:" - echo "-h, --help show brief help" - echo "-b, --base-dir=DIR project base directory" - echo "-p, --package-name=NAME project package name" - echo "-o, --output-dir=DIR file output directory" - exit 0 - ;; - -b|--base-dir) - shift - BASEDIR=`echo $1 | sed -e 's/\/*$//g'` - shift - ;; - -p|--package-name) - shift - PACKAGENAME=`echo $1` - shift - ;; - -o|--output-dir) - shift - OUTPUTDIR=`echo $1 | sed -e 's/\/*$//g'` - shift - ;; - --) - break - ;; - esac -done - -BASEDIR=${BASEDIR:-`pwd`} -if ! [ -d $BASEDIR ] -then - echo "${0##*/}: missing project base directory" >&2 ; print_hint ; exit 1 -elif [[ $BASEDIR != /* ]] -then - BASEDIR=$(cd "$BASEDIR" && pwd) -fi - -PACKAGENAME=${PACKAGENAME:-${BASEDIR##*/}} -TARGETDIR=$BASEDIR/$PACKAGENAME -if ! [ -d $TARGETDIR ] -then - echo "${0##*/}: invalid project package name" >&2 ; print_hint ; exit 1 -fi - -OUTPUTDIR=${OUTPUTDIR:-$BASEDIR/etc} -# NOTE(bnemec): Some projects put their sample config in etc/, -# some in etc/$PACKAGENAME/ -if [ -d $OUTPUTDIR/$PACKAGENAME ] -then - OUTPUTDIR=$OUTPUTDIR/$PACKAGENAME -elif ! [ -d $OUTPUTDIR ] -then - echo "${0##*/}: cannot access \`$OUTPUTDIR': No such file or directory" >&2 - exit 1 -fi - -BASEDIRESC=`echo $BASEDIR | sed -e 's/\//\\\\\//g'` -find $TARGETDIR -type f -name "*.pyc" -delete -FILES=$(find $TARGETDIR -type f -name "*.py" ! -path "*/tests/*" \ - -exec grep -l "Opt(" {} + | sed -e "s/^$BASEDIRESC\///g" | sort -u) - -EXTRA_MODULES_FILE="`dirname $0`/oslo.config.generator.rc" -if test -r "$EXTRA_MODULES_FILE" -then - source "$EXTRA_MODULES_FILE" -fi - -export EVENTLET_NO_GREENDNS=yes - -OS_VARS=$(set | sed -n '/^OS_/s/=[^=]*$//gp' | xargs) -[ "$OS_VARS" ] && eval "unset \$OS_VARS" -DEFAULT_MODULEPATH=mistral.openstack.common.config.generator -MODULEPATH=${MODULEPATH:-$DEFAULT_MODULEPATH} -OUTPUTFILE=$OUTPUTDIR/$PACKAGENAME.conf.sample -python -m $MODULEPATH $FILES > $OUTPUTFILE - -# Hook to allow projects to append custom config file snippets -CONCAT_FILES=$(ls $BASEDIR/tools/config/*.conf.sample 2>/dev/null) -for CONCAT_FILE in $CONCAT_FILES; do - cat $CONCAT_FILE >> $OUTPUTFILE -done diff --git a/tools/mistral.bash_completion b/tools/mistral.bash_completion deleted file mode 100644 index 9bc24e8..0000000 --- a/tools/mistral.bash_completion +++ /dev/null @@ -1,25 +0,0 @@ -_mistral_opts="" # lazy init -_mistral_flags="" # lazy init -_mistral_opts_exp="" # lazy init -_mistral() -{ - local cur prev mbc cflags - COMPREPLY=() - cur="${COMP_WORDS[COMP_CWORD]}" - prev="${COMP_WORDS[COMP_CWORD-1]}" - - if [ "x$_mistral_opts" == "x" ] ; then - mbc="`mistral bash-completion`" - _mistral_opts="`echo "$mbc" | sed -e "s/\s-[a-z0-9_-]*//g" -e "s/\s\s*/ /g"`" - _mistral_flags="`echo " $mbc" | sed -e "s/ [^-][^-][a-z0-9_-]*//g" -e "s/\s\s*/ /g"`" - _mistral_opts_exp="`echo "$_mistral_opts" | sed -e "s/\s/|/g"`" - fi - - if [[ " ${COMP_WORDS[@]} " =~ " "($_mistral_opts_exp)" " && "$prev" != "help" ]] ; then - COMPREPLY=($(compgen -W "${_mistral_flags}" -- ${cur})) - else - COMPREPLY=($(compgen -W "${_mistral_opts}" -- ${cur})) - fi - return 0 -} -complete -F _mistral mistral diff --git a/tools/run_pep8 b/tools/run_pep8 deleted file mode 100755 index 256ec83..0000000 --- a/tools/run_pep8 +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -tox -epep8 diff --git a/tools/tox_install.sh b/tools/tox_install.sh deleted file mode 100755 index 8c37fd1..0000000 --- a/tools/tox_install.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env bash - -# Upper constraint file contains mistralclient version pin that is in -# conflict with installing mistral from source. We should replace -# the version pin in the constraints file before applying it for from-source -# installation. - -ZUUL_CLONER=/usr/zuul-env/bin/zuul-cloner -BRANCH_NAME=master -MODULE_NAME=python-mistralclient -requirements_installed=$(echo "import openstack_requirements" | python 2>/dev/null ; echo $?) - -set -e - -CONSTRAINTS_FILE=$1 -shift - -install_cmd="pip install" -mydir=$(mktemp -dt "$MODULE_NAME-tox_install-XXXXXXX") -trap "rm -rf $mydir" EXIT -localfile=$mydir/upper-constraints.txt -if [[ $CONSTRAINTS_FILE != http* ]]; then - CONSTRAINTS_FILE=file://$CONSTRAINTS_FILE -fi -curl $CONSTRAINTS_FILE -k -o $localfile -install_cmd="$install_cmd -c$localfile" - -if [ $requirements_installed -eq 0 ]; then - echo "ALREADY INSTALLED" > /tmp/tox_install.txt - echo "Requirements already installed; using existing package" -elif [ -x "$ZUUL_CLONER" ]; then - echo "ZUUL CLONER" > /tmp/tox_install.txt - pushd $mydir - $ZUUL_CLONER --cache-dir \ - /opt/git \ - --branch $BRANCH_NAME \ - git://git.openstack.org \ - openstack/requirements - cd openstack/requirements - $install_cmd -e . - popd -else - echo "PIP HARDCODE" > /tmp/tox_install.txt - if [ -z "$REQUIREMENTS_PIP_LOCATION" ]; then - REQUIREMENTS_PIP_LOCATION="git+https://git.openstack.org/openstack/requirements@$BRANCH_NAME#egg=requirements" - fi - $install_cmd -U -e ${REQUIREMENTS_PIP_LOCATION} -fi - -# This is the main purpose of the script: Allow local installation of -# the current repo. It is listed in constraints file and thus any -# install will be constrained and we need to unconstrain it. -edit-constraints $localfile -- $MODULE_NAME "-e file://$PWD#egg=$MODULE_NAME" - -$install_cmd -U $* -exit $? diff --git a/tools/update_env_deps b/tools/update_env_deps deleted file mode 100755 index 5551daf..0000000 --- a/tools/update_env_deps +++ /dev/null @@ -1,16 +0,0 @@ -TOX_ENVLIST=`grep envlist tox.ini | cut -d '=' -f 2 | tr ',' ' '` -TESTENVS=`grep testenv tox.ini | awk -F ':' '{print $2}' | tr '[]' ' '` -UNFILTERED_ENVLIST=`echo "$TOX_ENVLIST $TESTENVS"` -ENVLIST=$( awk 'BEGIN{RS=ORS=" "}!a[$0]++' <<<$UNFILTERED_ENVLIST ); -for env in $ENVLIST -do - ENV_PATH=.tox/$env - PIP_PATH=$ENV_PATH/bin/pip - echo -e "\nUpdate environment ${env}...\n" - if [ ! -d $ENV_PATH -o ! -f $PIP_PATH ] - then - tox --notest -e$env - else - $PIP_PATH install -r requirements.txt -r test-requirements.txt - fi -done diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 66ae77d..0000000 --- a/tox.ini +++ /dev/null @@ -1,54 +0,0 @@ -[tox] -envlist = py35,py27,pep8 -minversion = 1.6 -skipsdist = True - -[testenv] -usedevelop = True -install_command = {toxinidir}/tools/tox_install.sh {env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages} -setenv = - VIRTUAL_ENV={envdir} - NOSE_WITH_OPENSTACK=1 - NOSE_OPENSTACK_COLOR=1 - NOSE_OPENSTACK_RED=0.05 - NOSE_OPENSTACK_YELLOW=0.025 - NOSE_OPENSTACK_SHOW_ELAPSED=1 - NOSE_OPENSTACK_STDOUT=1 - NOSE_XUNIT=1 - DISCOVER_DIRECTORY=mistralclient/tests/unit -passenv = http_proxy HTTP_PROXY https_proxy HTTPS_PROXY no_proxy NO_PROXY -deps = - -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt -commands = - find . -type f -name "*.pyc" -delete - nosetests mistralclient/tests/unit -whitelist_externals = find - rm -[testenv:functional] -setenv = - OS_TEST_PATH = ./mistralclient/tests/functional -commands = {posargs} - -[testenv:pep8] -commands = flake8 {posargs} - -[testenv:venv] -commands = {posargs} - -[testenv:docs] -commands = - rm -rf doc/html doc/build - rm -rf doc/source/apidoc doc/source/api - python setup.py build_sphinx - -[flake8] -# H106: Don’t put vim configuration in source files -# H203: Use assertIs(Not)None to check for None -enable-extensions=H106,H203 -show-source = true -builtins = _ -exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,tools - -[testenv:releasenotes] -commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html