python-watcherclient-2.2.0/ 0000775 0001750 0001750 00000000000 13364113665 015720 5 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/lower-constraints.txt 0000666 0001750 0001750 00000003015 13364113436 022153 0 ustar zuul zuul 0000000 0000000 alabaster==0.7.10
appdirs==1.4.3
asn1crypto==0.23.0
Babel==2.5.3
certifi==2018.1.18
cffi==1.7.0
chardet==3.0.4
cliff==2.11.0
cmd2==0.8.2
coverage==4.0
cryptography==2.1
debtcollector==1.19.0
decorator==4.2.1
deprecation==2.0
docutils==0.11
dogpile.cache==0.6.5
dulwich==0.15.0
extras==1.0.0
fasteners==0.7.0
fixtures==3.0.0
flake8==2.5.5
future==0.16.0
hacking==0.12.0
idna==2.6
imagesize==0.7.1
iso8601==0.1.12
Jinja2==2.10
jmespath==0.9.3
jsonpatch==1.21
jsonpointer==2.0
jsonschema==2.6.0
keystoneauth1==3.4.0
linecache2==1.0.0
MarkupSafe==1.0
mccabe==0.2.1
mock==2.0.0
monotonic==1.4
mox3==0.20.0
msgpack-python==0.4.0
munch==2.2.0
netaddr==0.7.19
netifaces==0.10.6
openstackdocstheme==1.18.1
openstacksdk==0.12.0
os-client-config==1.29.0
os-service-types==1.2.0
os-testr==1.0.0
osc-lib==1.10.0
oslo.concurrency==3.25.0
oslo.config==5.2.0
oslo.context==2.19.2
oslo.i18n==3.20.0
oslo.log==3.36.0
oslo.serialization==2.18.0
oslo.utils==3.36.0
oslotest==3.2.0
packaging==17.1
paramiko==2.0.0
pbr==3.1.1
pep8==1.5.7
prettytable==0.7.2
pyasn1==0.1.8
pycparser==2.18
pyflakes==0.8.1
Pygments==2.2.0
pyinotify==0.9.6
pyparsing==2.2.0
pyperclip==1.6.0
python-dateutil==2.5.3
python-mimeparse==1.6.0
python-subunit==1.0.0
pytz==2018.3
PyYAML==3.12
requests==2.18.4
requestsexceptions==1.4.0
rfc3986==0.3.1
simplejson==3.13.2
six==1.11.0
snowballstemmer==1.2.1
Sphinx==1.6.5
sphinxcontrib-websupport==1.0.1
stestr==2.0.0
stevedore==1.28.0
tempest==17.1.0
testscenarios==0.4
testtools==2.2.0
traceback2==1.4.0
unittest2==1.1.0
urllib3==1.22
wrapt==1.10.11
python-watcherclient-2.2.0/requirements.txt 0000666 0001750 0001750 00000000762 13364113436 021207 0 ustar zuul zuul 0000000 0000000 # 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.
Babel!=2.4.0,>=2.5.3 # BSD
cliff!=2.9.0,>=2.11.0 # Apache-2.0
osc-lib>=1.10.0 # Apache-2.0
oslo.i18n>=3.20.0 # Apache-2.0
oslo.utils>=3.36.0 # Apache-2.0
pbr!=2.1.0,>=3.1.1 # Apache-2.0
PrettyTable<0.8,>=0.7.2 # BSD
keystoneauth1>=3.4.0 # Apache-2.0
six>=1.11.0 # MIT
PyYAML>=3.12 # MIT
python-watcherclient-2.2.0/HACKING.rst 0000666 0001750 0001750 00000000242 13364113436 017512 0 ustar zuul zuul 0000000 0000000 python-watcherclient Style Commandments
=======================================
Read the OpenStack Style Commandments https://docs.openstack.org/hacking/latest/
python-watcherclient-2.2.0/tools/ 0000775 0001750 0001750 00000000000 13364113665 017060 5 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/tools/watcher.bash_completion 0000666 0001750 0001750 00000002004 13364113436 023577 0 ustar zuul zuul 0000000 0000000 _watcher_opts="" # lazy init
_watcher_flags="" # lazy init
_watcher_opts_exp="" # lazy init
_watcher()
{
local cur prev nbc cflags
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
if [ "x$_watcher_opts" == "x" ] ; then
nbc="`watcher bash-completion | sed -e "s/ *-h */ /" -e "s/ *-i */ /"`"
_watcher_opts="`echo "$nbc" | sed -e "s/--[a-z0-9_-]*//g" -e "s/ */ /g"`"
_watcher_flags="`echo " $nbc" | sed -e "s/ [^-][^-][a-z0-9_-]*//g" -e "s/ */ /g"`"
_watcher_opts_exp="`echo "$_watcher_opts" | tr ' ' '|'`"
fi
if [[ " ${COMP_WORDS[@]} " =~ " "($_watcher_opts_exp)" " && "$prev" != "help" ]] ; then
COMPLETION_CACHE=$HOME/.cache/python-watcherclient/*/*-cache
cflags="$_watcher_flags "$(cat $COMPLETION_CACHE 2> /dev/null | tr '\n' ' ')
COMPREPLY=($(compgen -W "${cflags}" -- ${cur}))
else
COMPREPLY=($(compgen -W "${_watcher_opts}" -- ${cur}))
fi
return 0
}
complete -F _watcher watcher
python-watcherclient-2.2.0/babel.cfg 0000666 0001750 0001750 00000000021 13364113436 017435 0 ustar zuul zuul 0000000 0000000 [python: **.py]
python-watcherclient-2.2.0/README.rst 0000666 0001750 0001750 00000007721 13364113436 017414 0 ustar zuul zuul 0000000 0000000 ========================
Team and repository tags
========================
.. image:: https://governance.openstack.org/tc/badges/python-watcherclient.svg
:target: https://governance.openstack.org/tc/reference/tags/index.html
.. Change things from this point on
====================
python-watcherclient
====================
Client for resource optimization service for OpenStack.
OpenStack Watcher provides a flexible and scalable resource optimization
service for multi-tenant OpenStack-based clouds.
Watcher provides a complete optimization loop-including everything from a
metrics receiver, complex event processor and profiler, optimization processor
and an action plan applier. This provides a robust framework to realize a wide
range of cloud optimization goals, including the reduction of data center
operating costs, increased system performance via intelligent virtual machine
migration, increased energy efficiency and more!
* Free software: Apache license
* Wiki: https://wiki.openstack.org/wiki/Watcher
* Source: https://git.openstack.org/cgit/openstack/python-watcher
* Bugs: https://bugs.launchpad.net/watcher
Installation
============
Install the prerequisite packages
---------------------------------
On Ubuntu (tested on 14.04-64)
.. code::
sudo apt-get install python-dev libssl-dev python-pip git-core libmysqlclient-dev libffi-dev
On Fedora-based distributions e.g., Fedora/RHEL/CentOS/Scientific Linux (tested on CentOS 6.5)
.. code::
sudo yum install python-virtualenv openssl-devel python-pip git gcc libffi-devel mysql-devel postgresql-devel
On openSUSE-based distributions (SLES 12, openSUSE 13.1, Factory or Tumbleweed)
.. code::
sudo zypper install gcc git libmysqlclient-devel libopenssl-devel postgresql-devel python-devel python-pip
Install the Watcher client
--------------------------
You can install the Watcher CLI with the following command:
.. code::
sudo pip install python-watcherclient
You can also use the `OpenStack client `_
with Watcher (our watcher plugin for OpenStack client is included in the
python-watcherclient package). To install it, you have just to run this command:
.. code::
sudo pip install python-openstackclient
Configuration
=============
Create a **creds** file containing your OpenStack credentials:
.. code::
export OS_IDENTITY_API_VERSION=3
export OS_AUTH_URL=http://:5000/v3
export OS_PROJECT_DOMAIN_ID=default
export OS_USER_DOMAIN_ID=default
export OS_USERNAME=admin
export OS_PASSWORD=
export OS_PROJECT_NAME=
Source these credentials into your current shell session:
.. code::
# source creds
You should be able to launch the following command which gets the list of
previously created Audit Templates:
.. code::
# watcher audittemplate list
or::
# openstack optimize audittemplate list
+--------------------------------+------+----------------------+----------+
| UUID | Name | Goal | Strategy |
+--------------------------------+------+----------------------+----------+
+--------------------------------+------+----------------------+----------+
You can view the entire list of available Watcher commands and options using
this command:
.. code::
# watcher help
or::
# openstack help optimize
Troubleshootings
================
If any watcher command fails, you can obtain more details with the **--debug**
option :
.. code::
# watcher --debug audittemplate list
or::
# openstack --debug optimize audittemplate list
Install the openstack CLI :
.. code::
# pip install python-openstackclient
Make sure that your Openstack credentials are correct. If so, you should be able
to verify that the watcher user has been declared in your Openstack keystone :
.. code::
# openstack user list
and that the watcher endpoints have been declared as well :
.. code::
# openstack endpoint list
python-watcherclient-2.2.0/setup.py 0000666 0001750 0001750 00000002006 13364113436 017426 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
import setuptools
# In python < 2.7.4, a lazy loading of package `pbr` will break
# setuptools if some other modules registered functions in `atexit`.
# solution from: http://bugs.python.org/issue15881#msg170215
try:
import multiprocessing # noqa
except ImportError:
pass
setuptools.setup(
setup_requires=['pbr>=2.0.0'],
pbr=True)
python-watcherclient-2.2.0/tox.ini 0000666 0001750 0001750 00000003711 13364113436 017233 0 ustar zuul zuul 0000000 0000000 [tox]
minversion = 1.8
envlist = py35,py27,pep8
skipsdist = True
[testenv]
usedevelop = True
install_command =
constraints: pip install -U --force-reinstall -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages}
pip install -U {opts} {packages}
setenv =
VIRTUAL_ENV={envdir}
deps = -r{toxinidir}/test-requirements.txt
commands = rm -f .testrepository/times.dbm
stestr --test-path=./watcherclient/tests/unit run {posargs}
stestr slowest
[testenv:pep8]
basepython = python3
commands = flake8
[testenv:venv]
basepython = python3
commands = {posargs}
[testenv:cover]
basepython = python3
setenv =
PYTHON=coverage run --source watcherclient --parallel-mode
commands =
stestr run {posargs}
coverage combine
coverage html -d cover
coverage xml -o cover/coverage.xml
coverage report
[testenv:docs]
basepython = python3
commands = python setup.py build_sphinx
[testenv:debug]
basepython = python3
commands = oslo_debug_helper -t watcherclient/tests/unit {posargs}
[testenv:functional]
basepython = python2.7
passenv =
OS_PROJECT_DOMAIN_NAME
OS_USER_DOMAIN_NAME
OS_PROJECT_NAME
OS_USERNAME
OS_PASSWORD
OS_AUTH_URL
OS_IDENTITY_API_VERSION
OS_IMAGE_API_VERSION
commands = stestr --test-path=./watcherclient/tests/functional run --concurrency=1 {posargs}
stestr slowest
[flake8]
# E123, E125 skipped as they are invalid PEP-8.
show-source = True
enable-extensions = H203,H106
ignore = E123,E125
builtins = _
exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build
[testenv:wheel]
basepython = python3
commands = python setup.py bdist_wheel
[hacking]
import_exceptions = watcherclient._i18n
[testenv:lower-constraints]
basepython = python3
install_command = pip install -U {opts} {packages}
deps =
-c{toxinidir}/lower-constraints.txt
-r{toxinidir}/test-requirements.txt
-r{toxinidir}/requirements.txt
python-watcherclient-2.2.0/AUTHORS 0000664 0001750 0001750 00000005127 13364113665 016775 0 ustar zuul zuul 0000000 0000000 Alexander Chadin
Alexander Chadin
Alexandr Stavitskiy
Andreas Jaeger
Antoine Cabot
Cao Xuan Hoang
Chihiro Yokoyama
Chris Spencer
Daniel Pawlik
Dao Cong Tien
David TARDIVEL
David.T
DeepaJon
Doug Hellmann
Dougal Matthews
Edwin Zhai
Flavio Percoco
Hangdong Zhang
Hidekazu Nakamura
James E. Blair
Jean-Emile DARTOIS
Jeremy Liu
Jeremy Stanley
Larry Rensing
Lucky samadhiya
Luong Anh Tuan
M V P Nitesh
Nam Nguyen Hoai
Nguyen Hai
PanFengyun
Prashanth Hari
Steve Martinelli
Swapnil Kulkarni (coolsvap)
Taylor Peoples
Tin Lam
Tin Lam
Tomasz Kaczynski
Tony Xu
Vincent Francoise
Vladimir Ostroverkhov
Yumeng Bao
aditi
aditi
avnish
blue55
caihui
chenke
daohanli
deepak_mourya
digambar
ericxiett
gecong1973
gengchc2
hongzhezheng
huang.zhiping
kavithahr
licanwei
melissaml
qinchunhua
rajat29
ricolin
ricolin
shu-mutou
suzhengwei
venkatamahesh
zhangguoqing
zhangyangyang
zhurong
zhuzeyu
zte-hanrong
python-watcherclient-2.2.0/ChangeLog 0000664 0001750 0001750 00000020517 13364113665 017477 0 ustar zuul zuul 0000000 0000000 CHANGES
=======
2.2.0
-----
* Allow CLI to pass goal and strategy names
* Use templates lower-constraints, remove cover
* Switch to stestr
* add python 3.6 unit test job
* switch documentation job to new PTI
* import zuul job settings from project-config
* fix watcher actionplan show command
* Update watcher strategy state in CLI
* Add --marker help info
* Organize the use of 'log' and replace 'log' with LOG
* Add audit name to CLI help doc
2.1.0
-----
* Fix watherclient error in py3
* Add --marker help info
* Add hostname field to support HA
* Invalid doc for Client exceptions
* Don't run voting jobs in gate
* fix tox python3 overrides
2.0.0
-----
* Modify Watcher start actionplan command
* Remove 'actionplan create' command
1.7.0
-----
* [WiP] functional jobs fix
* ZuulV3 support for watcherclient
* add lower-constraints job
* Add tempest plugin
* Delete the unnecessary '-'
* Updated from global requirements
* Updated from global requirements
* Update links in README
* Updated from global requirements
* Fix global efficacy format
* Zuul: Remove project name
1.6.0
-----
* Add strategy state command
* Updated from global requirements
* Updated from global requirements
* Updated from global requirements
* Audit Template Help Message
* Fix test\_action\_plan functional tests
* Updated from global requirements
* Fix watcher actionplan list command
1.5.0
-----
* Migrate to Zuul v3
* Updated from global requirements
* Update audit\_template create help message
* marker when retrive audit
* marker when retrive action
* marker when retrive audit template
* Add --marker for 'watcher actionplan list'
* Updated from global requirements
* Updated from global requirements
* Multiple global efficacy
* add name for audit, changes for python-watcherclient
* Fix unnecessary retries during conflict
* Use generic user for both zuul v2 and v3
1.4.0
-----
* Updated from global requirements
* Update audit\_template create help message
* Fix gate-watcherclient-dsvm-functional-ubuntu-xenial job
* Updated from global requirements
* Updated from global requirements
* Updated from global requirements
* Fix to use "." to source script files
* import content from cli-reference in openstack-manuals
* Updated from global requirements
* Updated from global requirements
* Add the filed of description to shell command for action
1.3.0
-----
* Update .gitignore because of doc migration
* Fix Audit Update functional test
* Update the documentation link for doc migration
* Updated from global requirements
* Update permissions for post\_test\_hook.sh
* Update URLs in documents according to document migration
* Updated from global requirements
* Add support for cron syntax
* Updated from global requirements
* Fixed wrap from taking negative values
* Add post\_test\_hook
* Move existing content into the new standard structure
* Fix for README.rst of tests
* switch to openstackdocstheme
* Updated from global requirements
* Turn on warning-is-error in sphinx build
* Enable some off-by-default checks
* Updated from global requirements
* Add CLI for Action Plan Cancel
1.2.0
-----
* Updated from global requirements
* Updated from global requirements
* Updated from global requirements
* Updated from global requirements
* Add 'rm -f .testrepository/times.dbm' command in testenv
1.1.0
-----
* Updated from global requirements
* Optimize the link address
* Remove log translations
* Indicating the location tests directory in oslo\_debug\_helper
* Using assert methods instead of assertTrue
* Updated from global requirements
* [Fix gate]Update test requirement
* Remove RST files located in doc/source/api
* Remove support for py34
* update help description about actionplan create
* Using jsonutils instead of json
* Updated from global requirements
* Remove useless utf-8 coding
* Add functional env to tox
1.0.0
-----
* update '--detail' help in goal list
* Updated from global requirements
* Add functional tests to watcherclient
* Support parents field along with planner changes
* changes to make consistent with other openstack component
* Use keystoneauth instead of keystoneclient
* Remove unused files
* Enable coverage report in console output
* Add param 'goal' and 'strategy' in list()
* Removes unnecessary utf-8 encoding
* update audit create '--interval' description
* Add unit for continuous audit's interval
* Fix a typo in audittemplate help
* use 'auto' instead of None
* Add auto\_trigger support
* Fix TOKENID format which should without dashed
* too many digits after the decimal point
0.27.0
------
* Remove readme reference because of sphinx error
* Replace six.iteritems() with .items()
* Updated from global requirements
* Show team and repo badges on README
* Updated from global requirements
* Use uuidutils instead of uuid.uuid4()
0.26.0
------
* Updated from global requirements
* Remove obsolete object attributes
* Fix a typo error in a help message in the client
* Updated from global requirements
* Remove unnecessary ')'
* Add Python 3.5 classifier and venv
* Add \_\_ne\_\_ built-in function
* Updated from global requirements
* Add support for Audit Scope
* Add parameters in Audit creation attributes list
* Updated from global requirements
* Added support for Client creation from KS session
* Updated from global requirements
* Add fixtures to test-requirements
* Add constraint target to tox.ini and remove 1 dep
* Add service support
* python-openstackclient ClientManager interface changed
* Update home page link in cfg file
* Clean imports in code
0.25.0
------
* Add again parameters as Audit creation attributes
* Updated from global requirements
* Add strategy name in action plan fields
* Updated from global requirements
* remove redundant ')'
* Add goal\_id, strategy\_id and host\_aggregate CLI options to audit
* Optimiz the help information for audit type parameter
* Updated from global requirements
* Add scoring engine commands
* Remove discover from test-requirements
* Updated from global requirements
* Updated from global requirements
* Fix for importing osc-lib instead openstackclient
* Updated from global requirements
0.24.0
------
* Fix for error importing of exception class
* Add support continuously-optimization
* Remove the blank space between the function name and the parenthesis
* Prints '-' instead of 'None' when data is None
* Enable strategy parameter
* Fix field type to audit\_type
* Add license file
* Updated from global requirements
* Remove tempest-lib
* Updated from global requirements
* Revert "Add support continuously-optimization"
* Replaced UUID of goal with name
* Remove useless index on root doc page
* Updated CLI to display efficacy related fields
* Updated from global requirements
* Add support continuously-optimization
0.23.0
------
* Update Watcher CLI documentation
* Use goal name as strategy list filter
* Replaced UUID of goal and strategy with name
* Flatten the project structure
* Switch Watcher CLI to an OSC-compatible version
* OpenStackClient plugin for action
* OpenStackClient plugin for action plan
* OpenStackClient plugin for audit
* OpenStackClient plugin for audit template
* OpenStackClient plugin for strategy
* OpenStackClient plugin for goal
* Tidy up
* Use the correct capitalization of OpenStack
* Support for refactored /audit\_templates endpoint
* Added Strategy support in Watcher CLI
* Updated CLI for new /goals API
* Add PrettyTable module
* Fixed audit creation bug in CLI
* Removed unused 'alarm' field
* Add audit-template name checking in CLI
* Updated from global requirements
0.22.0
------
* Rename TRIGGERED state as PENDING
* Updated from global requirements
* Updated from global requirements
* Replace deprecated LOG.warn with LOG.warning
* Removed host\_aggregate filter for Audit Template
* Removed useless '--name' in audit-template-list
* Sync with openstack/requirements master branch
0.21.0
------
* Updated STARTING to TRIGGERED
* Remove argparse from requirements
* Fix extraction of \_LI \_LW \_LE \_LC for translation
* Update Watcher documentation in README
* i18n - Make string translatable
* Respect the import order template
* Sync Action resource fields
* Sync with oslo-incubator
* use keystoneclient exceptions instead of oslo-incubator code
* Drop py33 support
0.20.0
------
* Remove py26 support
* Update requirements from OS Global Requirements
* bug and requirements fixes
* Change stackforge to openstack
* Update .gitreview for new namespace
* update README.rst file
* push initial version
* Added .gitreview
python-watcherclient-2.2.0/.zuul.yaml 0000666 0001750 0001750 00000000540 13364113436 017656 0 ustar zuul zuul 0000000 0000000 - project:
templates:
- openstack-lower-constraints-jobs
- openstack-python-jobs
- openstack-python35-jobs
- openstack-python36-jobs
- publish-openstack-docs-pti
- check-requirements
- openstackclient-plugin-jobs
check:
jobs:
- watcherclient-tempest-functional:
voting: false
python-watcherclient-2.2.0/watcherclient/ 0000775 0001750 0001750 00000000000 13364113665 020554 5 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/watcherclient/locale/ 0000775 0001750 0001750 00000000000 13364113665 022013 5 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/watcherclient/locale/fr/ 0000775 0001750 0001750 00000000000 13364113665 022422 5 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/watcherclient/locale/fr/LC_MESSAGES/ 0000775 0001750 0001750 00000000000 13364113665 024207 5 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/watcherclient/locale/fr/LC_MESSAGES/watcherclient.po 0000666 0001750 0001750 00000015075 13364113436 027411 0 ustar zuul zuul 0000000 0000000 # French translations for python-watcherclient.
# Copyright (C) 2016 ORGANIZATION
# This file is distributed under the same license as the
# python-watcherclient project.
# FIRST AUTHOR , 2016.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: python-watcherclient 0.20.1.dev4\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2016-01-14 14:57+0100\n"
"PO-Revision-Date: 2016-01-12 02:05+0100\n"
"Last-Translator: FULL NAME \n"
"Language: fr\n"
"Language-Team: fr \n"
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.1.1\n"
#: watcherclient/client.py:103
msgid "Must provide Keystone credentials or user-defined endpoint and token"
msgstr ""
#: watcherclient/shell.py:279
#, python-format
msgid ""
"Unable to determine the Keystone version to authenticate with using the "
"given auth_url. Identity service may not support API version discovery. "
"Please provide a versioned auth_url instead. %s"
msgstr ""
#: watcherclient/shell.py:344
msgid ""
"Unable to determine the Keystone version to authenticate with using the "
"given auth_url."
msgstr ""
#: watcherclient/shell.py:380
msgid ""
"You must provide a username via either --os-username or via "
"env[OS_USERNAME]"
msgstr ""
#: watcherclient/shell.py:396
msgid ""
"You must provide a password via either --os-password, env[OS_PASSWORD], "
"or prompted response"
msgstr ""
#: watcherclient/shell.py:403
msgid ""
"You must provide a project name or project id via --os-project-name, "
"--os-project-id, env[OS_PROJECT_ID] or env[OS_PROJECT_NAME]. You may use"
" os-project and os-tenant interchangeably."
msgstr ""
#: watcherclient/shell.py:410
msgid ""
"You must provide an auth url via either --os-auth-url or via "
"env[OS_AUTH_URL]"
msgstr ""
#: watcherclient/shell.py:473
msgid "Invalid OpenStack Identity credentials"
msgstr ""
#: watcherclient/shell.py:483
#, python-format
msgid "'%s' is not a valid subcommand"
msgstr ""
#: watcherclient/common/cliutils.py:40
#, python-format
msgid "Missing arguments: %s"
msgstr ""
#: watcherclient/common/cliutils.py:158
#, python-format
msgid ""
"Field labels list %(labels)s has different number of elements than fields"
" list %(fields)s"
msgstr ""
#: watcherclient/common/http.py:88
#, python-format
msgid "Unsupported scheme: %s"
msgstr ""
#: watcherclient/common/http.py:162
#, python-format
msgid "Error finding address for %(url)s: %(e)s"
msgstr ""
#: watcherclient/common/http.py:167
#, python-format
msgid "Error communicating with %(endpoint)s %(e)s"
msgstr ""
#: watcherclient/common/http.py:181
msgid "Request returned failure status."
msgstr ""
#: watcherclient/common/http.py:213 watcherclient/common/http.py:337
msgid "Could not decode response body as JSON"
msgstr ""
#: watcherclient/common/utils.py:87
#, python-format
msgid "Attributes must be a list of PATH=VALUE not \"%s\""
msgstr ""
#: watcherclient/common/utils.py:120
#, python-format
msgid "Unknown PATCH operation: %s"
msgstr ""
#: watcherclient/common/utils.py:136
#, python-format
msgid "Expected non-negative --limit, got %s"
msgstr ""
#: watcherclient/common/utils.py:147
#, python-format
msgid ""
"%(sort_key)s is an invalid field for sorting, valid values for --sort-key"
" are: %(valid)s"
msgstr ""
#: watcherclient/common/utils.py:155
#, python-format
msgid ""
"%s is an invalid value for sort direction, valid values for --sort-dir "
"are: 'asc', 'desc'"
msgstr ""
#: watcherclient/common/apiclient/base.py:244
#: watcherclient/common/apiclient/base.py:401
#, python-format
msgid "No %(name)s matching %(args)s."
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:83
#, python-format
msgid "Authentication failed. Missing options: %s"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:92
#, python-format
msgid "AuthSystemNotFound: %r"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:115
#, python-format
msgid "AmbiguousEndpoints: %r"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:122
msgid "HTTP Error"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:142
msgid "HTTP Redirection"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:150
msgid "HTTP Client Error"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:159
msgid "HTTP Server Error"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:169
msgid "Multiple Choices"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:178
msgid "Bad Request"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:188
msgid "Unauthorized"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:197
msgid "Payment Required"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:207
msgid "Forbidden"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:217
msgid "Not Found"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:227
msgid "Method Not Allowed"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:237
msgid "Not Acceptable"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:246
msgid "Proxy Authentication Required"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:255
msgid "Request Timeout"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:265
msgid "Conflict"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:275
msgid "Gone"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:285
msgid "Length Required"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:295
msgid "Precondition Failed"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:304
msgid "Request Entity Too Large"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:321
msgid "Request-URI Too Long"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:331
msgid "Unsupported Media Type"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:341
msgid "Requested Range Not Satisfiable"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:350
msgid "Expectation Failed"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:360
msgid "Unprocessable Entity"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:369
msgid "Internal Server Error"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:380
msgid "Not Implemented"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:390
msgid "Bad Gateway"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:399
msgid "Service Unavailable"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:409
msgid "Gateway Timeout"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:418
msgid "HTTP Version Not Supported"
msgstr ""
python-watcherclient-2.2.0/watcherclient/locale/watcherclient.pot 0000666 0001750 0001750 00000015007 13364113436 025374 0 ustar zuul zuul 0000000 0000000 # Translations template for python-watcherclient.
# Copyright (C) 2016 ORGANIZATION
# This file is distributed under the same license as the
# python-watcherclient project.
# FIRST AUTHOR , 2016.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: python-watcherclient 0.20.1.dev5\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2016-01-14 14:57+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.1.1\n"
#: watcherclient/client.py:103
msgid "Must provide Keystone credentials or user-defined endpoint and token"
msgstr ""
#: watcherclient/shell.py:279
#, python-format
msgid ""
"Unable to determine the Keystone version to authenticate with using the "
"given auth_url. Identity service may not support API version discovery. "
"Please provide a versioned auth_url instead. %s"
msgstr ""
#: watcherclient/shell.py:344
msgid ""
"Unable to determine the Keystone version to authenticate with using the "
"given auth_url."
msgstr ""
#: watcherclient/shell.py:380
msgid ""
"You must provide a username via either --os-username or via "
"env[OS_USERNAME]"
msgstr ""
#: watcherclient/shell.py:396
msgid ""
"You must provide a password via either --os-password, env[OS_PASSWORD], "
"or prompted response"
msgstr ""
#: watcherclient/shell.py:403
msgid ""
"You must provide a project name or project id via --os-project-name, "
"--os-project-id, env[OS_PROJECT_ID] or env[OS_PROJECT_NAME]. You may use"
" os-project and os-tenant interchangeably."
msgstr ""
#: watcherclient/shell.py:410
msgid ""
"You must provide an auth url via either --os-auth-url or via "
"env[OS_AUTH_URL]"
msgstr ""
#: watcherclient/shell.py:473
msgid "Invalid OpenStack Identity credentials"
msgstr ""
#: watcherclient/shell.py:483
#, python-format
msgid "'%s' is not a valid subcommand"
msgstr ""
#: watcherclient/common/cliutils.py:40
#, python-format
msgid "Missing arguments: %s"
msgstr ""
#: watcherclient/common/cliutils.py:158
#, python-format
msgid ""
"Field labels list %(labels)s has different number of elements than fields"
" list %(fields)s"
msgstr ""
#: watcherclient/common/http.py:88
#, python-format
msgid "Unsupported scheme: %s"
msgstr ""
#: watcherclient/common/http.py:162
#, python-format
msgid "Error finding address for %(url)s: %(e)s"
msgstr ""
#: watcherclient/common/http.py:167
#, python-format
msgid "Error communicating with %(endpoint)s %(e)s"
msgstr ""
#: watcherclient/common/http.py:181
msgid "Request returned failure status."
msgstr ""
#: watcherclient/common/http.py:213 watcherclient/common/http.py:337
msgid "Could not decode response body as JSON"
msgstr ""
#: watcherclient/common/utils.py:87
#, python-format
msgid "Attributes must be a list of PATH=VALUE not \"%s\""
msgstr ""
#: watcherclient/common/utils.py:120
#, python-format
msgid "Unknown PATCH operation: %s"
msgstr ""
#: watcherclient/common/utils.py:136
#, python-format
msgid "Expected non-negative --limit, got %s"
msgstr ""
#: watcherclient/common/utils.py:147
#, python-format
msgid ""
"%(sort_key)s is an invalid field for sorting, valid values for --sort-key"
" are: %(valid)s"
msgstr ""
#: watcherclient/common/utils.py:155
#, python-format
msgid ""
"%s is an invalid value for sort direction, valid values for --sort-dir "
"are: 'asc', 'desc'"
msgstr ""
#: watcherclient/common/apiclient/base.py:244
#: watcherclient/common/apiclient/base.py:401
#, python-format
msgid "No %(name)s matching %(args)s."
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:83
#, python-format
msgid "Authentication failed. Missing options: %s"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:92
#, python-format
msgid "AuthSystemNotFound: %r"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:115
#, python-format
msgid "AmbiguousEndpoints: %r"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:122
msgid "HTTP Error"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:142
msgid "HTTP Redirection"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:150
msgid "HTTP Client Error"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:159
msgid "HTTP Server Error"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:169
msgid "Multiple Choices"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:178
msgid "Bad Request"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:188
msgid "Unauthorized"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:197
msgid "Payment Required"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:207
msgid "Forbidden"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:217
msgid "Not Found"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:227
msgid "Method Not Allowed"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:237
msgid "Not Acceptable"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:246
msgid "Proxy Authentication Required"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:255
msgid "Request Timeout"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:265
msgid "Conflict"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:275
msgid "Gone"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:285
msgid "Length Required"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:295
msgid "Precondition Failed"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:304
msgid "Request Entity Too Large"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:321
msgid "Request-URI Too Long"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:331
msgid "Unsupported Media Type"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:341
msgid "Requested Range Not Satisfiable"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:350
msgid "Expectation Failed"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:360
msgid "Unprocessable Entity"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:369
msgid "Internal Server Error"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:380
msgid "Not Implemented"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:390
msgid "Bad Gateway"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:399
msgid "Service Unavailable"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:409
msgid "Gateway Timeout"
msgstr ""
#: watcherclient/common/apiclient/exceptions.py:418
msgid "HTTP Version Not Supported"
msgstr ""
python-watcherclient-2.2.0/watcherclient/_i18n.py 0000666 0001750 0001750 00000002175 13364113436 022047 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
# 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 oslo_i18n
DOMAIN = "watcherclient"
_translators = oslo_i18n.TranslatorFactory(domain=DOMAIN)
# The primary translation function using the well-known name "_"
_ = _translators.primary
# The contextual translation function using the name "_C"
# requires oslo.i18n >=2.1.0
_C = _translators.contextual_form
# The plural translation function using the name "_P"
# requires oslo.i18n >=2.1.0
_P = _translators.plural_form
def get_available_languages():
return oslo_i18n.get_available_languages(DOMAIN)
python-watcherclient-2.2.0/watcherclient/tests/ 0000775 0001750 0001750 00000000000 13364113665 021716 5 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/watcherclient/tests/README.rst 0000666 0001750 0001750 00000003470 13364113436 023407 0 ustar zuul zuul 0000000 0000000 ..
Except where otherwise noted, this document is licensed under Creative
Commons Attribution 3.0 License. You can view the license at:
https://creativecommons.org/licenses/by/3.0/
=======
Testing
=======
.. _functional_tests:
Functional tests
================
The following procedure gets you started with Tempest testing but you can also
refer to the `Tempest documentation`_ for more details.
.. _Tempest documentation: https://docs.openstack.org/tempest/latest/
Tempest installation
--------------------
You need to install virtualenv, create a virtual environment and activate it::
$ pip install virtualenv
$ virtualenv watcher-env
$ . watcher-env/bin/activate
Then, to install Tempest you can issue the following commands::
$ git clone https://github.com/openstack/tempest/
$ pip install tempest/
There should be set environment variables using the OpenStack RC file. If
you don't have RC file yet, create ``admin-openrc`` file and fill it using
the following example::
export OS_PROJECT_DOMAIN_NAME=default
export OS_USER_DOMAIN_NAME=default
export OS_PROJECT_NAME=admin
export OS_USERNAME=admin
export OS_PASSWORD=admin
export OS_AUTH_URL=http://controller:35357/v3
export OS_IDENTITY_API_VERSION=3
export OS_IMAGE_API_VERSION=2
Then, save file and execute ``source admin-openrc`` to set environment
variables.
To run functional tests you need to go to python-watcherclient folder, install
all requirements and execute ``tempest run`` command::
$ pip install -r requirements.txt -r test-requirements.txt
$ pip install .
$ tempest run --regex watcherclient.tests.functional
You can run specified test(s) by using regular expression::
$ tempest run --regex watcherclient.tests.functional.v1.test_action.ActionTests.test_action_list
python-watcherclient-2.2.0/watcherclient/tests/unit/ 0000775 0001750 0001750 00000000000 13364113665 022675 5 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/watcherclient/tests/unit/test_import.py 0000666 0001750 0001750 00000002506 13364113436 025621 0 ustar zuul zuul 0000000 0000000 #
# 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 watcherclient.tests.unit import utils
module_str = 'watcherclient'
class ImportTest(utils.BaseTestCase):
def check_exported_symbols(self, exported_symbols):
self.assertIn('client', exported_symbols)
self.assertIn('exceptions', exported_symbols)
def test_import_objects(self):
module = __import__(module_str)
exported_symbols = dir(module)
self.check_exported_symbols(exported_symbols)
def test_default_import(self):
default_imports = __import__(module_str, globals(), locals(), ['*'])
exported_symbols = dir(default_imports)
self.check_exported_symbols(exported_symbols)
def test_import__all__(self):
module = __import__(module_str)
self.check_exported_symbols(module.__all__)
python-watcherclient-2.2.0/watcherclient/tests/unit/v1/ 0000775 0001750 0001750 00000000000 13364113665 023223 5 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/watcherclient/tests/unit/v1/test_action_shell.py 0000666 0001750 0001750 00000014373 13364113436 027306 0 ustar zuul zuul 0000000 0000000 #
# Copyright 2013 IBM Corp
#
# 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 mock
import six
from watcherclient import exceptions
from watcherclient import shell
from watcherclient.tests.unit.v1 import base
from watcherclient import v1 as resource
from watcherclient.v1 import resource_fields
ACTION_1 = {
'uuid': '770ef053-ecb3-48b0-85b5-d55a2dbc6588',
'action_plan_uuid': 'f8e47706-efcf-49a4-a5c4-af604eb492f2',
'state': 'PENDING',
'action_type': 'migrate',
'parents': ['239f02a5-9649-4e14-9d33-ac2bf67cb755'],
'input_parameters': {"test": 1},
'description': 'test',
'created_at': datetime.datetime.now().isoformat(),
'updated_at': None,
'deleted_at': None,
}
ACTION_2 = {
'uuid': '239f02a5-9649-4e14-9d33-ac2bf67cb755',
'action_plan_uuid': 'f8e47706-efcf-49a4-a5c4-af604eb492f2',
'state': 'PENDING',
'action_type': 'migrate',
'parents': ['67653274-eb24-c7ba-70f6-a84e73d80843'],
'input_parameters': {"test": 2},
'description': 'test',
'created_at': datetime.datetime.now().isoformat(),
'updated_at': None,
'deleted_at': None,
}
ACTION_3 = {
'uuid': '67653274-eb24-c7ba-70f6-a84e73d80843',
'action_plan_uuid': 'a5199d0e-0702-4613-9234-5ae2af8dafea',
'parents': [],
'state': 'PENDING',
'action_type': 'sleep',
'description': 'test',
'created_at': datetime.datetime.now().isoformat(),
'updated_at': None,
'deleted_at': None,
}
ACTION_PLAN_1 = {
'uuid': 'a5199d0e-0702-4613-9234-5ae2af8dafea',
'action': '770ef053-ecb3-48b0-85b5-d55a2dbc6588',
'state': 'RECOMMENDED',
'created_at': datetime.datetime.now().isoformat(),
'updated_at': None,
'deleted_at': None,
}
class ActionShellTest(base.CommandTestCase):
SHORT_LIST_FIELDS = resource_fields.ACTION_SHORT_LIST_FIELDS
SHORT_LIST_FIELD_LABELS = resource_fields.ACTION_SHORT_LIST_FIELD_LABELS
FIELDS = resource_fields.ACTION_FIELDS
FIELD_LABELS = resource_fields.ACTION_FIELD_LABELS
def setUp(self):
super(self.__class__, self).setUp()
p_action_manager = mock.patch.object(resource, 'ActionManager')
p_action_plan_manager = mock.patch.object(
resource, 'ActionPlanManager')
self.m_action_mgr_cls = p_action_manager.start()
self.m_action_plan_mgr_cls = p_action_plan_manager.start()
self.addCleanup(p_action_manager.stop)
self.addCleanup(p_action_plan_manager.stop)
self.m_action_mgr = mock.Mock()
self.m_action_plan_mgr = mock.Mock()
self.m_action_mgr_cls.return_value = self.m_action_mgr
self.m_action_plan_mgr_cls.return_value = self.m_action_plan_mgr
self.stdout = six.StringIO()
self.cmd = shell.WatcherShell(stdout=self.stdout)
def test_do_action_list(self):
action1 = resource.Action(mock.Mock(), ACTION_1)
action2 = resource.Action(mock.Mock(), ACTION_2)
self.m_action_mgr.list.return_value = [action1, action2]
exit_code, results = self.run_cmd('action list')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(action1, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS),
self.resource_as_dict(action2, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS)],
results)
self.m_action_mgr.list.assert_called_once_with(detail=False)
def test_do_action_list_detail(self):
action1 = resource.Action(mock.Mock(), ACTION_1)
action2 = resource.Action(mock.Mock(), ACTION_2)
self.m_action_mgr.list.return_value = [action1, action2]
exit_code, results = self.run_cmd('action list --detail')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(action1, self.FIELDS,
self.FIELD_LABELS),
self.resource_as_dict(action2, self.FIELDS,
self.FIELD_LABELS)],
results)
self.m_action_mgr.list.assert_called_once_with(detail=True)
def test_do_action_list_marker(self):
action2 = resource.Action(mock.Mock(), ACTION_2)
action3 = resource.Action(mock.Mock(), ACTION_3)
self.m_action_mgr.list.return_value = [
action2, action3]
exit_code, results = self.run_cmd(
'action list --marker 770ef053-ecb3-48b0-85b5-d55a2dbc6588')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(action2, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS),
self.resource_as_dict(action3, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS)],
results)
self.m_action_mgr.list.assert_called_once_with(
detail=False,
marker='770ef053-ecb3-48b0-85b5-d55a2dbc6588')
def test_do_action_show_by_uuid(self):
action = resource.Action(mock.Mock(), ACTION_1)
self.m_action_mgr.get.return_value = action
self.m_action_plan_mgr.get.return_value = action
exit_code, result = self.run_cmd(
'action show 5869da81-4876-4687-a1ed-12cd64cf53d9')
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(action, self.FIELDS, self.FIELD_LABELS),
result)
self.m_action_mgr.get.assert_called_once_with(
'5869da81-4876-4687-a1ed-12cd64cf53d9')
def test_do_action_show_by_not_uuid(self):
self.m_action_mgr.get.side_effect = exceptions.HTTPNotFound
exit_code, result = self.run_cmd(
'action show not_uuid', formatting=None)
self.assertEqual(1, exit_code)
self.assertEqual('', result)
python-watcherclient-2.2.0/watcherclient/tests/unit/v1/base.py 0000666 0001750 0001750 00000005367 13364113436 024520 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2016 b<>com
#
# 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 shlex
import mock
from osc_lib import utils as oscutils
from oslo_serialization import jsonutils
from watcherclient.common import httpclient
from watcherclient.tests.unit import utils
class CommandTestCase(utils.BaseTestCase):
def setUp(self):
super(CommandTestCase, self).setUp()
self.fake_env = {
'debug': False,
'insecure': False,
'no_auth': False,
'os_auth_token': '',
'os_auth_url': 'http://127.0.0.1:5000/v2.0',
'os_endpoint_override': 'http://watcher-endpoint:9322',
'os_username': 'test',
'os_password': 'test',
'timeout': 600,
'os_watcher_api_version': '1'}
self.m_env = mock.Mock(
name='m_env',
side_effect=lambda x, *args, **kwargs: self.fake_env.get(
x.lower(), kwargs.get('default', '')))
self.p_env = mock.patch.object(oscutils, 'env', self.m_env)
self.p_env.start()
self.addCleanup(self.p_env.stop)
self.p_construct_http_client = mock.patch.object(
httpclient, '_construct_http_client')
self.m_construct_http_client = self.p_construct_http_client.start()
self.addCleanup(self.p_construct_http_client.stop)
def run_cmd(self, cmd, formatting='json'):
if formatting:
formatter_arg = " -f %s" % formatting
formatter = jsonutils.loads
else:
formatter_arg = ''
formatter = str
formatted_cmd = "%(cmd)s%(formatter)s" % dict(
cmd=cmd, formatter=formatter_arg)
exit_code = self.cmd.run(shlex.split(formatted_cmd))
try:
raw_data = self.stdout.getvalue()
formatted_output = formatter(self.stdout.getvalue())
except Exception:
self.fail("Formatting error (`%s` -> '%s')" %
(raw_data, formatting))
return exit_code, formatted_output
def resource_as_dict(self, resource, columns=(), column_headers=()):
mapping = dict(zip(columns, column_headers))
return {mapping[k]: v for k, v in resource.to_dict().items()
if not columns or columns and k in mapping}
python-watcherclient-2.2.0/watcherclient/tests/unit/v1/test_audit_template_shell.py 0000666 0001750 0001750 00000035241 13364113436 031027 0 ustar zuul zuul 0000000 0000000 #
# Copyright 2013 IBM Corp
#
# 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 mock
import six
from watcherclient import shell
from watcherclient.tests.unit.v1 import base
from watcherclient import v1 as resource
from watcherclient.v1 import resource_fields
GOAL_1 = {
'uuid': "fc087747-61be-4aad-8126-b701731ae836",
'name': "SERVER_CONSOLIDATION",
'display_name': 'Server Consolidation',
'created_at': datetime.datetime.now().isoformat(),
'updated_at': None,
'deleted_at': None,
}
STRATEGY_1 = {
'uuid': '2cf86250-d309-4b81-818e-1537f3dba6e5',
'name': 'basic',
'display_name': 'Basic consolidation',
'goal_uuid': 'fc087747-61be-4aad-8126-b701731ae836',
'created_at': datetime.datetime.now().isoformat(),
'updated_at': None,
'deleted_at': None,
}
AUDIT_TEMPLATE_1 = {
'uuid': 'f8e47706-efcf-49a4-a5c4-af604eb492f2',
'name': 'at1',
'description': 'Audit Template 1 description',
'goal_uuid': 'fc087747-61be-4aad-8126-b701731ae836',
'goal_name': 'SERVER_CONSOLIDATION',
'strategy_uuid': '2cf86250-d309-4b81-818e-1537f3dba6e5',
'strategy_name': 'basic',
'created_at': datetime.datetime.now().isoformat(),
'updated_at': None,
'deleted_at': None,
'scope': []
}
AUDIT_TEMPLATE_2 = {
'uuid': '2a60ca9b-09b0-40ff-8674-de8a36fc4bc8',
'name': 'at2',
'description': 'Audit Template 2',
'goal_uuid': 'fc087747-61be-4aad-8126-b701731ae836',
'goal_name': 'SERVER_CONSOLIDATION',
'strategy_uuid': None,
'strategy_name': None,
'created_at': datetime.datetime.now().isoformat(),
'updated_at': None,
'deleted_at': None,
'scope': []
}
class AuditTemplateShellTest(base.CommandTestCase):
SHORT_LIST_FIELDS = resource_fields.AUDIT_TEMPLATE_SHORT_LIST_FIELDS
SHORT_LIST_FIELD_LABELS = (
resource_fields.AUDIT_TEMPLATE_SHORT_LIST_FIELD_LABELS)
FIELDS = resource_fields.AUDIT_TEMPLATE_FIELDS
FIELD_LABELS = resource_fields.AUDIT_TEMPLATE_FIELD_LABELS
def setUp(self):
super(self.__class__, self).setUp()
# goal mock
p_goal_manager = mock.patch.object(resource, 'GoalManager')
self.m_goal_mgr_cls = p_goal_manager.start()
self.addCleanup(p_goal_manager.stop)
self.m_goal_mgr = mock.Mock()
self.m_goal_mgr_cls.return_value = self.m_goal_mgr
# strategy mock
p_strategy_manager = mock.patch.object(resource, 'StrategyManager')
self.m_strategy_mgr_cls = p_strategy_manager.start()
self.addCleanup(p_strategy_manager.stop)
self.m_strategy_mgr = mock.Mock()
self.m_strategy_mgr_cls.return_value = self.m_strategy_mgr
# audit template mock
p_audit_template_manager = mock.patch.object(
resource, 'AuditTemplateManager')
self.m_audit_template_mgr_cls = p_audit_template_manager.start()
self.addCleanup(p_audit_template_manager.stop)
self.m_audit_template_mgr = mock.Mock()
self.m_audit_template_mgr_cls.return_value = self.m_audit_template_mgr
# stdout mock
self.stdout = six.StringIO()
self.cmd = shell.WatcherShell(stdout=self.stdout)
def test_do_audit_template_list(self):
audit_template1 = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_1)
audit_template2 = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_2)
self.m_audit_template_mgr.list.return_value = [
audit_template1, audit_template2]
exit_code, results = self.run_cmd('audittemplate list')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(audit_template1, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS),
self.resource_as_dict(audit_template2, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS)],
results)
self.m_audit_template_mgr.list.assert_called_once_with(detail=False)
def test_do_audit_template_list_marker(self):
audit_template2 = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_2)
self.m_audit_template_mgr.list.return_value = [audit_template2]
exit_code, results = self.run_cmd(
'audittemplate list --marker '
'f8e47706-efcf-49a4-a5c4-af604eb492f2')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(audit_template2, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS)],
results)
self.m_audit_template_mgr.list.assert_called_once_with(
detail=False,
marker='f8e47706-efcf-49a4-a5c4-af604eb492f2')
def test_do_audit_template_list_detail(self):
audit_template1 = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_1)
audit_template2 = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_2)
self.m_audit_template_mgr.list.return_value = [
audit_template1, audit_template2]
exit_code, results = self.run_cmd('audittemplate list --detail')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(audit_template1, self.FIELDS,
self.FIELD_LABELS),
self.resource_as_dict(audit_template2, self.FIELDS,
self.FIELD_LABELS)],
results)
self.m_audit_template_mgr.list.assert_called_once_with(detail=True)
def test_do_audit_template_list_filter_by_goal_uuid(self):
audit_template1 = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_1)
audit_template2 = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_2)
self.m_audit_template_mgr.list.return_value = [
audit_template1, audit_template2]
exit_code, results = self.run_cmd(
'audittemplate list --goal '
'fc087747-61be-4aad-8126-b701731ae836')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(audit_template1, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS),
self.resource_as_dict(audit_template2, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS)],
results)
self.m_audit_template_mgr.list.assert_called_once_with(
detail=False,
goal='fc087747-61be-4aad-8126-b701731ae836',
)
def test_do_audit_template_list_filter_by_goal_name(self):
goal1 = resource.Goal(mock.Mock(), GOAL_1)
strategy1 = resource.Strategy(mock.Mock(), STRATEGY_1)
audit_template1 = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_1)
audit_template2 = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_2)
self.m_goal_mgr.get.return_value = goal1
self.m_strategy_mgr.get.return_value = strategy1
self.m_audit_template_mgr.list.return_value = [
audit_template1, audit_template2]
exit_code, results = self.run_cmd(
'audittemplate list --goal SERVER_CONSOLIDATION')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(audit_template1, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS),
self.resource_as_dict(audit_template2, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS)],
results)
self.m_audit_template_mgr.list.assert_called_once_with(
detail=False,
goal='SERVER_CONSOLIDATION',
)
def test_do_audit_template_list_filter_by_strategy_uuid(self):
goal1 = resource.Goal(mock.Mock(), GOAL_1)
strategy1 = resource.Strategy(mock.Mock(), STRATEGY_1)
audit_template1 = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_1)
self.m_goal_mgr.get.return_value = goal1
self.m_strategy_mgr.get.return_value = strategy1
self.m_audit_template_mgr.list.return_value = [audit_template1]
exit_code, results = self.run_cmd(
'audittemplate list --strategy '
'2cf86250-d309-4b81-818e-1537f3dba6e5')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(audit_template1, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS)],
results)
self.m_audit_template_mgr.list.assert_called_once_with(
detail=False,
strategy='2cf86250-d309-4b81-818e-1537f3dba6e5',
)
def test_do_audit_template_list_filter_by_strategy_name(self):
audit_template1 = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_1)
self.m_audit_template_mgr.list.return_value = [audit_template1]
exit_code, results = self.run_cmd(
'audittemplate list --strategy '
'basic')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(audit_template1, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS)],
results)
self.m_audit_template_mgr.list.assert_called_once_with(
detail=False,
strategy='basic',
)
def test_do_audit_template_show_by_name(self):
audit_template = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_1)
self.m_audit_template_mgr.get.return_value = audit_template
exit_code, result = self.run_cmd('audittemplate show at1')
self.assertEqual(0, exit_code)
self.assertEqual(self.resource_as_dict(audit_template, self.FIELDS,
self.FIELD_LABELS),
result)
self.m_audit_template_mgr.get.assert_called_once_with('at1')
def test_do_audit_template_show_by_uuid(self):
audit_template = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_1)
self.m_audit_template_mgr.get.return_value = audit_template
exit_code, result = self.run_cmd(
'audittemplate show f8e47706-efcf-49a4-a5c4-af604eb492f2')
self.assertEqual(0, exit_code)
self.assertEqual(self.resource_as_dict(audit_template, self.FIELDS,
self.FIELD_LABELS),
result)
self.m_audit_template_mgr.get.assert_called_once_with(
'f8e47706-efcf-49a4-a5c4-af604eb492f2')
def test_do_audit_template_delete(self):
self.m_audit_template_mgr.delete.return_value = ''
exit_code, result = self.run_cmd(
'audittemplate delete f8e47706-efcf-49a4-a5c4-af604eb492f2',
formatting=None)
self.assertEqual(0, exit_code)
self.assertEqual('', result)
self.m_audit_template_mgr.delete.assert_called_once_with(
'f8e47706-efcf-49a4-a5c4-af604eb492f2')
def test_do_audit_template_delete_multiple(self):
self.m_audit_template_mgr.delete.return_value = ''
exit_code, result = self.run_cmd(
'audittemplate delete f8e47706-efcf-49a4-a5c4-af604eb492f2 '
'92dfce2f-0a5e-473f-92b7-d92e21839e4d',
formatting=None)
self.assertEqual(0, exit_code)
self.assertEqual('', result)
self.m_audit_template_mgr.delete.assert_any_call(
'f8e47706-efcf-49a4-a5c4-af604eb492f2')
self.m_audit_template_mgr.delete.assert_any_call(
'92dfce2f-0a5e-473f-92b7-d92e21839e4d')
def test_do_audit_template_update(self):
audit_template = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_1)
self.m_audit_template_mgr.update.return_value = audit_template
exit_code, result = self.run_cmd(
'audittemplate update at1 replace description="New description"')
self.assertEqual(0, exit_code)
self.assertEqual(self.resource_as_dict(audit_template, self.FIELDS,
self.FIELD_LABELS),
result)
self.m_audit_template_mgr.update.assert_called_once_with(
'at1',
[{'op': 'replace', 'path': '/description',
'value': 'New description'}])
def test_do_audit_template_create(self):
audit_template = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_1)
self.m_audit_template_mgr.create.return_value = audit_template
exit_code, result = self.run_cmd(
'audittemplate create at1 fc087747-61be-4aad-8126-b701731ae836')
self.assertEqual(0, exit_code)
self.assertEqual(self.resource_as_dict(audit_template, self.FIELDS,
self.FIELD_LABELS),
result)
self.m_audit_template_mgr.create.assert_called_once_with(
goal='fc087747-61be-4aad-8126-b701731ae836',
name='at1')
def test_do_audit_template_create_with_description(self):
audit_template = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_1)
self.m_audit_template_mgr.create.return_value = audit_template
exit_code, result = self.run_cmd(
'audittemplate create at1 fc087747-61be-4aad-8126-b701731ae836 '
'-d "Audit Template 1 description"')
self.assertEqual(0, exit_code)
self.assertEqual(self.resource_as_dict(audit_template, self.FIELDS,
self.FIELD_LABELS),
result)
self.m_audit_template_mgr.create.assert_called_once_with(
goal='fc087747-61be-4aad-8126-b701731ae836',
name='at1',
description='Audit Template 1 description')
def test_do_audit_template_create_with_aggregate(self):
audit_template = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_1)
self.m_audit_template_mgr.create.return_value = audit_template
exit_code, result = self.run_cmd(
'audittemplate create at1 fc087747-61be-4aad-8126-b701731ae836')
self.assertEqual(0, exit_code)
self.assertEqual(self.resource_as_dict(audit_template, self.FIELDS,
self.FIELD_LABELS),
result)
self.m_audit_template_mgr.create.assert_called_once_with(
goal='fc087747-61be-4aad-8126-b701731ae836',
name='at1')
python-watcherclient-2.2.0/watcherclient/tests/unit/v1/test_goal.py 0000666 0001750 0001750 00000011501 13364113436 025552 0 ustar zuul zuul 0000000 0000000 # Copyright 2013 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import testtools
from testtools import matchers
from watcherclient.tests.unit import utils
import watcherclient.v1.goal
GOAL1 = {
'uuid': "fc087747-61be-4aad-8126-b701731ae836",
'name': "SERVER_CONSOLIDATION",
'display_name': 'Server Consolidation'
}
GOAL2 = {
'uuid': "407b03b1-63c6-49b2-adaf-4df5c0090047",
'name': "COST_OPTIMIZATION",
'display_name': 'Cost Optimization'
}
fake_responses = {
'/v1/goals':
{
'GET': (
{},
{"goals": [GOAL1]},
),
},
'/v1/goals/detail':
{
'GET': (
{},
{"goals": [GOAL1]},
)
},
'/v1/goals/%s' % GOAL1['uuid']:
{
'GET': (
{},
GOAL1,
),
},
'/v1/goals/%s' % GOAL1['name']:
{
'GET': (
{},
GOAL1,
),
},
}
fake_responses_pagination = {
'/v1/goals':
{
'GET': (
{},
{"goals": [GOAL1],
"next": "http://127.0.0.1:9322/v1/goals/?limit=1"}
),
},
'/v1/goals/?limit=1':
{
'GET': (
{},
{"goals": [GOAL2]}
),
},
}
fake_responses_sorting = {
'/v1/goals/?sort_key=id':
{
'GET': (
{},
{"goals": [GOAL1, GOAL2]}
),
},
'/v1/goals/?sort_dir=desc':
{
'GET': (
{},
{"goals": [GOAL2, GOAL1]}
),
},
}
class GoalManagerTest(testtools.TestCase):
def setUp(self):
super(GoalManagerTest, self).setUp()
self.api = utils.FakeAPI(fake_responses)
self.mgr = watcherclient.v1.goal.GoalManager(self.api)
def test_goals_list(self):
goals = self.mgr.list()
expect = [
('GET', '/v1/goals', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(goals))
def test_goals_list_detail(self):
goals = self.mgr.list(detail=True)
expect = [
('GET', '/v1/goals/detail', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(goals))
def test_goals_list_limit(self):
self.api = utils.FakeAPI(fake_responses_pagination)
self.mgr = watcherclient.v1.goal.GoalManager(self.api)
goals = self.mgr.list(limit=1)
expect = [
('GET', '/v1/goals/?limit=1', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertThat(goals, matchers.HasLength(1))
def test_goals_list_pagination_no_limit(self):
self.api = utils.FakeAPI(fake_responses_pagination)
self.mgr = watcherclient.v1.goal.GoalManager(self.api)
goals = self.mgr.list(limit=0)
expect = [
('GET', '/v1/goals', {}, None),
('GET', '/v1/goals/?limit=1', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertThat(goals, matchers.HasLength(2))
def test_goals_list_sort_key(self):
self.api = utils.FakeAPI(fake_responses_sorting)
self.mgr = watcherclient.v1.goal.GoalManager(self.api)
goals = self.mgr.list(sort_key='id')
expect = [
('GET', '/v1/goals/?sort_key=id', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(2, len(goals))
def test_goals_list_sort_dir(self):
self.api = utils.FakeAPI(fake_responses_sorting)
self.mgr = watcherclient.v1.goal.GoalManager(self.api)
goals = self.mgr.list(sort_dir='desc')
expect = [
('GET', '/v1/goals/?sort_dir=desc', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(2, len(goals))
def test_goals_show(self):
goal = self.mgr.get(GOAL1['uuid'])
expect = [
('GET', '/v1/goals/%s' % GOAL1['uuid'], {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(GOAL1['uuid'], goal.uuid)
def test_goals_show_by_name(self):
goal = self.mgr.get(GOAL1['name'])
expect = [
('GET', '/v1/goals/%s' % GOAL1['name'], {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(GOAL1['name'], goal.name)
python-watcherclient-2.2.0/watcherclient/tests/unit/v1/test_strategy_shell.py 0000666 0001750 0001750 00000015656 13364113436 027700 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2016 b<>com
#
# 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 mock
import six
from oslo_serialization import jsonutils
from watcherclient import shell
from watcherclient.tests.unit.v1 import base
from watcherclient import v1 as resource
from watcherclient.v1 import resource_fields
STRATEGY_1 = {
'uuid': '2cf86250-d309-4b81-818e-1537f3dba6e5',
'name': 'basic',
'display_name': 'Basic consolidation',
'goal_uuid': 'fc087747-61be-4aad-8126-b701731ae836',
'goal_name': 'SERVER_CONSOLIDATION',
'created_at': datetime.datetime.now().isoformat(),
'updated_at': None,
'deleted_at': None,
'parameters_spec': {},
}
STRATEGY_2 = {
'uuid': 'b20bb987-ea8f-457a-a4ea-ab3ffdfeff8b',
'name': 'dummy',
'display_name': 'Dummy',
'goal_uuid': '407b03b1-63c6-49b2-adaf-4df5c0090047',
'goal_name': 'DUMMY',
'created_at': datetime.datetime.now().isoformat(),
'updated_at': None,
'deleted_at': None,
'parameters_spec': {},
}
class StrategyShellTest(base.CommandTestCase):
SHORT_LIST_FIELDS = resource_fields.STRATEGY_SHORT_LIST_FIELDS
SHORT_LIST_FIELD_LABELS = (
resource_fields.STRATEGY_SHORT_LIST_FIELD_LABELS)
FIELDS = resource_fields.STRATEGY_FIELDS
FIELD_LABELS = resource_fields.STRATEGY_FIELD_LABELS
STATE_FIELDS = resource_fields.STRATEGY_STATE_FIELDS
STATE_FIELD_LABELS = resource_fields.STRATEGY_STATE_FIELD_LABELS
def setUp(self):
super(self.__class__, self).setUp()
p_strategy_manager = mock.patch.object(resource, 'StrategyManager')
self.m_strategy_mgr_cls = p_strategy_manager.start()
self.addCleanup(p_strategy_manager.stop)
self.m_strategy_mgr = mock.Mock()
self.m_strategy_mgr_cls.return_value = self.m_strategy_mgr
self.stdout = six.StringIO()
self.cmd = shell.WatcherShell(stdout=self.stdout)
def test_do_strategy_list(self):
strategy1 = resource.Strategy(mock.Mock(), STRATEGY_1)
strategy2 = resource.Strategy(mock.Mock(), STRATEGY_2)
self.m_strategy_mgr.list.return_value = [
strategy1, strategy2]
exit_code, results = self.run_cmd('strategy list')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(strategy1, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS),
self.resource_as_dict(strategy2, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS)],
results)
self.m_strategy_mgr.list.assert_called_once_with(detail=False)
def test_do_strategy_list_detail(self):
strategy1 = resource.Strategy(mock.Mock(), STRATEGY_1)
strategy2 = resource.Strategy(mock.Mock(), STRATEGY_2)
self.m_strategy_mgr.list.return_value = [
strategy1, strategy2]
exit_code, results = self.run_cmd('strategy list --detail')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(strategy1, self.FIELDS,
self.FIELD_LABELS),
self.resource_as_dict(strategy2, self.FIELDS,
self.FIELD_LABELS)],
results)
self.m_strategy_mgr.list.assert_called_once_with(detail=True)
def test_do_strategy_list_filter_by_goal_name(self):
strategy2 = resource.Strategy(mock.Mock(), STRATEGY_2)
self.m_strategy_mgr.list.return_value = [strategy2]
exit_code, results = self.run_cmd(
'strategy list --goal '
'DUMMY')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(strategy2, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS)],
results)
self.m_strategy_mgr.list.assert_called_once_with(
detail=False,
goal='DUMMY',
)
def test_do_strategy_list_filter_by_goal_uuid(self):
strategy1 = resource.Strategy(mock.Mock(), STRATEGY_1)
self.m_strategy_mgr.list.return_value = [strategy1]
exit_code, results = self.run_cmd(
'strategy list --goal '
'fc087747-61be-4aad-8126-b701731ae836')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(strategy1, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS)],
results)
self.m_strategy_mgr.list.assert_called_once_with(
detail=False,
goal='fc087747-61be-4aad-8126-b701731ae836',
)
def test_do_strategy_show_by_uuid(self):
strategy = resource.Strategy(mock.Mock(), STRATEGY_1)
self.m_strategy_mgr.get.return_value = strategy
exit_code, result = self.run_cmd(
'strategy show f8e47706-efcf-49a4-a5c4-af604eb492f2')
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(strategy, self.FIELDS, self.FIELD_LABELS),
result)
self.m_strategy_mgr.get.assert_called_once_with(
'f8e47706-efcf-49a4-a5c4-af604eb492f2')
def test_do_strategy_state(self):
strategy1 = resource.Strategy(mock.Mock(), STRATEGY_1)
strategy_req = [
{'type': 'Datasource', 'mandatory': True,
'comment': '', 'state': 'gnocchi: True'},
{'type': 'Metrics', 'mandatory': False,
'comment': '', 'state': jsonutils.dumps([
{'compute.node.cpu.percent': 'available'},
{'cpu_util': 'available'},
{'memory.resident': 'available'},
{'hardware.memory.used': 'not available'}])},
{'type': 'CDM', 'mandatory': True,
'comment': '',
'state': jsonutils.dumps([{'compute_model': 'available'},
{'storage_model': 'not available'}])},
{'type': 'Name', 'mandatory': '', 'comment': '',
'state': strategy1.name}]
requirements = [resource.Strategy(mock.Mock(), req)
for req in strategy_req]
self.m_strategy_mgr.state.return_value = requirements
exit_code, results = self.run_cmd('strategy state basic')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(req, self.STATE_FIELDS,
self.STATE_FIELD_LABELS)
for req in requirements],
results)
python-watcherclient-2.2.0/watcherclient/tests/unit/v1/test_action.py 0000666 0001750 0001750 00000017021 13364113436 026110 0 ustar zuul zuul 0000000 0000000 # Copyright 2013 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import testtools
from testtools import matchers
from watcherclient.tests.unit import utils
import watcherclient.v1.action
ACTION1 = {
'id': 1,
'uuid': '770ef053-ecb3-48b0-85b5-d55a2dbc6588',
'action_plan': 'f8e47706-efcf-49a4-a5c4-af604eb492f2',
'description': 'Action_1 description',
'next': '239f02a5-9649-4e14-9d33-ac2bf67cb755',
'state': 'PENDING',
}
ACTION2 = {
'id': 2,
'uuid': '239f02a5-9649-4e14-9d33-ac2bf67cb755',
'action_plan': 'f8e47706-efcf-49a4-a5c4-af604eb492f2',
'description': 'Action_2 description',
'next': '67653274-eb24-c7ba-70f6-a84e73d80843',
'state': 'PENDING',
}
ACTION3 = {
'id': 3,
'uuid': '67653274-eb24-c7ba-70f6-a84e73d80843',
'action_plan': 'a5199d0e-0702-4613-9234-5ae2af8dafea',
'description': 'Action_3 description',
'next': None,
'state': 'PENDING',
}
ACTION_PLAN1 = {
'id': 1,
'uuid': 'a5199d0e-0702-4613-9234-5ae2af8dafea',
'audit': '770ef053-ecb3-48b0-85b5-d55a2dbc6588',
'state': 'RECOMMENDED'
}
fake_responses = {
'/v1/actions':
{
'GET': (
{},
{"actions": [ACTION1, ACTION2, ACTION3]},
),
},
'/v1/actions/?action_plan_uuid=%s' % ACTION1['action_plan']:
{
'GET': (
{},
{"actions": [ACTION1, ACTION2]},
),
},
'/v1/actions/?audit_uuid=%s' % ACTION_PLAN1['audit']:
{
'GET': (
{},
{"actions": [ACTION3]},
),
},
'/v1/actions/detail':
{
'GET': (
{},
{"actions": [ACTION1, ACTION2, ACTION3]},
),
},
'/v1/actions/%s' % ACTION1['uuid']:
{
'GET': (
{},
ACTION1,
),
'DELETE': (
{},
None,
),
},
'/v1/actions/detail?action_plan_uuid=%s' % ACTION1['action_plan']:
{
'GET': (
{},
{"actions": [ACTION1, ACTION2]},
),
},
'/v1/actions/detail?audit_uuid=%s' % ACTION_PLAN1['audit']:
{
'GET': (
{},
{"actions": [ACTION3]},
),
}
}
fake_responses_pagination = {
'/v1/actions':
{
'GET': (
{},
{"actions": [ACTION1],
"next": "http://127.0.0.1:9322/v1/actions/?limit=1"}
),
},
'/v1/actions/?limit=1':
{
'GET': (
{},
{"actions": [ACTION2]}
),
},
}
fake_responses_sorting = {
'/v1/actions/?sort_key=updated_at':
{
'GET': (
{},
{"actions": [ACTION3, ACTION2, ACTION1]}
),
},
'/v1/actions/?sort_dir=desc':
{
'GET': (
{},
{"actions": [ACTION3, ACTION2, ACTION1]}
),
},
}
fake_responses_marker = {
'/v1/actions/?marker=770ef053-ecb3-48b0-85b5-d55a2dbc6588':
{
'GET': (
{},
{"actions": [ACTION2, ACTION3]}
),
},
}
class ActionManagerTest(testtools.TestCase):
def setUp(self):
super(ActionManagerTest, self).setUp()
self.api = utils.FakeAPI(fake_responses)
self.mgr = watcherclient.v1.action.ActionManager(self.api)
def test_actions_list(self):
actions = self.mgr.list()
expect = [
('GET', '/v1/actions', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(3, len(actions))
def test_actions_list_by_action_plan(self):
actions = self.mgr.list(action_plan=ACTION1['action_plan'])
expect = [
('GET',
'/v1/actions/?action_plan_uuid=%s' % ACTION1['action_plan'],
{}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(2, len(actions))
def test_actions_list_detail(self):
actions = self.mgr.list(detail=True)
expect = [
('GET', '/v1/actions/detail', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(3, len(actions))
def test_actions_list_by_action_plan_detail(self):
actions = self.mgr.list(action_plan=ACTION1['action_plan'],
detail=True)
expect = [
('GET',
'/v1/actions/detail?action_plan_uuid=%s' % ACTION1['action_plan'],
{},
None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(2, len(actions))
def test_actions_list_limit(self):
self.api = utils.FakeAPI(fake_responses_pagination)
self.mgr = watcherclient.v1.action.ActionManager(self.api)
actions = self.mgr.list(limit=1)
expect = [
('GET', '/v1/actions/?limit=1', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertThat(actions, matchers.HasLength(1))
def test_actions_list_pagination_no_limit(self):
self.api = utils.FakeAPI(fake_responses_pagination)
self.mgr = watcherclient.v1.action.ActionManager(self.api)
actions = self.mgr.list(limit=0)
expect = [
('GET', '/v1/actions', {}, None),
('GET', '/v1/actions/?limit=1', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertThat(actions, matchers.HasLength(2))
def test_actions_list_sort_key(self):
self.api = utils.FakeAPI(fake_responses_sorting)
self.mgr = watcherclient.v1.action.ActionManager(self.api)
actions = self.mgr.list(sort_key='updated_at')
expect = [
('GET', '/v1/actions/?sort_key=updated_at', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(3, len(actions))
def test_actions_list_sort_dir(self):
self.api = utils.FakeAPI(fake_responses_sorting)
self.mgr = watcherclient.v1.action.ActionManager(self.api)
actions = self.mgr.list(sort_dir='desc')
expect = [
('GET', '/v1/actions/?sort_dir=desc', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(3, len(actions))
def test_actions_list_marker(self):
self.api = utils.FakeAPI(fake_responses_marker)
self.mgr = watcherclient.v1.action.ActionManager(self.api)
actions = self.mgr.list(
marker='770ef053-ecb3-48b0-85b5-d55a2dbc6588')
expect = [
('GET',
'/v1/actions/?marker=770ef053-ecb3-48b0-85b5-d55a2dbc6588',
{},
None)
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(2, len(actions))
def test_actions_show(self):
action = self.mgr.get(ACTION1['uuid'])
expect = [
('GET', '/v1/actions/%s' % ACTION1['uuid'], {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(ACTION1['uuid'], action.uuid)
self.assertEqual(ACTION1['action_plan'], action.action_plan)
self.assertEqual(ACTION1['next'], action.next)
python-watcherclient-2.2.0/watcherclient/tests/unit/v1/test_audit.py 0000666 0001750 0001750 00000016110 13364113436 025737 0 ustar zuul zuul 0000000 0000000 # Copyright 2013 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import copy
import testtools
from testtools import matchers
from watcherclient.tests.unit import utils
import watcherclient.v1.audit
AUDIT1 = {
'id': 1,
'uuid': '5869da81-4876-4687-a1ed-12cd64cf53d9',
'audit_type': 'ONE_SHOT',
'goal': 'fc087747-61be-4aad-8126-b701731ae836',
'strategy': '2cf86250-d309-4b81-818e-1537f3dba6e5',
}
AUDIT2 = {
'id': 2,
'uuid': 'a5199d0e-0702-4613-9234-5ae2af8dafea',
'audit_type': 'ONE_SHOT',
'goal': 'fc087747-61be-4aad-8126-b701731ae836',
'strategy': None,
}
CREATE_AUDIT = copy.deepcopy(AUDIT1)
del CREATE_AUDIT['id']
del CREATE_AUDIT['uuid']
UPDATED_AUDIT1 = copy.deepcopy(AUDIT1)
NEW_STATE = 'SUCCESS'
UPDATED_AUDIT1['state'] = NEW_STATE
fake_responses = {
'/v1/audits':
{
'GET': (
{},
{"audits": [AUDIT1]},
),
'POST': (
{},
CREATE_AUDIT,
),
},
'/v1/audits/detail':
{
'GET': (
{},
{"audits": [AUDIT1]},
),
},
'/v1/audits/%s' % AUDIT1['uuid']:
{
'GET': (
{},
AUDIT1,
),
'DELETE': (
{},
None,
),
'PATCH': (
{},
UPDATED_AUDIT1,
),
},
'/v1/audits/detail?uuid=%s' % AUDIT1['uuid']:
{
'GET': (
{},
{"audits": [AUDIT1]},
),
},
}
fake_responses_pagination = {
'/v1/audits':
{
'GET': (
{},
{"audits": [AUDIT1],
"next": "http://127.0.0.1:9322/v1/audits/?limit=1"}
),
},
'/v1/audits/?limit=1':
{
'GET': (
{},
{"audits": [AUDIT2]}
),
},
}
fake_responses_sorting = {
'/v1/audits/?sort_key=updated_at':
{
'GET': (
{},
{"audits": [AUDIT2, AUDIT1]}
),
},
'/v1/audits/?sort_dir=desc':
{
'GET': (
{},
{"audits": [AUDIT2, AUDIT1]}
),
},
}
fake_responses_goal = {
'/v1/audits/?goal=dummy':
{
'GET': (
{},
{"audits": [AUDIT2, AUDIT1]}
),
},
}
fake_responses_strategy = {
'/v1/audits/?strategy=dummy':
{
'GET': (
{},
{"audits": [AUDIT1]}
),
},
}
fake_responses_marker = {
'/v1/audits/?marker=5869da81-4876-4687-a1ed-12cd64cf53d9':
{
'GET': (
{},
{"audits": [AUDIT2]}
),
},
}
class AuditManagerTest(testtools.TestCase):
def setUp(self):
super(AuditManagerTest, self).setUp()
self.api = utils.FakeAPI(fake_responses)
self.mgr = watcherclient.v1.audit.AuditManager(self.api)
def test_audits_list(self):
audits = self.mgr.list()
expect = [
('GET', '/v1/audits', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(audits))
def test_audits_list_detail(self):
audits = self.mgr.list(detail=True)
expect = [
('GET', '/v1/audits/detail', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(audits))
def test_audits_list_limit(self):
self.api = utils.FakeAPI(fake_responses_pagination)
self.mgr = watcherclient.v1.audit.AuditManager(self.api)
audits = self.mgr.list(limit=1)
expect = [
('GET', '/v1/audits/?limit=1', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertThat(audits, matchers.HasLength(1))
def test_audits_list_pagination_no_limit(self):
self.api = utils.FakeAPI(fake_responses_pagination)
self.mgr = watcherclient.v1.audit.AuditManager(self.api)
audits = self.mgr.list(limit=0)
expect = [
('GET', '/v1/audits', {}, None),
('GET', '/v1/audits/?limit=1', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertThat(audits, matchers.HasLength(2))
def test_audits_list_sort_key(self):
self.api = utils.FakeAPI(fake_responses_sorting)
self.mgr = watcherclient.v1.audit.AuditManager(self.api)
audits = self.mgr.list(sort_key='updated_at')
expect = [
('GET', '/v1/audits/?sort_key=updated_at', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(2, len(audits))
def test_audits_list_sort_dir(self):
self.api = utils.FakeAPI(fake_responses_sorting)
self.mgr = watcherclient.v1.audit.AuditManager(self.api)
audits = self.mgr.list(sort_dir='desc')
expect = [
('GET', '/v1/audits/?sort_dir=desc', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(2, len(audits))
def test_audits_list_goal(self):
self.api = utils.FakeAPI(fake_responses_goal)
self.mgr = watcherclient.v1.audit.AuditManager(self.api)
audits = self.mgr.list(goal='dummy')
expect = [
('GET', '/v1/audits/?goal=dummy', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(2, len(audits))
def test_audits_list_strategy(self):
self.api = utils.FakeAPI(fake_responses_strategy)
self.mgr = watcherclient.v1.audit.AuditManager(self.api)
audits = self.mgr.list(strategy='dummy')
expect = [
('GET', '/v1/audits/?strategy=dummy', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(audits))
def test_audits_list_marker(self):
self.api = utils.FakeAPI(fake_responses_marker)
self.mgr = watcherclient.v1.audit.AuditManager(self.api)
audits = self.mgr.list(marker=AUDIT1['uuid'])
expect = [
('GET', '/v1/audits/?marker=5869da81-4876-4687-a1ed-12cd64cf53d9',
{}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(audits))
def test_audits_show(self):
audit = self.mgr.get(AUDIT1['uuid'])
expect = [
('GET', '/v1/audits/%s' % AUDIT1['uuid'], {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(AUDIT1['uuid'], audit.uuid)
def test_create(self):
audit = self.mgr.create(**CREATE_AUDIT)
expect = [
('POST', '/v1/audits', {}, CREATE_AUDIT),
]
self.assertEqual(expect, self.api.calls)
self.assertTrue(audit)
python-watcherclient-2.2.0/watcherclient/tests/unit/v1/test_service.py 0000666 0001750 0001750 00000011756 13364113436 026304 0 ustar zuul zuul 0000000 0000000 # Copyright 2013 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import testtools
from testtools import matchers
from watcherclient.tests.unit import utils
import watcherclient.v1.service
SERVICE1 = {
'id': 1,
'name': 'watcher-applier',
'host': 'controller',
'status': 'ACTIVE',
}
SERVICE2 = {
'id': 2,
'name': 'watcher-decision-engine',
'host': 'controller',
'status': 'FAILED',
}
fake_responses = {
'/v1/services':
{
'GET': (
{},
{"services": [SERVICE1]},
),
},
'/v1/services/detail':
{
'GET': (
{},
{"services": [SERVICE1]},
)
},
'/v1/services/%s' % SERVICE1['id']:
{
'GET': (
{},
SERVICE1,
),
},
'/v1/services/%s' % SERVICE1['name']:
{
'GET': (
{},
SERVICE1,
),
},
}
fake_responses_pagination = {
'/v1/services':
{
'GET': (
{},
{"services": [SERVICE1],
"next": "http://127.0.0.1:6385/v1/services/?limit=1"}
),
},
'/v1/services/?limit=1':
{
'GET': (
{},
{"services": [SERVICE2]}
),
},
}
fake_responses_sorting = {
'/v1/services/?sort_key=id':
{
'GET': (
{},
{"services": [SERVICE1, SERVICE2]}
),
},
'/v1/services/?sort_dir=desc':
{
'GET': (
{},
{"services": [SERVICE2, SERVICE1]}
),
},
}
class ServiceManagerTest(testtools.TestCase):
def setUp(self):
super(ServiceManagerTest, self).setUp()
self.api = utils.FakeAPI(fake_responses)
self.mgr = watcherclient.v1.service.ServiceManager(self.api)
def test_services_list(self):
services = self.mgr.list()
expect = [
('GET', '/v1/services', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(services))
def test_services_list_detail(self):
services = self.mgr.list(detail=True)
expect = [
('GET', '/v1/services/detail', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(services))
def test_services_list_limit(self):
self.api = utils.FakeAPI(fake_responses_pagination)
self.mgr = watcherclient.v1.service.ServiceManager(self.api)
services = self.mgr.list(limit=1)
expect = [
('GET', '/v1/services/?limit=1', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertThat(services, matchers.HasLength(1))
def test_services_list_pagination_no_limit(self):
self.api = utils.FakeAPI(fake_responses_pagination)
self.mgr = watcherclient.v1.service.ServiceManager(self.api)
services = self.mgr.list(limit=0)
expect = [
('GET', '/v1/services', {}, None),
('GET', '/v1/services/?limit=1', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertThat(services, matchers.HasLength(2))
def test_services_list_sort_key(self):
self.api = utils.FakeAPI(fake_responses_sorting)
self.mgr = watcherclient.v1.service.ServiceManager(self.api)
services = self.mgr.list(sort_key='id')
expect = [
('GET', '/v1/services/?sort_key=id', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(2, len(services))
def test_services_list_sort_dir(self):
self.api = utils.FakeAPI(fake_responses_sorting)
self.mgr = watcherclient.v1.service.ServiceManager(self.api)
services = self.mgr.list(sort_dir='desc')
expect = [
('GET', '/v1/services/?sort_dir=desc', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(2, len(services))
def test_services_show(self):
service = self.mgr.get(SERVICE1['id'])
expect = [
('GET', '/v1/services/%s' % SERVICE1['id'], {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(SERVICE1['id'], service.id)
def test_services_show_by_name(self):
service = self.mgr.get(SERVICE1['name'])
expect = [
('GET', '/v1/services/%s' % SERVICE1['name'], {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(SERVICE1['name'], service.name)
python-watcherclient-2.2.0/watcherclient/tests/unit/v1/test_audit_shell.py 0000777 0001750 0001750 00000037527 13364113436 027150 0 ustar zuul zuul 0000000 0000000 #
# Copyright 2013 IBM Corp
#
# 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 mock
import six
from watcherclient import shell
from watcherclient.tests.unit.v1 import base
from watcherclient import v1 as resource
from watcherclient.v1 import resource_fields
AUDIT_TEMPLATE_1 = {
'uuid': 'f8e47706-efcf-49a4-a5c4-af604eb492f2',
'name': 'at1',
'description': 'Audit Template 1 description',
'goal_uuid': 'fc087747-61be-4aad-8126-b701731ae836',
'strategy_uuid': '2cf86250-d309-4b81-818e-1537f3dba6e5',
'created_at': datetime.datetime.now().isoformat(),
'updated_at': None,
'deleted_at': None,
}
GOAL_1 = {
'uuid': "fc087747-61be-4aad-8126-b701731ae836",
'name': "SERVER_CONSOLIDATION",
'display_name': 'Server Consolidation',
'created_at': datetime.datetime.now().isoformat(),
'updated_at': None,
'deleted_at': None,
}
STRATEGY_1 = {
'uuid': '2cf86250-d309-4b81-818e-1537f3dba6e5',
'name': 'basic',
'display_name': 'Basic consolidation',
'goal_uuid': 'fc087747-61be-4aad-8126-b701731ae836',
'created_at': datetime.datetime.now().isoformat(),
'updated_at': None,
'deleted_at': None,
}
AUDIT_1 = {
'uuid': '5869da81-4876-4687-a1ed-12cd64cf53d9',
'audit_type': 'ONESHOT',
'state': 'PENDING',
'audit_template_uuid': 'f8e47706-efcf-49a4-a5c4-af604eb492f2',
'audit_template_name': 'at1',
'goal_name': 'SERVER_CONSOLIDATION',
'strategy_name': 'basic',
'created_at': datetime.datetime.now().isoformat(),
'updated_at': None,
'deleted_at': None,
'parameters': None,
'interval': None,
'scope': '',
'auto_trigger': False,
'next_run_time': None,
'name': 'my_audit1',
'hostname': '',
}
AUDIT_2 = {
'uuid': 'a5199d0e-0702-4613-9234-5ae2af8dafea',
'audit_type': 'ONESHOT',
'state': 'PENDING',
'audit_template_uuid': 'f8e47706-efcf-49a4-a5c4-af604eb492f2',
'audit_template_name': 'at1',
'goal_name': 'fc087747-61be-4aad-8126-b701731ae836',
'strategy_name': 'auto',
'created_at': datetime.datetime.now().isoformat(),
'updated_at': None,
'deleted_at': None,
'parameters': None,
'interval': None,
'scope': '',
'auto_trigger': False,
'next_run_time': None,
'name': 'my_audit2',
'hostname': '',
}
AUDIT_3 = {
'uuid': '43199d0e-0712-1213-9674-5ae2af8dhgte',
'audit_type': 'ONESHOT',
'state': 'PENDING',
'audit_template_uuid': 'f8e47706-efcf-49a4-a5c4-af604eb492f2',
'audit_template_name': 'at1',
'goal_name': None,
'strategy_name': 'auto',
'created_at': datetime.datetime.now().isoformat(),
'updated_at': None,
'deleted_at': None,
'parameters': None,
'interval': 3600,
'scope': '',
'auto_trigger': True,
'next_run_time': None,
'name': 'my_audit3',
'hostname': '',
}
class AuditShellTest(base.CommandTestCase):
SHORT_LIST_FIELDS = resource_fields.AUDIT_SHORT_LIST_FIELDS
SHORT_LIST_FIELD_LABELS = resource_fields.AUDIT_SHORT_LIST_FIELD_LABELS
FIELDS = resource_fields.AUDIT_FIELDS
FIELD_LABELS = resource_fields.AUDIT_FIELD_LABELS
def setUp(self):
super(self.__class__, self).setUp()
# goal mock
p_goal_manager = mock.patch.object(resource, 'GoalManager')
self.m_goal_mgr_cls = p_goal_manager.start()
self.addCleanup(p_goal_manager.stop)
self.m_goal_mgr = mock.Mock()
self.m_goal_mgr_cls.return_value = self.m_goal_mgr
# strategy mock
p_strategy_manager = mock.patch.object(resource, 'StrategyManager')
self.m_strategy_mgr_cls = p_strategy_manager.start()
self.addCleanup(p_strategy_manager.stop)
self.m_strategy_mgr = mock.Mock()
self.m_strategy_mgr_cls.return_value = self.m_strategy_mgr
p_audit_manager = mock.patch.object(resource, 'AuditManager')
p_audit_template_manager = mock.patch.object(
resource, 'AuditTemplateManager')
self.m_audit_mgr_cls = p_audit_manager.start()
self.m_audit_template_mgr_cls = p_audit_template_manager.start()
self.addCleanup(p_audit_manager.stop)
self.addCleanup(p_audit_template_manager.stop)
self.m_audit_mgr = mock.Mock()
self.m_audit_template_mgr = mock.Mock()
self.m_audit_mgr_cls.return_value = self.m_audit_mgr
self.m_audit_template_mgr_cls.return_value = self.m_audit_template_mgr
# stdout mock
self.stdout = six.StringIO()
self.cmd = shell.WatcherShell(stdout=self.stdout)
def test_do_audit_list(self):
audit1 = resource.Audit(mock.Mock(), AUDIT_1)
audit2 = resource.Audit(mock.Mock(), AUDIT_2)
self.m_audit_mgr.list.return_value = [
audit1, audit2]
exit_code, results = self.run_cmd('audit list')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(audit1, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS),
self.resource_as_dict(audit2, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS)],
results)
self.m_audit_mgr.list.assert_called_once_with(detail=False)
def test_do_audit_list_marker(self):
audit2 = resource.Audit(mock.Mock(), AUDIT_2)
self.m_audit_mgr.list.return_value = [audit2]
exit_code, results = self.run_cmd(
'audit list --marker 5869da81-4876-4687-a1ed-12cd64cf53d9')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(audit2, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS)],
results)
self.m_audit_mgr.list.assert_called_once_with(
detail=False,
marker='5869da81-4876-4687-a1ed-12cd64cf53d9')
def test_do_audit_list_detail(self):
audit1 = resource.Audit(mock.Mock(), AUDIT_1)
audit2 = resource.Audit(mock.Mock(), AUDIT_2)
self.m_audit_mgr.list.return_value = [
audit1, audit2]
exit_code, results = self.run_cmd('audit list --detail')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(audit1, self.FIELDS,
self.FIELD_LABELS),
self.resource_as_dict(audit2, self.FIELDS,
self.FIELD_LABELS)],
results)
self.m_audit_mgr.list.assert_called_once_with(detail=True)
def test_do_audit_show_by_uuid(self):
audit = resource.Audit(mock.Mock(), AUDIT_1)
self.m_audit_mgr.get.return_value = audit
exit_code, result = self.run_cmd(
'audit show 5869da81-4876-4687-a1ed-12cd64cf53d9')
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(audit, self.FIELDS, self.FIELD_LABELS),
result)
self.m_audit_mgr.get.assert_called_once_with(
'5869da81-4876-4687-a1ed-12cd64cf53d9')
def test_do_audit_show_by_name(self):
audit = resource.Audit(mock.Mock(), AUDIT_1)
self.m_audit_mgr.get.return_value = audit
exit_code, result = self.run_cmd(
'audit show my_audit')
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(audit, self.FIELDS, self.FIELD_LABELS),
result)
self.m_audit_mgr.get.assert_called_once_with(
'my_audit')
def test_do_audit_delete(self):
self.m_audit_mgr.delete.return_value = ''
exit_code, result = self.run_cmd(
'audit delete 5869da81-4876-4687-a1ed-12cd64cf53d9',
formatting=None)
self.assertEqual(0, exit_code)
self.assertEqual('', result)
self.m_audit_mgr.delete.assert_called_once_with(
'5869da81-4876-4687-a1ed-12cd64cf53d9')
def test_do_audit_delete_by_name(self):
self.m_audit_mgr.delete.return_value = ''
exit_code, result = self.run_cmd(
'audit delete my_audit',
formatting=None)
self.assertEqual(0, exit_code)
self.assertEqual('', result)
self.m_audit_mgr.delete.assert_called_once_with(
'my_audit')
def test_do_audit_delete_multiple(self):
self.m_audit_mgr.delete.return_value = ''
exit_code, result = self.run_cmd(
'audit delete 5869da81-4876-4687-a1ed-12cd64cf53d9 '
'5b157edd-5a7e-4aaa-b511-f7b33ec86e9f',
formatting=None)
self.assertEqual(0, exit_code)
self.assertEqual('', result)
self.m_audit_mgr.delete.assert_any_call(
'5869da81-4876-4687-a1ed-12cd64cf53d9')
self.m_audit_mgr.delete.assert_any_call(
'5b157edd-5a7e-4aaa-b511-f7b33ec86e9f')
def test_do_audit_update(self):
audit = resource.Audit(mock.Mock(), AUDIT_1)
self.m_audit_mgr.update.return_value = audit
exit_code, result = self.run_cmd(
'audit update 5869da81-4876-4687-a1ed-12cd64cf53d9 '
'replace state=PENDING')
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(audit, self.FIELDS, self.FIELD_LABELS),
result)
self.m_audit_mgr.update.assert_called_once_with(
'5869da81-4876-4687-a1ed-12cd64cf53d9',
[{'op': 'replace', 'path': '/state', 'value': 'PENDING'}])
def test_do_audit_update_by_name(self):
audit = resource.Audit(mock.Mock(), AUDIT_1)
self.m_audit_mgr.update.return_value = audit
exit_code, result = self.run_cmd(
'audit update my_audit replace state=PENDING')
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(audit, self.FIELDS, self.FIELD_LABELS),
result)
self.m_audit_mgr.update.assert_called_once_with(
'my_audit',
[{'op': 'replace', 'path': '/state', 'value': 'PENDING'}])
def test_do_audit_create_with_audit_template_uuid(self):
audit = resource.Audit(mock.Mock(), AUDIT_3)
audit_template = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_1)
self.m_audit_template_mgr.get.return_value = audit_template
self.m_audit_mgr.create.return_value = audit
exit_code, result = self.run_cmd(
'audit create -a f8e47706-efcf-49a4-a5c4-af604eb492f2')
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(audit, self.FIELDS, self.FIELD_LABELS),
result)
self.m_audit_mgr.create.assert_called_once_with(
audit_template_uuid='f8e47706-efcf-49a4-a5c4-af604eb492f2',
audit_type='ONESHOT',
auto_trigger=False
)
def test_do_audit_create_with_audit_template_name(self):
audit = resource.Audit(mock.Mock(), AUDIT_3)
audit_template = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_1)
self.m_audit_template_mgr.get.return_value = audit_template
self.m_audit_mgr.create.return_value = audit
exit_code, result = self.run_cmd('audit create -a at1')
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(audit, self.FIELDS, self.FIELD_LABELS),
result)
self.m_audit_mgr.create.assert_called_once_with(
audit_template_uuid='f8e47706-efcf-49a4-a5c4-af604eb492f2',
auto_trigger=False,
audit_type='ONESHOT'
)
def test_do_audit_create_with_goal(self):
audit = resource.Audit(mock.Mock(), AUDIT_1)
self.m_audit_mgr.create.return_value = audit
exit_code, result = self.run_cmd(
'audit create -g fc087747-61be-4aad-8126-b701731ae836')
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(audit, self.FIELDS, self.FIELD_LABELS),
result)
self.m_audit_mgr.create.assert_called_once_with(
goal='fc087747-61be-4aad-8126-b701731ae836',
auto_trigger=False,
audit_type='ONESHOT'
)
def test_do_audit_create_with_goal_and_strategy(self):
audit = resource.Audit(mock.Mock(), AUDIT_1)
self.m_audit_mgr.create.return_value = audit
exit_code, result = self.run_cmd(
'audit create -g fc087747-61be-4aad-8126-b701731ae836 -s '
'2cf86250-d309-4b81-818e-1537f3dba6e5')
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(audit, self.FIELDS, self.FIELD_LABELS),
result)
self.m_audit_mgr.create.assert_called_once_with(
goal='fc087747-61be-4aad-8126-b701731ae836',
strategy='2cf86250-d309-4b81-818e-1537f3dba6e5',
auto_trigger=False,
audit_type='ONESHOT'
)
def test_do_audit_create_with_type(self):
audit = resource.Audit(mock.Mock(), AUDIT_1)
self.m_audit_mgr.create.return_value = audit
exit_code, result = self.run_cmd(
'audit create -g fc087747-61be-4aad-8126-b701731ae836 -t ONESHOT')
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(audit, self.FIELDS, self.FIELD_LABELS),
result)
self.m_audit_mgr.create.assert_called_once_with(
goal='fc087747-61be-4aad-8126-b701731ae836',
auto_trigger=False,
audit_type='ONESHOT'
)
def test_do_audit_create_with_parameter(self):
audit = resource.Audit(mock.Mock(), AUDIT_1)
self.m_audit_mgr.create.return_value = audit
exit_code, result = self.run_cmd(
'audit create -g fc087747-61be-4aad-8126-b701731ae836 -p para1=10 '
'-p para2=20')
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(audit, self.FIELDS, self.FIELD_LABELS),
result)
self.m_audit_mgr.create.assert_called_once_with(
goal='fc087747-61be-4aad-8126-b701731ae836',
audit_type='ONESHOT',
auto_trigger=False,
parameters={'para1': 10, 'para2': 20}
)
def test_do_audit_create_with_type_continuous(self):
audit = resource.Audit(mock.Mock(), AUDIT_1)
self.m_audit_mgr.create.return_value = audit
exit_code, result = self.run_cmd(
'audit create -g fc087747-61be-4aad-8126-b701731ae836 '
'-t CONTINUOUS -i 3600')
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(audit, self.FIELDS, self.FIELD_LABELS),
result)
self.m_audit_mgr.create.assert_called_once_with(
goal='fc087747-61be-4aad-8126-b701731ae836',
audit_type='CONTINUOUS',
auto_trigger=False,
interval='3600'
)
def test_do_audit_create_with_name(self):
audit = resource.Audit(mock.Mock(), AUDIT_1)
self.m_audit_mgr.create.return_value = audit
exit_code, result = self.run_cmd(
'audit create -g fc087747-61be-4aad-8126-b701731ae836 '
'-t CONTINUOUS -i 3600 --name my_audit')
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(audit, self.FIELDS, self.FIELD_LABELS),
result)
self.m_audit_mgr.create.assert_called_once_with(
goal='fc087747-61be-4aad-8126-b701731ae836',
audit_type='CONTINUOUS',
auto_trigger=False,
interval='3600',
name='my_audit'
)
python-watcherclient-2.2.0/watcherclient/tests/unit/v1/test_action_plan_shell.py 0000666 0001750 0001750 00000025766 13364113436 030330 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2016 b<>com
#
# 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 mock
import six
from watcherclient import exceptions
from watcherclient import shell
from watcherclient.tests.unit.v1 import base
from watcherclient import v1 as resource
from watcherclient.v1 import resource_fields
ACTION_PLAN_1 = {
'uuid': 'd9d9978e-6db5-4a05-8eab-1531795d7004',
'audit_uuid': '770ef053-ecb3-48b0-85b5-d55a2dbc6588',
'strategy_name': 'dummy',
'state': 'RECOMMENDED',
'efficacy_indicators': [{'description': 'Indicator 1',
'name': 'indicator1',
'unit': '%'}],
'created_at': datetime.datetime.now().isoformat(),
'updated_at': None,
'global_efficacy': [
{"value": 99,
"unit": "%",
"name": "dummy_global_efficacy",
"description": "Dummy Global Efficacy"},
{"value": 75,
"unit": "%",
"name": "dummy_global_efficacy2",
"description": "Dummy Global Efficacy2"}
],
'deleted_at': None,
'hostname': ''
}
ACTION_PLAN_2 = {
'uuid': 'd6363285-5afa-4a26-96f2-89441e335765',
'audit_uuid': '239f02a5-9649-4e14-9d33-ac2bf67cb755',
'strategy_name': 'dummy',
'state': 'RECOMMENDED',
'created_at': datetime.datetime.now().isoformat(),
'efficacy_indicators': [{'description': 'Indicator 2',
'name': 'indicator2',
'unit': '%'}],
'updated_at': None,
'global_efficacy': [{
"value": 87,
"unit": "%",
"name": "dummy_global_efficacy",
"description": "Dummy Global Efficacy",
}],
'deleted_at': None,
'hostname': ''
}
class ActionPlanShellTest(base.CommandTestCase):
SHORT_LIST_FIELDS = resource_fields.ACTION_PLAN_SHORT_LIST_FIELDS
SHORT_LIST_FIELD_LABELS = (
resource_fields.ACTION_PLAN_SHORT_LIST_FIELD_LABELS)
FIELDS = resource_fields.ACTION_PLAN_FIELDS
FIELD_LABELS = resource_fields.ACTION_PLAN_FIELD_LABELS
GLOBAL_EFFICACY_FIELDS = resource_fields.GLOBAL_EFFICACY_FIELDS
def setUp(self):
super(self.__class__, self).setUp()
p_audit_manager = mock.patch.object(resource, 'AuditManager')
p_audit_template_manager = mock.patch.object(
resource, 'ActionPlanManager')
p_action_plan_manager = mock.patch.object(
resource, 'ActionPlanManager')
self.m_audit_mgr_cls = p_audit_manager.start()
self.m_audit_template_mgr_cls = p_audit_template_manager.start()
self.m_action_plan_mgr_cls = p_action_plan_manager.start()
self.addCleanup(p_audit_manager.stop)
self.addCleanup(p_audit_template_manager.stop)
self.addCleanup(p_action_plan_manager.stop)
self.m_audit_mgr = mock.Mock()
self.m_audit_template_mgr = mock.Mock()
self.m_action_plan_mgr = mock.Mock()
self.m_audit_mgr_cls.return_value = self.m_audit_mgr
self.m_audit_template_mgr_cls.return_value = self.m_audit_template_mgr
self.m_action_plan_mgr_cls.return_value = self.m_action_plan_mgr
self.stdout = six.StringIO()
self.cmd = shell.WatcherShell(stdout=self.stdout)
def test_do_action_plan_list(self):
action_plan1 = resource.ActionPlan(mock.Mock(), ACTION_PLAN_1)
action_plan2 = resource.ActionPlan(mock.Mock(), ACTION_PLAN_2)
self.m_action_plan_mgr.list.return_value = [
action_plan1, action_plan2]
exit_code, results = self.run_cmd('actionplan list')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(action_plan1, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS),
self.resource_as_dict(action_plan2, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS)],
results)
self.assertEqual(action_plan1.global_efficacy,
results[0]['Global efficacy'])
self.assertEqual(action_plan2.global_efficacy,
results[1]['Global efficacy'])
self.m_action_plan_mgr.list.assert_called_once_with(detail=False)
def test_do_action_plan_list_detail(self):
action_plan1 = resource.ActionPlan(mock.Mock(), ACTION_PLAN_1)
action_plan2 = resource.ActionPlan(mock.Mock(), ACTION_PLAN_2)
self.m_action_plan_mgr.list.return_value = [
action_plan1, action_plan2]
exit_code, results = self.run_cmd('actionplan list --detail')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(action_plan1, self.FIELDS,
self.FIELD_LABELS),
self.resource_as_dict(action_plan2, self.FIELDS,
self.FIELD_LABELS)],
results)
self.assertEqual(action_plan1.global_efficacy,
results[0]['Global efficacy'])
self.assertEqual(action_plan2.global_efficacy,
results[1]['Global efficacy'])
self.m_action_plan_mgr.list.assert_called_once_with(detail=True)
def test_do_action_plan_list_filter_by_audit(self):
action_plan1 = resource.ActionPlan(mock.Mock(), ACTION_PLAN_1)
self.m_action_plan_mgr.list.return_value = [action_plan1]
exit_code, results = self.run_cmd(
'actionplan list --audit '
'770ef053-ecb3-48b0-85b5-d55a2dbc6588')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(action_plan1, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS)],
results)
self.m_action_plan_mgr.list.assert_called_once_with(
detail=False,
audit='770ef053-ecb3-48b0-85b5-d55a2dbc6588',
)
def test_do_action_plan_show_by_uuid(self):
action_plan = resource.ActionPlan(mock.Mock(), ACTION_PLAN_1)
self.m_action_plan_mgr.get.return_value = action_plan
exit_code, result = self.run_cmd(
'actionplan show d9d9978e-6db5-4a05-8eab-1531795d7004')
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(
action_plan, self.FIELDS, self.FIELD_LABELS),
result)
self.assertEqual(action_plan.global_efficacy,
result['Global efficacy'])
self.m_action_plan_mgr.get.assert_called_once_with(
'd9d9978e-6db5-4a05-8eab-1531795d7004')
def test_do_action_plan_show_by_not_uuid(self):
self.m_action_plan_mgr.get.side_effect = exceptions.HTTPNotFound
exit_code, result = self.run_cmd(
'actionplan show not_uuid', formatting=None)
self.assertEqual(1, exit_code)
self.assertEqual('', result)
def test_do_action_plan_delete(self):
self.m_action_plan_mgr.delete.return_value = ''
exit_code, result = self.run_cmd(
'actionplan delete 5869da81-4876-4687-a1ed-12cd64cf53d9',
formatting=None)
self.assertEqual(0, exit_code)
self.assertEqual('', result)
self.m_action_plan_mgr.delete.assert_called_once_with(
'5869da81-4876-4687-a1ed-12cd64cf53d9')
def test_do_action_plan_delete_not_uuid(self):
exit_code, result = self.run_cmd(
'actionplan delete not_uuid', formatting=None)
self.assertEqual(1, exit_code)
self.assertEqual('', result)
def test_do_action_plan_delete_multiple(self):
self.m_action_plan_mgr.delete.return_value = ''
exit_code, result = self.run_cmd(
'actionplan delete 5869da81-4876-4687-a1ed-12cd64cf53d9 '
'c20627fa-ea70-4d56-ae15-4106358f773b',
formatting=None)
self.assertEqual(0, exit_code)
self.assertEqual('', result)
self.m_action_plan_mgr.delete.assert_any_call(
'5869da81-4876-4687-a1ed-12cd64cf53d9')
self.m_action_plan_mgr.delete.assert_any_call(
'c20627fa-ea70-4d56-ae15-4106358f773b')
def test_do_action_plan_update(self):
action_plan = resource.ActionPlan(mock.Mock(), ACTION_PLAN_1)
self.m_action_plan_mgr.update.return_value = action_plan
exit_code, result = self.run_cmd(
'actionplan update 5869da81-4876-4687-a1ed-12cd64cf53d9 '
'replace state=CANCELLED')
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(action_plan, self.FIELDS, self.FIELD_LABELS),
result)
self.m_action_plan_mgr.update.assert_called_once_with(
'5869da81-4876-4687-a1ed-12cd64cf53d9',
[{'op': 'replace', 'path': '/state', 'value': 'CANCELLED'}])
def test_do_action_plan_update_not_uuid(self):
exit_code, result = self.run_cmd(
'actionplan update not_uuid '
'replace state=CANCELLED',
formatting=None)
self.assertEqual(1, exit_code)
self.assertEqual('', result)
def test_do_action_plan_start(self):
action_plan = resource.ActionPlan(mock.Mock(), ACTION_PLAN_1)
self.m_action_plan_mgr.start.return_value = action_plan
exit_code, result = self.run_cmd(
'actionplan start 5869da81-4876-4687-a1ed-12cd64cf53d9')
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(action_plan, self.FIELDS, self.FIELD_LABELS),
result)
self.m_action_plan_mgr.start.assert_called_once_with(
'5869da81-4876-4687-a1ed-12cd64cf53d9')
def test_do_action_plan_start_not_uuid(self):
exit_code, result = self.run_cmd(
'actionplan start not_uuid',
formatting=None)
self.assertEqual(1, exit_code)
self.assertEqual('', result)
def test_do_action_plan_cancel(self):
action_plan = resource.ActionPlan(mock.Mock(), ACTION_PLAN_1)
self.m_action_plan_mgr.cancel.return_value = action_plan
exit_code, result = self.run_cmd(
'actionplan cancel 5869da81-4876-4687-a1ed-12cd64cf53d9')
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(action_plan, self.FIELDS, self.FIELD_LABELS),
result)
self.m_action_plan_mgr.cancel.assert_called_once_with(
'5869da81-4876-4687-a1ed-12cd64cf53d9')
def test_do_action_plan_cancel_not_uuid(self):
exit_code, result = self.run_cmd(
'actionplan cancel not_uuid',
formatting=None)
self.assertEqual(1, exit_code)
self.assertEqual('', result)
python-watcherclient-2.2.0/watcherclient/tests/unit/v1/test_scoring_engine_shell.py 0000666 0001750 0001750 00000010717 13364113436 031020 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2016 Intel
#
# 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 mock
import six
from watcherclient import shell
from watcherclient.tests.unit.v1 import base
from watcherclient import v1 as resource
from watcherclient.v1 import resource_fields
SCORING_ENGINE_1 = {
'uuid': '5b558998-57ed-11e6-9ca8-08002722cb22',
'name': 'se-01',
'description': 'Scoring Engine 0.1',
'metainfo': '{ "columns": ["cpu", "mem", "pci"] }',
'created_at': datetime.datetime.now().isoformat(),
'updated_at': None,
'deleted_at': None,
}
SCORING_ENGINE_2 = {
'uuid': '1f856554-57ee-11e6-ac72-08002722cb22',
'name': 'se-02',
'description': 'Some other Scoring Engine',
'metainfo': 'mode=simplified',
'created_at': datetime.datetime.now().isoformat(),
'updated_at': None,
'deleted_at': None,
}
class ScoringEngineShellTest(base.CommandTestCase):
SHORT_LIST_FIELDS = resource_fields.SCORING_ENGINE_SHORT_LIST_FIELDS
SHORT_LIST_FIELD_LABELS = (
resource_fields.SCORING_ENGINE_SHORT_LIST_FIELD_LABELS)
FIELDS = resource_fields.SCORING_ENGINE_FIELDS
FIELD_LABELS = resource_fields.SCORING_ENGINE_FIELD_LABELS
def setUp(self):
super(self.__class__, self).setUp()
p_se_manager = mock.patch.object(
resource, 'ScoringEngineManager')
self.m_se_mgr_cls = p_se_manager.start()
self.addCleanup(p_se_manager.stop)
self.m_se_mgr = mock.Mock()
self.m_se_mgr_cls.return_value = self.m_se_mgr
self.stdout = six.StringIO()
self.cmd = shell.WatcherShell(stdout=self.stdout)
def test_do_scoringengine_list(self):
se1 = resource.ScoringEngine(mock.Mock(), SCORING_ENGINE_1)
se2 = resource.ScoringEngine(mock.Mock(), SCORING_ENGINE_2)
self.m_se_mgr.list.return_value = [
se1, se2]
exit_code, results = self.run_cmd('scoringengine list')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(se1, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS),
self.resource_as_dict(se2, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS)],
results)
self.m_se_mgr.list.assert_called_once_with(detail=False)
def test_do_scoringengine_list_detail(self):
se1 = resource.Goal(mock.Mock(), SCORING_ENGINE_1)
se2 = resource.Goal(mock.Mock(), SCORING_ENGINE_2)
self.m_se_mgr.list.return_value = [
se1, se2]
exit_code, results = self.run_cmd('scoringengine list --detail')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(se1, self.FIELDS, self.FIELD_LABELS),
self.resource_as_dict(se2, self.FIELDS, self.FIELD_LABELS)],
results)
self.m_se_mgr.list.assert_called_once_with(detail=True)
def test_do_scoringengine_show_by_name(self):
scoringengine = resource.Goal(mock.Mock(), SCORING_ENGINE_1)
self.m_se_mgr.get.return_value = scoringengine
exit_code, result = self.run_cmd('scoringengine show se-01')
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(scoringengine, self.FIELDS,
self.FIELD_LABELS),
result)
self.m_se_mgr.get.assert_called_once_with('se-01')
def test_do_scoringengine_show_by_uuid(self):
scoringengine = resource.Goal(mock.Mock(), SCORING_ENGINE_1)
self.m_se_mgr.get.return_value = scoringengine
exit_code, result = self.run_cmd(
'scoringengine show 5b558998-57ed-11e6-9ca8-08002722cb22')
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(scoringengine, self.FIELDS,
self.FIELD_LABELS),
result)
self.m_se_mgr.get.assert_called_once_with(
'5b558998-57ed-11e6-9ca8-08002722cb22')
python-watcherclient-2.2.0/watcherclient/tests/unit/v1/test_service_shell.py 0000666 0001750 0001750 00000007670 13364113436 027473 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2016 Servionica
#
# 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 mock
import six
from watcherclient import shell
from watcherclient.tests.unit.v1 import base
from watcherclient import v1 as resource
from watcherclient.v1 import resource_fields
SERVICE_1 = {
'name': 'watcher-applier',
'host': 'controller',
'status': 'ACTIVE',
'last_seen_up': None,
'created_at': datetime.datetime.now().isoformat(),
'updated_at': None,
'deleted_at': None,
}
SERVICE_2 = {
'name': 'watcher-decision-engine',
'host': 'controller',
'status': 'FAILED',
'last_seen_up': None,
'created_at': datetime.datetime.now().isoformat(),
'updated_at': None,
'deleted_at': None,
}
class ServiceShellTest(base.CommandTestCase):
SHORT_LIST_FIELDS = resource_fields.SERVICE_SHORT_LIST_FIELDS
SHORT_LIST_FIELD_LABELS = (
resource_fields.SERVICE_SHORT_LIST_FIELD_LABELS)
FIELDS = resource_fields.SERVICE_FIELDS
FIELD_LABELS = resource_fields.SERVICE_FIELD_LABELS
def setUp(self):
super(self.__class__, self).setUp()
p_service_manager = mock.patch.object(resource, 'ServiceManager')
self.m_service_mgr_cls = p_service_manager.start()
self.addCleanup(p_service_manager.stop)
self.m_service_mgr = mock.Mock()
self.m_service_mgr_cls.return_value = self.m_service_mgr
self.stdout = six.StringIO()
self.cmd = shell.WatcherShell(stdout=self.stdout)
def test_do_service_list(self):
service1 = resource.Service(mock.Mock(), SERVICE_1)
service2 = resource.Service(mock.Mock(), SERVICE_2)
self.m_service_mgr.list.return_value = [
service1, service2]
exit_code, results = self.run_cmd('service list')
for res in results:
del res['ID']
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(service1, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS),
self.resource_as_dict(service2, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS)],
results)
self.m_service_mgr.list.assert_called_once_with(detail=False)
def test_do_service_list_detail(self):
service1 = resource.Service(mock.Mock(), SERVICE_1)
service2 = resource.Service(mock.Mock(), SERVICE_2)
self.m_service_mgr.list.return_value = [
service1, service2]
exit_code, results = self.run_cmd('service list --detail')
for res in results:
del res['ID']
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(service1, self.FIELDS,
self.FIELD_LABELS),
self.resource_as_dict(service2, self.FIELDS,
self.FIELD_LABELS)],
results)
self.m_service_mgr.list.assert_called_once_with(detail=True)
def test_do_service_show_by_name(self):
service = resource.Service(mock.Mock(), SERVICE_1)
self.m_service_mgr.get.return_value = service
exit_code, result = self.run_cmd('service show watcher-applier')
del result['ID']
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(service, self.FIELDS, self.FIELD_LABELS),
result)
self.m_service_mgr.get.assert_called_once_with('watcher-applier')
python-watcherclient-2.2.0/watcherclient/tests/unit/v1/test_audit_template.py 0000666 0001750 0001750 00000036050 13364113436 027637 0 ustar zuul zuul 0000000 0000000 # Copyright 2013 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import copy
from six.moves.urllib import parse as urlparse
from testtools import matchers
from watcherclient.tests.unit import utils
import watcherclient.v1.audit_template
AUDIT_TMPL1 = {
'id': 1,
'uuid': 'f8e47706-efcf-49a4-a5c4-af604eb492f2',
'name': 'Audit Template 1',
'description': 'Audit Template 1 description',
'goal_uuid': '7568667b-51fe-4087-9eb1-29b26891036f',
'goal_name': 'SERVER_CONSOLIDATION',
'strategy_uuid': 'bbe6b966-f98e-439b-a01a-17b9b3b8478b',
'strategy_name': 'server_consolidation',
}
AUDIT_TMPL2 = {
'id': 2,
'uuid': 'a5199d0e-0702-4613-9234-5ae2af8dafea',
'name': 'Audit Template 2',
'description': 'Audit Template 2 description',
'goal_uuid': 'e75ee410-b32b-465f-88b5-4397705f9473',
'goal_name': 'DUMMY',
'strategy_uuid': 'ae99a4a4-acbc-4c67-abe1-e37128fac45d',
'strategy_name': 'dummy',
}
AUDIT_TMPL3 = {
'id': 3,
'uuid': '770ef053-ecb3-48b0-85b5-d55a2dbc6588',
'name': 'Audit Template 3',
'description': 'Audit Template 3 description',
'goal_uuid': '7568667b-51fe-4087-9eb1-29b26891036f',
'goal_name': 'SERVER_CONSOLIDATION',
}
CREATE_AUDIT_TEMPLATE = copy.deepcopy(AUDIT_TMPL1)
del CREATE_AUDIT_TEMPLATE['id']
del CREATE_AUDIT_TEMPLATE['uuid']
del CREATE_AUDIT_TEMPLATE['goal_name']
del CREATE_AUDIT_TEMPLATE['strategy_name']
CREATE_AUDIT_TEMPLATE['goal'] = CREATE_AUDIT_TEMPLATE.pop('goal_uuid')
CREATE_AUDIT_TEMPLATE['strategy'] = CREATE_AUDIT_TEMPLATE.pop('strategy_uuid')
UPDATED_AUDIT_TMPL1 = copy.deepcopy(AUDIT_TMPL1)
NEW_NAME = 'Audit Template_1 new name'
UPDATED_AUDIT_TMPL1['name'] = NEW_NAME
fake_responses = {
'/v1/audit_templates':
{
'GET': (
{},
{"audit_templates": [AUDIT_TMPL1]},
),
'POST': (
{},
CREATE_AUDIT_TEMPLATE,
),
},
'/v1/audit_templates/detail':
{
'GET': (
{},
{"audit_templates": [AUDIT_TMPL1]},
),
},
'/v1/audit_templates/%s' % AUDIT_TMPL1['uuid']:
{
'GET': (
{},
AUDIT_TMPL1,
),
'DELETE': (
{},
None,
),
'PATCH': (
{},
UPDATED_AUDIT_TMPL1,
),
},
urlparse.quote('/v1/audit_templates/%s' % AUDIT_TMPL1['name']):
{
'GET': (
{},
AUDIT_TMPL1,
),
'DELETE': (
{},
None,
),
'PATCH': (
{},
UPDATED_AUDIT_TMPL1,
),
},
'/v1/audit_templates/detail?name=%s' % AUDIT_TMPL1['name']:
{
'GET': (
{},
{"audit_templates": [AUDIT_TMPL1]},
),
},
'/v1/audit_templates/?name=%s' % AUDIT_TMPL1['name']:
{
'GET': (
{},
{"audit_templates": [AUDIT_TMPL1]},
),
},
'/v1/audit_templates/detail?goal=%s' % AUDIT_TMPL1['goal_uuid']:
{
'GET': (
{},
{"audit_templates": [AUDIT_TMPL1, AUDIT_TMPL3]},
),
},
'/v1/audit_templates/?goal=%s' % AUDIT_TMPL1['goal_uuid']:
{
'GET': (
{},
{"audit_templates": [AUDIT_TMPL1, AUDIT_TMPL3]},
),
}
}
fake_responses_pagination = {
'/v1/audit_templates':
{
'GET': (
{},
{"audit_templates": [AUDIT_TMPL1],
"next": "http://127.0.0.1:9322/v1/audit_templates/?limit=1"}
),
},
'/v1/audit_templates/?limit=1':
{
'GET': (
{},
{"audit_templates": [AUDIT_TMPL2]}
),
},
}
fake_responses_sorting = {
'/v1/audit_templates/?sort_key=updated_at':
{
'GET': (
{},
{"audit_templates": [AUDIT_TMPL3, AUDIT_TMPL2, AUDIT_TMPL1]}
),
},
'/v1/audit_templates/?sort_dir=desc':
{
'GET': (
{},
{"audit_templates": [AUDIT_TMPL3, AUDIT_TMPL2, AUDIT_TMPL1]}
),
},
}
fake_responses_marker = {
'/v1/audit_templates/?marker=f8e47706-efcf-49a4-a5c4-af604eb492f2':
{
'GET': (
{},
{"audit_templates": [AUDIT_TMPL2, AUDIT_TMPL3]}
),
},
}
fake_responses_filter_by_goal_uuid = {
'/v1/audit_templates/?goal=e75ee410-b32b-465f-88b5-4397705f9473':
{
'GET': (
{},
{"audit_templates": [AUDIT_TMPL2]}
),
},
}
fake_responses_filter_by_goal_name = {
'/v1/audit_templates/?goal=DUMMY':
{
'GET': (
{},
{"audit_templates": [AUDIT_TMPL2]}
),
},
}
fake_responses_filter_by_strategy_uuid = {
'/v1/audit_templates/?strategy=ae99a4a4-acbc-4c67-abe1-e37128fac45d':
{
'GET': (
{},
{"audit_templates": [AUDIT_TMPL2]}
),
},
}
fake_responses_filter_by_strategy_name = {
'/v1/audit_templates/?strategy=dummy':
{
'GET': (
{},
{"audit_templates": [AUDIT_TMPL2]}
),
},
}
fake_responses_filter_by_strategy_and_goal_name = {
'/v1/audit_templates/?goal=DUMMY&strategy=dummy':
{
'GET': (
{},
{"audit_templates": [AUDIT_TMPL2]}
),
},
}
class AuditTemplateManagerTest(utils.BaseTestCase):
def setUp(self):
super(AuditTemplateManagerTest, self).setUp()
self.api = utils.FakeAPI(fake_responses)
self.mgr = watcherclient.v1.audit_template.AuditTemplateManager(
self.api)
def test_audit_templates_list(self):
audit_templates = self.mgr.list()
expect = [
('GET', '/v1/audit_templates', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(audit_templates))
def test_audit_templates_list_filter_by_name(self):
audit_templates = self.mgr.list(name=AUDIT_TMPL1['name'])
expect = [
('GET', '/v1/audit_templates/?name=%s' % AUDIT_TMPL1['name'],
{}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(audit_templates))
def test_audit_templates_list_filter_by_goal_uuid(self):
self.api = utils.FakeAPI(fake_responses_filter_by_goal_uuid)
self.mgr = watcherclient.v1.audit_template.AuditTemplateManager(
self.api)
audit_templates = self.mgr.list(
goal="e75ee410-b32b-465f-88b5-4397705f9473")
expect = [
('GET',
'/v1/audit_templates/?goal=%s' % AUDIT_TMPL2['goal_uuid'],
{}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(audit_templates))
def test_audit_templates_list_filter_by_goal_name(self):
self.api = utils.FakeAPI(fake_responses_filter_by_goal_name)
self.mgr = watcherclient.v1.audit_template.AuditTemplateManager(
self.api)
audit_templates = self.mgr.list(goal="DUMMY")
expect = [
('GET',
'/v1/audit_templates/?goal=%s' % AUDIT_TMPL2['goal_name'],
{}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(audit_templates))
def test_audit_templates_list_filter_by_strategy_uuid(self):
self.api = utils.FakeAPI(fake_responses_filter_by_strategy_uuid)
self.mgr = watcherclient.v1.audit_template.AuditTemplateManager(
self.api)
audit_templates = self.mgr.list(
strategy="ae99a4a4-acbc-4c67-abe1-e37128fac45d")
expect = [
('GET',
'/v1/audit_templates/?strategy=%s' % (
AUDIT_TMPL2['strategy_uuid']),
{}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(audit_templates))
def test_audit_templates_list_filter_by_strategy_name(self):
self.api = utils.FakeAPI(fake_responses_filter_by_strategy_name)
self.mgr = watcherclient.v1.audit_template.AuditTemplateManager(
self.api)
audit_templates = self.mgr.list(strategy="dummy")
expect = [
('GET',
'/v1/audit_templates/?strategy=%s' % (
AUDIT_TMPL2['strategy_name']),
{}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(audit_templates))
def test_audit_templates_list_filter_by_goal_and_strategy_name(self):
self.api = utils.FakeAPI(
fake_responses_filter_by_strategy_and_goal_name)
self.mgr = watcherclient.v1.audit_template.AuditTemplateManager(
self.api)
audit_templates = self.mgr.list(goal="DUMMY", strategy="dummy")
expect = [
('GET',
'/v1/audit_templates/?goal=%s&strategy=%s' % (
AUDIT_TMPL2['goal_name'], AUDIT_TMPL2['strategy_name']),
{}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(audit_templates))
def test_audit_templates_list_detail(self):
audit_templates = self.mgr.list(detail=True)
expect = [
('GET', '/v1/audit_templates/detail', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(audit_templates))
def test_audit_templates_list_by_name_detail(self):
audit_templates = self.mgr.list(name=AUDIT_TMPL1['name'], detail=True)
expect = [
('GET',
'/v1/audit_templates/detail?name=%s' % AUDIT_TMPL1['name'],
{},
None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(audit_templates))
def test_audit_templates_list_limit(self):
self.api = utils.FakeAPI(fake_responses_pagination)
self.mgr = watcherclient.v1.audit_template.AuditTemplateManager(
self.api)
audit_templates = self.mgr.list(limit=1)
expect = [
('GET', '/v1/audit_templates/?limit=1', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertThat(audit_templates, matchers.HasLength(1))
def test_audit_templates_list_pagination_no_limit(self):
self.api = utils.FakeAPI(fake_responses_pagination)
self.mgr = watcherclient.v1.audit_template.AuditTemplateManager(
self.api)
audit_templates = self.mgr.list(limit=0)
expect = [
('GET', '/v1/audit_templates', {}, None),
('GET', '/v1/audit_templates/?limit=1', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertThat(audit_templates, matchers.HasLength(2))
def test_audit_templates_list_sort_key(self):
self.api = utils.FakeAPI(fake_responses_sorting)
self.mgr = watcherclient.v1.audit_template.AuditTemplateManager(
self.api)
audit_templates = self.mgr.list(sort_key='updated_at')
expect = [
('GET', '/v1/audit_templates/?sort_key=updated_at', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(3, len(audit_templates))
def test_audit_templates_list_sort_dir(self):
self.api = utils.FakeAPI(fake_responses_sorting)
self.mgr = watcherclient.v1.audit_template.AuditTemplateManager(
self.api)
audit_templates = self.mgr.list(sort_dir='desc')
expect = [
('GET', '/v1/audit_templates/?sort_dir=desc', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(3, len(audit_templates))
def test_audit_templates_list_marker(self):
self.api = utils.FakeAPI(fake_responses_marker)
self.mgr = watcherclient.v1.audit_template.AuditTemplateManager(
self.api)
audit_templates = self.mgr.list(marker=AUDIT_TMPL1['uuid'])
expect_url = '/v1/audit_templates/?marker=%s' % AUDIT_TMPL1['uuid']
expect = [
('GET', expect_url, {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(2, len(audit_templates))
def test_audit_templates_show(self):
audit_template = self.mgr.get(AUDIT_TMPL1['uuid'])
expect = [
('GET', '/v1/audit_templates/%s' % AUDIT_TMPL1['uuid'], {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(AUDIT_TMPL1['uuid'], audit_template.uuid)
self.assertEqual(AUDIT_TMPL1['name'], audit_template.name)
self.assertEqual(AUDIT_TMPL1['description'],
audit_template.description)
self.assertEqual(AUDIT_TMPL1['goal_uuid'], audit_template.goal_uuid)
self.assertEqual(AUDIT_TMPL1['strategy_uuid'],
audit_template.strategy_uuid)
def test_audit_templates_show_by_name(self):
audit_template = self.mgr.get(urlparse.quote(AUDIT_TMPL1['name']))
expect = [
('GET',
urlparse.quote('/v1/audit_templates/%s' % AUDIT_TMPL1['name']),
{}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(AUDIT_TMPL1['uuid'], audit_template.uuid)
self.assertEqual(AUDIT_TMPL1['name'], audit_template.name)
self.assertEqual(AUDIT_TMPL1['description'],
audit_template.description)
self.assertEqual(AUDIT_TMPL1['goal_uuid'], audit_template.goal_uuid)
self.assertEqual(AUDIT_TMPL1['strategy_uuid'],
audit_template.strategy_uuid)
def test_create(self):
audit_template = self.mgr.create(**CREATE_AUDIT_TEMPLATE)
expect = [
('POST', '/v1/audit_templates', {}, CREATE_AUDIT_TEMPLATE),
]
self.assertEqual(expect, self.api.calls)
self.assertTrue(audit_template)
def test_delete(self):
audit_template = self.mgr.delete(audit_template_id=AUDIT_TMPL1['uuid'])
expect = [
('DELETE',
'/v1/audit_templates/%s' % AUDIT_TMPL1['uuid'],
{},
None),
]
self.assertEqual(expect, self.api.calls)
self.assertIsNone(audit_template)
def test_update(self):
patch = {'op': 'replace',
'value': NEW_NAME,
'path': '/name'}
audit_template = self.mgr.update(audit_template_id=AUDIT_TMPL1['uuid'],
patch=patch)
expect = [
('PATCH',
'/v1/audit_templates/%s' % AUDIT_TMPL1['uuid'],
{},
patch),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(NEW_NAME, audit_template.name)
python-watcherclient-2.2.0/watcherclient/tests/unit/v1/__init__.py 0000666 0001750 0001750 00000000000 13364113436 025320 0 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/watcherclient/tests/unit/v1/test_goal_shell.py 0000666 0001750 0001750 00000011236 13364113436 026746 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2016 b<>com
#
# 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 mock
import six
from watcherclient import shell
from watcherclient.tests.unit.v1 import base
from watcherclient import v1 as resource
from watcherclient.v1 import resource_fields
GOAL_1 = {
'uuid': "fc087747-61be-4aad-8126-b701731ae836",
'name': "SERVER_CONSOLIDATION",
'display_name': 'Server Consolidation',
'efficacy_specification': [
{'description': 'Indicator 1', 'name': 'indicator1',
'schema': 'Range(min=0, max=100, min_included=True, '
'max_included=True, msg=None)',
'unit': '%'}
],
'created_at': datetime.datetime.now().isoformat(),
'updated_at': None,
'deleted_at': None,
}
GOAL_2 = {
'uuid': "407b03b1-63c6-49b2-adaf-4df5c0090047",
'name': "COST_OPTIMIZATION",
'display_name': 'Cost Optimization',
'efficacy_specification': [
{'description': 'Indicator 2', 'name': 'indicator2',
'schema': 'Range(min=0, max=100, min_included=True, '
'max_included=True, msg=None)',
'unit': '%'}
],
'created_at': datetime.datetime.now().isoformat(),
'updated_at': None,
'deleted_at': None,
}
class GoalShellTest(base.CommandTestCase):
SHORT_LIST_FIELDS = resource_fields.GOAL_SHORT_LIST_FIELDS
SHORT_LIST_FIELD_LABELS = (
resource_fields.GOAL_SHORT_LIST_FIELD_LABELS)
FIELDS = resource_fields.GOAL_FIELDS
FIELD_LABELS = resource_fields.GOAL_FIELD_LABELS
def setUp(self):
super(self.__class__, self).setUp()
p_goal_manager = mock.patch.object(
resource, 'GoalManager')
self.m_goal_mgr_cls = p_goal_manager.start()
self.addCleanup(p_goal_manager.stop)
self.m_goal_mgr = mock.Mock()
self.m_goal_mgr_cls.return_value = self.m_goal_mgr
self.stdout = six.StringIO()
self.cmd = shell.WatcherShell(stdout=self.stdout)
def test_do_goal_list(self):
goal1 = resource.Goal(mock.Mock(), GOAL_1)
goal2 = resource.Goal(mock.Mock(), GOAL_2)
self.m_goal_mgr.list.return_value = [
goal1, goal2]
exit_code, results = self.run_cmd('goal list')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(goal1, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS),
self.resource_as_dict(goal2, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS)],
results)
self.m_goal_mgr.list.assert_called_once_with(detail=False)
def test_do_goal_list_detail(self):
goal1 = resource.Goal(mock.Mock(), GOAL_1)
goal2 = resource.Goal(mock.Mock(), GOAL_2)
self.m_goal_mgr.list.return_value = [
goal1, goal2]
exit_code, results = self.run_cmd('goal list --detail')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(goal1, self.FIELDS, self.FIELD_LABELS),
self.resource_as_dict(goal2, self.FIELDS, self.FIELD_LABELS)],
results)
self.m_goal_mgr.list.assert_called_once_with(detail=True)
def test_do_goal_show_by_name(self):
goal = resource.Goal(mock.Mock(), GOAL_1)
self.m_goal_mgr.get.return_value = goal
exit_code, result = self.run_cmd('goal show SERVER_CONSOLIDATION')
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(goal, self.FIELDS,
self.FIELD_LABELS),
result)
self.m_goal_mgr.get.assert_called_once_with('SERVER_CONSOLIDATION')
def test_do_goal_show_by_uuid(self):
goal = resource.Goal(mock.Mock(), GOAL_1)
self.m_goal_mgr.get.return_value = goal
exit_code, result = self.run_cmd(
'goal show fc087747-61be-4aad-8126-b701731ae836')
self.assertEqual(0, exit_code)
self.assertEqual(
self.resource_as_dict(goal, self.FIELDS,
self.FIELD_LABELS),
result)
self.m_goal_mgr.get.assert_called_once_with(
'fc087747-61be-4aad-8126-b701731ae836')
python-watcherclient-2.2.0/watcherclient/tests/unit/v1/test_scoring_engine.py 0000666 0001750 0001750 00000012607 13364113436 027631 0 ustar zuul zuul 0000000 0000000 #
# Copyright 2016 Intel
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import testtools
from testtools import matchers
from watcherclient.tests.unit import utils
import watcherclient.v1.scoring_engine
SE1 = {
'uuid': '5b558998-57ed-11e6-9ca8-08002722cb22',
'name': 'se-01',
'description': 'Some Scoring Engine'
}
SE2 = {
'uuid': '1f856554-57ee-11e6-ac72-08002722cb22',
'name': 'se-02',
'description': 'Some Other Scoring Engine'
}
fake_responses = {
'/v1/scoring_engines':
{
'GET': (
{},
{"scoring_engines": [SE1]},
),
},
'/v1/scoring_engines/detail':
{
'GET': (
{},
{"scoring_engines": [SE1]},
)
},
'/v1/scoring_engines/%s' % SE1['uuid']:
{
'GET': (
{},
SE1,
),
},
'/v1/scoring_engines/%s' % SE1['name']:
{
'GET': (
{},
SE1,
),
},
}
fake_responses_pagination = {
'/v1/scoring_engines':
{
'GET': (
{},
{"scoring_engines": [SE1],
"next": "http://127.0.0.1:9322/v1/scoring_engines/?limit=1"}
),
},
'/v1/scoring_engines/?limit=1':
{
'GET': (
{},
{"scoring_engines": [SE2]}
),
},
}
fake_responses_sorting = {
'/v1/scoring_engines/?sort_key=id':
{
'GET': (
{},
{"scoring_engines": [SE1, SE2]}
),
},
'/v1/scoring_engines/?sort_dir=desc':
{
'GET': (
{},
{"scoring_engines": [SE2, SE1]}
),
},
}
class ScoringEngineManagerTest(testtools.TestCase):
def setUp(self):
super(ScoringEngineManagerTest, self).setUp()
self.api = utils.FakeAPI(fake_responses)
self.mgr = \
watcherclient.v1.scoring_engine.ScoringEngineManager(self.api)
def test_scoring_engines_list(self):
scoring_engines = self.mgr.list()
expect = [
('GET', '/v1/scoring_engines', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(scoring_engines))
def test_scoring_engines_list_detail(self):
scoring_engines = self.mgr.list(detail=True)
expect = [
('GET', '/v1/scoring_engines/detail', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(scoring_engines))
def test_scoring_engines_list_limit(self):
self.api = utils.FakeAPI(fake_responses_pagination)
self.mgr = \
watcherclient.v1.scoring_engine.ScoringEngineManager(self.api)
scoring_engines = self.mgr.list(limit=1)
expect = [
('GET', '/v1/scoring_engines/?limit=1', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertThat(scoring_engines, matchers.HasLength(1))
def test_scoring_engines_list_pagination_no_limit(self):
self.api = utils.FakeAPI(fake_responses_pagination)
self.mgr = \
watcherclient.v1.scoring_engine.ScoringEngineManager(self.api)
scoring_engines = self.mgr.list(limit=0)
expect = [
('GET', '/v1/scoring_engines', {}, None),
('GET', '/v1/scoring_engines/?limit=1', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertThat(scoring_engines, matchers.HasLength(2))
def test_scoring_engines_list_sort_key(self):
self.api = utils.FakeAPI(fake_responses_sorting)
self.mgr = \
watcherclient.v1.scoring_engine.ScoringEngineManager(self.api)
scoring_engines = self.mgr.list(sort_key='id')
expect = [
('GET', '/v1/scoring_engines/?sort_key=id', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(2, len(scoring_engines))
def test_scoring_engines_list_sort_dir(self):
self.api = utils.FakeAPI(fake_responses_sorting)
self.mgr = \
watcherclient.v1.scoring_engine.ScoringEngineManager(self.api)
scoring_engines = self.mgr.list(sort_dir='desc')
expect = [
('GET', '/v1/scoring_engines/?sort_dir=desc', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(2, len(scoring_engines))
def test_scoring_engines_show(self):
scoring_engine = self.mgr.get(SE1['uuid'])
expect = [
('GET', '/v1/scoring_engines/%s' % SE1['uuid'], {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(SE1['uuid'], scoring_engine.uuid)
def test_scoring_engines_show_by_name(self):
scoring_engine = self.mgr.get(SE1['name'])
expect = [
('GET', '/v1/scoring_engines/%s' % SE1['name'], {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(SE1['name'], scoring_engine.name)
python-watcherclient-2.2.0/watcherclient/tests/unit/v1/test_action_plan.py 0000666 0001750 0001750 00000016245 13364113436 027131 0 ustar zuul zuul 0000000 0000000 # Copyright 2013 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import copy
import testtools
from testtools import matchers
from watcherclient.tests.unit import utils
import watcherclient.v1.action_plan
ACTION_PLAN1 = {
'id': 1,
'uuid': 'f8e47706-efcf-49a4-a5c4-af604eb492f2',
'audit': '770ef053-ecb3-48b0-85b5-d55a2dbc6588',
'state': 'RECOMMENDED'
}
ACTION_PLAN2 = {
'id': 2,
'uuid': 'a5199d0e-0702-4613-9234-5ae2af8dafea',
'audit': '239f02a5-9649-4e14-9d33-ac2bf67cb755',
'state': 'RECOMMENDED'
}
UPDATED_ACTION_PLAN = copy.deepcopy(ACTION_PLAN1)
NEW_STATE = 'PENDING'
UPDATED_ACTION_PLAN['state'] = NEW_STATE
START_ACTION_PLAN = copy.deepcopy(ACTION_PLAN1)
START_ACTION_PLAN['state'] = NEW_STATE
fake_responses = {
'/v1/action_plans':
{
'GET': (
{},
{"action_plans": [ACTION_PLAN1, ACTION_PLAN2]},
),
},
'/v1/action_plans/detail':
{
'GET': (
{},
{"action_plans": [ACTION_PLAN1, ACTION_PLAN2]},
),
},
'/v1/action_plans/%s' % ACTION_PLAN1['uuid']:
{
'GET': (
{},
ACTION_PLAN1,
),
'DELETE': (
{},
None,
),
'PATCH': (
{},
UPDATED_ACTION_PLAN,
),
},
'/v1/action_plans/%s/start' % ACTION_PLAN1['uuid']:
{
'POST': (
{},
START_ACTION_PLAN,
),
},
'/v1/action_plans/detail?uuid=%s' % ACTION_PLAN1['uuid']:
{
'GET': (
{},
{"action_plans": [ACTION_PLAN1]},
),
},
}
fake_responses_pagination = {
'/v1/action_plans':
{
'GET': (
{},
{"action_plans": [ACTION_PLAN1],
"next": "http://127.0.0.1:9322/v1/action_plans/?limit=1"}
),
},
'/v1/action_plans/?limit=1':
{
'GET': (
{},
{"action_plans": [ACTION_PLAN2]}
),
},
'/v1/action_plans/?marker=f8e47706-efcf-49a4-a5c4-af604eb492f2':
{
'GET': (
{},
{"action_plans": [ACTION_PLAN2]}
),
},
}
fake_responses_sorting = {
'/v1/action_plans/?sort_key=updated_at':
{
'GET': (
{},
{"action_plans": [ACTION_PLAN2, ACTION_PLAN1]}
),
},
'/v1/action_plans/?sort_dir=desc':
{
'GET': (
{},
{"action_plans": [ACTION_PLAN2, ACTION_PLAN1]}
),
},
}
class ActionPlanManagerTest(testtools.TestCase):
def setUp(self):
super(ActionPlanManagerTest, self).setUp()
self.api = utils.FakeAPI(fake_responses)
self.mgr = watcherclient.v1.action_plan.ActionPlanManager(self.api)
def test_action_plans_list(self):
action_plans = self.mgr.list()
expect = [
('GET', '/v1/action_plans', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(2, len(action_plans))
def test_action_plans_list_detail(self):
action_plans = self.mgr.list(detail=True)
expect = [
('GET', '/v1/action_plans/detail', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(2, len(action_plans))
def test_action_plans_list_limit(self):
self.api = utils.FakeAPI(fake_responses_pagination)
self.mgr = watcherclient.v1.action_plan.ActionPlanManager(self.api)
action_plans = self.mgr.list(limit=1)
expect = [
('GET', '/v1/action_plans/?limit=1', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertThat(action_plans, matchers.HasLength(1))
def test_action_plans_list_pagination_no_limit(self):
self.api = utils.FakeAPI(fake_responses_pagination)
self.mgr = watcherclient.v1.action_plan.ActionPlanManager(self.api)
action_plans = self.mgr.list(limit=0)
expect = [
('GET', '/v1/action_plans', {}, None),
('GET', '/v1/action_plans/?limit=1', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertThat(action_plans, matchers.HasLength(2))
def test_action_plans_list_marker(self):
self.api = utils.FakeAPI(fake_responses_pagination)
self.mgr = watcherclient.v1.action_plan.ActionPlanManager(self.api)
action_plans = self.mgr.list(
marker='f8e47706-efcf-49a4-a5c4-af604eb492f2')
expect = [
('GET', '/v1/action_plans/?'
'marker=f8e47706-efcf-49a4-a5c4-af604eb492f2',
{}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertThat(action_plans, matchers.HasLength(1))
def test_action_plans_list_sort_key(self):
self.api = utils.FakeAPI(fake_responses_sorting)
self.mgr = watcherclient.v1.action_plan.ActionPlanManager(self.api)
action_plans = self.mgr.list(sort_key='updated_at')
expect = [
('GET', '/v1/action_plans/?sort_key=updated_at', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(2, len(action_plans))
def test_action_plans_list_sort_dir(self):
self.api = utils.FakeAPI(fake_responses_sorting)
self.mgr = watcherclient.v1.action_plan.ActionPlanManager(self.api)
action_plans = self.mgr.list(sort_dir='desc')
expect = [
('GET', '/v1/action_plans/?sort_dir=desc', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(2, len(action_plans))
def test_action_plans_show(self):
action_plan = self.mgr.get(ACTION_PLAN1['uuid'])
expect = [
('GET', '/v1/action_plans/%s' % ACTION_PLAN1['uuid'], {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(ACTION_PLAN1['uuid'], action_plan.uuid)
def test_action_plan_update(self):
patch = {'op': 'replace',
'value': NEW_STATE,
'path': '/state'}
action_plan = self.mgr.update(action_plan_id=ACTION_PLAN1['uuid'],
patch=patch)
expect = [
('PATCH',
'/v1/action_plans/%s' % ACTION_PLAN1['uuid'],
{},
patch),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(NEW_STATE, action_plan.state)
def test_action_plan_start(self):
action_plan = self.mgr.start(ACTION_PLAN1['uuid'])
expect = [('POST', '/v1/action_plans/%s/start'
% ACTION_PLAN1['uuid'], {}, {})]
self.assertEqual(expect, self.api.calls)
self.assertEqual(NEW_STATE, action_plan.state)
python-watcherclient-2.2.0/watcherclient/tests/unit/v1/test_strategy.py 0000666 0001750 0001750 00000013101 13364113436 026470 0 ustar zuul zuul 0000000 0000000 # Copyright 2013 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import testtools
from testtools import matchers
from watcherclient.tests.unit import utils
import watcherclient.v1.strategy
STRATEGY1 = {
'uuid': '2cf86250-d309-4b81-818e-1537f3dba6e5',
'name': 'basic',
'display_name': 'Basic consolidation',
'strategy_id': 'SERVER_CONSOLIDATION',
}
STRATEGY2 = {
'uuid': 'b20bb987-ea8f-457a-a4ea-ab3ffdfeff8b',
'name': 'dummy',
'display_name': 'Dummy',
'strategy_id': 'DUMMY',
}
fake_responses = {
'/v1/strategies':
{
'GET': (
{},
{"strategies": [STRATEGY1]},
),
},
'/v1/strategies/detail':
{
'GET': (
{},
{"strategies": [STRATEGY1]},
)
},
'/v1/strategies/%s' % STRATEGY1['uuid']:
{
'GET': (
{},
STRATEGY1,
),
},
'/v1/strategies/%s' % STRATEGY1['name']:
{
'GET': (
{},
STRATEGY1,
),
},
'/v1/strategies/%s/state' % STRATEGY1['name']:
{
'GET': (
{},
STRATEGY1,
),
},
}
fake_responses_pagination = {
'/v1/strategies':
{
'GET': (
{},
{"strategies": [STRATEGY1],
"next": "http://127.0.0.1:9322/v1/strategies/?limit=1"}
),
},
'/v1/strategies/?limit=1':
{
'GET': (
{},
{"strategies": [STRATEGY2]}
),
},
}
fake_responses_sorting = {
'/v1/strategies/?sort_key=id':
{
'GET': (
{},
{"strategies": [STRATEGY1, STRATEGY2]}
),
},
'/v1/strategies/?sort_dir=desc':
{
'GET': (
{},
{"strategies": [STRATEGY2, STRATEGY1]}
),
},
}
class StrategyManagerTest(testtools.TestCase):
def setUp(self):
super(StrategyManagerTest, self).setUp()
self.api = utils.FakeAPI(fake_responses)
self.mgr = watcherclient.v1.strategy.StrategyManager(self.api)
def test_strategies_list(self):
strategies = self.mgr.list()
expect = [
('GET', '/v1/strategies', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(strategies))
def test_strategies_list_detail(self):
strategies = self.mgr.list(detail=True)
expect = [
('GET', '/v1/strategies/detail', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(strategies))
def test_strategies_list_limit(self):
self.api = utils.FakeAPI(fake_responses_pagination)
self.mgr = watcherclient.v1.strategy.StrategyManager(self.api)
strategies = self.mgr.list(limit=1)
expect = [
('GET', '/v1/strategies/?limit=1', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertThat(strategies, matchers.HasLength(1))
def test_strategies_list_pagination_no_limit(self):
self.api = utils.FakeAPI(fake_responses_pagination)
self.mgr = watcherclient.v1.strategy.StrategyManager(self.api)
strategies = self.mgr.list(limit=0)
expect = [
('GET', '/v1/strategies', {}, None),
('GET', '/v1/strategies/?limit=1', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertThat(strategies, matchers.HasLength(2))
def test_strategies_list_sort_key(self):
self.api = utils.FakeAPI(fake_responses_sorting)
self.mgr = watcherclient.v1.strategy.StrategyManager(self.api)
strategies = self.mgr.list(sort_key='id')
expect = [
('GET', '/v1/strategies/?sort_key=id', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(2, len(strategies))
def test_strategies_list_sort_dir(self):
self.api = utils.FakeAPI(fake_responses_sorting)
self.mgr = watcherclient.v1.strategy.StrategyManager(self.api)
strategies = self.mgr.list(sort_dir='desc')
expect = [
('GET', '/v1/strategies/?sort_dir=desc', {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(2, len(strategies))
def test_strategies_show(self):
strategy = self.mgr.get(STRATEGY1['uuid'])
expect = [
('GET', '/v1/strategies/%s' % STRATEGY1['uuid'], {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(STRATEGY1['uuid'], strategy.uuid)
def test_strategies_show_by_name(self):
strategy = self.mgr.get(STRATEGY1['name'])
expect = [
('GET', '/v1/strategies/%s' % STRATEGY1['name'], {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(STRATEGY1['name'], strategy.name)
def test_strategies_state(self):
self.mgr.state(STRATEGY1['name'])
expect = [
('GET', '/v1/strategies/%s/state' % STRATEGY1['name'], {}, None),
]
self.assertEqual(expect, self.api.calls)
python-watcherclient-2.2.0/watcherclient/tests/unit/utils.py 0000666 0001750 0001750 00000010415 13364113436 024406 0 ustar zuul zuul 0000000 0000000 # Copyright 2012 OpenStack LLC.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import copy
import os
import fixtures
import mock
from oslo_utils import strutils
import six
import testtools
class BaseTestCase(testtools.TestCase):
def setUp(self):
super(BaseTestCase, self).setUp()
self.useFixture(fixtures.FakeLogger())
# If enabled, stdout and/or stderr is captured and will appear in
# test results if that test fails.
if strutils.bool_from_string(os.environ.get('OS_STDOUT_CAPTURE')):
stdout = self.useFixture(fixtures.StringStream('stdout')).stream
self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
if strutils.bool_from_string(os.environ.get('OS_STDERR_CAPTURE')):
stderr = self.useFixture(fixtures.StringStream('stderr')).stream
self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
class FakeAPI(object):
def __init__(self, responses):
self.responses = responses
self.calls = []
def _request(self, method, url, headers=None, body=None):
call = (method, url, headers or {}, body)
self.calls.append(call)
return self.responses[url][method]
def raw_request(self, *args, **kwargs):
response = self._request(*args, **kwargs)
body_iter = iter(six.StringIO(response[1]))
return FakeResponse(response[0]), body_iter
def json_request(self, *args, **kwargs):
response = self._request(*args, **kwargs)
return FakeResponse(response[0]), response[1]
class FakeConnection(object):
def __init__(self, response=None):
self._response = response
self._last_request = None
def request(self, method, conn_url, **kwargs):
self._last_request = (method, conn_url, kwargs)
def setresponse(self, response):
self._response = response
def getresponse(self):
return self._response
def __repr__(self):
return ("FakeConnection(response=%s)" % (self._response))
class FakeResponse(object):
def __init__(self, headers, body=None, version=None, status=None,
reason=None):
"""Fake object to help testing.
:param headers: dict representing HTTP response headers
:param body: file-like object
"""
self.headers = headers
self.body = body
self.raw = mock.Mock()
self.raw.version = version
self.status_code = status
self.reason = reason
def getheaders(self):
return copy.deepcopy(self.headers).items()
def getheader(self, key, default):
return self.headers.get(key, default)
def read(self, amt):
return self.body.read(amt)
def __repr__(self):
return ("FakeResponse(%s, body=%s, version=%s, status=%s, reason=%s)" %
(self.headers, self.body, self.version, self.status,
self.reason))
class FakeSessionResponse(object):
def __init__(self, headers, content=None, status_code=None, version=None):
self.headers = headers
self.content = content
self.status_code = status_code
self.raw = mock.Mock()
self.raw.version = version
self.reason = ''
def iter_content(self, chunk_size):
return iter(self.content)
class FakeSession(object):
def __init__(self, headers, content=None, status_code=None, version=None):
self.headers = headers
self.content = content
self.status_code = status_code
self.version = version
self.verify = False
self.cert = ('test_cert', 'test_key')
def request(self, url, method, **kwargs):
request = FakeSessionResponse(
self.headers, self.content, self.status_code, self.version)
return request
python-watcherclient-2.2.0/watcherclient/tests/unit/common/ 0000775 0001750 0001750 00000000000 13364113665 024165 5 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/watcherclient/tests/unit/common/__init__.py 0000666 0001750 0001750 00000000000 13364113436 026262 0 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/watcherclient/tests/unit/common/test_api_versioning.py 0000666 0001750 0001750 00000013303 13364113436 030610 0 ustar zuul zuul 0000000 0000000 # Copyright 2016 Mirantis
# 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 watcherclient.common import api_versioning
from watcherclient import exceptions
from watcherclient.tests.unit import utils
class APIVersionTestCase(utils.BaseTestCase):
def test_valid_version_strings(self):
def _test_string(version, exp_major, exp_minor):
v = api_versioning.APIVersion(version)
self.assertEqual(v.ver_major, exp_major)
self.assertEqual(v.ver_minor, exp_minor)
_test_string("1.1", 1, 1)
_test_string("2.10", 2, 10)
_test_string("5.234", 5, 234)
_test_string("12.5", 12, 5)
_test_string("2.0", 2, 0)
_test_string("2.200", 2, 200)
def test_null_version(self):
v = api_versioning.APIVersion()
self.assertTrue(v.is_null())
def test_invalid_version_strings(self):
self.assertRaises(exceptions.UnsupportedVersion,
api_versioning.APIVersion, "2")
self.assertRaises(exceptions.UnsupportedVersion,
api_versioning.APIVersion, "200")
self.assertRaises(exceptions.UnsupportedVersion,
api_versioning.APIVersion, "2.1.4")
self.assertRaises(exceptions.UnsupportedVersion,
api_versioning.APIVersion, "200.23.66.3")
self.assertRaises(exceptions.UnsupportedVersion,
api_versioning.APIVersion, "5 .3")
self.assertRaises(exceptions.UnsupportedVersion,
api_versioning.APIVersion, "5. 3")
self.assertRaises(exceptions.UnsupportedVersion,
api_versioning.APIVersion, "5.03")
self.assertRaises(exceptions.UnsupportedVersion,
api_versioning.APIVersion, "02.1")
self.assertRaises(exceptions.UnsupportedVersion,
api_versioning.APIVersion, "2.001")
self.assertRaises(exceptions.UnsupportedVersion,
api_versioning.APIVersion, "")
self.assertRaises(exceptions.UnsupportedVersion,
api_versioning.APIVersion, " 2.1")
self.assertRaises(exceptions.UnsupportedVersion,
api_versioning.APIVersion, "2.1 ")
def test_version_comparisons(self):
v1 = api_versioning.APIVersion("2.0")
v2 = api_versioning.APIVersion("2.5")
v3 = api_versioning.APIVersion("5.23")
v4 = api_versioning.APIVersion("2.0")
v_null = api_versioning.APIVersion()
self.assertLess(v1, v2)
self.assertGreater(v3, v2)
self.assertNotEqual(v1, v2)
self.assertEqual(v1, v4)
self.assertNotEqual(v1, v_null)
self.assertEqual(v_null, v_null)
self.assertRaises(TypeError, v1.__le__, "2.1")
def test_version_matches(self):
v1 = api_versioning.APIVersion("2.0")
v2 = api_versioning.APIVersion("2.5")
v3 = api_versioning.APIVersion("2.45")
v4 = api_versioning.APIVersion("3.3")
v5 = api_versioning.APIVersion("3.23")
v6 = api_versioning.APIVersion("2.0")
v7 = api_versioning.APIVersion("3.3")
v8 = api_versioning.APIVersion("4.0")
v_null = api_versioning.APIVersion()
self.assertTrue(v2.matches(v1, v3))
self.assertTrue(v2.matches(v1, v_null))
self.assertTrue(v1.matches(v6, v2))
self.assertTrue(v4.matches(v2, v7))
self.assertTrue(v4.matches(v_null, v7))
self.assertTrue(v4.matches(v_null, v8))
self.assertFalse(v1.matches(v2, v3))
self.assertFalse(v5.matches(v2, v4))
self.assertFalse(v2.matches(v3, v1))
self.assertRaises(ValueError, v_null.matches, v1, v3)
def test_get_string(self):
v1_string = "3.23"
v1 = api_versioning.APIVersion(v1_string)
self.assertEqual(v1_string, v1.get_string())
self.assertRaises(ValueError,
api_versioning.APIVersion().get_string)
class GetAPIVersionTestCase(utils.BaseTestCase):
def test_get_available_client_versions(self):
output = api_versioning.get_available_major_versions()
self.assertNotEqual([], output)
def test_wrong_format(self):
self.assertRaises(exceptions.UnsupportedVersion,
api_versioning.get_api_version, "something_wrong")
def test_wrong_major_version(self):
self.assertRaises(exceptions.UnsupportedVersion,
api_versioning.get_api_version, "2")
@mock.patch("watcherclient.common.api_versioning.APIVersion")
def test_only_major_part_is_presented(self, mock_apiversion):
version = 7
self.assertEqual(mock_apiversion.return_value,
api_versioning.get_api_version(version))
mock_apiversion.assert_called_once_with("%s.0" % str(version))
@mock.patch("watcherclient.common.api_versioning.APIVersion")
def test_major_and_minor_parts_is_presented(self, mock_apiversion):
version = "2.7"
self.assertEqual(mock_apiversion.return_value,
api_versioning.get_api_version(version))
mock_apiversion.assert_called_once_with(version)
python-watcherclient-2.2.0/watcherclient/tests/unit/__init__.py 0000666 0001750 0001750 00000000000 13364113436 024772 0 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/watcherclient/tests/unit/test_client.py 0000666 0001750 0001750 00000033146 13364113436 025571 0 ustar zuul zuul 0000000 0000000 # 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 keystoneauth1 import loading as kaloading
from watcherclient import client as watcherclient
from watcherclient.common import httpclient
from watcherclient import exceptions
from watcherclient.tests.unit import utils
class ClientTest(utils.BaseTestCase):
def test_get_client_with_auth_token_watcher_url(self):
kwargs = {
'watcher_url': 'http://watcher.example.org:9322/',
'os_auth_token': 'USER_AUTH_TOKEN',
}
client = watcherclient.get_client('1', **kwargs)
self.assertEqual('USER_AUTH_TOKEN', client.http_client.auth_token)
self.assertEqual('http://watcher.example.org:9322/',
client.http_client.endpoint)
@mock.patch.object(kaloading.session, 'Session', autospec=True)
@mock.patch.object(kaloading, 'get_plugin_loader', autospec=True)
def _test_get_client(self, mock_ks_loader, mock_ks_session,
version=None, auth='password', **kwargs):
session = mock_ks_session.return_value.load_from_options.return_value
session.get_endpoint.return_value = 'http://localhost:9322/v1/f14b4123'
mock_ks_loader.return_value.load_from_options.return_value = 'auth'
watcherclient.get_client('1', **kwargs)
mock_ks_loader.assert_called_once_with(auth)
mock_ks_session.return_value.load_from_options.assert_called_once_with(
auth='auth', timeout=kwargs.get('timeout'),
insecure=kwargs.get('insecure'), cert=kwargs.get('cert'),
cacert=kwargs.get('cacert'), key=kwargs.get('key'))
session.get_endpoint.assert_called_once_with(
service_type=kwargs.get('os_service_type') or 'infra-optim',
interface=kwargs.get('os_endpoint_type') or 'publicURL',
region_name=kwargs.get('os_region_name'))
def test_get_client_no_auth_token(self):
kwargs = {
'os_tenant_name': 'TENANT_NAME',
'os_username': 'USERNAME',
'os_password': 'PASSWORD',
'os_auth_url': 'http://localhost:35357/v2.0',
'os_auth_token': '',
}
self._test_get_client(**kwargs)
def test_get_client_service_and_endpoint_type_defaults(self):
kwargs = {
'os_tenant_name': 'TENANT_NAME',
'os_username': 'USERNAME',
'os_password': 'PASSWORD',
'os_auth_url': 'http://localhost:35357/v2.0',
'os_auth_token': '',
'os_service_type': '',
'os_endpoint_type': ''
}
self._test_get_client(**kwargs)
def test_get_client_with_region_no_auth_token(self):
kwargs = {
'os_tenant_name': 'TENANT_NAME',
'os_username': 'USERNAME',
'os_password': 'PASSWORD',
'os_region_name': 'REGIONONE',
'os_auth_url': 'http://localhost:35357/v2.0',
'os_auth_token': '',
}
self._test_get_client(**kwargs)
def test_get_client_no_url(self):
kwargs = {
'os_tenant_name': 'TENANT_NAME',
'os_username': 'USERNAME',
'os_password': 'PASSWORD',
'os_auth_url': '',
}
self.assertRaises(
exceptions.AmbiguousAuthSystem, watcherclient.get_client,
'1', **kwargs)
# test the alias as well to ensure backwards compatibility
self.assertRaises(
exceptions.AmbigiousAuthSystem, watcherclient.get_client,
'1', **kwargs)
def test_get_client_incorrect_auth_params(self):
kwargs = {
'os_tenant_name': 'TENANT_NAME',
'os_username': 'USERNAME',
'os_auth_url': 'http://localhost:35357/v2.0',
}
self.assertRaises(
exceptions.AmbiguousAuthSystem, watcherclient.get_client,
'1', **kwargs)
def test_get_client_with_api_version_latest(self):
kwargs = {
'os_tenant_name': 'TENANT_NAME',
'os_username': 'USERNAME',
'os_password': 'PASSWORD',
'os_auth_url': 'http://localhost:35357/v2.0',
'os_auth_token': '',
'os_watcher_api_version': "latest",
}
self._test_get_client(**kwargs)
def test_get_client_with_api_version_numeric(self):
kwargs = {
'os_tenant_name': 'TENANT_NAME',
'os_username': 'USERNAME',
'os_password': 'PASSWORD',
'os_auth_url': 'http://localhost:35357/v2.0',
'os_auth_token': '',
'os_watcher_api_version': "1.4",
}
self._test_get_client(**kwargs)
def test_get_client_with_auth_token(self):
kwargs = {
'os_auth_url': 'http://localhost:35357/v2.0',
'os_auth_token': 'USER_AUTH_TOKEN',
}
self._test_get_client(auth='token', **kwargs)
def test_get_client_with_region_name_auth_token(self):
kwargs = {
'os_auth_url': 'http://localhost:35357/v2.0',
'os_region_name': 'REGIONONE',
'os_auth_token': 'USER_AUTH_TOKEN',
}
self._test_get_client(auth='token', **kwargs)
def test_get_client_only_session_passed(self):
session = mock.Mock()
session.get_endpoint.return_value = 'http://localhost:35357/v2.0'
kwargs = {
'session': session,
}
watcherclient.get_client('1', **kwargs)
session.get_endpoint.assert_called_once_with(
service_type='infra-optim',
interface='publicURL',
region_name=None)
def test_get_client_incorrect_session_passed(self):
session = mock.Mock()
session.get_endpoint.side_effect = Exception('boo')
kwargs = {
'session': session,
}
self.assertRaises(
exceptions.AmbiguousAuthSystem, watcherclient.get_client,
'1', **kwargs)
@mock.patch.object(kaloading.session, 'Session', autospec=True)
@mock.patch.object(kaloading, 'get_plugin_loader', autospec=True)
def _test_loader_arguments_passed_correctly(
self, mock_ks_loader, mock_ks_session,
passed_kwargs, expected_kwargs):
session = mock_ks_session.return_value.load_from_options.return_value
session.get_endpoint.return_value = 'http://localhost:9322/v1/f14b4123'
mock_ks_loader.return_value.load_from_options.return_value = 'auth'
watcherclient.get_client('1', **passed_kwargs)
mock_ks_loader.return_value.load_from_options.assert_called_once_with(
**expected_kwargs)
mock_ks_session.return_value.load_from_options.assert_called_once_with(
auth='auth', timeout=passed_kwargs.get('timeout'),
insecure=passed_kwargs.get('insecure'),
cert=passed_kwargs.get('cert'),
cacert=passed_kwargs.get('cacert'), key=passed_kwargs.get('key'))
session.get_endpoint.assert_called_once_with(
service_type=passed_kwargs.get('os_service_type') or 'infra-optim',
interface=passed_kwargs.get('os_endpoint_type') or 'publicURL',
region_name=passed_kwargs.get('os_region_name'))
def test_loader_arguments_token(self):
passed_kwargs = {
'os_auth_url': 'http://localhost:35357/v3',
'os_region_name': 'REGIONONE',
'os_auth_token': 'USER_AUTH_TOKEN',
}
expected_kwargs = {
'auth_url': 'http://localhost:35357/v3',
'project_id': None,
'project_name': None,
'user_domain_id': None,
'user_domain_name': None,
'project_domain_id': None,
'project_domain_name': None,
'token': 'USER_AUTH_TOKEN'
}
self._test_loader_arguments_passed_correctly(
passed_kwargs=passed_kwargs, expected_kwargs=expected_kwargs)
def test_loader_arguments_password_tenant_name(self):
passed_kwargs = {
'os_auth_url': 'http://localhost:35357/v3',
'os_region_name': 'REGIONONE',
'os_tenant_name': 'TENANT',
'os_username': 'user',
'os_password': '1234',
'os_project_domain_id': 'DEFAULT',
'os_user_domain_id': 'DEFAULT'
}
expected_kwargs = {
'auth_url': 'http://localhost:35357/v3',
'project_id': None,
'project_name': 'TENANT',
'user_domain_id': 'DEFAULT',
'user_domain_name': None,
'project_domain_id': 'DEFAULT',
'project_domain_name': None,
'username': 'user',
'password': '1234'
}
self._test_loader_arguments_passed_correctly(
passed_kwargs=passed_kwargs, expected_kwargs=expected_kwargs)
def test_loader_arguments_password_project_id(self):
passed_kwargs = {
'os_auth_url': 'http://localhost:35357/v3',
'os_region_name': 'REGIONONE',
'os_project_id': '1000',
'os_username': 'user',
'os_password': '1234',
'os_project_domain_name': 'domain1',
'os_user_domain_name': 'domain1'
}
expected_kwargs = {
'auth_url': 'http://localhost:35357/v3',
'project_id': '1000',
'project_name': None,
'user_domain_id': None,
'user_domain_name': 'domain1',
'project_domain_id': None,
'project_domain_name': 'domain1',
'username': 'user',
'password': '1234'
}
self._test_loader_arguments_passed_correctly(
passed_kwargs=passed_kwargs, expected_kwargs=expected_kwargs)
@mock.patch.object(watcherclient, 'Client')
@mock.patch.object(kaloading.session, 'Session', autospec=True)
def test_correct_arguments_passed_to_client_constructor_noauth_mode(
self, mock_ks_session, mock_client):
kwargs = {
'watcher_url': 'http://watcher.example.org:9322/',
'os_auth_token': 'USER_AUTH_TOKEN',
'os_watcher_api_version': 'latest',
'insecure': True,
'max_retries': 10,
'retry_interval': 10,
'os_cacert': 'data'
}
watcherclient.get_client('1', **kwargs)
mock_client.assert_called_once_with(
'1', 'http://watcher.example.org:9322/',
**{
'os_watcher_api_version': 'latest',
'max_retries': 10,
'retry_interval': 10,
'token': 'USER_AUTH_TOKEN',
'insecure': True,
'ca_file': 'data',
'cert_file': None,
'key_file': None,
'timeout': None,
'session': None
}
)
self.assertFalse(mock_ks_session.called)
@mock.patch.object(watcherclient, 'Client')
@mock.patch.object(kaloading.session, 'Session', autospec=True)
def test_correct_arguments_passed_to_client_constructor_session_created(
self, mock_ks_session, mock_client):
session = mock_ks_session.return_value.load_from_options.return_value
kwargs = {
'os_auth_url': 'http://localhost:35357/v3',
'os_region_name': 'REGIONONE',
'os_project_id': '1000',
'os_username': 'user',
'os_password': '1234',
'os_project_domain_name': 'domain1',
'os_user_domain_name': 'domain1'
}
watcherclient.get_client('1', **kwargs)
mock_client.assert_called_once_with(
'1', session.get_endpoint.return_value,
**{
'os_watcher_api_version': None,
'max_retries': None,
'retry_interval': None,
'session': session,
}
)
@mock.patch.object(watcherclient, 'Client')
@mock.patch.object(kaloading.session, 'Session', autospec=True)
def test_correct_arguments_passed_to_client_constructor_session_passed(
self, mock_ks_session, mock_client):
session = mock.Mock()
kwargs = {
'session': session,
}
watcherclient.get_client('1', **kwargs)
mock_client.assert_called_once_with(
'1', session.get_endpoint.return_value,
**{
'os_watcher_api_version': None,
'max_retries': None,
'retry_interval': None,
'session': session,
}
)
self.assertFalse(mock_ks_session.called)
def test_safe_header_with_auth_token(self):
(name, value) = ('X-Auth-Token', u'3b640e2e64d946ac8f55615aff221dc1')
expected_header = (u'X-Auth-Token',
'{SHA1}6de9fb3b0b89099030a54abfeb468e7b1b1f0f2b')
client = httpclient.HTTPClient('http://localhost/')
header_redact = client._process_header(name, value)
self.assertEqual(expected_header, header_redact)
def test_safe_header_with_no_auth_token(self):
name, value = ('Accept', 'application/json')
header = ('Accept', 'application/json')
client = httpclient.HTTPClient('http://localhost/')
header_redact = client._process_header(name, value)
self.assertEqual(header, header_redact)
python-watcherclient-2.2.0/watcherclient/tests/unit/keystone_client_fixtures.py 0000666 0001750 0001750 00000006055 13364113436 030403 0 ustar zuul zuul 0000000 0000000 # Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_serialization import jsonutils
from oslo_utils import uuidutils
from keystoneauth1.fixture import v2 as ks_v2_fixture
from keystoneauth1.fixture import v3 as ks_v3_fixture
# these are copied from python-keystoneclient tests
BASE_HOST = 'http://keystone.example.com'
BASE_URL = "%s:5000/" % BASE_HOST
UPDATED = '2013-03-06T00:00:00Z'
V2_URL = "%sv2.0" % BASE_URL
V2_DESCRIBED_BY_HTML = {'href': 'http://docs.openstack.org/api/'
'openstack-identity-service/2.0/content/',
'rel': 'describedby',
'type': 'text/html'}
V2_DESCRIBED_BY_PDF = {'href': 'http://docs.openstack.org/api/openstack-ident'
'ity-service/2.0/identity-dev-guide-2.0.pdf',
'rel': 'describedby',
'type': 'application/pdf'}
V2_VERSION = {'id': 'v2.0',
'links': [{'href': V2_URL, 'rel': 'self'},
V2_DESCRIBED_BY_HTML, V2_DESCRIBED_BY_PDF],
'status': 'stable',
'updated': UPDATED}
V3_URL = "%sv3" % BASE_URL
V3_MEDIA_TYPES = [{'base': 'application/json',
'type': 'application/vnd.openstack.identity-v3+json'},
{'base': 'application/xml',
'type': 'application/vnd.openstack.identity-v3+xml'}]
V3_VERSION = {'id': 'v3.0',
'links': [{'href': V3_URL, 'rel': 'self'}],
'media-types': V3_MEDIA_TYPES,
'status': 'stable',
'updated': UPDATED}
TOKENID = uuidutils.generate_uuid(dashed=False)
def _create_version_list(versions):
return jsonutils.dumps({'versions': {'values': versions}})
def _create_single_version(version):
return jsonutils.dumps({'version': version})
V3_VERSION_LIST = _create_version_list([V3_VERSION, V2_VERSION])
V2_VERSION_LIST = _create_version_list([V2_VERSION])
V3_VERSION_ENTRY = _create_single_version(V3_VERSION)
V2_VERSION_ENTRY = _create_single_version(V2_VERSION)
def keystone_request_callback(request, uri, headers):
response_headers = {"content-type": "application/json"}
token_id = TOKENID
if uri == BASE_URL:
return (200, headers, V3_VERSION_LIST)
elif uri == BASE_URL + "/v2.0":
v2_token = ks_v2_fixture.Token(token_id)
return (200, response_headers, jsonutils.dumps(v2_token))
elif uri == BASE_URL + "/v3":
v3_token = ks_v3_fixture.Token()
response_headers["X-Subject-Token"] = token_id
return (201, response_headers, jsonutils.dumps(v3_token))
python-watcherclient-2.2.0/watcherclient/tests/unit/test_utils.py 0000666 0001750 0001750 00000015641 13364113436 025453 0 ustar zuul zuul 0000000 0000000 #
# Copyright 2013 OpenStack LLC.
# 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 watcherclient.common.apiclient import exceptions as exc
from watcherclient.common import utils
from watcherclient.tests.unit import utils as test_utils
class UtilsTest(test_utils.BaseTestCase):
def test_args_array_to_dict(self):
my_args = {
'matching_metadata': ['str=foo', 'int=1', 'bool=true',
'list=[1, 2, 3]', 'dict={"foo": "bar"}'],
'other': 'value'
}
cleaned_dict = utils.args_array_to_dict(my_args,
"matching_metadata")
self.assertEqual({
'matching_metadata': {'str': 'foo', 'int': 1, 'bool': True,
'list': [1, 2, 3], 'dict': {'foo': 'bar'}},
'other': 'value'
}, cleaned_dict)
def test_args_array_to_patch(self):
my_args = {
'attributes': ['str=foo', 'int=1', 'bool=true',
'list=[1, 2, 3]', 'dict={"foo": "bar"}'],
'op': 'add',
}
patch = utils.args_array_to_patch(my_args['op'],
my_args['attributes'])
self.assertEqual([{'op': 'add', 'value': 'foo', 'path': '/str'},
{'op': 'add', 'value': 1, 'path': '/int'},
{'op': 'add', 'value': True, 'path': '/bool'},
{'op': 'add', 'value': [1, 2, 3], 'path': '/list'},
{'op': 'add', 'value': {"foo": "bar"},
'path': '/dict'}], patch)
def test_args_array_to_patch_format_error(self):
my_args = {
'attributes': ['foobar'],
'op': 'add',
}
self.assertRaises(exc.CommandError, utils.args_array_to_patch,
my_args['op'], my_args['attributes'])
def test_args_array_to_patch_remove(self):
my_args = {
'attributes': ['/foo', 'extra/bar'],
'op': 'remove',
}
patch = utils.args_array_to_patch(my_args['op'],
my_args['attributes'])
self.assertEqual([{'op': 'remove', 'path': '/foo'},
{'op': 'remove', 'path': '/extra/bar'}], patch)
def test_split_and_deserialize(self):
ret = utils.split_and_deserialize('str=foo')
self.assertEqual(('str', 'foo'), ret)
ret = utils.split_and_deserialize('int=1')
self.assertEqual(('int', 1), ret)
ret = utils.split_and_deserialize('bool=false')
self.assertEqual(('bool', False), ret)
ret = utils.split_and_deserialize('list=[1, "foo", 2]')
self.assertEqual(('list', [1, "foo", 2]), ret)
ret = utils.split_and_deserialize('dict={"foo": 1}')
self.assertEqual(('dict', {"foo": 1}), ret)
ret = utils.split_and_deserialize('str_int="1"')
self.assertEqual(('str_int', "1"), ret)
def test_split_and_deserialize_fail(self):
self.assertRaises(exc.CommandError,
utils.split_and_deserialize, 'foo:bar')
class CommonParamsForListTest(test_utils.BaseTestCase):
def setUp(self):
super(CommonParamsForListTest, self).setUp()
self.args = mock.Mock(limit=None, marker=None,
sort_key=None, sort_dir=None)
self.args.detail = False
self.expected_params = {'detail': False}
def test_nothing_set(self):
self.assertEqual(self.expected_params,
utils.common_params_for_list(self.args, [], []))
def test_limit(self):
self.args.limit = 42
self.expected_params.update({'limit': 42})
self.assertEqual(self.expected_params,
utils.common_params_for_list(self.args, [], []))
def test_invalid_limit(self):
self.args.limit = -42
self.assertRaises(exc.CommandError,
utils.common_params_for_list,
self.args, [], [])
def test_marker(self):
self.args.marker = 'e420a881-d7df-4de2-bbf3-378cc13d9b3a'
self.expected_params.update(
{'marker': 'e420a881-d7df-4de2-bbf3-378cc13d9b3a'})
self.assertEqual(self.expected_params,
utils.common_params_for_list(self.args, [], []))
def test_sort_key_and_sort_dir(self):
self.args.sort_key = 'field'
self.args.sort_dir = 'desc'
self.expected_params.update({'sort_key': 'field', 'sort_dir': 'desc'})
self.assertEqual(self.expected_params,
utils.common_params_for_list(self.args,
['field'],
[]))
def test_sort_key_allows_label(self):
self.args.sort_key = 'Label'
self.expected_params.update({'sort_key': 'field'})
self.assertEqual(self.expected_params,
utils.common_params_for_list(self.args,
['field', 'field2'],
['Label', 'Label2']))
def test_sort_key_invalid(self):
self.args.sort_key = 'something'
self.assertRaises(exc.CommandError,
utils.common_params_for_list,
self.args,
['field', 'field2'],
[])
def test_sort_dir_invalid(self):
self.args.sort_dir = 'something'
self.assertRaises(exc.CommandError,
utils.common_params_for_list,
self.args,
[],
[])
def test_detail(self):
self.args.detail = True
self.expected_params['detail'] = True
self.assertEqual(self.expected_params,
utils.common_params_for_list(self.args, [], []))
class CommonFiltersTest(test_utils.BaseTestCase):
def test_limit(self):
result = utils.common_filters(limit=42)
self.assertEqual(['limit=42'], result)
def test_limit_0(self):
result = utils.common_filters(limit=0)
self.assertEqual([], result)
def test_other(self):
for key in ('sort_key', 'sort_dir'):
result = utils.common_filters(**{key: 'test'})
self.assertEqual(['%s=test' % key], result)
python-watcherclient-2.2.0/watcherclient/tests/__init__.py 0000666 0001750 0001750 00000000000 13364113436 024013 0 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/watcherclient/tests/functional/ 0000775 0001750 0001750 00000000000 13364113665 024060 5 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/watcherclient/tests/functional/v1/ 0000775 0001750 0001750 00000000000 13364113665 024406 5 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/watcherclient/tests/functional/v1/base.py 0000666 0001750 0001750 00000012202 13364113436 025665 0 ustar zuul zuul 0000000 0000000 # Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import os
import re
import shlex
import subprocess
import testtools
import six
from tempest import clients
from tempest.common import credentials_factory as creds_factory
from tempest.lib.cli import output_parser
from tempest.lib import exceptions
def credentials():
# You can get credentials either from tempest.conf file or
# from OS environment.
tempest_creds = clients.get_auth_provider(
creds_factory.get_configured_admin_credentials())
creds = tempest_creds.credentials
creds_dict = {
'--os-username': os.environ.get('OS_USERNAME', creds.username),
'--os-password': os.environ.get('OS_PASSWORD', creds.password),
'--os-project-name': os.environ.get('OS_PROJECT_NAME',
creds.project_name),
'--os-auth-url': os.environ.get('OS_AUTH_URL',
tempest_creds.auth_url),
'--os-project-domain-name': os.environ.get('OS_PROJECT_DOMAIN_ID',
creds.project_domain_name),
'--os-user-domain-name': os.environ.get('OS_USER_DOMAIN_ID',
creds.user_domain_name),
}
return [x for sub in creds_dict.items() for x in sub]
def execute(cmd, fail_ok=False, merge_stderr=False):
"""Executes specified command for the given action."""
cmdlist = shlex.split(cmd)
cmdlist.extend(credentials())
stdout = subprocess.PIPE
stderr = subprocess.STDOUT if merge_stderr else subprocess.PIPE
proc = subprocess.Popen(cmdlist, stdout=stdout, stderr=stderr)
result, result_err = proc.communicate()
result = result.decode('utf-8')
if not fail_ok and proc.returncode != 0:
raise exceptions.CommandFailed(proc.returncode, cmd, result,
result_err)
return result
class TestCase(testtools.TestCase):
delimiter_line = re.compile('^\+\-[\+\-]+\-\+$')
@classmethod
def watcher(cls, cmd, fail_ok=False):
"""Executes watcherclient command for the given action."""
return execute('watcher {0}'.format(cmd), fail_ok=fail_ok)
@classmethod
def get_opts(cls, fields, format='value'):
return ' -f {0} {1}'.format(format,
' '.join(['-c ' + it for it in fields]))
@classmethod
def assertOutput(cls, expected, actual):
if expected != actual:
raise Exception('{0} != {1}'.format(expected, actual))
@classmethod
def assertInOutput(cls, expected, actual):
if expected not in actual:
raise Exception('{0} not in {1}'.format(expected, actual))
def assert_table_structure(self, items, field_names):
"""Verify that all items have keys listed in field_names."""
for item in items:
for field in field_names:
self.assertIn(field, item)
def assert_show_fields(self, items, field_names):
"""Verify that all items have keys listed in field_names."""
for item in items:
for key in six.iterkeys(item):
self.assertIn(key, field_names)
def assert_show_structure(self, items, field_names):
"""Verify that all field_names listed in keys of all items."""
if isinstance(items, list):
o = {}
for d in items:
o.update(d)
else:
o = items
item_keys = o.keys()
for field in field_names:
self.assertIn(field, item_keys)
@staticmethod
def parse_show_as_object(raw_output):
"""Return a dict with values parsed from cli output."""
items = TestCase.parse_show(raw_output)
o = {}
for item in items:
o.update(item)
return o
@staticmethod
def parse_show(raw_output):
"""Return list of dicts with item values parsed from cli output."""
items = []
table_ = output_parser.table(raw_output)
for row in table_['values']:
item = {}
item[row[0]] = row[1]
items.append(item)
return items
def parse_listing(self, raw_output):
"""Return list of dicts with basic item parsed from cli output."""
return output_parser.listing(raw_output)
def has_actionplan_succeeded(self, ap_uuid):
return self.parse_show_as_object(
self.watcher('actionplan show %s' % ap_uuid)
)['State'] == 'SUCCEEDED'
@classmethod
def has_audit_created(cls, audit_uuid):
return cls.parse_show_as_object(
cls.watcher('audit show %s' % audit_uuid))['State'] == 'SUCCEEDED'
python-watcherclient-2.2.0/watcherclient/tests/functional/v1/test_goal.py 0000666 0001750 0001750 00000003017 13364113436 026740 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2016 Servionica
#
# 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 watcherclient.tests.functional.v1 import base
class GoalTests(base.TestCase):
"""Functional tests for goal."""
dummy_name = 'dummy'
list_fields = ['UUID', 'Name', 'Display name']
def test_goal_list(self):
raw_output = self.watcher('goal list')
self.assertIn(self.dummy_name, raw_output)
self.assert_table_structure([raw_output], self.list_fields)
def test_goal_detailed_list(self):
raw_output = self.watcher('goal list --detail')
self.assertIn(self.dummy_name, raw_output)
self.assert_table_structure(
[raw_output], self.list_fields + ['Efficacy specification'])
def test_goal_show(self):
raw_output = self.watcher('goal show %s' % self.dummy_name)
self.assertIn(self.dummy_name, raw_output)
self.assert_table_structure(
[raw_output], self.list_fields + ['Efficacy specification'])
self.assertNotIn('server_consolidation', raw_output)
python-watcherclient-2.2.0/watcherclient/tests/functional/v1/test_action.py 0000666 0001750 0001750 00000006221 13364113436 027273 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2016 Servionica
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from oslo_utils import uuidutils
import functools
from tempest.lib.common.utils import test_utils
from watcherclient.tests.functional.v1 import base
class ActionTests(base.TestCase):
"""Functional tests for action."""
dummy_name = 'dummy'
list_fields = ['UUID', 'Parents', 'State', 'Action Plan', 'Action']
detailed_list_fields = list_fields + ['Created At', 'Updated At',
'Deleted At', 'Parameters']
audit_template_name = 'a' + uuidutils.generate_uuid()
audit_uuid = None
@classmethod
def setUpClass(cls):
template_raw_output = cls.watcher(
'audittemplate create %s dummy -s dummy' % cls.audit_template_name)
template_output = cls.parse_show_as_object(template_raw_output)
audit_output = cls.parse_show_as_object(cls.watcher(
'audit create -a %s' % template_output['Name']))
cls.audit_uuid = audit_output['UUID']
audit_created = test_utils.call_until_true(
func=functools.partial(cls.has_audit_created, cls.audit_uuid),
duration=600,
sleep_for=2)
if not audit_created:
raise Exception('Audit has not been succeeded')
@classmethod
def tearDownClass(cls):
# Delete Action Plan and all related actions.
output = cls.parse_show(
cls.watcher('actionplan list --audit %s' % cls.audit_uuid))
action_plan_uuid = list(output[0])[0]
raw_output = cls.watcher('actionplan delete %s' % action_plan_uuid)
cls.assertOutput('', raw_output)
# Delete audit
raw_output = cls.watcher('audit delete %s' % cls.audit_uuid)
cls.assertOutput('', raw_output)
# Delete Template
raw_output = cls.watcher(
'audittemplate delete %s' % cls.audit_template_name)
cls.assertOutput('', raw_output)
def test_action_list(self):
raw_output = self.watcher('action list')
self.assert_table_structure([raw_output], self.list_fields)
def test_action_detailed_list(self):
raw_output = self.watcher('action list --detail')
self.assert_table_structure([raw_output], self.detailed_list_fields)
def test_action_show(self):
action_list = self.parse_show(self.watcher('action list --audit %s'
% self.audit_uuid))
action_uuid = list(action_list[0])[0]
action = self.watcher('action show %s' % action_uuid)
self.assertIn(action_uuid, action)
self.assert_table_structure([action],
self.detailed_list_fields)
python-watcherclient-2.2.0/watcherclient/tests/functional/v1/test_audit.py 0000666 0001750 0001750 00000012460 13364113436 027126 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2016 Servionica
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from oslo_utils import uuidutils
import functools
from tempest.lib.common.utils import test_utils
from watcherclient.tests.functional.v1 import base
class AuditTests(base.TestCase):
"""Functional tests for audit."""
dummy_name = 'dummy'
list_fields = ['UUID', 'Name', 'Audit Type', 'State', 'Goal', 'Strategy']
detailed_list_fields = list_fields + ['Created At', 'Updated At',
'Deleted At', 'Parameters',
'Interval', 'Audit Scope',
'Next Run Time', 'Hostname']
audit_template_name = 'a' + uuidutils.generate_uuid()
audit_uuid = None
@classmethod
def setUpClass(cls):
raw_output = cls.watcher('audittemplate create %s dummy -s dummy'
% cls.audit_template_name)
template_output = cls.parse_show_as_object(raw_output)
audit_raw_output = cls.watcher(
'audit create -a %s' % template_output['Name'])
audit_output = cls.parse_show_as_object(audit_raw_output)
cls.audit_uuid = audit_output['UUID']
audit_created = test_utils.call_until_true(
func=functools.partial(cls.has_audit_created, cls.audit_uuid),
duration=600,
sleep_for=2)
if not audit_created:
raise Exception('Audit has not been succeeded')
@classmethod
def tearDownClass(cls):
output = cls.parse_show(
cls.watcher('actionplan list --audit %s' % cls.audit_uuid))
action_plan_uuid = list(output[0])[0]
cls.watcher('actionplan delete %s' % action_plan_uuid)
cls.watcher('audit delete %s' % cls.audit_uuid)
cls.watcher('audittemplate delete %s' % cls.audit_template_name)
def test_audit_list(self):
raw_output = self.watcher('audit list')
self.assert_table_structure([raw_output], self.list_fields)
def test_audit_detailed_list(self):
raw_output = self.watcher('audit list --detail')
self.assert_table_structure([raw_output], self.detailed_list_fields)
def test_audit_show(self):
audit = self.watcher('audit show ' + self.audit_uuid)
self.assertIn(self.audit_uuid, audit)
self.assert_table_structure([audit], self.detailed_list_fields)
def test_audit_update(self):
audit_raw_output = self.watcher('audit update %s add interval=2'
% self.audit_uuid)
audit_output = self.parse_show_as_object(audit_raw_output)
assert int(audit_output['Interval']) == 2
class AuditActiveTests(base.TestCase):
list_fields = ['UUID', 'Name', 'Audit Type', 'State', 'Goal', 'Strategy']
detailed_list_fields = list_fields + ['Created At', 'Updated At',
'Deleted At', 'Parameters',
'Interval', 'Audit Scope']
audit_template_name = 'a' + uuidutils.generate_uuid()
@classmethod
def setUpClass(cls):
cls.watcher('audittemplate create %s dummy -s dummy'
% cls.audit_template_name)
@classmethod
def tearDownClass(cls):
cls.watcher('audittemplate delete %s' % cls.audit_template_name)
def _create_audit(self):
return self.parse_show_as_object(
self.watcher('audit create -a %s'
% self.audit_template_name))['UUID']
def _delete_audit(self, audit_uuid):
self.assertTrue(test_utils.call_until_true(
func=functools.partial(
self.has_audit_created, audit_uuid),
duration=600,
sleep_for=2
))
output = self.parse_show(
self.watcher('actionplan list --audit %s' % audit_uuid))
action_plan_uuid = list(output[0])[0]
self.watcher('actionplan delete %s' % action_plan_uuid)
self.watcher('audit delete %s' % audit_uuid)
def test_create_audit(self):
audit = self.watcher('audit create -a %s' % self.audit_template_name)
audit_uuid = self.parse_show_as_object(audit)['UUID']
self.assert_table_structure([audit], self.detailed_list_fields)
self._delete_audit(audit_uuid)
def test_delete_audit(self):
audit_uuid = self._create_audit()
self.assertTrue(test_utils.call_until_true(
func=functools.partial(
self.has_audit_created, audit_uuid),
duration=600,
sleep_for=2
))
raw_output = self.watcher('audit delete %s' % audit_uuid)
self.assertOutput('', raw_output)
output = self.parse_show(
self.watcher('actionplan list --audit %s' % audit_uuid))
action_plan_uuid = list(output[0])[0]
self.watcher('actionplan delete %s' % action_plan_uuid)
python-watcherclient-2.2.0/watcherclient/tests/functional/v1/test_service.py 0000666 0001750 0001750 00000003640 13364113436 027460 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2016 Servionica
#
# 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 watcherclient.tests.functional.v1 import base
class ServiceTests(base.TestCase):
"""Functional tests for service."""
decision_engine_name = 'watcher-decision-engine'
applier_name = 'watcher-applier'
list_fields = ['ID', 'Name', 'Host', 'Status']
def test_service_list(self):
raw_output = self.watcher('service list')
self.assertIn(self.decision_engine_name, raw_output)
self.assertIn(self.applier_name, raw_output)
self.assert_table_structure([raw_output], self.list_fields)
def test_service_detailed_list(self):
raw_output = self.watcher('service list --detail')
self.assertIn(self.decision_engine_name, raw_output)
self.assertIn(self.applier_name, raw_output)
self.assert_table_structure([raw_output],
self.list_fields + ['Last seen up'])
def test_service_show(self):
# TODO(alexchadin): this method should be refactored since Watcher will
# get HA support soon.
raw_output = self.watcher('service show %s'
% self.decision_engine_name)
self.assertIn(self.decision_engine_name, raw_output)
self.assert_table_structure([raw_output],
self.list_fields + ['Last seen up'])
self.assertNotIn(self.applier_name, raw_output)
python-watcherclient-2.2.0/watcherclient/tests/functional/v1/test_audit_template.py 0000666 0001750 0001750 00000007131 13364113436 031020 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2016 Servionica
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from oslo_utils import uuidutils
from watcherclient.tests.functional.v1 import base
class AuditTemplateTests(base.TestCase):
"""Functional tests for audit template."""
dummy_name = 'dummy'
list_fields = ['UUID', 'Name', 'Goal', 'Strategy']
detailed_list_fields = list_fields + ['Created At', 'Updated At',
'Deleted At', 'Description',
'Audit Scope']
audit_template_name = 'a' + uuidutils.generate_uuid()
@classmethod
def setUpClass(cls):
cls.watcher('audittemplate create %s dummy -s dummy'
% cls.audit_template_name)
@classmethod
def tearDownClass(cls):
cls.watcher('audittemplate delete %s' % cls.audit_template_name)
def test_audit_template_list(self):
raw_output = self.watcher('audittemplate list')
self.assert_table_structure([raw_output], self.list_fields)
def test_audit_template_detailed_list(self):
raw_output = self.watcher('audittemplate list --detail')
self.assert_table_structure([raw_output], self.detailed_list_fields)
def test_audit_template_show(self):
audit_template = self.watcher(
'audittemplate show %s' % self.audit_template_name)
self.assertIn(self.audit_template_name, audit_template)
self.assert_table_structure([audit_template],
self.detailed_list_fields)
def test_audit_template_update(self):
raw_output = self.watcher('audittemplate update %s replace '
'description="Updated Desc"'
% self.audit_template_name)
audit_template_output = self.parse_show_as_object(raw_output)
assert audit_template_output['Description'] == 'Updated Desc'
class AuditTemplateActiveTests(base.TestCase):
audit_template_name = 'b' + uuidutils.generate_uuid()
list_fields = ['UUID', 'Name', 'Goal', 'Strategy']
detailed_list_fields = list_fields + ['Created At', 'Updated At',
'Deleted At', 'Description',
'Audit Scope']
def _create_audit_template(self):
self.watcher('audittemplate create %s dummy -s dummy '
'-d "Test Audit Template"' % self.audit_template_name)
def _delete_audit_template(self):
self.watcher('audittemplate delete %s' % self.audit_template_name)
def test_create_audit_template(self):
raw_output = self.watcher('audittemplate create %s dummy '
'-s dummy -d "Test Audit Template"'
% self.audit_template_name)
self.assert_table_structure([raw_output], self.detailed_list_fields)
self._delete_audit_template()
def test_delete_audit_template(self):
self._create_audit_template()
raw_output = self.watcher('audittemplate delete %s'
% self.audit_template_name)
self.assertOutput('', raw_output)
python-watcherclient-2.2.0/watcherclient/tests/functional/v1/__init__.py 0000666 0001750 0001750 00000000000 13364113436 026503 0 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/watcherclient/tests/functional/v1/test_scoring_engine.py 0000666 0001750 0001750 00000003116 13364113436 031007 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2016 Servionica
#
# 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 watcherclient.tests.functional.v1 import base
class ScoringEngineTests(base.TestCase):
"""Functional tests for scoring engine."""
dummy_name = 'dummy_scorer'
list_fields = ['UUID', 'Name', 'Description']
detailed_list_fields = list_fields + ['Metainfo']
def test_scoringengine_list(self):
raw_output = self.watcher('scoringengine list')
self.assertIn(self.dummy_name, raw_output)
self.assert_table_structure([raw_output], self.list_fields)
def test_scoringengine_detailed_list(self):
raw_output = self.watcher('scoringengine list --detail')
self.assertIn(self.dummy_name, raw_output)
self.assert_table_structure([raw_output], self.detailed_list_fields)
def test_scoringengine_show(self):
raw_output = self.watcher('scoringengine show %s' % self.dummy_name)
self.assertIn(self.dummy_name, raw_output)
self.assert_table_structure([raw_output], self.detailed_list_fields)
self.assertNotIn('dummy_avg_scorer', raw_output)
python-watcherclient-2.2.0/watcherclient/tests/functional/v1/test_action_plan.py 0000666 0001750 0001750 00000007634 13364113436 030316 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2016 Servionica
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from oslo_utils import uuidutils
import functools
from tempest.lib.common.utils import test_utils
from watcherclient.tests.functional.v1 import base
class ActionPlanTests(base.TestCase):
"""Functional tests for action plan."""
dummy_name = 'dummy'
list_fields = ['UUID', 'Audit', 'State', 'Updated At', 'Global efficacy']
detailed_list_fields = list_fields + ['Created At', 'Deleted At',
'Strategy', 'Efficacy indicators',
'Hostname']
audit_template_name = 'a' + uuidutils.generate_uuid()
audit_uuid = None
@classmethod
def setUpClass(cls):
template_raw_output = cls.watcher(
'audittemplate create %s dummy -s dummy' % cls.audit_template_name)
template_output = cls.parse_show_as_object(template_raw_output)
audit_raw_output = cls.watcher('audit create -a %s'
% template_output['Name'])
audit_output = cls.parse_show_as_object(audit_raw_output)
cls.audit_uuid = audit_output['UUID']
audit_created = test_utils.call_until_true(
func=functools.partial(cls.has_audit_created, cls.audit_uuid),
duration=600,
sleep_for=2)
if not audit_created:
raise Exception('Audit has not been succeeded')
@classmethod
def tearDownClass(cls):
# Delete action plan
output = cls.parse_show(
cls.watcher('actionplan list --audit %s' % cls.audit_uuid))
action_plan_uuid = list(output[0])[0]
raw_output = cls.watcher('actionplan delete %s' % action_plan_uuid)
cls.assertOutput('', raw_output)
# Delete audit
raw_output = cls.watcher('audit delete %s' % cls.audit_uuid)
cls.assertOutput('', raw_output)
# Delete Template
raw_output = cls.watcher(
'audittemplate delete %s' % cls.audit_template_name)
cls.assertOutput('', raw_output)
def test_action_plan_list(self):
raw_output = self.watcher('actionplan list')
self.assert_table_structure([raw_output], self.list_fields)
def test_action_plan_detailed_list(self):
raw_output = self.watcher('actionplan list --detail')
self.assert_table_structure([raw_output], self.detailed_list_fields)
def test_action_plan_show(self):
action_plan_list = self.parse_show(self.watcher('actionplan list'))
action_plan_uuid = list(action_plan_list[0])[0]
actionplan = self.watcher('actionplan show %s' % action_plan_uuid)
self.assertIn(action_plan_uuid, actionplan)
self.assert_table_structure([actionplan],
self.detailed_list_fields)
def test_action_plan_start(self):
output = self.parse_show(self.watcher('actionplan list --audit %s'
% self.audit_uuid))
action_plan_uuid = list(output[0])[0]
self.watcher('actionplan start %s' % action_plan_uuid)
raw_output = self.watcher('actionplan show %s' % action_plan_uuid)
self.assert_table_structure([raw_output], self.detailed_list_fields)
self.assertTrue(test_utils.call_until_true(
func=functools.partial(
self.has_actionplan_succeeded, action_plan_uuid),
duration=600,
sleep_for=2
))
python-watcherclient-2.2.0/watcherclient/tests/functional/v1/test_strategy.py 0000666 0001750 0001750 00000003616 13364113436 027665 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2016 Servionica
#
# 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 watcherclient.tests.functional.v1 import base
class StrategyTests(base.TestCase):
"""Functional tests for strategy."""
dummy_name = 'dummy'
basic_strategy = 'basic'
list_fields = ['UUID', 'Name', 'Display name', 'Goal']
state_fields = ['Datasource', 'Metrics', 'CDM', 'Name']
def test_strategy_list(self):
raw_output = self.watcher('strategy list')
self.assertIn(self.dummy_name, raw_output)
self.assert_table_structure([raw_output], self.list_fields)
def test_strategy_detailed_list(self):
raw_output = self.watcher('strategy list --detail')
self.assertIn(self.dummy_name, raw_output)
self.assert_table_structure([raw_output],
self.list_fields + ['Parameters spec'])
def test_strategy_show(self):
raw_output = self.watcher('strategy show %s' % self.dummy_name)
self.assertIn(self.dummy_name, raw_output)
self.assert_table_structure([raw_output],
self.list_fields + ['Parameters spec'])
self.assertNotIn('basic', raw_output)
def test_strategy_state(self):
raw_output = self.watcher('strategy state %s' % self.basic_strategy)
self.assertIn(self.basic_strategy, raw_output)
self.assert_table_structure([raw_output], self.state_fields)
python-watcherclient-2.2.0/watcherclient/tests/functional/__init__.py 0000666 0001750 0001750 00000000000 13364113436 026155 0 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/watcherclient/config.py 0000666 0001750 0001750 00000001531 13364113436 022371 0 ustar zuul zuul 0000000 0000000 # -*- encoding: utf-8 -*-
# Copyright (c) 2018 Servionica
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from oslo_config import cfg
service_option = cfg.BoolOpt("watcher_client",
default=True,
help="Whether or not watcher_client is expected"
"to be available")
python-watcherclient-2.2.0/watcherclient/version.py 0000666 0001750 0001750 00000001317 13364113436 022613 0 ustar zuul zuul 0000000 0000000 # Copyright 2014
# The Cloudscaling Group, 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 pbr import version
version_info = version.VersionInfo('python-watcherclient')
__version__ = version_info.version_string()
python-watcherclient-2.2.0/watcherclient/v1/ 0000775 0001750 0001750 00000000000 13364113665 021102 5 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/watcherclient/v1/resource_fields.py 0000777 0001750 0001750 00000012260 13364113436 024633 0 ustar zuul zuul 0000000 0000000 #
# Copyright 2015 b<>com
# 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.
# Audit Template
AUDIT_TEMPLATE_FIELDS = [
'uuid', 'created_at', 'updated_at', 'deleted_at',
'description', 'name', 'goal_name', 'strategy_name', 'scope']
AUDIT_TEMPLATE_FIELD_LABELS = [
'UUID', 'Created At', 'Updated At', 'Deleted At',
'Description', 'Name', 'Goal', 'Strategy', 'Audit Scope']
AUDIT_TEMPLATE_SHORT_LIST_FIELDS = [
'uuid', 'name', 'goal_name', 'strategy_name']
AUDIT_TEMPLATE_SHORT_LIST_FIELD_LABELS = ['UUID', 'Name', 'Goal', 'Strategy']
# Audit
AUDIT_FIELDS = ['uuid', 'name', 'created_at', 'updated_at', 'deleted_at',
'state', 'audit_type', 'parameters', 'interval', 'goal_name',
'strategy_name', 'scope', 'auto_trigger', 'next_run_time',
'hostname']
AUDIT_FIELD_LABELS = ['UUID', 'Name', 'Created At', 'Updated At', 'Deleted At',
'State', 'Audit Type', 'Parameters', 'Interval', 'Goal',
'Strategy', 'Audit Scope', 'Auto Trigger',
'Next Run Time', 'Hostname']
AUDIT_SHORT_LIST_FIELDS = ['uuid', 'name', 'audit_type',
'state', 'goal_name', 'strategy_name',
'auto_trigger']
AUDIT_SHORT_LIST_FIELD_LABELS = ['UUID', 'Name', 'Audit Type', 'State', 'Goal',
'Strategy', 'Auto Trigger']
# Action Plan
ACTION_PLAN_FIELDS = ['uuid', 'created_at', 'updated_at', 'deleted_at',
'audit_uuid', 'strategy_name', 'state',
'efficacy_indicators', 'global_efficacy', 'hostname']
ACTION_PLAN_FIELD_LABELS = ['UUID', 'Created At', 'Updated At', 'Deleted At',
'Audit', 'Strategy', 'State',
'Efficacy indicators', 'Global efficacy',
'Hostname']
ACTION_PLAN_SHORT_LIST_FIELDS = ['uuid', 'audit_uuid', 'state',
'updated_at', 'global_efficacy']
ACTION_PLAN_SHORT_LIST_FIELD_LABELS = ['UUID', 'Audit', 'State',
'Updated At', 'Global efficacy']
GLOBAL_EFFICACY_FIELDS = ['value', 'unit', 'name', 'description']
# Action
ACTION_FIELDS = ['uuid', 'created_at', 'updated_at', 'deleted_at', 'parents',
'state', 'action_plan_uuid', 'action_type',
'input_parameters', 'description']
ACTION_FIELD_LABELS = ['UUID', 'Created At', 'Updated At', 'Deleted At',
'Parents', 'State', 'Action Plan', 'Action',
'Parameters', 'Description']
ACTION_SHORT_LIST_FIELDS = ['uuid', 'parents',
'state', 'action_plan_uuid', 'action_type']
ACTION_SHORT_LIST_FIELD_LABELS = ['UUID', 'Parents', 'State',
'Action Plan', 'Action']
# Goals
GOAL_FIELDS = ['uuid', 'name', 'display_name', 'efficacy_specification']
GOAL_FIELD_LABELS = ['UUID', 'Name', 'Display name', 'Efficacy specification']
GOAL_SHORT_LIST_FIELDS = ['uuid', 'name', 'display_name']
GOAL_SHORT_LIST_FIELD_LABELS = ['UUID', 'Name', 'Display name']
# Strategies
STRATEGY_FIELDS = ['uuid', 'name', 'display_name', 'goal_name',
'parameters_spec']
STRATEGY_FIELD_LABELS = ['UUID', 'Name', 'Display name', 'Goal',
'Parameters spec']
STRATEGY_SHORT_LIST_FIELDS = ['uuid', 'name', 'display_name', 'goal_name']
STRATEGY_SHORT_LIST_FIELD_LABELS = ['UUID', 'Name', 'Display name', 'Goal']
STRATEGY_STATE_FIELDS = ['type', 'state', 'mandatory', 'comment']
STRATEGY_STATE_FIELD_LABELS = ['Type', 'State', 'Mandatory', 'Comment']
# Metric Collector
METRIC_COLLECTOR_FIELDS = ['uuid', 'created_at', 'updated_at', 'deleted_at',
'endpoint', 'category']
METRIC_COLLECTOR_FIELD_LABELS = ['UUID', 'Created At', 'Updated At',
'Deleted At', 'Endpoint URL',
'Metric Category']
METRIC_COLLECTOR_SHORT_LIST_FIELDS = ['uuid', 'endpoint', 'category']
METRIC_COLLECTOR_SHORT_LIST_FIELD_LABELS = ['UUID', 'Endpoint URL',
'Metric Category']
# Scoring Engines
SCORING_ENGINE_FIELDS = ['uuid', 'name', 'description', 'metainfo']
SCORING_ENGINE_FIELD_LABELS = ['UUID', 'Name', 'Description', 'Metainfo']
SCORING_ENGINE_SHORT_LIST_FIELDS = ['uuid', 'name', 'description']
SCORING_ENGINE_SHORT_LIST_FIELD_LABELS = ['UUID', 'Name', 'Description']
# Services
SERVICE_FIELDS = ['id', 'name', 'host', 'status', 'last_seen_up']
SERVICE_FIELD_LABELS = ['ID', 'Name', 'Host', 'Status', 'Last seen up']
SERVICE_SHORT_LIST_FIELDS = ['id', 'name', 'host', 'status']
SERVICE_SHORT_LIST_FIELD_LABELS = ['ID', 'Name', 'Host', 'Status']
python-watcherclient-2.2.0/watcherclient/v1/audit.py 0000666 0001750 0001750 00000007050 13364113436 022562 0 ustar zuul zuul 0000000 0000000 #
# Copyright 2013 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from watcherclient.common import base
from watcherclient.common import utils
from watcherclient import exceptions as exc
CREATION_ATTRIBUTES = ['audit_template_uuid', 'audit_type', 'interval',
'parameters', 'goal', 'strategy', 'auto_trigger',
'name']
class Audit(base.Resource):
def __repr__(self):
return "" % self._info
class AuditManager(base.Manager):
resource_class = Audit
@staticmethod
def _path(id=None):
return '/v1/audits/%s' % id if id else '/v1/audits'
def list(self, audit_template=None, limit=None, sort_key=None,
sort_dir=None, detail=False, goal=None, strategy=None,
marker=None):
"""Retrieve a list of audit.
:param audit_template: Name of the audit template
:param limit: The maximum number of results to return per
request, if:
1) limit > 0, the maximum number of audits to return.
2) limit == 0, return the entire list of audits.
3) limit param is NOT specified (None), the number of items
returned respect the maximum imposed by the Watcher API
(see Watcher's api.max_limit option).
:param sort_key: Optional, field used for sorting.
:param sort_dir: Optional, direction of sorting, either 'asc' (the
default) or 'desc'.
:param detail: Optional, boolean whether to return detailed information
about audits.
:param marker: Optional, UUID of the last audit in the previous page.
:returns: A list of audits.
"""
if limit is not None:
limit = int(limit)
filters = utils.common_filters(limit, sort_key, sort_dir, marker)
if audit_template is not None:
filters.append('audit_template=%s' % audit_template)
if goal is not None:
filters.append('goal=%s' % goal)
if strategy is not None:
filters.append('strategy=%s' % strategy)
path = ''
if detail:
path += 'detail'
if filters:
path += '?' + '&'.join(filters)
if limit is None:
return self._list(self._path(path), "audits")
else:
return self._list_pagination(self._path(path), "audits",
limit=limit)
def create(self, **kwargs):
new = {}
for (key, value) in kwargs.items():
if key in CREATION_ATTRIBUTES:
new[key] = value
else:
raise exc.InvalidAttribute()
return self._create(self._path(), new)
def get(self, audit):
try:
return self._list(self._path(audit))[0]
except IndexError:
return None
def delete(self, audit):
return self._delete(self._path(audit))
def update(self, audit, patch):
return self._update(self._path(audit), patch)
python-watcherclient-2.2.0/watcherclient/v1/action_plan.py 0000666 0001750 0001750 00000007237 13364113436 023752 0 ustar zuul zuul 0000000 0000000 #
# Copyright 2013 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from watcherclient.common import base
from watcherclient.common import utils
# from watcherclient import exceptions as exc
class ActionPlan(base.Resource):
def __repr__(self):
return "" % self._info
class ActionPlanManager(base.Manager):
resource_class = ActionPlan
@staticmethod
def _path(id=None, q_param=None):
if id and q_param:
return '/v1/action_plans/%s/%s' % (id, q_param)
elif id:
return '/v1/action_plans/%s' % id
else:
return '/v1/action_plans'
def list(self, audit=None, limit=None, sort_key=None,
sort_dir=None, detail=False, marker=None):
"""Retrieve a list of action plan.
:param audit: Name of the audit
:param limit: The maximum number of results to return per
request, if:
1) limit > 0, the maximum number of action plans to return.
2) limit == 0, return the entire list of action plans.
3) limit param is NOT specified (None), the number of items
returned respect the maximum imposed by the Watcher API
(see Watcher's api.max_limit option).
:param sort_key: Optional, field used for sorting.
:param sort_dir: Optional, direction of sorting, either 'asc' (the
default) or 'desc'.
:param detail: Optional, boolean whether to return detailed information
about action plans.
:param marker: The last actionplan UUID of the previous page;
displays list of actionplans after "marker".
:returns: A list of action plans.
"""
if limit is not None:
limit = int(limit)
filters = utils.common_filters(limit, sort_key, sort_dir, marker)
if audit is not None:
filters.append('audit_uuid=%s' % audit)
path = ''
if detail:
path += 'detail'
if filters:
path += '?' + '&'.join(filters)
if limit is None:
return self._list(self._path(path), "action_plans")
else:
return self._list_pagination(self._path(path), "action_plans",
limit=limit)
def get(self, action_plan_id):
try:
return self._list(self._path(action_plan_id))[0]
except IndexError:
return None
def delete(self, action_plan_id):
return self._delete(self._path(action_plan_id))
def update(self, action_plan_id, patch):
return self._update(self._path(action_plan_id), patch)
def start(self, action_plan_id):
return self._start(self._path(action_plan_id, 'start'))
def cancel(self, action_plan_id):
action_plan = self.get(action_plan_id)
if action_plan.state == "ONGOING":
patch = [{'op': 'replace', 'value': 'CANCELLING',
'path': '/state'}]
else:
patch = [{'op': 'replace', 'value': 'CANCELLED', 'path': '/state'}]
return self._update(self._path(action_plan_id), patch)
python-watcherclient-2.2.0/watcherclient/v1/goal_shell.py 0000666 0001750 0001750 00000012020 13364113436 023556 0 ustar zuul zuul 0000000 0000000 #
# Copyright 2013 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from osc_lib import utils
import six
from watcherclient._i18n import _
from watcherclient.common import command
from watcherclient.common import utils as common_utils
from watcherclient import exceptions
from watcherclient.v1 import resource_fields as res_fields
class ShowGoal(command.ShowOne):
"""Show detailed information about a given goal."""
def get_parser(self, prog_name):
parser = super(ShowGoal, self).get_parser(prog_name)
parser.add_argument(
'goal',
metavar='',
help=_('UUID or name of the goal'),
)
return parser
def _format_indicator_spec_table(self, spec, parsed_args):
out = six.StringIO()
self.formatter.emit_one(
column_names=list(field.capitalize() for field in spec.keys()),
data=utils.get_dict_properties(spec, spec.keys()),
stdout=out,
parsed_args=parsed_args,
)
return out.getvalue() or ''
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
try:
goal = client.goal.get(parsed_args.goal)
except exceptions.HTTPNotFound as exc:
raise exceptions.CommandError(str(exc))
columns = res_fields.GOAL_FIELDS
column_headers = res_fields.GOAL_FIELD_LABELS
if parsed_args.formatter == 'table':
indicator_specs = ''
# Format complex data types:
for indicator_spec in goal.efficacy_specification:
indicator_specs += self._format_indicator_spec_table(
indicator_spec, parsed_args)
# Update the raw efficacy specs with the formatted one
goal.efficacy_specification = indicator_specs
return column_headers, utils.get_item_properties(goal, columns)
class ListGoal(command.Lister):
"""List information on retrieved goals."""
def get_parser(self, prog_name):
parser = super(ListGoal, self).get_parser(prog_name)
parser.add_argument(
'--detail',
dest='detail',
action='store_true',
default=False,
help=_("Show detailed information about each goal."))
parser.add_argument(
'--limit',
metavar='',
type=int,
help=_('Maximum number of goals to return per request, '
'0 for no limit. Default is the maximum number used '
'by the Watcher API Service.'))
parser.add_argument(
'--sort-key',
metavar='',
help=_('Goal field that will be used for sorting.'))
parser.add_argument(
'--sort-dir',
metavar='',
choices=['asc', 'desc'],
help=_('Sort direction: "asc" (the default) or "desc".'))
return parser
def _format_indicator_spec_table(self, goal, parsed_args):
out = six.StringIO()
efficacy_specification = goal.efficacy_specification
fields = ['name', 'unit']
self.formatter.emit_list(
column_names=list(field.capitalize()
for field in fields),
data=[utils.get_dict_properties(spec, fields)
for spec in efficacy_specification],
stdout=out,
parsed_args=parsed_args,
)
return out.getvalue() or ''
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
if parsed_args.detail:
fields = res_fields.GOAL_FIELDS
field_labels = res_fields.GOAL_FIELD_LABELS
else:
fields = res_fields.GOAL_SHORT_LIST_FIELDS
field_labels = res_fields.GOAL_SHORT_LIST_FIELD_LABELS
params = {}
params.update(
common_utils.common_params_for_list(
parsed_args, fields, field_labels))
try:
data = client.goal.list(**params)
except exceptions.HTTPNotFound as ex:
raise exceptions.CommandError(str(ex))
if parsed_args.formatter == 'table':
for goal in data:
# Update the raw efficacy specs with the formatted one
goal.efficacy_specification = (
self._format_indicator_spec_table(goal, parsed_args))
return (field_labels,
(utils.get_item_properties(item, fields) for item in data))
python-watcherclient-2.2.0/watcherclient/v1/action.py 0000666 0001750 0001750 00000005522 13364113436 022733 0 ustar zuul zuul 0000000 0000000 #
# Copyright 2013 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from watcherclient.common import base
from watcherclient.common import utils
class Action(base.Resource):
def __repr__(self):
return "" % self._info
class ActionManager(base.Manager):
resource_class = Action
@staticmethod
def _path(id=None):
return '/v1/actions/%s' % id if id else '/v1/actions'
def list(self, action_plan=None, audit=None, limit=None, sort_key=None,
sort_dir=None, detail=False, marker=None):
"""Retrieve a list of action.
:param action_plan: UUID of the action plan
:param audit: UUID of the audit
:param limit: The maximum number of results to return per
request, if:
1) limit > 0, the maximum number of actions to return.
2) limit == 0, return the entire list of actions.
3) limit param is NOT specified (None), the number of items
returned respect the maximum imposed by the Watcher API
(see Watcher's api.max_limit option).
:param sort_key: Optional, field used for sorting.
:param sort_dir: Optional, direction of sorting, either 'asc' (the
default) or 'desc'.
:param detail: Optional, boolean whether to return detailed information
about actions.
:param marker: Optional, UUID of the last action in the previous page.
:returns: A list of actions.
"""
if limit is not None:
limit = int(limit)
filters = utils.common_filters(limit, sort_key, sort_dir, marker)
if action_plan is not None:
filters.append('action_plan_uuid=%s' % action_plan)
if audit is not None:
filters.append('audit_uuid=%s' % audit)
path = ''
if detail:
path += 'detail'
if filters:
path += '?' + '&'.join(filters)
if limit is None:
return self._list(self._path(path), "actions")
else:
return self._list_pagination(self._path(path), "actions",
limit=limit)
def get(self, action_id):
try:
return self._list(self._path(action_id))[0]
except IndexError:
return None
python-watcherclient-2.2.0/watcherclient/v1/strategy_shell.py 0000666 0001750 0001750 00000012221 13364113436 024501 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2016 b<>com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from osc_lib import utils
from oslo_serialization import jsonutils
from watcherclient._i18n import _
from watcherclient.common import command
from watcherclient.common import utils as common_utils
from watcherclient import exceptions
from watcherclient.v1 import resource_fields as res_fields
class ShowStrategy(command.ShowOne):
"""Show detailed information about a given strategy."""
def get_parser(self, prog_name):
parser = super(ShowStrategy, self).get_parser(prog_name)
parser.add_argument(
'strategy',
metavar='',
help=_('UUID or name of the strategy'),
)
return parser
def _format_spec(self, strategy):
parameters_spec = strategy.parameters_spec.get('properties')
if parameters_spec:
return jsonutils.dumps(parameters_spec, indent=2)
return {}
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
try:
strategy = client.strategy.get(parsed_args.strategy)
except exceptions.HTTPNotFound as exc:
raise exceptions.CommandError(str(exc))
strategy.parameters_spec = self._format_spec(strategy)
columns = res_fields.STRATEGY_FIELDS
column_headers = res_fields.STRATEGY_FIELD_LABELS
return column_headers, utils.get_item_properties(strategy, columns)
class StateStrategy(command.Lister):
"""Retrieve information about strategy requirements."""
def get_parser(self, prog_name):
parser = super(StateStrategy, self).get_parser(prog_name)
parser.add_argument(
'strategy',
metavar='',
help=_('Name of the strategy'),
)
return parser
def _format_spec(self, requirements):
for req in requirements:
if type(req.state) == list:
req.state = jsonutils.dumps(req.state, indent=2)
return requirements
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
try:
requirements = client.strategy.state(parsed_args.strategy)
except exceptions.HTTPNotFound as exc:
raise exceptions.CommandError(str(exc))
requirements = self._format_spec(requirements)
columns = res_fields.STRATEGY_STATE_FIELDS
column_headers = res_fields.STRATEGY_STATE_FIELD_LABELS
return (column_headers,
(utils.get_item_properties(item, columns)
for item in requirements))
class ListStrategy(command.Lister):
"""List information on retrieved strategies."""
def get_parser(self, prog_name):
parser = super(ListStrategy, self).get_parser(prog_name)
parser.add_argument(
'--goal',
metavar='',
dest='goal',
help=_('UUID or name of the goal'))
parser.add_argument(
'--detail',
dest='detail',
action='store_true',
default=False,
help=_("Show detailed information about each strategy."))
parser.add_argument(
'--limit',
metavar='',
type=int,
help=_('Maximum number of strategies to return per request, '
'0 for no limit. Default is the maximum number used '
'by the Watcher API Service.'))
parser.add_argument(
'--sort-key',
metavar='',
help=_('Goal field that will be used for sorting.'))
parser.add_argument(
'--sort-dir',
metavar='',
choices=['asc', 'desc'],
help='Sort direction: "asc" (the default) or "desc".')
return parser
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
params = {}
if parsed_args.detail:
fields = res_fields.STRATEGY_FIELDS
field_labels = res_fields.STRATEGY_FIELD_LABELS
else:
fields = res_fields.STRATEGY_SHORT_LIST_FIELDS
field_labels = res_fields.STRATEGY_SHORT_LIST_FIELD_LABELS
if parsed_args.goal:
params["goal"] = parsed_args.goal
params.update(
common_utils.common_params_for_list(
parsed_args, fields, field_labels))
try:
data = client.strategy.list(**params)
except exceptions.HTTPNotFound as ex:
raise exceptions.CommandError(str(ex))
return (field_labels,
(utils.get_item_properties(item, fields) for item in data))
python-watcherclient-2.2.0/watcherclient/v1/strategy.py 0000666 0001750 0001750 00000005620 13364113436 023317 0 ustar zuul zuul 0000000 0000000 #
# Copyright 2013 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import six.moves.urllib.parse as parse
from watcherclient.common import base
from watcherclient.common import utils
class Strategy(base.Resource):
def __repr__(self):
return "" % self._info
class StrategyManager(base.Manager):
resource_class = Strategy
@staticmethod
def _path(strategy=None, state=False):
if strategy:
path = '/v1/strategies/%s' % strategy
if state:
path = '/v1/strategies/%s/state' % strategy
else:
path = '/v1/strategies'
return path
def list(self, goal=None, limit=None, sort_key=None,
sort_dir=None, detail=False):
"""Retrieve a list of strategy.
:param goal: The UUID of the goal to filter by
:param limit: The maximum number of results to return per
request, if:
1) limit > 0, the maximum number of audits to return.
2) limit == 0, return the entire list of audits.
3) limit param is NOT specified (None), the number of items
returned respect the maximum imposed by the Watcher API
(see Watcher's api.max_limit option).
:param sort_key: Optional, field used for sorting.
:param sort_dir: Optional, direction of sorting, either 'asc' (the
default) or 'desc'.
:param detail: Optional, boolean whether to return detailed information
about audits.
:returns: A list of audits.
"""
if limit is not None:
limit = int(limit)
filters = utils.common_filters(limit, sort_key, sort_dir)
if goal:
filters.append(parse.urlencode(dict(goal=goal)))
path = ''
if detail:
path += 'detail'
if filters:
path += '?' + '&'.join(filters)
if limit is None:
return self._list(self._path(path), "strategies")
else:
return self._list_pagination(self._path(path), "strategies",
limit=limit)
def get(self, strategy):
try:
return self._list(self._path(strategy))[0]
except IndexError:
return None
def state(self, strategy):
return self._list(self._path(strategy, state=True))
python-watcherclient-2.2.0/watcherclient/v1/action_plan_shell.py 0000666 0001750 0001750 00000026544 13364113436 025143 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2016 b<>com
#
# 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 cliff.formatters import yaml_format
from osc_lib import utils
from oslo_utils import uuidutils
import six
from watcherclient._i18n import _
from watcherclient.common import command
from watcherclient.common import utils as common_utils
from watcherclient import exceptions
from watcherclient.v1 import resource_fields as res_fields
def format_global_efficacy(global_efficacy):
formatted_global_eff = {}
for eff in global_efficacy:
eff_name = eff.get('name')
if (eff.get('value') is not None and eff.get('unit')):
formatted_global_eff[eff_name] = "%(value).2f %(unit)s" % dict(
unit=eff.get('unit'),
value=eff.get('value'))
elif eff.get('value') is not None:
formatted_global_eff[eff_name] = eff.get('value')
return formatted_global_eff
class ShowActionPlan(command.ShowOne):
"""Show detailed information about a given action plan."""
def get_parser(self, prog_name):
parser = super(ShowActionPlan, self).get_parser(prog_name)
parser.add_argument(
'action_plan',
metavar='',
help=_('UUID of the action plan'),
)
return parser
def _format_indicators(self, action_plan, parsed_args):
out = six.StringIO()
efficacy_indicators = action_plan.efficacy_indicators
fields = ['name', 'description', 'value', 'unit']
yaml_format.YAMLFormatter().emit_list(
column_names=list(field.capitalize()
for field in fields),
data=[utils.get_dict_properties(spec, fields)
for spec in efficacy_indicators],
stdout=out,
parsed_args=parsed_args,
)
return out.getvalue() or ''
def _format_global_efficacy(self, global_efficacy, parsed_args):
formatted_global_efficacy = format_global_efficacy(global_efficacy)
out = six.StringIO()
yaml_format.YAMLFormatter().emit_one(
column_names=list(resource.capitalize()
for resource in formatted_global_efficacy),
data=[value for value in formatted_global_efficacy.values()],
stdout=out,
parsed_args=parsed_args,
)
return out.getvalue() or ''
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
action_plan_uuid = parsed_args.action_plan
if not uuidutils.is_uuid_like(action_plan_uuid):
raise exceptions.ValidationError()
try:
action_plan = client.action_plan.get(action_plan_uuid)
except exceptions.HTTPNotFound as exc:
raise exceptions.CommandError(str(exc))
if parsed_args.formatter == 'table':
# Update the raw efficacy indicators with the formatted ones
action_plan.efficacy_indicators = (
self._format_indicators(action_plan, parsed_args))
# Update the raw global efficacy with the formatted one
action_plan.global_efficacy = self._format_global_efficacy(
action_plan.global_efficacy, parsed_args)
columns = res_fields.ACTION_PLAN_FIELDS
column_headers = res_fields.ACTION_PLAN_FIELD_LABELS
return column_headers, utils.get_item_properties(action_plan, columns)
class ListActionPlan(command.Lister):
"""List information on retrieved action plans."""
def get_parser(self, prog_name):
parser = super(ListActionPlan, self).get_parser(prog_name)
parser.add_argument(
'--audit',
metavar='',
help=_('UUID of an audit used for filtering.'))
parser.add_argument(
'--detail',
dest='detail',
action='store_true',
default=False,
help=_("Show detailed information about action plans."))
parser.add_argument(
'--limit',
metavar='',
type=int,
help=_('Maximum number of action plans to return per request, '
'0 for no limit. Default is the maximum number used '
'by the Watcher API Service.'))
parser.add_argument(
'--marker',
metavar='',
help=_('The last actionplan UUID of the previous page; '
'displays list of actionplans after "marker".'))
parser.add_argument(
'--sort-key',
metavar='',
help=_('Action Plan field that will be used for sorting.'))
parser.add_argument(
'--sort-dir',
metavar='',
choices=['asc', 'desc'],
help=_('Sort direction: "asc" (the default) or "desc".'))
return parser
def _format_indicators(self, action_plan, parsed_args):
out = six.StringIO()
efficacy_indicators = action_plan.efficacy_indicators
fields = ['name', 'value', 'unit']
yaml_format.YAMLFormatter().emit_list(
column_names=list(field.capitalize()
for field in fields),
data=[utils.get_dict_properties(spec, fields)
for spec in efficacy_indicators],
stdout=out,
parsed_args=parsed_args,
)
return out.getvalue() or ''
def _format_global_efficacy(self, global_efficacy, parsed_args):
formatted_global_efficacy = format_global_efficacy(global_efficacy)
out = six.StringIO()
yaml_format.YAMLFormatter().emit_one(
column_names=list(resource.capitalize()
for resource in formatted_global_efficacy),
data=[value for value in formatted_global_efficacy.values()],
stdout=out,
parsed_args=parsed_args,
)
return out.getvalue() or ''
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
params = {}
if parsed_args.audit is not None:
params['audit'] = parsed_args.audit
if parsed_args.detail:
fields = res_fields.ACTION_PLAN_FIELDS
field_labels = res_fields.ACTION_PLAN_FIELD_LABELS
else:
fields = res_fields.ACTION_PLAN_SHORT_LIST_FIELDS
field_labels = res_fields.ACTION_PLAN_SHORT_LIST_FIELD_LABELS
params.update(common_utils.common_params_for_list(
parsed_args, fields, field_labels))
data = client.action_plan.list(**params)
if parsed_args.formatter == 'table':
for action_plan in data:
# Update the raw efficacy indicators with the formatted ones
action_plan.efficacy_indicators = (
self._format_indicators(action_plan, parsed_args))
# Update the raw global efficacy with the formatted one
action_plan.global_efficacy = self._format_global_efficacy(
action_plan.global_efficacy, parsed_args)
return (field_labels,
(utils.get_item_properties(item, fields) for item in data))
class UpdateActionPlan(command.ShowOne):
"""Update action plan command."""
def get_parser(self, prog_name):
parser = super(UpdateActionPlan, self).get_parser(prog_name)
parser.add_argument(
'action_plan',
metavar='',
help=_("UUID of the action_plan."))
parser.add_argument(
'op',
metavar='',
choices=['add', 'replace', 'remove'],
help=_("Operation: 'add', 'replace', or 'remove'."))
parser.add_argument(
'attributes',
metavar='',
nargs='+',
action='append',
default=[],
help=_("Attribute to add, replace, or remove. Can be specified "
"multiple times. For 'remove', only is necessary."))
return parser
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
if not uuidutils.is_uuid_like(parsed_args.action_plan):
raise exceptions.ValidationError()
patch = common_utils.args_array_to_patch(
parsed_args.op, parsed_args.attributes[0])
action_plan = client.action_plan.update(parsed_args.action_plan, patch)
columns = res_fields.ACTION_PLAN_FIELDS
column_headers = res_fields.ACTION_PLAN_FIELD_LABELS
return column_headers, utils.get_item_properties(action_plan, columns)
class StartActionPlan(command.ShowOne):
"""Start action plan command."""
def get_parser(self, prog_name):
parser = super(StartActionPlan, self).get_parser(prog_name)
parser.add_argument(
'action_plan',
metavar='',
help=_("UUID of the action_plan."))
return parser
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
if not uuidutils.is_uuid_like(parsed_args.action_plan):
raise exceptions.ValidationError()
action_plan = client.action_plan.start(parsed_args.action_plan)
columns = res_fields.ACTION_PLAN_FIELDS
column_headers = res_fields.ACTION_PLAN_FIELD_LABELS
return column_headers, utils.get_item_properties(action_plan, columns)
class DeleteActionPlan(command.Command):
"""Delete action plan command."""
def get_parser(self, prog_name):
parser = super(DeleteActionPlan, self).get_parser(prog_name)
parser.add_argument(
'action_plans',
metavar='',
nargs='+',
help=_('UUID of the action plan'),
)
return parser
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
for action_plan in parsed_args.action_plans:
if not uuidutils.is_uuid_like(action_plan):
raise exceptions.ValidationError()
client.action_plan.delete(action_plan)
class CancelActionPlan(command.ShowOne):
"""Cancel action plan command."""
def get_parser(self, prog_name):
parser = super(CancelActionPlan, self).get_parser(prog_name)
parser.add_argument(
'action_plan',
metavar='',
help=_("UUID of the action_plan."))
return parser
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
if not uuidutils.is_uuid_like(parsed_args.action_plan):
raise exceptions.ValidationError()
action_plan = client.action_plan.cancel(parsed_args.action_plan)
columns = res_fields.ACTION_PLAN_FIELDS
column_headers = res_fields.ACTION_PLAN_FIELD_LABELS
return column_headers, utils.get_item_properties(action_plan, columns)
python-watcherclient-2.2.0/watcherclient/v1/__init__.py 0000666 0001750 0001750 00000003336 13364113436 023216 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2016 b<>com
#
# 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 watcherclient.v1 import action
from watcherclient.v1 import action_plan
from watcherclient.v1 import audit
from watcherclient.v1 import audit_template
from watcherclient.v1 import goal
from watcherclient.v1 import scoring_engine
from watcherclient.v1 import service
from watcherclient.v1 import strategy
Action = action.Action
ActionManager = action.ActionManager
ActionPlan = action_plan.ActionPlan
ActionPlanManager = action_plan.ActionPlanManager
Audit = audit.Audit
AuditManager = audit.AuditManager
AuditTemplate = audit_template.AuditTemplate
AuditTemplateManager = audit_template.AuditTemplateManager
Goal = goal.Goal
GoalManager = goal.GoalManager
ScoringEngine = scoring_engine.ScoringEngine
ScoringEngineManager = scoring_engine.ScoringEngineManager
Service = service.Service
ServiceManager = service.ServiceManager
Strategy = strategy.Strategy
StrategyManager = strategy.StrategyManager
__all__ = (
"Action", "ActionManager", "ActionPlan", "ActionPlanManager",
"Audit", "AuditManager", "AuditTemplate", "AuditTemplateManager",
"Goal", "GoalManager", "ScoringEngine", "ScoringEngineManager",
"Service", "ServiceManager", "Strategy", "StrategyManager")
python-watcherclient-2.2.0/watcherclient/v1/audit_shell.py 0000666 0001750 0001750 00000022475 13364113436 023761 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2016 b<>com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from osc_lib import utils
from oslo_utils import uuidutils
from watcherclient._i18n import _
from watcherclient.common import command
from watcherclient.common import utils as common_utils
from watcherclient import exceptions
from watcherclient.v1 import resource_fields as res_fields
class ShowAudit(command.ShowOne):
"""Show detailed information about a given audit."""
def get_parser(self, prog_name):
parser = super(ShowAudit, self).get_parser(prog_name)
parser.add_argument(
'audit',
metavar='',
help=_('UUID or name of the audit'),
)
return parser
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
try:
audit = client.audit.get(parsed_args.audit)
if audit.strategy_name is None:
audit.strategy_name = 'auto'
except exceptions.HTTPNotFound as exc:
raise exceptions.CommandError(str(exc))
columns = res_fields.AUDIT_FIELDS
column_headers = res_fields.AUDIT_FIELD_LABELS
return column_headers, utils.get_item_properties(audit, columns)
class ListAudit(command.Lister):
"""List information on retrieved audits."""
def get_parser(self, prog_name):
parser = super(ListAudit, self).get_parser(prog_name)
parser.add_argument(
'--detail',
dest='detail',
action='store_true',
default=False,
help=_("Show detailed information about audits."))
parser.add_argument(
'--goal',
dest='goal',
metavar='',
help=_('UUID or name of the goal used for filtering.'))
parser.add_argument(
'--strategy',
dest='strategy',
metavar='',
help=_('UUID or name of the strategy used for filtering.'))
parser.add_argument(
'--limit',
metavar='',
type=int,
help=_('Maximum number of audits to return per request, '
'0 for no limit. Default is the maximum number used '
'by the Watcher API Service.'))
parser.add_argument(
'--sort-key',
metavar='',
help=_('Audit field that will be used for sorting.'))
parser.add_argument(
'--sort-dir',
metavar='',
choices=['asc', 'desc'],
help=_('Sort direction: "asc" (the default) or "desc".'))
parser.add_argument(
'--marker',
dest='marker',
metavar='',
default=None,
help=_('UUID of the last audit in the previous page; '
'displays list of audits after "marker".'))
return parser
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
params = {}
# Optional
if parsed_args.goal:
params['goal'] = parsed_args.goal
# Optional
if parsed_args.strategy:
params['strategy'] = parsed_args.strategy
if parsed_args.detail:
fields = res_fields.AUDIT_FIELDS
field_labels = res_fields.AUDIT_FIELD_LABELS
else:
fields = res_fields.AUDIT_SHORT_LIST_FIELDS
field_labels = res_fields.AUDIT_SHORT_LIST_FIELD_LABELS
params.update(common_utils.common_params_for_list(
parsed_args, fields, field_labels))
try:
data = client.audit.list(**params)
for audit in data:
if audit.strategy_name is None:
audit.strategy_name = 'auto'
except exceptions.HTTPNotFound as ex:
raise exceptions.CommandError(str(ex))
return (field_labels,
(utils.get_item_properties(item, fields) for item in data))
class CreateAudit(command.ShowOne):
"""Create new audit."""
def get_parser(self, prog_name):
parser = super(CreateAudit, self).get_parser(prog_name)
parser.add_argument(
'-t', '--audit_type',
dest='audit_type',
metavar='',
default='ONESHOT',
choices=['ONESHOT', 'CONTINUOUS'],
help=_("Audit type. It must be ONESHOT or CONTINUOUS. "
"Default is ONESHOT."))
parser.add_argument(
'-p', '--parameter',
dest='parameters',
metavar='',
action='append',
help=_("Record strategy parameter/value metadata. "
"Can be specified multiple times."))
parser.add_argument(
'-i', '--interval',
dest='interval',
metavar='',
help=_('Audit interval (in seconds or cron format). '
'Cron inteval can be used like: "*/5 * * * *". '
'Only used if the audit is CONTINUOUS.'))
parser.add_argument(
'-g', '--goal',
dest='goal',
metavar='',
help=_('Goal UUID or name associated to this audit.'))
parser.add_argument(
'-s', '--strategy',
dest='strategy',
metavar='',
help=_('Strategy UUID or name associated to this audit.'))
parser.add_argument(
'-a', '--audit-template',
dest='audit_template_uuid',
metavar='',
help=_('Audit template used for this audit (name or uuid).'))
parser.add_argument(
'--auto-trigger',
dest='auto_trigger',
action='store_true',
default=False,
help=_('Trigger automatically action plan '
'once audit is succeeded.'))
parser.add_argument(
'--name',
dest='name',
metavar='',
help=_('Name for this audit.'))
return parser
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
field_list = ['audit_template_uuid', 'audit_type', 'parameters',
'interval', 'goal', 'strategy', 'auto_trigger', 'name']
fields = dict((k, v) for (k, v) in vars(parsed_args).items()
if k in field_list and v is not None)
fields = common_utils.args_array_to_dict(fields, 'parameters')
if fields.get('audit_template_uuid'):
if not uuidutils.is_uuid_like(fields['audit_template_uuid']):
fields['audit_template_uuid'] = client.audit_template.get(
fields['audit_template_uuid']).uuid
audit = client.audit.create(**fields)
if audit.strategy_name is None:
audit.strategy_name = 'auto'
columns = res_fields.AUDIT_FIELDS
column_headers = res_fields.AUDIT_FIELD_LABELS
return column_headers, utils.get_item_properties(audit, columns)
class UpdateAudit(command.ShowOne):
"""Update audit command."""
def get_parser(self, prog_name):
parser = super(UpdateAudit, self).get_parser(prog_name)
parser.add_argument(
'audit',
metavar='',
help=_("UUID or name of the audit."))
parser.add_argument(
'op',
metavar='',
choices=['add', 'replace', 'remove'],
help=_("Operation: 'add', 'replace', or 'remove'."))
parser.add_argument(
'attributes',
metavar='',
nargs='+',
action='append',
default=[],
help=_("Attribute to add, replace, or remove. Can be specified "
"multiple times. For 'remove', only is necessary."))
return parser
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
patch = common_utils.args_array_to_patch(
parsed_args.op, parsed_args.attributes[0],
exclude_fields=['/interval'])
audit = client.audit.update(parsed_args.audit, patch)
columns = res_fields.AUDIT_FIELDS
column_headers = res_fields.AUDIT_FIELD_LABELS
return column_headers, utils.get_item_properties(audit, columns)
class DeleteAudit(command.Command):
"""Delete audit command."""
def get_parser(self, prog_name):
parser = super(DeleteAudit, self).get_parser(prog_name)
parser.add_argument(
'audits',
metavar='',
nargs='+',
help=_('UUID or name of the audit'),
)
return parser
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
for audit in parsed_args.audits:
client.audit.delete(audit)
python-watcherclient-2.2.0/watcherclient/v1/action_shell.py 0000666 0001750 0001750 00000010247 13364113436 024122 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2016 b<>com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from osc_lib import utils
from watcherclient._i18n import _
from watcherclient.common import command
from watcherclient.common import utils as common_utils
from watcherclient import exceptions
from watcherclient.v1 import resource_fields as res_fields
class ShowAction(command.ShowOne):
"""Show detailed information about a given action."""
def get_parser(self, prog_name):
parser = super(ShowAction, self).get_parser(prog_name)
parser.add_argument(
'action',
metavar='',
help=_('UUID of the action'),
)
return parser
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
try:
action = client.action.get(parsed_args.action)
except exceptions.HTTPNotFound as exc:
raise exceptions.CommandError(str(exc))
columns = res_fields.ACTION_FIELDS
column_headers = res_fields.ACTION_FIELD_LABELS
return column_headers, utils.get_item_properties(action, columns)
class ListAction(command.Lister):
"""List information on retrieved actions."""
def get_parser(self, prog_name):
parser = super(ListAction, self).get_parser(prog_name)
parser.add_argument(
'--action-plan',
metavar='',
help=_('UUID of the action plan used for filtering.'))
parser.add_argument(
'--audit',
metavar='',
help=_(' UUID of the audit used for filtering.'))
parser.add_argument(
'--detail',
dest='detail',
action='store_true',
default=False,
help=_("Show detailed information about actions."))
parser.add_argument(
'--limit',
metavar='',
type=int,
help=_('Maximum number of actions to return per request, '
'0 for no limit. Default is the maximum number used '
'by the Watcher API Service.'))
parser.add_argument(
'--sort-key',
metavar='',
help=_('Action field that will be used for sorting.'))
parser.add_argument(
'--sort-dir',
metavar='',
choices=['asc', 'desc'],
help=_('Sort direction: "asc" (the default) or "desc".'))
parser.add_argument(
'--marker',
dest='marker',
metavar='',
default=None,
help=_('UUID of the last action in the previous page; '
'displays list of actions after "marker".'))
return parser
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
params = {}
if parsed_args.action_plan is not None:
params['action_plan'] = parsed_args.action_plan
if parsed_args.audit is not None:
params['audit'] = parsed_args.audit
if parsed_args.detail:
fields = res_fields.ACTION_FIELDS
field_labels = res_fields.ACTION_FIELD_LABELS
else:
fields = res_fields.ACTION_SHORT_LIST_FIELDS
field_labels = res_fields.ACTION_SHORT_LIST_FIELD_LABELS
params.update(
common_utils.common_params_for_list(
parsed_args, fields, field_labels))
try:
data = client.action.list(**params)
except exceptions.HTTPNotFound as ex:
raise exceptions.CommandError(str(ex))
return (field_labels,
(utils.get_item_properties(item, fields) for item in data))
python-watcherclient-2.2.0/watcherclient/v1/scoring_engine_shell.py 0000666 0001750 0001750 00000007215 13364113436 025637 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2016 Intel
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from osc_lib import utils
from watcherclient._i18n import _
from watcherclient.common import command
from watcherclient.common import utils as common_utils
from watcherclient import exceptions
from watcherclient.v1 import resource_fields as res_fields
class ShowScoringEngine(command.ShowOne):
"""Show detailed information about a given scoring engine."""
def get_parser(self, prog_name):
parser = super(ShowScoringEngine, self).get_parser(prog_name)
parser.add_argument(
'scoring_engine',
metavar='',
help=_('Name of the scoring engine'),
)
return parser
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
try:
scoring_engine = client.scoring_engine.get(
parsed_args.scoring_engine)
except exceptions.HTTPNotFound as exc:
raise exceptions.CommandError(str(exc))
columns = res_fields.SCORING_ENGINE_FIELDS
column_headers = res_fields.SCORING_ENGINE_FIELD_LABELS
return column_headers, utils.get_item_properties(scoring_engine,
columns)
class ListScoringEngine(command.Lister):
"""List information on retrieved scoring engines."""
def get_parser(self, prog_name):
parser = super(ListScoringEngine, self).get_parser(prog_name)
parser.add_argument(
'--detail',
dest='detail',
action='store_true',
default=False,
help=_("Show detailed information about scoring engines."))
parser.add_argument(
'--limit',
metavar='',
type=int,
help=_('Maximum number of actions to return per request, '
'0 for no limit. Default is the maximum number used '
'by the Watcher API Service.'))
parser.add_argument(
'--sort-key',
metavar='',
help=_('Action field that will be used for sorting.'))
parser.add_argument(
'--sort-dir',
metavar='',
choices=['asc', 'desc'],
help=_('Sort direction: "asc" (the default) or "desc".'))
return parser
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
params = {}
if parsed_args.detail:
fields = res_fields.SCORING_ENGINE_FIELDS
field_labels = res_fields.SCORING_ENGINE_FIELD_LABELS
else:
fields = res_fields.SCORING_ENGINE_SHORT_LIST_FIELDS
field_labels = res_fields.SCORING_ENGINE_SHORT_LIST_FIELD_LABELS
params.update(
common_utils.common_params_for_list(
parsed_args, fields, field_labels))
try:
data = client.scoring_engine.list(**params)
except exceptions.HTTPNotFound as ex:
raise exceptions.CommandError(str(ex))
return (field_labels,
(utils.get_item_properties(item, fields) for item in data))
python-watcherclient-2.2.0/watcherclient/v1/client.py 0000666 0001750 0001750 00000004660 13364113436 022736 0 ustar zuul zuul 0000000 0000000 # Copyright 2012 OpenStack LLC.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from watcherclient._i18n import _
from watcherclient.common import httpclient
from watcherclient import exceptions
from watcherclient import v1
class Client(object):
"""Client for the Watcher v1 API.
:param string endpoint: A user-supplied endpoint URL for the watcher
service.
:param function token: Provides token for authentication.
:param integer timeout: Allows customization of the timeout for client
http requests. (optional)
"""
def __init__(self, endpoint=None, *args, **kwargs):
"""Initialize a new client for the Watcher v1 API."""
if kwargs.get('os_watcher_api_version'):
kwargs['api_version_select_state'] = "user"
else:
if not endpoint:
raise exceptions.EndpointException(
_("Must provide 'endpoint' if os_watcher_api_version "
"isn't specified"))
# If the user didn't specify a version, use a cached version if
# one has been stored
host, netport = httpclient.get_server(endpoint)
kwargs['api_version_select_state'] = "default"
kwargs['os_watcher_api_version'] = httpclient.DEFAULT_VER
self.http_client = httpclient._construct_http_client(
endpoint, *args, **kwargs)
self.audit = v1.AuditManager(self.http_client)
self.audit_template = v1.AuditTemplateManager(self.http_client)
self.action = v1.ActionManager(self.http_client)
self.action_plan = v1.ActionPlanManager(self.http_client)
self.goal = v1.GoalManager(self.http_client)
self.scoring_engine = v1.ScoringEngineManager(self.http_client)
self.service = v1.ServiceManager(self.http_client)
self.strategy = v1.StrategyManager(self.http_client)
python-watcherclient-2.2.0/watcherclient/v1/scoring_engine.py 0000666 0001750 0001750 00000005127 13364113436 024450 0 ustar zuul zuul 0000000 0000000 #
# Copyright 2016 Intel
#
# 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 watcherclient.common import base
from watcherclient.common import utils
class ScoringEngine(base.Resource):
def __repr__(self):
return "" % self._info
class ScoringEngineManager(base.Manager):
resource_class = ScoringEngine
@staticmethod
def _path(scoring_engine=None):
return ('/v1/scoring_engines/%s' % scoring_engine
if scoring_engine else '/v1/scoring_engines')
def list(self, limit=None, sort_key=None, sort_dir=None, detail=False):
"""Retrieve a list of scoring engines.
:param limit: The maximum number of results to return per
request, if:
1) limit > 0, the maximum number of scoring engines to return.
2) limit == 0, return the entire list of scoring engines.
3) limit param is NOT specified (None), the number of items
returned respect the maximum imposed by the Watcher API
(see Watcher's api.max_limit option).
:param sort_key: Optional, field used for sorting.
:param sort_dir: Optional, direction of sorting, either 'asc' (the
default) or 'desc'.
:param detail: Optional, boolean whether to return detailed information
about scoring engines.
:returns: A list of scoring engines.
"""
if limit is not None:
limit = int(limit)
filters = utils.common_filters(limit, sort_key, sort_dir)
path = ''
if detail:
path += 'detail'
if filters:
path += '?' + '&'.join(filters)
if limit is None:
return self._list(self._path(path), "scoring_engines")
else:
return self._list_pagination(self._path(path), "scoring_engines",
limit=limit)
def get(self, scoring_engine_name):
try:
return self._list(self._path(scoring_engine_name))[0]
except IndexError:
return None
python-watcherclient-2.2.0/watcherclient/v1/audit_template_shell.py 0000666 0001750 0001750 00000030611 13364113436 025643 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2016 b<>com
#
# 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 import utils
from oslo_utils import uuidutils
from watcherclient._i18n import _
from watcherclient.common import command
from watcherclient.common import utils as common_utils
from watcherclient import exceptions
from watcherclient.v1 import resource_fields as res_fields
class ShowAuditTemplate(command.ShowOne):
"""Show detailed information about a given audit template."""
def get_parser(self, prog_name):
parser = super(ShowAuditTemplate, self).get_parser(prog_name)
parser.add_argument(
'audit_template',
metavar='',
help=_('UUID or name of the audit template'),
)
return parser
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
audit_template_uuid = parsed_args.audit_template
try:
audit_template = client.audit_template.get(audit_template_uuid)
except exceptions.HTTPNotFound as exc:
raise exceptions.CommandError(str(exc))
columns = res_fields.AUDIT_TEMPLATE_FIELDS
column_headers = res_fields.AUDIT_TEMPLATE_FIELD_LABELS
return column_headers, utils.get_item_properties(
audit_template, columns)
class ListAuditTemplate(command.Lister):
"""List information on retrieved audit templates."""
def get_parser(self, prog_name):
parser = super(ListAuditTemplate, self).get_parser(prog_name)
parser.add_argument(
'--detail',
dest='detail',
action='store_true',
default=False,
help=_("Show detailed information about audit templates."))
parser.add_argument(
'--goal',
dest='goal',
metavar='',
help=_('UUID or name of the goal used for filtering.'))
parser.add_argument(
'--strategy',
dest='strategy',
metavar='',
help=_('UUID or name of the strategy used for filtering.'))
parser.add_argument(
'--limit',
metavar='',
type=int,
help=_('Maximum number of audit templates to return per request, '
'0 for no limit. Default is the maximum number used '
'by the Watcher API Service.'))
parser.add_argument(
'--sort-key',
metavar='',
help=_('Audit template field that will be used for sorting.'))
parser.add_argument(
'--sort-dir',
metavar='',
choices=['asc', 'desc'],
help=_('Sort direction: "asc" (the default) or "desc".'))
parser.add_argument(
'--marker',
dest='marker',
metavar='',
default=None,
help=_('UUID of the last audit template of the previous page; '
'displays list of audit templates after "marker".'))
return parser
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
params = {}
# Optional
if parsed_args.goal:
params['goal'] = parsed_args.goal
# Optional
if parsed_args.strategy:
params['strategy'] = parsed_args.strategy
if parsed_args.detail:
fields = res_fields.AUDIT_TEMPLATE_FIELDS
field_labels = res_fields.AUDIT_TEMPLATE_FIELD_LABELS
else:
fields = res_fields.AUDIT_TEMPLATE_SHORT_LIST_FIELDS
field_labels = res_fields.AUDIT_TEMPLATE_SHORT_LIST_FIELD_LABELS
params.update(common_utils.common_params_for_list(
parsed_args, fields, field_labels))
data = client.audit_template.list(**params)
return (field_labels,
(utils.get_item_properties(item, fields) for item in data))
class CreateAuditTemplate(command.ShowOne):
"""Create new audit template."""
def get_parser(self, prog_name):
class SmartFormatter(argparse.HelpFormatter):
def _split_lines(self, text, width):
if '\n' in text:
return text.splitlines()
else:
return argparse.HelpFormatter._split_lines(
self, text, width)
parser = super(CreateAuditTemplate, self).get_parser(
prog_name, formatter_class=SmartFormatter)
parser.add_argument(
'name',
metavar='',
help=_('Name for this audit template.'))
parser.add_argument(
'goal',
metavar='',
help=_('Goal UUID or name associated to this audit template.'))
parser.add_argument(
'-s', '--strategy',
dest='strategy',
metavar='',
help=_('Strategy UUID or name associated to this audit template.'))
parser.add_argument(
'-d', '--description',
metavar='',
help=_('Description of the audit template.'))
parser.add_argument(
'--scope',
metavar='',
help=_("Part of the cluster on which an audit will be done.\n"
"Can be provided either in yaml or json file.\n"
"YAML example:\n"
"---\n"
" - compute:\n"
" - host_aggregates:\n"
" - id: 1\n"
" - id: 2\n"
" - id: 3\n"
" - availability_zones:\n"
" - name: AZ1\n"
" - name: AZ2\n"
" - exclude:\n"
" - instances:\n"
" - uuid: UUID1\n"
" - uuid: UUID2\n"
" - compute_nodes:\n"
" - name: compute1\n"
" - storage: \n"
" - availability_zones:\n"
" - name: AZ1\n"
" - name: AZ2\n"
" - volume_types:\n"
" - name: lvm1\n"
" - name: lvm2\n"
" - exclude:\n"
" - storage_pools:\n"
" - name: host0@backend0#pool0\n"
" - name: host1@backend1#pool1\n"
" - volumes:\n"
" - uuid: UUID1\n"
" - uuid: UUID2\n"
" - projects:\n"
" - uuid: UUID1\n"
" - uuid: UUID2\n"
"\n"
"JSON example:\n"
"[\n"
" {\"compute\":\n"
" [{\"host_aggregates\": [\n"
" {\"id\": 1},\n"
" {\"id\": 2},\n"
" {\"id\": 3}]},\n"
" {\"availability_zones\": [\n"
" {\"name\": \"AZ1\"},\n"
" {\"name\": \"AZ2\"}]},\n"
" {\"exclude\": [\n"
" {\"instances\": [\n"
" {\"uuid\": \"UUID1\"},\n"
" {\"uuid\": \"UUID2\"}\n"
" ]},\n"
" {\"compute_nodes\": [\n"
" {\"name\": \"compute1\"}\n"
" ]}\n"
" ]}]\n"
" },\n"
" {\"storage\":\n"
" [{\"availability_zones\": [\n"
" {\"name\": \"AZ1\"},\n"
" {\"name\": \"AZ2\"}]},\n"
" {\"volume_types\": [\n"
" {\"name\": \"lvm1\"},\n"
" {\"name\": \"lvm2\"}]},\n"
" {\"exclude\": [\n"
" {\"storage_pools\": [\n"
" {\"name\": \"host0@backend0#pool0\"},\n"
" {\"name\": \"host1@backend1#pool1\"}\n"
" ]},\n"
" {\"volumes\": [\n"
" {\"uuid\": \"UUID1\"},\n"
" {\"uuid\": \"UUID2\"}\n"
" ]},\n"
" {\"projects\": [\n"
" {\"uuid\": \"UUID1\"},\n"
" {\"uuid\": \"UUID2\"}\n"
" ]},\n"
" ]}]\n"
" }\n"
" ]\n"
)
)
return parser
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
field_list = ['description', 'name', 'goal', 'strategy', 'scope']
fields = dict((k, v) for (k, v) in vars(parsed_args).items()
if k in field_list and v is not None)
# mandatory
if not uuidutils.is_uuid_like(fields['goal']):
fields['goal'] = client.goal.get(fields['goal']).uuid
# optional
if fields.get('strategy'):
if not uuidutils.is_uuid_like(fields['strategy']):
fields['strategy'] = client.strategy.get(
fields['strategy']).uuid
if fields.get('scope'):
fields['scope'] = common_utils.serialize_file_to_dict(
fields['scope'])
audit_template = client.audit_template.create(**fields)
columns = res_fields.AUDIT_TEMPLATE_FIELDS
column_headers = res_fields.AUDIT_TEMPLATE_FIELD_LABELS
return (column_headers,
utils.get_item_properties(audit_template, columns))
class UpdateAuditTemplate(command.ShowOne):
"""Update audit template command."""
def get_parser(self, prog_name):
parser = super(UpdateAuditTemplate, self).get_parser(prog_name)
parser.add_argument(
'audit_template',
metavar='',
help=_("UUID or name of the audit_template."))
parser.add_argument(
'op',
metavar='',
choices=['add', 'replace', 'remove'],
help=_("Operation: 'add', 'replace', or 'remove'."))
parser.add_argument(
'attributes',
metavar='',
nargs='+',
action='append',
default=[],
help=_("Attribute to add, replace, or remove. Can be specified "
"multiple times. For 'remove', only is necessary."))
return parser
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
patch = common_utils.args_array_to_patch(
parsed_args.op, parsed_args.attributes[0])
audit_template = client.audit_template.update(
parsed_args.audit_template, patch)
columns = res_fields.AUDIT_TEMPLATE_FIELDS
column_headers = res_fields.AUDIT_TEMPLATE_FIELD_LABELS
return column_headers, utils.get_item_properties(
audit_template, columns)
class DeleteAuditTemplate(command.Command):
"""Delete audit template command."""
def get_parser(self, prog_name):
parser = super(DeleteAuditTemplate, self).get_parser(prog_name)
parser.add_argument(
'audit_templates',
metavar='',
nargs='+',
help=_('UUID or name of the audit template'),
)
return parser
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
for audit_template in parsed_args.audit_templates:
client.audit_template.delete(audit_template)
python-watcherclient-2.2.0/watcherclient/v1/audit_template.py 0000666 0001750 0001750 00000007137 13364113436 024463 0 ustar zuul zuul 0000000 0000000 #
# Copyright 2013 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from watcherclient.common import base
from watcherclient.common import utils
from watcherclient import exceptions as exc
CREATION_ATTRIBUTES = ['description', 'name', 'goal', 'strategy', 'scope']
class AuditTemplate(base.Resource):
def __repr__(self):
return "" % self._info
class AuditTemplateManager(base.Manager):
resource_class = AuditTemplate
@staticmethod
def _path(id_=None):
return '/v1/audit_templates/%s' % id_ if id_ else '/v1/audit_templates'
def list(self, name=None, goal=None, strategy=None, limit=None,
sort_key=None, sort_dir=None, detail=False, marker=None):
"""Retrieve a list of audit template.
:param name: Name of the audit template
:param limit: The maximum number of results to return per
request, if:
1) limit > 0, the maximum number of audit templates to return.
2) limit == 0, return the entire list of audit_templates.
3) limit param is NOT specified (None), the number of items
returned respect the maximum imposed by the Watcher API
(see Watcher's api.max_limit option).
:param sort_key: Optional, field used for sorting.
:param sort_dir: Optional, direction of sorting, either 'asc' (the
default) or 'desc'.
:param detail: Optional, boolean whether to return detailed information
about audit_templates.
:param marker: Optional, UUID of the last audit template of
the previous page.
:returns: A list of audit templates.
"""
if limit is not None:
limit = int(limit)
filters = utils.common_filters(limit, sort_key, sort_dir, marker)
if name is not None:
filters.append('name=%s' % name)
if goal is not None:
filters.append("goal=%s" % goal)
if strategy is not None:
filters.append("strategy=%s" % strategy)
path = ''
if detail:
path += 'detail'
if filters:
path += '?' + '&'.join(filters)
if limit is None:
return self._list(self._path(path), "audit_templates")
else:
return self._list_pagination(self._path(path), "audit_templates",
limit=limit)
def get(self, audit_template_id):
try:
return self._list(self._path(audit_template_id))[0]
except IndexError:
return None
def create(self, **kwargs):
new = {}
for (key, value) in kwargs.items():
if key in CREATION_ATTRIBUTES:
new[key] = value
else:
raise exc.InvalidAttribute()
return self._create(self._path(), new)
def delete(self, audit_template_id):
return self._delete(self._path(audit_template_id))
def update(self, audit_template_id, patch):
return self._update(self._path(audit_template_id), patch)
python-watcherclient-2.2.0/watcherclient/v1/goal.py 0000666 0001750 0001750 00000004625 13364113436 022403 0 ustar zuul zuul 0000000 0000000 #
# Copyright 2013 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from watcherclient.common import base
from watcherclient.common import utils
class Goal(base.Resource):
def __repr__(self):
return "" % self._info
class GoalManager(base.Manager):
resource_class = Goal
@staticmethod
def _path(goal=None):
return '/v1/goals/%s' % goal if goal else '/v1/goals'
def list(self, limit=None, sort_key=None, sort_dir=None, detail=False):
"""Retrieve a list of goal.
:param limit: The maximum number of results to return per
request, if:
1) limit > 0, the maximum number of audits to return.
2) limit == 0, return the entire list of audits.
3) limit param is NOT specified (None), the number of items
returned respect the maximum imposed by the Watcher API
(see Watcher's api.max_limit option).
:param sort_key: Optional, field used for sorting.
:param sort_dir: Optional, direction of sorting, either 'asc' (the
default) or 'desc'.
:param detail: Optional, boolean whether to return detailed information
about audits.
:returns: A list of audits.
"""
if limit is not None:
limit = int(limit)
filters = utils.common_filters(limit, sort_key, sort_dir)
path = ''
if detail:
path += 'detail'
if filters:
path += '?' + '&'.join(filters)
if limit is None:
return self._list(self._path(path), "goals")
else:
return self._list_pagination(self._path(path), "goals",
limit=limit)
def get(self, goal):
try:
return self._list(self._path(goal))[0]
except IndexError:
return None
python-watcherclient-2.2.0/watcherclient/v1/service.py 0000666 0001750 0001750 00000004730 13364113436 023116 0 ustar zuul zuul 0000000 0000000 #
# Copyright 2016 Servionica
#
# 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 watcherclient.common import base
from watcherclient.common import utils
class Service(base.Resource):
def __repr__(self):
return "" % self._info
class ServiceManager(base.Manager):
resource_class = Service
@staticmethod
def _path(service=None):
return ('/v1/services/%s' % service
if service else '/v1/services')
def list(self, limit=None, sort_key=None, sort_dir=None, detail=False):
"""Retrieve a list of services.
:param limit: The maximum number of results to return per
request, if:
1) limit > 0, the maximum number of services to return.
2) limit == 0, return the entire list of services.
3) limit param is NOT specified (None), the number of items
returned respect the maximum imposed by the Watcher API
(see Watcher's api.max_limit option).
:param sort_key: Optional, field used for sorting.
:param sort_dir: Optional, direction of sorting, either 'asc' (the
default) or 'desc'.
:param detail: Optional, boolean whether to return detailed information
about services.
:returns: A list of services.
"""
if limit is not None:
limit = int(limit)
filters = utils.common_filters(limit, sort_key, sort_dir)
path = ''
if detail:
path += 'detail'
if filters:
path += '?' + '&'.join(filters)
if limit is None:
return self._list(self._path(path), "services")
else:
return self._list_pagination(self._path(path), "services",
limit=limit)
def get(self, service):
try:
return self._list(self._path(service))[0]
except IndexError:
return None
python-watcherclient-2.2.0/watcherclient/v1/service_shell.py 0000666 0001750 0001750 00000006677 13364113436 024321 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2016 Servionica
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from osc_lib import utils
from watcherclient._i18n import _
from watcherclient.common import command
from watcherclient.common import utils as common_utils
from watcherclient import exceptions
from watcherclient.v1 import resource_fields as res_fields
class ShowService(command.ShowOne):
"""Show detailed information about a given service."""
def get_parser(self, prog_name):
parser = super(ShowService, self).get_parser(prog_name)
parser.add_argument(
'service',
metavar='',
help=_('ID or name of the service'),
)
return parser
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
try:
service = client.service.get(parsed_args.service)
except exceptions.HTTPNotFound as exc:
raise exceptions.CommandError(str(exc))
columns = res_fields.SERVICE_FIELDS
column_headers = res_fields.SERVICE_FIELD_LABELS
return column_headers, utils.get_item_properties(service, columns)
class ListService(command.Lister):
"""List information on retrieved services."""
def get_parser(self, prog_name):
parser = super(ListService, self).get_parser(prog_name)
parser.add_argument(
'--detail',
dest='detail',
action='store_true',
default=False,
help=_("Show detailed information about each service."))
parser.add_argument(
'--limit',
metavar='',
type=int,
help=_('Maximum number of services to return per request, '
'0 for no limit. Default is the maximum number used '
'by the Watcher API Service.'))
parser.add_argument(
'--sort-key',
metavar='',
help=_('Goal field that will be used for sorting.'))
parser.add_argument(
'--sort-dir',
metavar='',
choices=['asc', 'desc'],
help='Sort direction: "asc" (the default) or "desc".')
return parser
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
params = {}
if parsed_args.detail:
fields = res_fields.SERVICE_FIELDS
field_labels = res_fields.SERVICE_FIELD_LABELS
else:
fields = res_fields.SERVICE_SHORT_LIST_FIELDS
field_labels = res_fields.SERVICE_SHORT_LIST_FIELD_LABELS
params.update(
common_utils.common_params_for_list(
parsed_args, fields, field_labels))
try:
data = client.service.list(**params)
except exceptions.HTTPNotFound as ex:
raise exceptions.CommandError(str(ex))
return (field_labels,
(utils.get_item_properties(item, fields) for item in data))
python-watcherclient-2.2.0/watcherclient/common/ 0000775 0001750 0001750 00000000000 13364113665 022044 5 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/watcherclient/common/base.py 0000666 0001750 0001750 00000011274 13364113436 023333 0 ustar zuul zuul 0000000 0000000 #
# Copyright 2012 OpenStack LLC.
# 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.
"""
Base utilities to build API operation managers and objects on top of.
"""
import copy
import six.moves.urllib.parse as urlparse
from watcherclient.common.apiclient import base
def getid(obj):
"""Wrapper to get object's ID.
Abstracts the common pattern of allowing both an object or an
object's ID (UUID) as a parameter when dealing with relationships.
"""
try:
return obj.id
except AttributeError:
return obj
class Manager(object):
"""Provides CRUD operations with a particular API."""
resource_class = None
def __init__(self, api):
self.api = api
def _create(self, url, body):
resp, body = self.api.json_request('POST', url, body=body)
if body:
return self.resource_class(self, body)
def _format_body_data(self, body, response_key):
if response_key:
try:
data = body[response_key]
except KeyError:
return []
else:
data = body
if not isinstance(data, list):
data = [data]
return data
def _list_pagination(self, url, response_key=None, obj_class=None,
limit=None):
"""Retrieve a list of items.
The Watcher API is configured to return a maximum number of
items per request, (see Watcher's api.max_limit option). This
iterates over the 'next' link (pagination) in the responses,
to get the number of items specified by 'limit'. If 'limit'
is None this function will continue pagination until there are
no more values to be returned.
:param url: a partial URL, e.g. '/nodes'
:param response_key: the key to be looked up in response
dictionary, e.g. 'nodes'
:param obj_class: class for constructing the returned objects.
:param limit: maximum number of items to return. If None returns
everything.
"""
if obj_class is None:
obj_class = self.resource_class
if limit is not None:
limit = int(limit)
object_list = []
object_count = 0
limit_reached = False
while url:
resp, body = self.api.json_request('GET', url)
data = self._format_body_data(body, response_key)
for obj in data:
object_list.append(obj_class(self, obj, loaded=True))
object_count += 1
if limit and object_count >= limit:
# break the for loop
limit_reached = True
break
# break the while loop and return
if limit_reached:
break
url = body.get('next')
if url:
# NOTE(lucasagomes): We need to edit the URL to remove
# the scheme and netloc
url_parts = list(urlparse.urlparse(url))
url_parts[0] = url_parts[1] = ''
url = urlparse.urlunparse(url_parts)
return object_list
def _list(self, url, response_key=None, obj_class=None, body=None):
resp, body = self.api.json_request('GET', url)
if obj_class is None:
obj_class = self.resource_class
data = self._format_body_data(body, response_key)
return [obj_class(self, res, loaded=True) for res in data if res]
def _update(self, url, body, method='PATCH', response_key=None):
resp, body = self.api.json_request(method, url, body=body)
# PATCH/PUT requests may not return a body
if body:
return self.resource_class(self, body)
def _delete(self, url):
self.api.raw_request('DELETE', url)
def _start(self, url, body=None, method='POST'):
resp, body = self.api.json_request(method, url, body={})
if body:
return self.resource_class(self, body)
class Resource(base.Resource):
"""Represents a particular instance of an object (tenant, user, etc).
This is pretty much just a bag for attributes.
"""
def to_dict(self):
return copy.deepcopy(self._info)
python-watcherclient-2.2.0/watcherclient/common/apiclient/ 0000775 0001750 0001750 00000000000 13364113665 024014 5 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/watcherclient/common/apiclient/base.py 0000666 0001750 0001750 00000042120 13364113436 025275 0 ustar zuul zuul 0000000 0000000 # Copyright 2010 Jacob Kaplan-Moss
# Copyright 2011 OpenStack Foundation
# Copyright 2012 Grid Dynamics
# Copyright 2013 OpenStack Foundation
# 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.
"""
Base utilities to build API operation managers and objects on top of.
"""
########################################################################
#
# THIS MODULE IS DEPRECATED
#
# Please refer to
# https://etherpad.openstack.org/p/kilo-watcherclient-library-proposals for
# the discussion leading to this deprecation.
#
# We recommend checking out the python-openstacksdk project
# (https://launchpad.net/python-openstacksdk) instead.
#
########################################################################
# E1102: %s is not callable
# pylint: disable=E1102
import abc
import copy
from oslo_utils import strutils
import six
from six.moves.urllib import parse
from watcherclient._i18n import _
from watcherclient.common.apiclient import exceptions
def getid(obj):
"""Return id if argument is a Resource.
Abstracts the common pattern of allowing both an object or an object's ID
(UUID) as a parameter when dealing with relationships.
"""
try:
if obj.uuid:
return obj.uuid
except AttributeError:
pass
try:
return obj.id
except AttributeError:
return obj
# TODO(aababilov): call run_hooks() in HookableMixin's child classes
class HookableMixin(object):
"""Mixin so classes can register and run hooks."""
_hooks_map = {}
@classmethod
def add_hook(cls, hook_type, hook_func):
"""Add a new hook of specified type.
:param cls: class that registers hooks
:param hook_type: hook type, e.g., '__pre_parse_args__'
:param hook_func: hook function
"""
if hook_type not in cls._hooks_map:
cls._hooks_map[hook_type] = []
cls._hooks_map[hook_type].append(hook_func)
@classmethod
def run_hooks(cls, hook_type, *args, **kwargs):
"""Run all hooks of specified type.
:param cls: class that registers hooks
:param hook_type: hook type, e.g., '__pre_parse_args__'
:param args: args to be passed to every hook function
:param kwargs: kwargs to be passed to every hook function
"""
hook_funcs = cls._hooks_map.get(hook_type) or []
for hook_func in hook_funcs:
hook_func(*args, **kwargs)
class BaseManager(HookableMixin):
"""Basic manager type providing common operations.
Managers interact with a particular type of API (servers, flavors, images,
etc.) and provide CRUD operations for them.
"""
resource_class = None
def __init__(self, client):
"""Initializes BaseManager with `client`.
:param client: instance of BaseClient descendant for HTTP requests
"""
super(BaseManager, self).__init__()
self.client = client
def _list(self, url, response_key=None, obj_class=None, json=None):
"""List the collection.
:param url: a partial URL, e.g., '/servers'
:param response_key: the key to be looked up in response dictionary,
e.g., 'servers'. If response_key is None - all response body
will be used.
:param obj_class: class for constructing the returned objects
(self.resource_class will be used by default)
:param json: data that will be encoded as JSON and passed in POST
request (GET will be sent by default)
"""
if json:
body = self.client.post(url, json=json).json()
else:
body = self.client.get(url).json()
if obj_class is None:
obj_class = self.resource_class
data = body[response_key] if response_key is not None else body
# NOTE(ja): keystone returns values as list as {'values': [ ... ]}
# unlike other services which just return the list...
try:
data = data['values']
except (KeyError, TypeError):
pass
return [obj_class(self, res, loaded=True) for res in data if res]
def _get(self, url, response_key=None):
"""Get an object from collection.
:param url: a partial URL, e.g., '/servers'
:param response_key: the key to be looked up in response dictionary,
e.g., 'server'. If response_key is None - all response body
will be used.
"""
body = self.client.get(url).json()
data = body[response_key] if response_key is not None else body
return self.resource_class(self, data, loaded=True)
def _head(self, url):
"""Retrieve request headers for an object.
:param url: a partial URL, e.g., '/servers'
"""
resp = self.client.head(url)
return resp.status_code == 204
def _post(self, url, json, response_key=None, return_raw=False):
"""Create an object.
:param url: a partial URL, e.g., '/servers'
:param json: data that will be encoded as JSON and passed in POST
request (GET will be sent by default)
:param response_key: the key to be looked up in response dictionary,
e.g., 'server'. If response_key is None - all response body
will be used.
:param return_raw: flag to force returning raw JSON instead of
Python object of self.resource_class
"""
body = self.client.post(url, json=json).json()
data = body[response_key] if response_key is not None else body
if return_raw:
return data
return self.resource_class(self, data)
def _put(self, url, json=None, response_key=None):
"""Update an object with PUT method.
:param url: a partial URL, e.g., '/servers'
:param json: data that will be encoded as JSON and passed in POST
request (GET will be sent by default)
:param response_key: the key to be looked up in response dictionary,
e.g., 'servers'. If response_key is None - all response body
will be used.
"""
resp = self.client.put(url, json=json)
# PUT requests may not return a body
if resp.content:
body = resp.json()
if response_key is not None:
return self.resource_class(self, body[response_key])
else:
return self.resource_class(self, body)
def _patch(self, url, json=None, response_key=None):
"""Update an object with PATCH method.
:param url: a partial URL, e.g., '/servers'
:param json: data that will be encoded as JSON and passed in POST
request (GET will be sent by default)
:param response_key: the key to be looked up in response dictionary,
e.g., 'servers'. If response_key is None - all response body
will be used.
"""
body = self.client.patch(url, json=json).json()
if response_key is not None:
return self.resource_class(self, body[response_key])
else:
return self.resource_class(self, body)
def _delete(self, url):
"""Delete an object.
:param url: a partial URL, e.g., '/servers/my-server'
"""
return self.client.delete(url)
@six.add_metaclass(abc.ABCMeta)
class ManagerWithFind(BaseManager):
"""Manager with additional `find()`/`findall()` methods."""
@abc.abstractmethod
def list(self):
pass
def find(self, **kwargs):
"""Find a single item with attributes matching ``**kwargs``.
This isn't very efficient: it loads the entire list then filters on
the Python side.
"""
matches = self.findall(**kwargs)
num_matches = len(matches)
if num_matches == 0:
msg = _("No %(name)s matching %(args)s.") % {
'name': self.resource_class.__name__,
'args': kwargs
}
raise exceptions.NotFound(msg)
elif num_matches > 1:
raise exceptions.NoUniqueMatch()
else:
return matches[0]
def findall(self, **kwargs):
"""Find all items with attributes matching ``**kwargs``.
This isn't very efficient: it loads the entire list then filters on
the Python side.
"""
found = []
searches = kwargs.items()
for obj in self.list():
try:
if all(getattr(obj, attr) == value
for (attr, value) in searches):
found.append(obj)
except AttributeError:
continue
return found
class CrudManager(BaseManager):
"""Base manager class for manipulating entities.
Children of this class are expected to define a `collection_key` and `key`.
- `collection_key`: Usually a plural noun by convention (e.g. `entities`);
used to refer collections in both URL's (e.g. `/v3/entities`) and JSON
objects containing a list of member resources (e.g. `{'entities': [{},
{}, {}]}`).
- `key`: Usually a singular noun by convention (e.g. `entity`); used to
refer to an individual member of the collection.
"""
collection_key = None
key = None
def build_url(self, base_url=None, **kwargs):
"""Builds a resource URL for the given kwargs.
Given an example collection where `collection_key = 'entities'` and
`key = 'entity'`, the following URL's could be generated.
By default, the URL will represent a collection of entities, e.g.::
/entities
If kwargs contains an `entity_id`, then the URL will represent a
specific member, e.g.::
/entities/{entity_id}
:param base_url: if provided, the generated URL will be appended to it
"""
url = base_url if base_url is not None else ''
url += '/%s' % self.collection_key
# do we have a specific entity?
entity_id = kwargs.get('%s_id' % self.key)
if entity_id is not None:
url += '/%s' % entity_id
return url
def _filter_kwargs(self, kwargs):
"""Drop null values and handle ids."""
for key, ref in kwargs.copy().items():
if ref is None:
kwargs.pop(key)
else:
if isinstance(ref, Resource):
kwargs.pop(key)
kwargs['%s_id' % key] = getid(ref)
return kwargs
def create(self, **kwargs):
kwargs = self._filter_kwargs(kwargs)
return self._post(
self.build_url(**kwargs),
{self.key: kwargs},
self.key)
def get(self, **kwargs):
kwargs = self._filter_kwargs(kwargs)
return self._get(
self.build_url(**kwargs),
self.key)
def head(self, **kwargs):
kwargs = self._filter_kwargs(kwargs)
return self._head(self.build_url(**kwargs))
def list(self, base_url=None, **kwargs):
"""List the collection.
:param base_url: if provided, the generated URL will be appended to it
"""
kwargs = self._filter_kwargs(kwargs)
return self._list(
'%(base_url)s%(query)s' % {
'base_url': self.build_url(base_url=base_url, **kwargs),
'query': '?%s' % parse.urlencode(kwargs) if kwargs else '',
},
self.collection_key)
def put(self, base_url=None, **kwargs):
"""Update an element.
:param base_url: if provided, the generated URL will be appended to it
"""
kwargs = self._filter_kwargs(kwargs)
return self._put(self.build_url(base_url=base_url, **kwargs))
def update(self, **kwargs):
kwargs = self._filter_kwargs(kwargs)
params = kwargs.copy()
params.pop('%s_id' % self.key)
return self._patch(
self.build_url(**kwargs),
{self.key: params},
self.key)
def delete(self, **kwargs):
kwargs = self._filter_kwargs(kwargs)
return self._delete(
self.build_url(**kwargs))
def find(self, base_url=None, **kwargs):
"""Find a single item with attributes matching ``**kwargs``.
:param base_url: if provided, the generated URL will be appended to it
"""
kwargs = self._filter_kwargs(kwargs)
rl = self._list(
'%(base_url)s%(query)s' % {
'base_url': self.build_url(base_url=base_url, **kwargs),
'query': '?%s' % parse.urlencode(kwargs) if kwargs else '',
},
self.collection_key)
num = len(rl)
if num == 0:
msg = _("No %(name)s matching %(args)s.") % {
'name': self.resource_class.__name__,
'args': kwargs
}
raise exceptions.NotFound(404, msg)
elif num > 1:
raise exceptions.NoUniqueMatch
else:
return rl[0]
class Extension(HookableMixin):
"""Extension descriptor."""
SUPPORTED_HOOKS = ('__pre_parse_args__', '__post_parse_args__')
manager_class = None
def __init__(self, name, module):
super(Extension, self).__init__()
self.name = name
self.module = module
self._parse_extension_module()
def _parse_extension_module(self):
self.manager_class = None
for attr_name, attr_value in self.module.__dict__.items():
if attr_name in self.SUPPORTED_HOOKS:
self.add_hook(attr_name, attr_value)
else:
try:
if issubclass(attr_value, BaseManager):
self.manager_class = attr_value
except TypeError:
pass
def __repr__(self):
return "" % self.name
class Resource(object):
"""Base class for OpenStack resources (tenant, user, etc.).
This is pretty much just a bag for attributes.
"""
HUMAN_ID = False
NAME_ATTR = 'name'
def __init__(self, manager, info, loaded=False):
"""Populate and bind to a manager.
:param manager: BaseManager object
:param info: dictionary representing resource attributes
:param loaded: prevent lazy-loading if set to True
"""
self.manager = manager
self._info = info
self._add_details(info)
self._loaded = loaded
def __repr__(self):
reprkeys = sorted(k
for k in self.__dict__.keys()
if k[0] != '_' and k != 'manager')
info = ", ".join("%s=%s" % (k, getattr(self, k)) for k in reprkeys)
return "<%s %s>" % (self.__class__.__name__, info)
@property
def human_id(self):
"""Human-readable ID which can be used for bash completion."""
if self.HUMAN_ID:
name = getattr(self, self.NAME_ATTR, None)
if name is not None:
return strutils.to_slug(name)
return None
def _add_details(self, info):
for (k, v) in info.items():
try:
setattr(self, k, v)
self._info[k] = v
except AttributeError:
# In this case we already defined the attribute on the class
pass
def __getattr__(self, k):
if k not in self.__dict__:
# NOTE(bcwaldon): disallow lazy-loading if already loaded once
if not self.is_loaded():
self.get()
return self.__getattr__(k)
raise AttributeError(k)
else:
return self.__dict__[k]
def get(self):
"""Support for lazy loading details.
Some clients, such as watcherclient have the option to lazy load the
details, details which can be loaded with this function.
"""
# set_loaded() first ... so if we have to bail, we know we tried.
self.set_loaded(True)
if not hasattr(self.manager, 'get'):
return
new = self.manager.get(self.id)
if new:
self._add_details(new._info)
self._add_details(
{'x_request_id': self.manager.client.last_request_id})
def __eq__(self, other):
if not isinstance(other, Resource):
return NotImplemented
# two resources of different types are not equal
if not isinstance(other, self.__class__):
return False
if hasattr(self, 'id') and hasattr(other, 'id'):
return self.id == other.id
return self._info == other._info
def __ne__(self, other):
return not self.__eq__(other)
def is_loaded(self):
return self._loaded
def set_loaded(self, val):
self._loaded = val
def to_dict(self):
return copy.deepcopy(self._info)
python-watcherclient-2.2.0/watcherclient/common/apiclient/__init__.py 0000666 0001750 0001750 00000000000 13364113436 026111 0 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/watcherclient/common/apiclient/exceptions.py 0000666 0001750 0001750 00000031016 13364113436 026546 0 ustar zuul zuul 0000000 0000000 # Copyright 2010 Jacob Kaplan-Moss
# Copyright 2011 Nebula, Inc.
# Copyright 2013 Alessio Ababilov
# Copyright 2013 OpenStack Foundation
# 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.
"""
Exception definitions.
"""
########################################################################
#
# THIS MODULE IS DEPRECATED
#
# Please refer to
# https://etherpad.openstack.org/p/kilo-watcherclient-library-proposals for
# the discussion leading to this deprecation.
#
# We recommend checking out the python-openstacksdk project
# (https://launchpad.net/python-openstacksdk) instead.
#
########################################################################
import inspect
import sys
import six
from watcherclient._i18n import _
class ClientException(Exception):
"""The base exception class for all exceptions this library raises."""
pass
class ValidationError(ClientException):
"""Error in validation on API client side."""
pass
class UnsupportedVersion(ClientException):
"""User is trying to use an unsupported version of the API."""
pass
class CommandError(ClientException):
"""Error in CLI tool."""
pass
class AuthorizationFailure(ClientException):
"""Cannot authorize API client."""
pass
class ConnectionError(ClientException):
"""Cannot connect to API service."""
pass
class ConnectionRefused(ConnectionError):
"""Connection refused while trying to connect to API service."""
pass
class AuthPluginOptionsMissing(AuthorizationFailure):
"""Auth plugin misses some options."""
def __init__(self, opt_names):
super(AuthPluginOptionsMissing, self).__init__(
_("Authentication failed. Missing options: %s") %
", ".join(opt_names))
self.opt_names = opt_names
class AuthSystemNotFound(AuthorizationFailure):
"""User has specified an AuthSystem that is not installed."""
def __init__(self, auth_system):
super(AuthSystemNotFound, self).__init__(
_("AuthSystemNotFound: %r") % auth_system)
self.auth_system = auth_system
class NoUniqueMatch(ClientException):
"""Multiple entities found instead of one."""
pass
class EndpointException(ClientException):
"""Something is rotten in Service Catalog."""
pass
class EndpointNotFound(EndpointException):
"""Could not find requested endpoint in Service Catalog."""
pass
class AmbiguousEndpoints(EndpointException):
"""Found more than one matching endpoint in Service Catalog."""
def __init__(self, endpoints=None):
super(AmbiguousEndpoints, self).__init__(
_("AmbiguousEndpoints: %r") % endpoints)
self.endpoints = endpoints
class HttpError(ClientException):
"""The base exception class for all HTTP exceptions."""
http_status = 0
message = _("HTTP Error")
def __init__(self, message=None, details=None,
response=None, request_id=None,
url=None, method=None, http_status=None):
self.http_status = http_status or self.http_status
self.message = message or self.message
self.details = details
self.request_id = request_id
self.response = response
self.url = url
self.method = method
formatted_string = "%s (HTTP %s)" % (self.message, self.http_status)
if request_id:
formatted_string += " (Request-ID: %s)" % request_id
super(HttpError, self).__init__(formatted_string)
class HTTPRedirection(HttpError):
"""HTTP Redirection."""
message = _("HTTP Redirection")
class HTTPClientError(HttpError):
"""Client-side HTTP error.
Exception for cases in which the client seems to have erred.
"""
message = _("HTTP Client Error")
class HttpServerError(HttpError):
"""Server-side HTTP error.
Exception for cases in which the server is aware that it has
erred or is incapable of performing the request.
"""
message = _("HTTP Server Error")
class MultipleChoices(HTTPRedirection):
"""HTTP 300 - Multiple Choices.
Indicates multiple options for the resource that the client may follow.
"""
http_status = 300
message = _("Multiple Choices")
class BadRequest(HTTPClientError):
"""HTTP 400 - Bad Request.
The request cannot be fulfilled due to bad syntax.
"""
http_status = 400
message = _("Bad Request")
class Unauthorized(HTTPClientError):
"""HTTP 401 - Unauthorized.
Similar to 403 Forbidden, but specifically for use when authentication
is required and has failed or has not yet been provided.
"""
http_status = 401
message = _("Unauthorized")
class PaymentRequired(HTTPClientError):
"""HTTP 402 - Payment Required.
Reserved for future use.
"""
http_status = 402
message = _("Payment Required")
class Forbidden(HTTPClientError):
"""HTTP 403 - Forbidden.
The request was a valid request, but the server is refusing to respond
to it.
"""
http_status = 403
message = _("Forbidden")
class NotFound(HTTPClientError):
"""HTTP 404 - Not Found.
The requested resource could not be found but may be available again
in the future.
"""
http_status = 404
message = _("Not Found")
class MethodNotAllowed(HTTPClientError):
"""HTTP 405 - Method Not Allowed.
A request was made of a resource using a request method not supported
by that resource.
"""
http_status = 405
message = _("Method Not Allowed")
class NotAcceptable(HTTPClientError):
"""HTTP 406 - Not Acceptable.
The requested resource is only capable of generating content not
acceptable according to the Accept headers sent in the request.
"""
http_status = 406
message = _("Not Acceptable")
class ProxyAuthenticationRequired(HTTPClientError):
"""HTTP 407 - Proxy Authentication Required.
The client must first authenticate itself with the proxy.
"""
http_status = 407
message = _("Proxy Authentication Required")
class RequestTimeout(HTTPClientError):
"""HTTP 408 - Request Timeout.
The server timed out waiting for the request.
"""
http_status = 408
message = _("Request Timeout")
class Conflict(HTTPClientError):
"""HTTP 409 - Conflict.
Indicates that the request could not be processed because of conflict
in the request, such as an edit conflict.
"""
http_status = 409
message = _("Conflict")
class Gone(HTTPClientError):
"""HTTP 410 - Gone.
Indicates that the resource requested is no longer available and will
not be available again.
"""
http_status = 410
message = _("Gone")
class LengthRequired(HTTPClientError):
"""HTTP 411 - Length Required.
The request did not specify the length of its content, which is
required by the requested resource.
"""
http_status = 411
message = _("Length Required")
class PreconditionFailed(HTTPClientError):
"""HTTP 412 - Precondition Failed.
The server does not meet one of the preconditions that the requester
put on the request.
"""
http_status = 412
message = _("Precondition Failed")
class RequestEntityTooLarge(HTTPClientError):
"""HTTP 413 - Request Entity Too Large.
The request is larger than the server is willing or able to process.
"""
http_status = 413
message = _("Request Entity Too Large")
def __init__(self, *args, **kwargs):
try:
self.retry_after = int(kwargs.pop('retry_after'))
except (KeyError, ValueError):
self.retry_after = 0
super(RequestEntityTooLarge, self).__init__(*args, **kwargs)
class RequestUriTooLong(HTTPClientError):
"""HTTP 414 - Request-URI Too Long.
The URI provided was too long for the server to process.
"""
http_status = 414
message = _("Request-URI Too Long")
class UnsupportedMediaType(HTTPClientError):
"""HTTP 415 - Unsupported Media Type.
The request entity has a media type which the server or resource does
not support.
"""
http_status = 415
message = _("Unsupported Media Type")
class RequestedRangeNotSatisfiable(HTTPClientError):
"""HTTP 416 - Requested Range Not Satisfiable.
The client has asked for a portion of the file, but the server cannot
supply that portion.
"""
http_status = 416
message = _("Requested Range Not Satisfiable")
class ExpectationFailed(HTTPClientError):
"""HTTP 417 - Expectation Failed.
The server cannot meet the requirements of the Expect request-header field.
"""
http_status = 417
message = _("Expectation Failed")
class UnprocessableEntity(HTTPClientError):
"""HTTP 422 - Unprocessable Entity.
The request was well-formed but was unable to be followed due to semantic
errors.
"""
http_status = 422
message = _("Unprocessable Entity")
class InternalServerError(HttpServerError):
"""HTTP 500 - Internal Server Error.
A generic error message, given when no more specific message is suitable.
"""
http_status = 500
message = _("Internal Server Error")
# NotImplemented is a python keyword.
class HttpNotImplemented(HttpServerError):
"""HTTP 501 - Not Implemented.
The server either does not recognize the request method, or it lacks
the ability to fulfill the request.
"""
http_status = 501
message = _("Not Implemented")
class BadGateway(HttpServerError):
"""HTTP 502 - Bad Gateway.
The server was acting as a gateway or proxy and received an invalid
response from the upstream server.
"""
http_status = 502
message = _("Bad Gateway")
class ServiceUnavailable(HttpServerError):
"""HTTP 503 - Service Unavailable.
The server is currently unavailable.
"""
http_status = 503
message = _("Service Unavailable")
class GatewayTimeout(HttpServerError):
"""HTTP 504 - Gateway Timeout.
The server was acting as a gateway or proxy and did not receive a timely
response from the upstream server.
"""
http_status = 504
message = _("Gateway Timeout")
class HttpVersionNotSupported(HttpServerError):
"""HTTP 505 - HttpVersion Not Supported.
The server does not support the HTTP protocol version used in the request.
"""
http_status = 505
message = _("HTTP Version Not Supported")
# _code_map contains all the classes that have http_status attribute.
_code_map = dict(
(getattr(obj, 'http_status', None), obj)
for name, obj in vars(sys.modules[__name__]).items()
if inspect.isclass(obj) and getattr(obj, 'http_status', False)
)
def from_response(response, method, url):
"""Returns an instance of :class:`HttpError` or subclass based on response.
:param response: instance of `requests.Response` class
:param method: HTTP method used for request
:param url: URL used for request
"""
req_id = response.headers.get("x-openstack-request-id")
kwargs = {
"http_status": response.status_code,
"response": response,
"method": method,
"url": url,
"request_id": req_id,
}
if "retry-after" in response.headers:
kwargs["retry_after"] = response.headers["retry-after"]
content_type = response.headers.get("Content-Type", "")
if content_type.startswith("application/json"):
try:
body = response.json()
except ValueError:
pass
else:
if isinstance(body, dict):
error = body.get(list(body)[0])
if isinstance(error, dict):
kwargs["message"] = (error.get("message") or
error.get("faultstring"))
kwargs["details"] = (error.get("details") or
six.text_type(body))
elif content_type.startswith("text/"):
kwargs["details"] = response.text
try:
cls = _code_map[response.status_code]
except KeyError:
if 500 <= response.status_code < 600:
cls = HttpServerError
elif 400 <= response.status_code < 500:
cls = HTTPClientError
else:
cls = HttpError
return cls(**kwargs)
python-watcherclient-2.2.0/watcherclient/common/utils.py 0000666 0001750 0001750 00000016061 13364113436 023560 0 ustar zuul zuul 0000000 0000000 #
# Copyright 2012 OpenStack LLC.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from __future__ import print_function
import argparse
import os
import uuid
import yaml
from oslo_serialization import jsonutils
from oslo_utils import importutils
from watcherclient._i18n import _
from watcherclient import exceptions as exc
class HelpFormatter(argparse.HelpFormatter):
def start_section(self, heading):
# Title-case the headings
heading = '%s%s' % (heading[0].upper(), heading[1:])
super(HelpFormatter, self).start_section(heading)
def define_command(subparsers, command, callback, cmd_mapper):
'''Define a command in the subparsers collection.
:param subparsers: subparsers collection where the command will go
:param command: command name
:param callback: function that will be used to process the command
'''
desc = callback.__doc__ or ''
help = desc.strip().split('\n')[0]
arguments = getattr(callback, 'arguments', [])
subparser = subparsers.add_parser(command, help=help,
description=desc,
add_help=False,
formatter_class=HelpFormatter)
subparser.add_argument('-h', '--help', action='help',
help=argparse.SUPPRESS)
cmd_mapper[command] = subparser
for (args, kwargs) in arguments:
subparser.add_argument(*args, **kwargs)
subparser.set_defaults(func=callback)
def define_commands_from_module(subparsers, command_module, cmd_mapper):
"""Add *do_* methods in a module and add as commands into a subparsers."""
for method_name in (a for a in dir(command_module) if a.startswith('do_')):
# Commands should be hypen-separated instead of underscores.
command = method_name[3:].replace('_', '-')
callback = getattr(command_module, method_name)
define_command(subparsers, command, callback, cmd_mapper)
def import_versioned_module(version, submodule=None):
module = 'watcherclient.v%s' % version
if submodule:
module = '.'.join((module, submodule))
return importutils.import_module(module)
def split_and_deserialize(string, exclude_fields=[]):
"""Split and try to JSON deserialize a string.
Gets a string with the KEY=VALUE format, split it (using '=' as the
separator) and try to JSON deserialize the VALUE.
:returns: A tuple of (key, value).
"""
try:
key, value = string.split("=", 1)
except ValueError:
raise exc.CommandError(_('Attributes must be a list of '
'PATH=VALUE not "%s"') % string)
if key not in exclude_fields:
try:
value = jsonutils.loads(value)
except ValueError:
pass
return (key, value)
def args_array_to_dict(kwargs, key_to_convert):
values_to_convert = kwargs.get(key_to_convert)
if values_to_convert:
kwargs[key_to_convert] = dict(split_and_deserialize(v)
for v in values_to_convert)
return kwargs
def args_array_to_patch(op, attributes, exclude_fields=[]):
patch = []
for attr in attributes:
# Sanitize
if not attr.startswith('/'):
attr = '/' + attr
if op in ['add', 'replace']:
path, value = split_and_deserialize(attr,
exclude_fields=exclude_fields)
patch.append({'op': op, 'path': path, 'value': value})
elif op == "remove":
# For remove only the key is needed
patch.append({'op': op, 'path': attr})
else:
raise exc.CommandError(_('Unknown PATCH operation: %s') % op)
return patch
def common_params_for_list(args, fields, field_labels):
"""Generate 'params' dict that is common for every 'list' command.
:param args: arguments from command line.
:param fields: possible fields for sorting.
:param field_labels: possible field labels for sorting.
:returns: a dict with params to pass to the client method.
"""
params = {}
if args.limit is not None:
if args.limit < 0:
raise exc.CommandError(
_('Expected non-negative --limit, got %s') % args.limit)
params['limit'] = args.limit
if args.sort_key is not None:
# Support using both heading and field name for sort_key
fields_map = dict(zip(field_labels, fields))
fields_map.update(zip(fields, fields))
try:
sort_key = fields_map[args.sort_key]
except KeyError:
raise exc.CommandError(
_("%(sort_key)s is an invalid field for sorting, "
"valid values for --sort-key are: %(valid)s") %
{'sort_key': args.sort_key,
'valid': list(fields_map)})
params['sort_key'] = sort_key
if args.sort_dir is not None:
if args.sort_dir not in ('asc', 'desc'):
raise exc.CommandError(
_("%s is an invalid value for sort direction, "
"valid values for --sort-dir are: 'asc', 'desc'") %
args.sort_dir)
params['sort_dir'] = args.sort_dir
marker = getattr(args, 'marker', None)
if marker is not None:
params['marker'] = marker
params['detail'] = args.detail
return params
def common_filters(limit=None, sort_key=None, sort_dir=None, marker=None):
"""Generate common filters for any list request.
:param limit: maximum number of entities to return.
:param sort_key: field to use for sorting.
:param sort_dir: direction of sorting: 'asc' or 'desc'.
:param marker: The last actionplan UUID of the previous page.
:returns: list of string filters.
"""
filters = []
if isinstance(limit, int) and limit > 0:
filters.append('limit=%s' % limit)
if sort_key is not None:
filters.append('sort_key=%s' % sort_key)
if sort_dir is not None:
filters.append('sort_dir=%s' % sort_dir)
if marker is not None:
filters.append('marker=%s' % marker)
return filters
def is_uuid_like(val):
"""Returns validation of a value as a UUID.
For our purposes, a UUID is a canonical form string:
aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
"""
try:
return str(uuid.UUID(val)) == val
except (TypeError, ValueError, AttributeError):
return False
def serialize_file_to_dict(filename):
filename = os.path.expanduser(filename)
with open(filename, "rb") as stream:
scope = yaml.safe_load(stream.read())
return scope
python-watcherclient-2.2.0/watcherclient/common/cliutils.py 0000666 0001750 0001750 00000017721 13364113436 024254 0 ustar zuul zuul 0000000 0000000 # Copyright 2012 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# W0603: Using the global statement
# W0621: Redefining name %s from outer scope
# pylint: disable=W0603,W0621
from __future__ import print_function
import getpass
import inspect
import os
import sys
import textwrap
from oslo_utils import encodeutils
from oslo_utils import strutils
import prettytable
import six
from six import moves
from watcherclient._i18n import _
class MissingArgs(Exception):
"""Supplied arguments are not sufficient for calling a function."""
def __init__(self, missing):
self.missing = missing
msg = _("Missing arguments: %s") % ", ".join(missing)
super(MissingArgs, self).__init__(msg)
def validate_args(fn, *args, **kwargs):
"""Check that the supplied args are sufficient for calling a function.
>>> validate_args(lambda a: None)
Traceback (most recent call last):
...
MissingArgs: Missing argument(s): a
>>> validate_args(lambda a, b, c, d: None, 0, c=1)
Traceback (most recent call last):
...
MissingArgs: Missing argument(s): b, d
:param fn: the function to check
:param arg: the positional arguments supplied
:param kwargs: the keyword arguments supplied
"""
argspec = inspect.getargspec(fn)
num_defaults = len(argspec.defaults or [])
required_args = argspec.args[:len(argspec.args) - num_defaults]
def isbound(method):
return getattr(method, '__self__', None) is not None
if isbound(fn):
required_args.pop(0)
missing = [arg for arg in required_args if arg not in kwargs]
missing = missing[len(args):]
if missing:
raise MissingArgs(missing)
def arg(*args, **kwargs):
"""Decorator for CLI args.
Example:
>>> @arg("name", help="Name of the new entity")
... def entity_create(args):
... pass
"""
def _decorator(func):
add_arg(func, *args, **kwargs)
return func
return _decorator
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', '')
def add_arg(func, *args, **kwargs):
"""Bind CLI arguments to a shell.py `do_foo` function."""
if not hasattr(func, 'arguments'):
func.arguments = []
# NOTE(sirp): avoid dups that can occur when the module is shared across
# tests.
if (args, kwargs) not in func.arguments:
# Because of the semantics of decorator composition if we just append
# to the options list positional options will appear to be backwards.
func.arguments.insert(0, (args, kwargs))
def unauthenticated(func):
"""Adds 'unauthenticated' attribute to decorated function.
Usage:
>>> @unauthenticated
... def mymethod(f):
... pass
"""
func.unauthenticated = True
return func
def isunauthenticated(func):
"""Checks if the function does not require authentication.
Mark such functions with the `@unauthenticated` decorator.
:returns: bool
"""
return getattr(func, 'unauthenticated', False)
def print_list(objs, fields, formatters=None, sortby_index=0,
mixed_case_fields=None, field_labels=None):
"""Print a list or objects as a table, one row per object.
:param objs: iterable of :class:`Resource`
:param fields: attributes that correspond to columns, in order
:param formatters: `dict` of callables for field formatting
:param sortby_index: index of the field for sorting table rows
:param mixed_case_fields: fields corresponding to object attributes that
have mixed case names (e.g., 'serverId')
:param field_labels: Labels to use in the heading of the table, default to
fields.
"""
formatters = formatters or {}
mixed_case_fields = mixed_case_fields or []
field_labels = field_labels or fields
if len(field_labels) != len(fields):
raise ValueError(_("Field labels list %(labels)s has different number "
"of elements than fields list %(fields)s"),
{'labels': field_labels, 'fields': fields})
if sortby_index is None:
kwargs = {}
else:
kwargs = {'sortby': field_labels[sortby_index]}
pt = prettytable.PrettyTable(field_labels)
pt.align = 'l'
for o in objs:
row = []
for field in fields:
data = '-'
if field in formatters:
data = formatters[field](o)
else:
if field in mixed_case_fields:
field_name = field.replace(' ', '_')
else:
field_name = field.lower().replace(' ', '_')
data = getattr(o, field_name, '')
if data is None:
data = '-'
row.append(data)
pt.add_row(row)
if six.PY3:
print(encodeutils.safe_encode(pt.get_string(**kwargs)).decode())
else:
print(encodeutils.safe_encode(pt.get_string(**kwargs)))
def print_dict(dct, dict_property="Property", wrap=0):
"""Print a `dict` as a table of two columns.
:param dct: `dict` to print
:param dict_property: name of the first column
:param wrap: wrapping for the second column
"""
pt = prettytable.PrettyTable([dict_property, 'Value'])
pt.align = 'l'
for k, v in dct.items():
# convert dict to str to check length
if isinstance(v, dict):
v = six.text_type(v)
if wrap > 0:
v = textwrap.fill(six.text_type(v), wrap)
elif wrap < 0:
raise ValueError(_("Wrap argument should be a positive integer"))
# if value has a newline, add in multiple rows
# e.g. fault with stacktrace
if v and isinstance(v, six.string_types) and r'\n' in v:
lines = v.strip().split(r'\n')
col1 = k
for line in lines:
pt.add_row([col1, line])
col1 = ''
else:
if v is None:
v = '-'
pt.add_row([k, v])
if six.PY3:
print(encodeutils.safe_encode(pt.get_string()).decode())
else:
print(encodeutils.safe_encode(pt.get_string()))
def get_password(max_password_prompts=3):
"""Read password from TTY."""
verify = strutils.bool_from_string(env("OS_VERIFY_PASSWORD"))
pw = None
if hasattr(sys.stdin, "isatty") and sys.stdin.isatty():
# Check for Ctrl-D
try:
for __ in moves.range(max_password_prompts):
pw1 = getpass.getpass("OS Password: ")
if verify:
pw2 = getpass.getpass("Please verify: ")
else:
pw2 = pw1
if pw1 == pw2 and pw1:
pw = pw1
break
except EOFError:
pass
return pw
def service_type(stype):
"""Adds 'service_type' attribute to decorated function.
Usage:
.. code-block:: python
@service_type('volume')
def mymethod(f):
...
"""
def inner(f):
f.service_type = stype
return f
return inner
def get_service_type(f):
"""Retrieves service type from function."""
return getattr(f, 'service_type', None)
def pretty_choice_list(l):
return ', '.join("'%s'" % i for i in l)
def exit(msg=''):
if msg:
print(msg, file=sys.stderr)
sys.exit(1)
python-watcherclient-2.2.0/watcherclient/common/__init__.py 0000666 0001750 0001750 00000000000 13364113436 024141 0 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/watcherclient/common/httpclient.py 0000666 0001750 0001750 00000063046 13364113436 024603 0 ustar zuul zuul 0000000 0000000 # Copyright 2012 OpenStack LLC.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import copy
from distutils import version
import functools
import hashlib
import logging
import os
import socket
import ssl
import textwrap
import time
from keystoneauth1 import adapter
from keystoneauth1 import exceptions as kexceptions
from oslo_serialization import jsonutils
from oslo_utils import strutils
import requests
import six
from six.moves import http_client
import six.moves.urllib.parse as urlparse
from watcherclient._i18n import _
from watcherclient import exceptions
# NOTE(deva): Record the latest version that this client was tested with.
# We still have a lot of work to do in the client to implement
# microversion support in the client properly! See
# http://specs.openstack.org/openstack/watcher-specs/specs/kilo/api-microversions.html # noqa
# for full details.
DEFAULT_VER = '1.0'
LOG = logging.getLogger(__name__)
USER_AGENT = 'python-watcherclient'
CHUNKSIZE = 1024 * 64 # 64kB
API_VERSION = '/v1'
API_VERSION_SELECTED_STATES = ('user', 'negotiated', 'cached', 'default')
DEFAULT_MAX_RETRIES = 5
DEFAULT_RETRY_INTERVAL = 2
SENSITIVE_HEADERS = ('X-Auth-Token',)
SUPPORTED_ENDPOINT_SCHEME = ('http', 'https')
def _trim_endpoint_api_version(url):
"""Trim API version and trailing slash from endpoint."""
return url.rstrip('/').rstrip(API_VERSION)
def _extract_error_json(body):
"""Return error_message from the HTTP response body."""
error_json = {}
try:
body_json = jsonutils.loads(body)
if 'error_message' in body_json:
raw_msg = body_json['error_message']
error_json = jsonutils.loads(raw_msg)
except ValueError:
pass
return error_json
def get_server(endpoint):
"""Extract and return the server & port that we're connecting to."""
if endpoint is None:
return None, None
parts = urlparse.urlparse(endpoint)
return parts.hostname, str(parts.port)
class VersionNegotiationMixin(object):
def negotiate_version(self, conn, resp):
"""Negotiate the server version
Assumption: Called after receiving a 406 error when doing a request.
param conn: A connection object
param resp: The response object from http request
"""
if self.api_version_select_state not in API_VERSION_SELECTED_STATES:
raise RuntimeError(
_('Error: self.api_version_select_state should be one of the '
'values in: "%(valid)s" but had the value: "%(value)s"') %
{'valid': ', '.join(API_VERSION_SELECTED_STATES),
'value': self.api_version_select_state})
min_ver, max_ver = self._parse_version_headers(resp)
# NOTE: servers before commit 32fb6e99 did not return version headers
# on error, so we need to perform a GET to determine
# the supported version range
if not max_ver:
LOG.debug('No version header in response, requesting from server')
if self.os_watcher_api_version:
base_version = ("/v%s" %
str(self.os_watcher_api_version).split('.')[0])
else:
base_version = API_VERSION
resp = self._make_simple_request(conn, 'GET', base_version)
min_ver, max_ver = self._parse_version_headers(resp)
# If the user requested an explicit version or we have negotiated a
# version and still failing then error now. The server could
# support the version requested but the requested operation may not
# be supported by the requested version.
if self.api_version_select_state == 'user':
raise exceptions.UnsupportedVersion(textwrap.fill(
_("Requested API version %(req)s is not supported by the "
"server or the requested operation is not supported by the "
"requested version. Supported version range is %(min)s to "
"%(max)s")
% {'req': self.os_watcher_api_version,
'min': min_ver, 'max': max_ver}))
if self.api_version_select_state == 'negotiated':
raise exceptions.UnsupportedVersion(textwrap.fill(
_("No API version was specified and the requested operation "
"was not supported by the client's negotiated API version "
"%(req)s. Supported version range is: %(min)s to %(max)s")
% {'req': self.os_watcher_api_version,
'min': min_ver, 'max': max_ver}))
negotiated_ver = str(
min(version.StrictVersion(self.os_watcher_api_version),
version.StrictVersion(max_ver)))
if negotiated_ver < min_ver:
negotiated_ver = min_ver
# server handles microversions, but doesn't support
# the requested version, so try a negotiated version
self.api_version_select_state = 'negotiated'
self.os_watcher_api_version = negotiated_ver
LOG.debug('Negotiated API version is %s', negotiated_ver)
return negotiated_ver
def _generic_parse_version_headers(self, accessor_func):
min_ver = accessor_func('X-OpenStack-Watcher-API-Minimum-Version',
None)
max_ver = accessor_func('X-OpenStack-Watcher-API-Maximum-Version',
None)
return min_ver, max_ver
def _parse_version_headers(self, accessor_func):
# NOTE(jlvillal): Declared for unit testing purposes
raise NotImplementedError()
def _make_simple_request(self, conn, method, url):
# NOTE(jlvillal): Declared for unit testing purposes
raise NotImplementedError()
_RETRY_EXCEPTIONS = (exceptions.ServiceUnavailable,
exceptions.ConnectionRefused,
kexceptions.RetriableConnectionFailure)
def with_retries(func):
"""Wrapper for _http_request adding support for retries."""
@functools.wraps(func)
def wrapper(self, url, method, **kwargs):
if self.conflict_max_retries is None:
self.conflict_max_retries = DEFAULT_MAX_RETRIES
if self.conflict_retry_interval is None:
self.conflict_retry_interval = DEFAULT_RETRY_INTERVAL
num_attempts = self.conflict_max_retries + 1
for attempt in range(1, num_attempts + 1):
try:
return func(self, url, method, **kwargs)
except _RETRY_EXCEPTIONS as error:
msg = ("Error contacting Watcher server: %(error)s. "
"Attempt %(attempt)d of %(total)d" %
{'attempt': attempt,
'total': num_attempts,
'error': error})
if attempt == num_attempts:
LOG.error(msg)
raise
else:
LOG.debug(msg)
time.sleep(self.conflict_retry_interval)
return wrapper
class HTTPClient(VersionNegotiationMixin):
def __init__(self, endpoint, **kwargs):
self.endpoint = endpoint
self.endpoint_trimmed = _trim_endpoint_api_version(endpoint)
self.auth_token = kwargs.get('token')
self.auth_ref = kwargs.get('auth_ref')
self.os_watcher_api_version = kwargs.get('os_watcher_api_version',
DEFAULT_VER)
self.api_version_select_state = kwargs.get(
'api_version_select_state', 'default')
self.conflict_max_retries = kwargs.pop('max_retries',
DEFAULT_MAX_RETRIES)
self.conflict_retry_interval = kwargs.pop('retry_interval',
DEFAULT_RETRY_INTERVAL)
self.session = requests.Session()
parts = urlparse.urlparse(endpoint)
if parts.scheme not in SUPPORTED_ENDPOINT_SCHEME:
msg = _('Unsupported scheme: %s') % parts.scheme
raise exceptions.EndpointException(msg)
if parts.scheme == 'https':
if kwargs.get('insecure') is True:
self.session.verify = False
elif kwargs.get('ca_file'):
self.session.verify = kwargs['ca_file']
self.session.cert = (kwargs.get('cert_file'),
kwargs.get('key_file'))
def _process_header(self, name, value):
"""Redacts any sensitive header
Redact a header that contains sensitive information, by returning an
updated header with the sha1 hash of that value. The redacted value is
prefixed by '{SHA1}' because that's the convention used within
OpenStack.
:returns: A tuple of (name, value)
name: the safe encoding format of name
value: the redacted value if name is x-auth-token,
or the safe encoding format of name
"""
if name in SENSITIVE_HEADERS:
v = value.encode('utf-8')
h = hashlib.sha1(v)
d = h.hexdigest()
return (name, "{SHA1}%s" % d)
else:
return (name, value)
def log_curl_request(self, method, url, kwargs):
curl = ['curl -i -X %s' % method]
for (key, value) in kwargs['headers'].items():
header = '-H \'%s: %s\'' % self._process_header(key, value)
curl.append(header)
if not self.session.verify:
curl.append('-k')
elif isinstance(self.session.verify, six.string_types):
curl.append('--cacert %s' % self.session.verify)
if self.session.cert:
curl.append('--cert %s' % self.session.cert[0])
curl.append('--key %s' % self.session.cert[1])
if 'body' in kwargs:
body = strutils.mask_password(kwargs['body'])
curl.append('-d \'%s\'' % body)
curl.append(urlparse.urljoin(self.endpoint_trimmed, url))
LOG.debug(' '.join(curl))
@staticmethod
def log_http_response(resp, body=None):
# NOTE(aarefiev): resp.raw is urllib3 response object, it's used
# only to get 'version', response from request with 'stream = True'
# should be used for raw reading.
status = (resp.raw.version / 10.0, resp.status_code, resp.reason)
dump = ['\nHTTP/%.1f %s %s' % status]
dump.extend(['%s: %s' % (k, v) for k, v in resp.headers.items()])
dump.append('')
if body:
body = strutils.mask_password(body)
dump.extend([body, ''])
LOG.debug('\n'.join(dump))
def _make_connection_url(self, url):
return urlparse.urljoin(self.endpoint_trimmed, url)
def _parse_version_headers(self, resp):
return self._generic_parse_version_headers(resp.headers.get)
def _make_simple_request(self, conn, method, url):
return conn.request(method, self._make_connection_url(url))
@with_retries
def _http_request(self, url, method, **kwargs):
"""Send an http request with the specified characteristics.
Wrapper around request.Session.request to handle tasks such
as setting headers and error handling.
"""
# Copy the kwargs so we can reuse the original in case of redirects
kwargs['headers'] = copy.deepcopy(kwargs.get('headers', {}))
kwargs['headers'].setdefault('User-Agent', USER_AGENT)
if self.os_watcher_api_version:
kwargs['headers'].setdefault('X-OpenStack-Watcher-API-Version',
self.os_watcher_api_version)
if self.auth_token:
kwargs['headers'].setdefault('X-Auth-Token', self.auth_token)
self.log_curl_request(method, url, kwargs)
# NOTE(aarefiev): This is for backwards compatibility, request
# expected body in 'data' field, previously we used httplib,
# which expected 'body' field.
body = kwargs.pop('body', None)
if body:
kwargs['data'] = body
conn_url = self._make_connection_url(url)
try:
resp = self.session.request(method,
conn_url,
**kwargs)
# TODO(deva): implement graceful client downgrade when connecting
# to servers that did not support microversions. Details here:
# http://specs.openstack.org/openstack/watcher-specs/specs/kilo/api-microversions.html#use-case-3b-new-client-communicating-with-a-old-watcher-user-specified # noqa
if resp.status_code == http_client.NOT_ACCEPTABLE:
negotiated_ver = self.negotiate_version(self.session, resp)
kwargs['headers']['X-OpenStack-Watcher-API-Version'] = (
negotiated_ver)
return self._http_request(url, method, **kwargs)
except requests.exceptions.RequestException as e:
message = (_("Error has occurred while handling "
"request for %(url)s: %(e)s") %
dict(url=conn_url, e=e))
# NOTE(aarefiev): not valid request(invalid url, missing schema,
# and so on), retrying is not needed.
if isinstance(e, ValueError):
raise exceptions.ValidationError(message)
raise exceptions.ConnectionRefused(message)
body_iter = resp.iter_content(chunk_size=CHUNKSIZE)
# Read body into string if it isn't obviously image data
body_str = None
if resp.headers.get('Content-Type') != 'application/octet-stream':
# decoding byte to string is necessary for Python 3 compatibility
# this issues has not been found with Python 3 unit tests
# because the test creates a fake http response of type str
# the if statement satisfies test (str) and real (bytes) behavior
body_list = [
chunk.decode("utf-8") if isinstance(chunk, bytes)
else chunk for chunk in body_iter
]
body_str = ''.join(body_list)
self.log_http_response(resp, body_str)
body_iter = six.StringIO(body_str)
else:
self.log_http_response(resp)
if resp.status_code >= http_client.BAD_REQUEST:
error_json = _extract_error_json(body_str)
raise exceptions.from_response(
resp, error_json.get('faultstring'),
error_json.get('debuginfo'), method, url)
elif resp.status_code in (http_client.MOVED_PERMANENTLY,
http_client.FOUND,
http_client.USE_PROXY):
# Redirected. Reissue the request to the new location.
return self._http_request(resp['location'], method, **kwargs)
elif resp.status_code == http_client.MULTIPLE_CHOICES:
raise exceptions.from_response(resp, method=method, url=url)
return resp, body_iter
def json_request(self, method, url, **kwargs):
kwargs.setdefault('headers', {})
kwargs['headers'].setdefault('Content-Type', 'application/json')
kwargs['headers'].setdefault('Accept', 'application/json')
if 'body' in kwargs:
kwargs['body'] = jsonutils.dumps(kwargs['body'])
resp, body_iter = self._http_request(url, method, **kwargs)
content_type = resp.headers.get('Content-Type')
if (resp.status_code in (http_client.NO_CONTENT,
http_client.RESET_CONTENT)
or content_type is None):
return resp, list()
if 'application/json' in content_type:
body = ''.join([chunk for chunk in body_iter])
try:
body = jsonutils.loads(body)
except ValueError:
LOG.error('Could not decode response body as JSON')
else:
body = None
return resp, body
def raw_request(self, method, url, **kwargs):
kwargs.setdefault('headers', {})
kwargs['headers'].setdefault('Content-Type',
'application/octet-stream')
return self._http_request(url, method, **kwargs)
class VerifiedHTTPSConnection(six.moves.http_client.HTTPSConnection):
"""httplib-compatible connection using client-side SSL authentication
:see http://code.activestate.com/recipes/
577548-https-httplib-client-connection-with-certificate-v/
"""
def __init__(self, host, port, key_file=None, cert_file=None,
ca_file=None, timeout=None, insecure=False):
six.moves.http_client.HTTPSConnection.__init__(self, host, port,
key_file=key_file,
cert_file=cert_file)
self.key_file = key_file
self.cert_file = cert_file
if ca_file is not None:
self.ca_file = ca_file
else:
self.ca_file = self.get_system_ca_file()
self.timeout = timeout
self.insecure = insecure
def connect(self):
"""Connect to a host on a given (SSL) port.
If ca_file is pointing somewhere, use it to check Server Certificate.
Redefined/copied and extended from httplib.py:1105 (Python 2.6.x).
This is needed to pass cert_reqs=ssl.CERT_REQUIRED as parameter to
ssl.wrap_socket(), which forces SSL to check server certificate against
our client certificate.
"""
sock = socket.create_connection((self.host, self.port), self.timeout)
if self._tunnel_host:
self.sock = sock
self._tunnel()
if self.insecure is True:
kwargs = {'cert_reqs': ssl.CERT_NONE}
else:
kwargs = {'cert_reqs': ssl.CERT_REQUIRED, 'ca_certs': self.ca_file}
if self.cert_file:
kwargs['certfile'] = self.cert_file
if self.key_file:
kwargs['keyfile'] = self.key_file
self.sock = ssl.wrap_socket(sock, **kwargs)
@staticmethod
def get_system_ca_file():
"""Return path to system default CA file."""
# Standard CA file locations for Debian/Ubuntu, RedHat/Fedora,
# Suse, FreeBSD/OpenBSD
ca_path = ['/etc/ssl/certs/ca-certificates.crt',
'/etc/pki/tls/certs/ca-bundle.crt',
'/etc/ssl/ca-bundle.pem',
'/etc/ssl/cert.pem']
for ca in ca_path:
if os.path.exists(ca):
return ca
return None
class SessionClient(VersionNegotiationMixin, adapter.LegacyJsonAdapter):
"""HTTP client based on Keystone client session."""
def __init__(self,
os_watcher_api_version,
api_version_select_state,
max_retries,
retry_interval,
endpoint,
**kwargs):
self.os_watcher_api_version = os_watcher_api_version
self.api_version_select_state = api_version_select_state
self.conflict_max_retries = max_retries
self.conflict_retry_interval = retry_interval
self.endpoint = endpoint
super(SessionClient, self).__init__(**kwargs)
def _parse_version_headers(self, resp):
return self._generic_parse_version_headers(resp.headers.get)
def _make_simple_request(self, conn, method, url):
# NOTE: conn is self.session for this class
return conn.request(url, method, raise_exc=False)
@with_retries
def _http_request(self, url, method, **kwargs):
kwargs.setdefault('user_agent', USER_AGENT)
kwargs.setdefault('auth', self.auth)
if isinstance(self.endpoint_override, six.string_types):
kwargs.setdefault(
'endpoint_override',
_trim_endpoint_api_version(self.endpoint_override)
)
if getattr(self, 'os_watcher_api_version', None):
kwargs['headers'].setdefault('X-OpenStack-Watcher-API-Version',
self.os_watcher_api_version)
endpoint_filter = kwargs.setdefault('endpoint_filter', {})
endpoint_filter.setdefault('interface', self.interface)
endpoint_filter.setdefault('service_type', self.service_type)
endpoint_filter.setdefault('region_name', self.region_name)
resp = self.session.request(url, method,
raise_exc=False, **kwargs)
if resp.status_code == http_client.NOT_ACCEPTABLE:
negotiated_ver = self.negotiate_version(self.session, resp)
kwargs['headers']['X-OpenStack-Watcher-API-Version'] = (
negotiated_ver)
return self._http_request(url, method, **kwargs)
if resp.status_code >= http_client.BAD_REQUEST:
error_json = _extract_error_json(resp.content)
raise exceptions.from_response(
resp, error_json.get('faultstring'),
error_json.get('debuginfo'), method, url)
elif resp.status_code in (http_client.MOVED_PERMANENTLY,
http_client.FOUND, http_client.USE_PROXY):
# Redirected. Reissue the request to the new location.
location = resp.headers.get('location')
resp = self._http_request(location, method, **kwargs)
elif resp.status_code == http_client.MULTIPLE_CHOICES:
raise exceptions.from_response(resp, method=method, url=url)
return resp
def json_request(self, method, url, **kwargs):
kwargs.setdefault('headers', {})
kwargs['headers'].setdefault('Content-Type', 'application/json')
kwargs['headers'].setdefault('Accept', 'application/json')
if 'body' in kwargs:
kwargs['data'] = jsonutils.dumps(kwargs.pop('body'))
resp = self._http_request(url, method, **kwargs)
body = resp.content
content_type = resp.headers.get('content-type', None)
status = resp.status_code
if (status in (http_client.NO_CONTENT, http_client.RESET_CONTENT) or
content_type is None):
return resp, list()
if 'application/json' in content_type:
try:
body = resp.json()
except ValueError:
LOG.error('Could not decode response body as JSON')
else:
body = None
return resp, body
def raw_request(self, method, url, **kwargs):
kwargs.setdefault('headers', {})
kwargs['headers'].setdefault('Content-Type',
'application/octet-stream')
return self._http_request(url, method, **kwargs)
def _construct_http_client(endpoint=None,
session=None,
token=None,
auth_ref=None,
os_watcher_api_version=DEFAULT_VER,
api_version_select_state='default',
max_retries=DEFAULT_MAX_RETRIES,
retry_interval=DEFAULT_RETRY_INTERVAL,
timeout=600,
ca_file=None,
cert_file=None,
key_file=None,
insecure=None,
**kwargs):
if session:
kwargs.setdefault('service_type', 'infra-optim')
kwargs.setdefault('user_agent', 'python-watcherclient')
kwargs.setdefault('interface', kwargs.pop('endpoint_type', None))
kwargs.setdefault('endpoint_override', endpoint)
ignored = {'token': token,
'auth_ref': auth_ref,
'timeout': timeout != 600,
'ca_file': ca_file,
'cert_file': cert_file,
'key_file': key_file,
'insecure': insecure}
dvars = [k for k, v in ignored.items() if v]
if dvars:
LOG.warning('The following arguments are ignored when using '
'the session to construct a client: %s',
', '.join(dvars))
return SessionClient(session=session,
os_watcher_api_version=os_watcher_api_version,
api_version_select_state=api_version_select_state,
max_retries=max_retries,
retry_interval=retry_interval,
endpoint=endpoint,
**kwargs)
else:
if kwargs:
LOG.warning('The following arguments are being ignored when '
'constructing the client: %s', ', '.join(kwargs))
return HTTPClient(endpoint=endpoint,
token=token,
auth_ref=auth_ref,
os_watcher_api_version=os_watcher_api_version,
api_version_select_state=api_version_select_state,
max_retries=max_retries,
retry_interval=retry_interval,
timeout=timeout,
ca_file=ca_file,
cert_file=cert_file,
key_file=key_file,
insecure=insecure)
python-watcherclient-2.2.0/watcherclient/common/command.py 0000666 0001750 0001750 00000002752 13364113436 024040 0 ustar zuul zuul 0000000 0000000 # Copyright 2016 NEC Corporation
#
# 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 logging
from cliff import command
from cliff import lister
from cliff import show
import six
class CommandMeta(abc.ABCMeta):
def __new__(mcs, name, bases, cls_dict):
if 'log' not in cls_dict:
cls_dict['log'] = logging.getLogger(
cls_dict['__module__'] + '.' + name)
return super(CommandMeta, mcs).__new__(mcs, name, bases, cls_dict)
@six.add_metaclass(CommandMeta)
class Command(command.Command):
def run(self, parsed_args):
self.log.debug('run(%s)', parsed_args)
return super(Command, self).run(parsed_args)
class Lister(Command, lister.Lister):
pass
class ShowOne(Command, show.ShowOne):
def get_parser(self, prog_name, formatter_class=None):
parser = super(ShowOne, self).get_parser(prog_name)
if formatter_class:
parser.formatter_class = formatter_class
return parser
python-watcherclient-2.2.0/watcherclient/common/api_versioning.py 0000666 0001750 0001750 00000017510 13364113436 025434 0 ustar zuul zuul 0000000 0000000 #
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import logging
import os
import pkgutil
import re
from oslo_utils import strutils
from watcherclient._i18n import _
from watcherclient import exceptions
LOG = logging.getLogger(__name__)
if not LOG.handlers:
LOG.addHandler(logging.StreamHandler())
HEADER_NAME = "OpenStack-API-Version"
SERVICE_TYPE = "infra-optim"
# key is a deprecated version and value is an alternative version.
DEPRECATED_VERSIONS = {}
_type_error_msg = _("'%(other)s' should be an instance of '%(cls)s'")
class APIVersion(object):
"""This class represents an API Version Request.
This class provides convenience methods for manipulation
and comparison of version numbers that we need to do to
implement microversions.
"""
def __init__(self, version_str=None):
"""Create an API version object.
:param version_str: String representation of APIVersionRequest.
Correct format is 'X.Y', where 'X' and 'Y'
are int values. None value should be used
to create Null APIVersionRequest, which is
equal to 0.0
"""
self.ver_major = 0
self.ver_minor = 0
if version_str is not None:
match = re.match(r"^([1-9]\d*)\.([1-9]\d*|0|latest)$", version_str)
if match:
self.ver_major = int(match.group(1))
if match.group(2) == "latest":
# NOTE(andreykurilin): Infinity allows to easily determine
# latest version and doesn't require any additional checks
# in comparison methods.
self.ver_minor = float("inf")
else:
self.ver_minor = int(match.group(2))
else:
msg = _("Invalid format of client version '%s'. "
"Expected format 'X.Y', where X is a major part and Y "
"is a minor part of version.") % version_str
raise exceptions.UnsupportedVersion(msg)
def __str__(self):
"""Debug/Logging representation of object."""
if self.is_latest():
return "Latest API Version Major: %s" % self.ver_major
return ("API Version Major: %s, Minor: %s"
% (self.ver_major, self.ver_minor))
def __repr__(self):
if self.is_null():
return ""
else:
return "" % self.get_string()
def is_null(self):
return self.ver_major == 0 and self.ver_minor == 0
def is_latest(self):
return self.ver_minor == float("inf")
def __lt__(self, other):
if not isinstance(other, APIVersion):
raise TypeError(_type_error_msg % {"other": other,
"cls": self.__class__})
return ((self.ver_major, self.ver_minor) <
(other.ver_major, other.ver_minor))
def __eq__(self, other):
if not isinstance(other, APIVersion):
raise TypeError(_type_error_msg % {"other": other,
"cls": self.__class__})
return ((self.ver_major, self.ver_minor) ==
(other.ver_major, other.ver_minor))
def __gt__(self, other):
if not isinstance(other, APIVersion):
raise TypeError(_type_error_msg % {"other": other,
"cls": self.__class__})
return ((self.ver_major, self.ver_minor) >
(other.ver_major, other.ver_minor))
def __le__(self, other):
return self < other or self == other
def __ne__(self, other):
return not self.__eq__(other)
def __ge__(self, other):
return self > other or self == other
def matches(self, min_version, max_version):
"""Matches the version object.
Returns whether the version object represents a version
greater than or equal to the minimum version and less than
or equal to the maximum version.
:param min_version: Minimum acceptable version.
:param max_version: Maximum acceptable version.
:returns: boolean
If min_version is null then there is no minimum limit.
If max_version is null then there is no maximum limit.
If self is null then raise ValueError
"""
if self.is_null():
raise ValueError(_("Null APIVersion doesn't support 'matches'."))
if max_version.is_null() and min_version.is_null():
return True
elif max_version.is_null():
return min_version <= self
elif min_version.is_null():
return self <= max_version
else:
return min_version <= self <= max_version
def get_string(self):
"""Version string representation.
Converts object to string representation which if used to create
an APIVersion object results in the same version.
"""
if self.is_null():
raise ValueError(
_("Null APIVersion cannot be converted to string."))
elif self.is_latest():
return "%s.%s" % (self.ver_major, "latest")
return "%s.%s" % (self.ver_major, self.ver_minor)
def get_available_major_versions():
# NOTE(andreykurilin): available clients version should not be
# hardcoded, so let's discover them.
matcher = re.compile(r"v[0-9]*$")
submodules = pkgutil.iter_modules(
[os.path.dirname(os.path.dirname(__file__))])
available_versions = [name[1:] for loader, name, ispkg in submodules
if matcher.search(name)]
return available_versions
def check_major_version(api_version):
"""Checks major part of ``APIVersion`` obj is supported.
:raises watcherclient.exceptions.UnsupportedVersion: if major part is not
supported
"""
available_versions = get_available_major_versions()
if (not api_version.is_null() and
str(api_version.ver_major) not in available_versions):
if len(available_versions) == 1:
msg = _("Invalid client version '%(version)s'. "
"Major part should be '%(major)s'") % {
"version": api_version.get_string(),
"major": available_versions[0]}
else:
msg = _("Invalid client version '%(version)s'. "
"Major part must be one of: '%(major)s'") % {
"version": api_version.get_string(),
"major": ", ".join(available_versions)}
raise exceptions.UnsupportedVersion(msg)
def get_api_version(version_string):
"""Returns checked APIVersion object"""
version_string = str(version_string)
if version_string in DEPRECATED_VERSIONS:
LOG.warning(
"Version %(deprecated_version)s is deprecated, using "
"alternative version %(alternative)s instead.",
{"deprecated_version": version_string,
"alternative": DEPRECATED_VERSIONS[version_string]})
version_string = DEPRECATED_VERSIONS[version_string]
if strutils.is_int_like(version_string):
version_string = "%s.0" % version_string
api_version = APIVersion(version_string)
check_major_version(api_version)
return api_version
python-watcherclient-2.2.0/watcherclient/__init__.py 0000666 0001750 0001750 00000001516 13364113436 022666 0 ustar zuul zuul 0000000 0000000 #
# Copyright 2013 Hewlett-Packard Development Company, L.P.
# 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 pbr.version
from watcherclient import client
from watcherclient import exceptions
__version__ = pbr.version.VersionInfo(
'python-watcherclient').version_string()
__all__ = ['client', 'exceptions', ]
python-watcherclient-2.2.0/watcherclient/osc/ 0000775 0001750 0001750 00000000000 13364113665 021340 5 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/watcherclient/osc/__init__.py 0000666 0001750 0001750 00000000000 13364113436 023435 0 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/watcherclient/osc/plugin.py 0000666 0001750 0001750 00000003476 13364113436 023220 0 ustar zuul zuul 0000000 0000000 # Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import logging
from osc_lib import utils
LOG = logging.getLogger(__name__)
DEFAULT_API_VERSION = '1'
API_VERSION_OPTION = 'os_infra_optim_api_version'
API_NAME = 'infra-optim'
API_VERSIONS = {
'1': 'watcherclient.v1.client.Client',
}
def make_client(instance):
"""Returns an infra-optim service client."""
infraoptim_client_class = utils.get_client_class(
API_NAME,
instance._api_version[API_NAME],
API_VERSIONS)
LOG.debug('Instantiating infraoptim client: %s', infraoptim_client_class)
client = infraoptim_client_class(
os_watcher_api_version=instance._api_version[API_NAME],
session=instance.session,
region_name=instance._region_name,
)
return client
def build_option_parser(parser):
"""Hook to add global options."""
parser.add_argument('--os-infra-optim-api-version',
metavar='',
default=utils.env(
'OS_INFRA_OPTIM_API_VERSION',
default=DEFAULT_API_VERSION),
help=('Watcher API version, default=' +
DEFAULT_API_VERSION +
' (Env: OS_INFRA_OPTIM_API_VERSION)'))
return parser
python-watcherclient-2.2.0/watcherclient/shell.py 0000666 0001750 0001750 00000021534 13364113436 022240 0 ustar zuul zuul 0000000 0000000 # Copyright (c) 2013 Rackspace, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Command-line interface to the Watcher API.
"""
from collections import namedtuple
import logging
import sys
from cliff import app
from cliff import command
from cliff import commandmanager
from cliff import complete
from cliff import help as cli_help
from keystoneauth1 import loading
from osc_lib import logs
from osc_lib import utils
from watcherclient import client as watcherclient
from watcherclient import version
LOG = logging.getLogger(__name__)
API_NAME = 'infra-optim'
API_VERSIONS = {
'1': 'watcherclient.v1.client.Client',
}
_DEFAULT_IDENTITY_API_VERSION = '3'
_IDENTITY_API_VERSION_2 = ['2', '2.0']
_IDENTITY_API_VERSION_3 = ['3']
class WatcherShell(app.App):
"""Watcher command line interface."""
def __init__(self, **kwargs):
self.client = None
# Patch command.Command to add a default auth_required = True
command.Command.auth_required = True
# Some commands do not need authentication
cli_help.HelpCommand.auth_required = False
complete.CompleteCommand.auth_required = False
super(WatcherShell, self).__init__(
description=__doc__.strip(),
version=version.__version__,
command_manager=commandmanager.CommandManager(
'watcherclient.v1'),
deferred_help=True,
**kwargs
)
def create_client(self, args):
client = watcherclient.get_client('1', **args.__dict__)
return client
def build_option_parser(self, description, version, argparse_kwargs=None):
"""Introduces global arguments for the application.
This is inherited from the framework.
"""
parser = super(WatcherShell, self).build_option_parser(
description, version, argparse_kwargs)
parser.add_argument('--no-auth', '-N', action='store_true',
help='Do not use authentication.')
parser.add_argument('--os-identity-api-version',
metavar='',
default=utils.env('OS_IDENTITY_API_VERSION'),
help='Specify Identity API version to use. '
'Defaults to env[OS_IDENTITY_API_VERSION]'
' or 3.')
parser.add_argument('--os-auth-url', '-A',
metavar='',
default=utils.env('OS_AUTH_URL'),
help='Defaults to env[OS_AUTH_URL].')
parser.add_argument('--os-region-name', '-R',
metavar='',
default=utils.env('OS_REGION_NAME'),
help='Defaults to env[OS_REGION_NAME].')
parser.add_argument('--os-username', '-U',
metavar='',
default=utils.env('OS_USERNAME'),
help='Defaults to env[OS_USERNAME].')
parser.add_argument('--os-user-id',
metavar='',
default=utils.env('OS_USER_ID'),
help='Defaults to env[OS_USER_ID].')
parser.add_argument('--os-password', '-P',
metavar='',
default=utils.env('OS_PASSWORD'),
help='Defaults to env[OS_PASSWORD].')
parser.add_argument('--os-user-domain-id',
metavar='',
default=utils.env('OS_USER_DOMAIN_ID'),
help='Defaults to env[OS_USER_DOMAIN_ID].')
parser.add_argument('--os-user-domain-name',
metavar='',
default=utils.env('OS_USER_DOMAIN_NAME'),
help='Defaults to env[OS_USER_DOMAIN_NAME].')
parser.add_argument('--os-tenant-name', '-T',
metavar='',
default=utils.env('OS_TENANT_NAME'),
help='Defaults to env[OS_TENANT_NAME].')
parser.add_argument('--os-tenant-id', '-I',
metavar='',
default=utils.env('OS_TENANT_ID'),
help='Defaults to env[OS_TENANT_ID].')
parser.add_argument('--os-project-id',
metavar='',
default=utils.env('OS_PROJECT_ID'),
help='Another way to specify tenant ID. '
'This option is mutually exclusive with '
' --os-tenant-id. '
'Defaults to env[OS_PROJECT_ID].')
parser.add_argument('--os-project-name',
metavar='',
default=utils.env('OS_PROJECT_NAME'),
help='Another way to specify tenant name. '
'This option is mutually exclusive with '
' --os-tenant-name. '
'Defaults to env[OS_PROJECT_NAME].')
parser.add_argument('--os-project-domain-id',
metavar='',
default=utils.env('OS_PROJECT_DOMAIN_ID'),
help='Defaults to env[OS_PROJECT_DOMAIN_ID].')
parser.add_argument('--os-project-domain-name',
metavar='',
default=utils.env('OS_PROJECT_DOMAIN_NAME'),
help='Defaults to env[OS_PROJECT_DOMAIN_NAME].')
parser.add_argument('--os-auth-token',
metavar='',
default=utils.env('OS_AUTH_TOKEN'),
help='Defaults to env[OS_AUTH_TOKEN].')
parser.add_argument('--os-watcher-api-version',
metavar='',
default=utils.env('OS_WATCHER_API_VERSION',
default='1'),
help='Defaults to env[OS_WATCHER_API_VERSION].')
parser.add_argument('--os-endpoint-type',
default=utils.env('OS_ENDPOINT_TYPE'),
help='Defaults to env[OS_ENDPOINT_TYPE] or '
'"publicURL"')
parser.add_argument('--os-endpoint-override',
metavar='',
default=utils.env('OS_ENDPOINT_OVERRIDE'),
help="Use this API endpoint instead of the "
"Service Catalog.")
parser.epilog = ('See "watcher help COMMAND" for help '
'on a specific command.')
loading.register_session_argparse_arguments(parser)
return parser
def configure_logging(self):
"""Configure logging for the app."""
self.log_configurator = logs.LogConfigurator(self.options)
self.dump_stack_trace = self.log_configurator.dump_trace
def prepare_to_run_command(self, cmd):
"""Prepares to run the command
Checks if the minimal parameters are provided and creates the
client interface.
This is inherited from the framework.
"""
self.client_manager = namedtuple('ClientManager', 'infra_optim')
if cmd.auth_required:
client = self.create_client(self.options)
setattr(self.client_manager, 'infra-optim', client)
def run(self, argv):
ret_val = 1
self.command_options = argv
try:
ret_val = super(WatcherShell, self).run(argv)
return ret_val
except Exception as e:
if not logging.getLogger('').handlers:
logging.basicConfig()
LOG.error('Exception raised: %s', str(e))
return ret_val
finally:
LOG.info("END return value: %s", ret_val)
def main(argv=sys.argv[1:]):
watcher_app = WatcherShell()
return watcher_app.run(argv)
if __name__ == '__main__': # pragma: no cover
sys.exit(main(sys.argv[1:]))
python-watcherclient-2.2.0/watcherclient/client.py 0000666 0001750 0001750 00000017403 13364113436 022407 0 ustar zuul zuul 0000000 0000000 # Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from keystoneauth1 import loading as kaloading
from oslo_utils import importutils
from watcherclient._i18n import _
from watcherclient.common import api_versioning
from watcherclient import exceptions
def get_client(api_version, os_auth_token=None, watcher_url=None,
os_username=None, os_password=None, os_auth_url=None,
os_project_id=None, os_project_name=None, os_tenant_id=None,
os_tenant_name=None, os_region_name=None,
os_user_domain_id=None, os_user_domain_name=None,
os_project_domain_id=None, os_project_domain_name=None,
os_service_type=None, os_endpoint_type=None,
insecure=None, timeout=None, os_cacert=None, ca_file=None,
os_cert=None, cert_file=None, os_key=None, key_file=None,
os_watcher_api_version=None, max_retries=None,
retry_interval=None, session=None, os_endpoint_override=None,
**ignored_kwargs):
"""Get an authenticated client, based on the credentials.
:param api_version: the API version to use. Valid value: '1'.
:param os_auth_token: pre-existing token to re-use
:param watcher_url: watcher API endpoint
:param os_username: name of a user
:param os_password: user's password
:param os_auth_url: endpoint to authenticate against
:param os_project_id: ID of a project
:param os_project_name: name of a project
:param os_tenant_id: ID of a tenant (deprecated in favour of
os_project_id)
:param os_tenant_name: name of a tenant (deprecated in favour of
os_project_name)
:param os_region_name: name of a keystone region
:param os_user_domain_id: ID of a domain the user belongs to
:param os_user_domain_name: name of a domain the user belongs to
:param os_project_domain_id: ID of a domain the project belongs to
:param os_project_domain_name: name of a domain the project belongs to
:param os_service_type: the type of service to lookup the endpoint for
:param os_endpoint_type: the type (exposure) of the endpoint
:param insecure: allow insecure SSL (no cert verification)
:param timeout: allows customization of the timeout for client HTTP
requests
:param os_cacert: path to cacert file
:param ca_file: path to cacert file, deprecated in favour of os_cacert
:param os_cert: path to cert file
:param cert_file: path to cert file, deprecated in favour of os_cert
:param os_key: path to key file
:param key_file: path to key file, deprecated in favour of os_key
:param os_watcher_api_version: watcher API version to use
:param max_retries: Maximum number of retries in case of conflict error
:param retry_interval: Amount of time (in seconds) between retries in case
of conflict error
:param session: Keystone session to use
:param os_endpoint_override: watcher API endpoint
:param ignored_kwargs: all the other params that are passed. Left for
backwards compatibility. They are ignored.
"""
os_service_type = os_service_type or 'infra-optim'
os_endpoint_type = os_endpoint_type or 'publicURL'
project_id = (os_project_id or os_tenant_id)
project_name = (os_project_name or os_tenant_name)
kwargs = {
'os_watcher_api_version': os_watcher_api_version,
'max_retries': max_retries,
'retry_interval': retry_interval,
}
endpoint = watcher_url or os_endpoint_override
cacert = os_cacert or ca_file
cert = os_cert or cert_file
key = os_key or key_file
if os_auth_token and endpoint:
kwargs.update({
'token': os_auth_token,
'insecure': insecure,
'ca_file': cacert,
'cert_file': cert,
'key_file': key,
'timeout': timeout,
})
elif os_auth_url:
auth_type = 'password'
auth_kwargs = {
'auth_url': os_auth_url,
'project_id': project_id,
'project_name': project_name,
'user_domain_id': os_user_domain_id,
'user_domain_name': os_user_domain_name,
'project_domain_id': os_project_domain_id,
'project_domain_name': os_project_domain_name,
}
if os_username and os_password:
auth_kwargs.update({
'username': os_username,
'password': os_password,
})
elif os_auth_token:
auth_type = 'token'
auth_kwargs.update({
'token': os_auth_token,
})
# Create new session only if it was not passed in
if not session:
loader = kaloading.get_plugin_loader(auth_type)
auth_plugin = loader.load_from_options(**auth_kwargs)
# Let keystoneauth do the necessary parameter conversions
session = kaloading.session.Session().load_from_options(
auth=auth_plugin, insecure=insecure, cacert=cacert,
cert=cert, key=key, timeout=timeout,
)
exception_msg = _('Must provide Keystone credentials or user-defined '
'endpoint and token')
if not endpoint:
if session:
try:
# Pass the endpoint, it will be used to get hostname
# and port that will be used for API version caching. It will
# be also set as endpoint_override.
endpoint = session.get_endpoint(
service_type=os_service_type,
interface=os_endpoint_type,
region_name=os_region_name
)
except Exception as e:
raise exceptions.AmbiguousAuthSystem(
exception_msg + _(', error was: %s') % e)
else:
# Neither session, nor valid auth parameters provided
raise exceptions.AmbiguousAuthSystem(exception_msg)
# Always pass the session
kwargs['session'] = session
return Client(api_version, endpoint, **kwargs)
def _get_client_class_and_version(version):
if not isinstance(version, api_versioning.APIVersion):
version = api_versioning.get_api_version(version)
else:
api_versioning.check_major_version(version)
if version.is_latest():
raise exceptions.UnsupportedVersion(
_("The version should be explicit, not latest."))
return version, importutils.import_class(
"watcherclient.v%s.client.Client" % version.ver_major)
def Client(version, *args, **kwargs):
"""Initialize client object based on given version.
HOW-TO:
The simplest way to create a client instance is initialization with your
credentials::
>>> from watcherclient import client
>>> watcher = client.Client(VERSION, USERNAME, PASSWORD,
... PROJECT_ID, AUTH_URL)
Here ``VERSION`` can be a string or
``watcherclient.api_versions.APIVersion`` obj. If you prefer string value,
you can use ``1`` or ``1.X`` (where X is a microversion).
Alternatively, you can create a client instance using the keystoneauth
session API. See "The watcherclient Python API" page at
python-watcherclient's doc.
"""
api_version, client_class = _get_client_class_and_version(version)
return client_class(*args, **kwargs)
python-watcherclient-2.2.0/watcherclient/exceptions.py 0000666 0001750 0001750 00000010033 13364113436 023302 0 ustar zuul zuul 0000000 0000000 #
# 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 watcherclient.common.apiclient import exceptions
# NOTE(akurilin): This alias is left here since v.0.1.3 to support backwards
# compatibility.
InvalidEndpoint = exceptions.EndpointException
CommunicationError = exceptions.ConnectionRefused
HTTPBadRequest = exceptions.BadRequest
HTTPInternalServerError = exceptions.InternalServerError
HTTPNotFound = exceptions.NotFound
HTTPServiceUnavailable = exceptions.ServiceUnavailable
CommandError = exceptions.CommandError
"""Error in CLI tool.
An alias of :py:exc:`watcherclient.common.apiclient.CommandError`
"""
Unauthorized = exceptions.Unauthorized
"""HTTP 401 - Unauthorized.
Similar to 403 Forbidden, but specifically for use when authentication
is required and has failed or has not yet been provided.
An alias of :py:exc:`watcherclient.common.apiclient.Unauthorized`
"""
InternalServerError = exceptions.InternalServerError
"""HTTP 500 - Internal Server Error.
A generic error message, given when no more specific message is suitable.
An alias of :py:exc:`watcherclient.common.apiclient.InternalServerError`
"""
ValidationError = exceptions.ValidationError
"""Error in validation on API client side.
A generic error message, given when no more specific message is suitable.
An alias of :py:exc:`watcherclient.common.apiclient.ValidationError`
"""
Conflict = exceptions.Conflict
ConnectionRefused = exceptions.ConnectionRefused
EndpointException = exceptions.EndpointException
EndpointNotFound = exceptions.EndpointNotFound
ServiceUnavailable = exceptions.ServiceUnavailable
class UnsupportedVersion(Exception):
"""Unsupported API Version
Indicates that the user is trying to use an unsupported version of the API.
"""
pass
class AmbiguousAuthSystem(exceptions.ClientException):
"""Could not obtain token and endpoint using provided credentials."""
pass
# Alias for backwards compatibility
AmbigiousAuthSystem = AmbiguousAuthSystem
class InvalidAttribute(exceptions.ClientException):
pass
def from_response(response, message=None, traceback=None, method=None,
url=None):
"""Return an HttpError instance based on response from httplib/requests."""
error_body = {}
if message:
error_body['message'] = message
if traceback:
error_body['details'] = traceback
if hasattr(response, 'status') and not hasattr(response, 'status_code'):
# NOTE(akurilin): These modifications around response object give
# ability to get all necessary information in method `from_response`
# from common code, which expecting response object from `requests`
# library instead of object from `httplib/httplib2` library.
response.status_code = response.status
response.headers = {
'Content-Type': response.getheader('content-type', "")}
if hasattr(response, 'status_code'):
# NOTE(hongbin): This allows SessionClient to handle faultstring.
response.json = lambda: {'error': error_body}
if (response.headers.get('Content-Type', '').startswith('text/') and
not hasattr(response, 'text')):
# NOTE(clif_h): There seems to be a case in the
# common.apiclient.exceptions module where if the
# content-type of the response is text/* then it expects
# the response to have a 'text' attribute, but that
# doesn't always seem to necessarily be the case.
# This is to work around that problem.
response.text = ''
return exceptions.from_response(response, method, url)
python-watcherclient-2.2.0/watcherclient/plugin.py 0000666 0001750 0001750 00000002313 13364113436 022421 0 ustar zuul zuul 0000000 0000000 # 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 tempest.test_discover import plugins
from watcherclient import config as watcher_config
class WatcherClientTempestPlugin(plugins.TempestPlugin):
def load_tests(self):
base_path = os.path.split(os.path.dirname(
os.path.abspath(__file__)))[0]
test_dir = "watcherclient/tests/functional/v1"
full_test_dir = os.path.join(base_path, test_dir)
return full_test_dir, base_path
def register_opts(self, conf):
conf.register_opt(watcher_config.service_option,
group='service_available')
def get_opt_lists(self):
return [('service_available', [watcher_config.service_option])]
python-watcherclient-2.2.0/setup.cfg 0000666 0001750 0001750 00000012366 13364113665 017553 0 ustar zuul zuul 0000000 0000000 [metadata]
name = python-watcherclient
summary = Python client library for Watcher API
description-file =
README.rst
author = OpenStack
author-email = openstack-dev@lists.openstack.org
home-page = https://docs.openstack.org/python-watcherclient/latest/
classifier =
Environment :: OpenStack
Intended Audience :: Information Technology
Intended Audience :: System Administrators
License :: OSI Approved :: Apache Software License
Operating System :: POSIX :: Linux
Programming Language :: Python
Programming Language :: Python :: 2
Programming Language :: Python :: 2.7
Programming Language :: Python :: 3
Programming Language :: Python :: 3.5
[files]
packages =
watcherclient
[entry_points]
console_scripts =
watcher = watcherclient.shell:main
tempest.test_plugins =
watcherclient_tests = watcherclient.plugin:WatcherClientTempestPlugin
openstack.cli.extension =
infra_optim = watcherclient.osc.plugin
openstack.infra_optim.v1 =
optimize_goal_show = watcherclient.v1.goal_shell:ShowGoal
optimize_goal_list = watcherclient.v1.goal_shell:ListGoal
optimize_strategy_show = watcherclient.v1.strategy_shell:ShowStrategy
optimize_strategy_list = watcherclient.v1.strategy_shell:ListStrategy
optimize_strategy_state = watcherclient.v1.strategy_shell:StateStrategy
optimize_audittemplate_show = watcherclient.v1.audit_template_shell:ShowAuditTemplate
optimize_audittemplate_list = watcherclient.v1.audit_template_shell:ListAuditTemplate
optimize_audittemplate_create = watcherclient.v1.audit_template_shell:CreateAuditTemplate
optimize_audittemplate_update = watcherclient.v1.audit_template_shell:UpdateAuditTemplate
optimize_audittemplate_delete = watcherclient.v1.audit_template_shell:DeleteAuditTemplate
optimize_audit_show = watcherclient.v1.audit_shell:ShowAudit
optimize_audit_list = watcherclient.v1.audit_shell:ListAudit
optimize_audit_create = watcherclient.v1.audit_shell:CreateAudit
optimize_audit_update = watcherclient.v1.audit_shell:UpdateAudit
optimize_audit_delete = watcherclient.v1.audit_shell:DeleteAudit
optimize_actionplan_show = watcherclient.v1.action_plan_shell:ShowActionPlan
optimize_actionplan_list = watcherclient.v1.action_plan_shell:ListActionPlan
optimize_actionplan_update = watcherclient.v1.action_plan_shell:UpdateActionPlan
optimize_actionplan_start = watcherclient.v1.action_plan_shell:StartActionPlan
optimize_actionplan_cancel = watcherclient.v1.action_plan_shell:CancelActionPlan
optimize_action_show = watcherclient.v1.action_shell:ShowAction
optimize_action_list = watcherclient.v1.action_shell:ListAction
optimize_scoringengine_show = watcherclient.v1.scoring_engine_shell:ShowScoringEngine
optimize_scoringengine_list = watcherclient.v1.scoring_engine_shell:ListScoringEngine
optimize_service_show = watcherclient.v1.service_shell:ShowService
optimize_service_list = watcherclient.v1.service_shell:ListService
watcherclient.v1 =
goal_show = watcherclient.v1.goal_shell:ShowGoal
goal_list = watcherclient.v1.goal_shell:ListGoal
strategy_show = watcherclient.v1.strategy_shell:ShowStrategy
strategy_list = watcherclient.v1.strategy_shell:ListStrategy
strategy_state = watcherclient.v1.strategy_shell:StateStrategy
audittemplate_show = watcherclient.v1.audit_template_shell:ShowAuditTemplate
audittemplate_list = watcherclient.v1.audit_template_shell:ListAuditTemplate
audittemplate_create = watcherclient.v1.audit_template_shell:CreateAuditTemplate
audittemplate_update = watcherclient.v1.audit_template_shell:UpdateAuditTemplate
audittemplate_delete = watcherclient.v1.audit_template_shell:DeleteAuditTemplate
audit_show = watcherclient.v1.audit_shell:ShowAudit
audit_list = watcherclient.v1.audit_shell:ListAudit
audit_create = watcherclient.v1.audit_shell:CreateAudit
audit_update = watcherclient.v1.audit_shell:UpdateAudit
audit_delete = watcherclient.v1.audit_shell:DeleteAudit
actionplan_show = watcherclient.v1.action_plan_shell:ShowActionPlan
actionplan_list = watcherclient.v1.action_plan_shell:ListActionPlan
actionplan_update = watcherclient.v1.action_plan_shell:UpdateActionPlan
actionplan_start = watcherclient.v1.action_plan_shell:StartActionPlan
actionplan_delete = watcherclient.v1.action_plan_shell:DeleteActionPlan
actionplan_cancel = watcherclient.v1.action_plan_shell:CancelActionPlan
action_show = watcherclient.v1.action_shell:ShowAction
action_list = watcherclient.v1.action_shell:ListAction
scoringengine_show = watcherclient.v1.scoring_engine_shell:ShowScoringEngine
scoringengine_list = watcherclient.v1.scoring_engine_shell:ListScoringEngine
service_show = watcherclient.v1.service_shell:ShowService
service_list = watcherclient.v1.service_shell:ListService
[pbr]
autodoc_index_modules = True
autodoc_exclude_modules =
watcherclient.tests.*
api_doc_dir = reference/api
[build_sphinx]
source-dir = doc/source
build-dir = doc/build
all_files = 1
warning-is-error = 1
[bdist_wheel]
universal = 1
[compile_catalog]
directory = watcherclient/locale
domain = watcherclient
[update_catalog]
domain = watcherclient
output_dir = watcherclient/locale
input_file = watcherclient/locale/watcherclient.pot
[extract_messages]
keywords = _ gettext ngettext l_ lazy_gettext _LI _LW _LE _LC
mapping_file = babel.cfg
output_file = watcherclient/locale/watcherclient.pot
[egg_info]
tag_build =
tag_date = 0
python-watcherclient-2.2.0/LICENSE 0000666 0001750 0001750 00000023637 13364113436 016736 0 ustar zuul zuul 0000000 0000000
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
python-watcherclient-2.2.0/test-requirements.txt 0000666 0001750 0001750 00000001126 13364113436 022157 0 ustar zuul zuul 0000000 0000000 # 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.
coverage!=4.4,>=4.0 # Apache-2.0
fixtures>=3.0.0 # Apache-2.0/BSD
hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0
mock>=2.0.0 # BSD
openstackdocstheme>=1.18.1 # Apache-2.0
oslotest>=3.2.0 # Apache-2.0
python-subunit>=1.0.0 # Apache-2.0/BSD
sphinx!=1.6.6,!=1.6.7,>=1.6.5 # BSD
stestr>=2.0.0 # Apache-2.0
testscenarios>=0.4 # Apache-2.0/BSD
testtools>=2.2.0 # MIT
tempest>=17.1.0 # Apache-2.0
python-watcherclient-2.2.0/doc/ 0000775 0001750 0001750 00000000000 13364113665 016465 5 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/doc/source/ 0000775 0001750 0001750 00000000000 13364113665 017765 5 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/doc/source/contributing.rst 0000666 0001750 0001750 00000002617 13364113436 023232 0 ustar zuul zuul 0000000 0000000 .. _contributing:
====================================
Contributing to python-watcherclient
====================================
If you're interested in contributing to the python-watcherclient project,
the following will help get you started.
Contributor License Agreement
-----------------------------
.. index::
single: license; agreement
In order to contribute to the python-watcherclient project, you need to have
signed OpenStack's contributor's agreement.
.. seealso::
* https://docs.openstack.org/infra/manual/developers.html
* https://wiki.openstack.org/CLA
LaunchPad Project
-----------------
Most of the tools used for OpenStack depend on a launchpad.net ID for
authentication. After signing up for a launchpad account, join the
"openstack" team to have access to the mailing list and receive
notifications of important events.
.. seealso::
* http://launchpad.net
* http://launchpad.net/python-watcherclient
* http://launchpad.net/~openstack
Project Hosting Details
-------------------------
Bug tracker
https://launchpad.net/python-watcherclient
Mailing list (prefix subjects with ``[watcher]`` for faster responses)
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
Code Hosting
https://git.openstack.org/cgit/openstack/python-watcherclient
Code Review
https://review.openstack.org/#/q/status:open+project:openstack/python-watcherclient,n,z
python-watcherclient-2.2.0/doc/source/reference/ 0000775 0001750 0001750 00000000000 13364113665 021723 5 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/doc/source/reference/api/ 0000775 0001750 0001750 00000000000 13364113665 022474 5 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/doc/source/reference/api/index.rst 0000666 0001750 0001750 00000000160 13364113436 024330 0 ustar zuul zuul 0000000 0000000 ======================
Python API Reference
======================
.. toctree::
:maxdepth: 2
autoindex
python-watcherclient-2.2.0/doc/source/reference/api_v1.rst 0000666 0001750 0001750 00000005756 13364113436 023647 0 ustar zuul zuul 0000000 0000000 .. _api_v1:
========================
watcherclient Python API
========================
The watcherclient python API lets you access watcher, the OpenStack
TODEFINE Service.
For example, to manipulate audits, you interact with an `watcherclient.v1.audit`_ object.
You obtain access to audits via attributes of the `watcherclient.v1.client.Client`_ object.
Usage
=====
Get a Client object
-------------------
First, create an `watcherclient.v1.client.Client`_ instance by passing your
credentials to `watcherclient.client.get_client()`_. By default, the
Watcher system is configured so that only administrators (users with
'admin' role) have access.
There are two different sets of credentials that can be used::
* watcher endpoint and auth token
* Identity Service (keystone) credentials
Using watcher endpoint and auth token
.....................................
An auth token and the watcher endpoint can be used to authenticate::
* os_auth_token: authentication token (from Identity Service)
* watcher_url: watcher API endpoint, eg http://watcher.example.org:9322/v1
To create the client, you can use the API like so::
>>> from watcherclient import client
>>>
>>> kwargs = {'os_auth_token': '3bcc3d3a03f44e3d8377f9247b0ad155'
>>> 'watcher_url': 'http://watcher.example.org:9322/'}
>>> watcher = client.get_client(1, **kwargs)
Using Identity Service (keystone) credentials
.............................................
These Identity Service credentials can be used to authenticate::
* os_username: name of user
* os_password: user's password
* os_auth_url: Identity Service endpoint for authorization
* os_tenant_{name|id}: name or ID of tenant
To create a client, you can use the API like so::
>>> from watcherclient import client
>>>
>>> kwargs = {'os_username': 'name',
>>> 'os_password': 'password',
>>> 'os_auth_url': 'http://keystone.example.org:5000/',
>>> 'os_tenant_name': 'tenant'}
>>> watcher = client.get_client(1, **kwargs)
Perform watcher operations
--------------------------
Once you have an watcher `Client`_, you can perform various tasks::
>>> watcher.action.list() # list of actions
>>> watcher.action_plan.list() # list of action_plan
>>> watcher.audit.get(audit_uuid_or_name) # information about a particular audit
When the `Client`_ needs to propagate an exception, it will usually
raise an instance listed in `watcherclient.exceptions`_.
Refer to the modules themselves, for more details.
=====================
watcherclient Modules
=====================
.. _watcherclient.v1.audit: api/watcherclient.v1.audit.html#watcherclient.v1.audit.Audit
.. _watcherclient.v1.client.Client: api/watcherclient.v1.client.html#watcherclient.v1.client.Client
.. _Client: api/watcherclient.v1.client.html#watcherclient.v1.client.Client
.. _watcherclient.client.get_client(): api/watcherclient.client.html#watcherclient.client.get_client
.. _watcherclient.exceptions: api/watcherclient.exceptions.html
python-watcherclient-2.2.0/doc/source/reference/index.rst 0000666 0001750 0001750 00000000473 13364113436 023566 0 ustar zuul zuul 0000000 0000000 ==========================
Python Library Reference
==========================
In order to use the python api directly, you must first obtain an auth
token and identify which endpoint you wish to speak to. Once you have
done so, you can use the API like so.
.. toctree::
:maxdepth: 2
api/index
api_v1
python-watcherclient-2.2.0/doc/source/index.rst 0000666 0001750 0001750 00000000616 13364113436 021627 0 ustar zuul zuul 0000000 0000000 Python bindings to the OpenStack Watcher API
============================================
This is a client for OpenStack Watcher API. There's a Python API
(the :mod:`watcherclient` modules), and a command-line script
(installed as :program:`watcher`). Each implements the entire
OpenStack Watcher API.
.. toctree::
:maxdepth: 2
cli/index
reference/index
installation
contributing
python-watcherclient-2.2.0/doc/source/conf.py 0000666 0001750 0001750 00000006430 13364113436 021265 0 ustar zuul zuul 0000000 0000000 # 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 watcherclient import version as watcherclient_version
# -- General configuration ----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc',
'sphinx.ext.viewcode',
'openstackdocstheme',
]
# autodoc generation is a bit aggressive and a nuisance when doing heavy
# text edit cycles.
# execute "export SPHINX_DEBUG=1" in your terminal to disable
# 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'python-watcherclient'
copyright = u'OpenStack Foundation'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
# The full version, including alpha/beta/rc tags.
release = watcherclient_version.version_info.release_string()
# The short X.Y version.
version = watcherclient_version.version_info.version_string()
# A list of ignored prefixes for module index sorting.
modindex_common_prefix = ['watcherclient.']
# If true, '()' will be appended to :func: etc. cross-reference text.
add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
add_module_names = True
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# -- Options for HTML output --------------------------------------------------
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
# html_theme_path = ["."]
# html_theme = '_theme'
# html_static_path = ['_static']
html_theme = 'openstackdocs'
# html_theme_path = [openstackdocstheme.get_html_theme_path()]
# Output file base name for HTML help builder.
htmlhelp_basename = '%sdoc' % project
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass
# [howto/manual]).
latex_documents = [
(
'index',
'%s.tex' % project,
u'%s Documentation' % project,
u'OpenStack Foundation', 'manual'
),
]
# openstackdocstheme options
repository_name = 'openstack/python-watcherclient'
bug_project = 'python-watcherclient'
bug_tag = ''
# Must set this variable to include year, month, day, hours, and minutes.
html_last_updated_fmt = '%Y-%m-%d %H:%M'
#html_theme_options = {"show_other_versions": "True"}
python-watcherclient-2.2.0/doc/source/installation.rst 0000666 0001750 0001750 00000000555 13364113436 023223 0 ustar zuul zuul 0000000 0000000 ============
Installation
============
If you have `virtualenvwrapper `_ installed::
$ mkvirtualenv python-watcherclient
$ git clone https://git.openstack.org/openstack/python-watcherclient
$ cd python-watcherclient && python setup.py install
$ pip install -r ./requirements.txt
python-watcherclient-2.2.0/doc/source/cli/ 0000775 0001750 0001750 00000000000 13364113665 020534 5 ustar zuul zuul 0000000 0000000 python-watcherclient-2.2.0/doc/source/cli/watcher.rst 0000666 0001750 0001750 00000005222 13364113436 022722 0 ustar zuul zuul 0000000 0000000 ===============================================
:program:`watcher` Command-Line Interface (CLI)
===============================================
.. program:: watcher
.. highlight:: bash
SYNOPSIS
========
:program:`watcher` [options] [command-options]
:program:`watcher help`
:program:`watcher help`
DESCRIPTION
===========
The :program:`watcher` command-line interface (CLI) interacts with the
OpenStack infra-optim Service (Watcher).
In order to use the CLI, you must provide your OpenStack username, password,
project (historically called tenant), and auth endpoint. You can use
configuration options :option:``--os-username``, :option:``--os-password``,
:option:``--os-tenant-id`` (or :option:``--os-tenant-name``),
and :option:``--os-auth-url``, or set the corresponding
environment variables::
$ export OS_USERNAME=user
$ export OS_PASSWORD=password
$ export OS_TENANT_ID=b363706f891f48019483f8bd6503c54b # or OS_TENANT_NAME
$ export OS_TENANT_NAME=project # or OS_TENANT_ID
$ export OS_AUTH_URL=http://auth.example.com:5000/v2.0
The command-line tool will attempt to reauthenticate using the provided
credentials for every request. You can override this behavior by manually
supplying an auth token using :option:``--watcher-url`` and
:option:``--os-auth-token``, or by setting the corresponding environment variables::
$ export WATCHER_URL=http://watcher.example.org:9322/
$ export OS_AUTH_TOKEN=3bcc3d3a03f44e3d8377f9247b0ad155
Since Keystone can return multiple regions in the Service Catalog, you can
specify the one you want with :option:``--os-region-name`` or set the following
environment variable. (It defaults to the first in the list returned.)
::
$ export OS_REGION_NAME=region
Watcher CLI supports bash completion. The command-line tool can automatically
fill partially typed commands. To use this feature, source the below file
(available at
https://git.openstack.org/cgit/openstack/python-watcherclient/tree/tools/watcher.bash_completion)
to your terminal and then bash completion should work::
$ . watcher.bash_completion
To avoid doing this every time, add this to your ``.bashrc`` or copy the
watcher.bash_completion file to the default bash completion scripts directory
on your linux distribution.
OPTIONS
=======
To get a list of available (sub)commands and options, run::
$ watcher help
To get usage and options of a command, run::
$ watcher help
EXAMPLES
========
Get information about the audit-create command::
$ watcher help audit create
Get a list of available goal::
$ watcher goal list
Get a list of audits::
$ watcher audit list
python-watcherclient-2.2.0/doc/source/cli/details.rst 0000666 0001750 0001750 00000071055 13364113436 022721 0 ustar zuul zuul 0000000 0000000 .. ###################################################
.. ## WARNING ######################################
.. ############## WARNING ##########################
.. ########################## WARNING ##############
.. ###################################### WARNING ##
.. ###################################################
.. ###################################################
.. ##
.. This file is tool-generated. Do not edit manually.
.. http://docs.openstack.org/contributor-guide/
.. doc-tools/cli-reference.html
.. ##
.. ## WARNING ######################################
.. ############## WARNING ##########################
.. ########################## WARNING ##############
.. ###################################### WARNING ##
.. ###################################################
=================================================================
Infrastructure Optimization service (watcher) command-line client
=================================================================
The watcher client is the command-line interface (CLI) for the
Infrastructure Optimization service (watcher) API
and its extensions.
This chapter documents :command:`watcher` version ``1.3.0``.
For help on a specific :command:`watcher` command, enter:
.. code-block:: console
$ watcher help COMMAND
.. _watcher_command_usage:
watcher usage
~~~~~~~~~~~~~
.. code-block:: console
usage: watcher [--version] [-v | -q] [--log-file LOG_FILE] [-h] [--debug]
[--no-auth] [--os-identity-api-version ]
[--os-auth-url ] [--os-region-name ]
[--os-username ] [--os-user-id ]
[--os-password ]
[--os-user-domain-id ]
[--os-user-domain-name ]
[--os-tenant-name ]
[--os-tenant-id ]
[--os-project-id ]
[--os-project-name ]
[--os-project-domain-id ]
[--os-project-domain-name ]
[--os-auth-token ]
[--os-watcher-api-version ]
[--os-endpoint-type OS_ENDPOINT_TYPE]
[--os-endpoint-override ] [--insecure]
[--os-cacert ] [--os-cert ]
[--os-key ] [--timeout ]
.. _watcher_command_options:
watcher optional arguments
~~~~~~~~~~~~~~~~~~~~~~~~~~
``--version``
show program's version number and exit
``-v, --verbose``
Increase verbosity of output. Can be repeated.
``-q, --quiet``
Suppress output except warnings and errors.
``--log-file LOG_FILE``
Specify a file to log output. Disabled by default.
``-h, --help``
Show help message and exit.
``--debug``
Show tracebacks on errors.
``--no-auth, -N``
Do not use authentication.
``--os-identity-api-version ``
Specify Identity API version to use. Defaults to
``env[OS_IDENTITY_API_VERSION]`` or 3.
``--os-auth-url , -A ``
Defaults to ``env[OS_AUTH_URL]``.
``--os-region-name , -R ``
Defaults to ``env[OS_REGION_NAME]``.
``--os-username , -U ``
Defaults to ``env[OS_USERNAME]``.
``--os-user-id ``
Defaults to ``env[OS_USER_ID]``.
``--os-password , -P ``
Defaults to ``env[OS_PASSWORD]``.
``--os-user-domain-id ``
Defaults to ``env[OS_USER_DOMAIN_ID]``.
``--os-user-domain-name ``
Defaults to ``env[OS_USER_DOMAIN_NAME]``.
``--os-tenant-name , -T ``
Defaults to ``env[OS_TENANT_NAME]``.
``--os-tenant-id , -I ``
Defaults to ``env[OS_TENANT_ID]``.
``--os-project-id ``
Another way to specify tenant ID. This option is
mutually exclusive with --os-tenant-id. Defaults to
``env[OS_PROJECT_ID]``.
``--os-project-name ``
Another way to specify tenant name. This option is
mutually exclusive with --os-tenant-name. Defaults to
``env[OS_PROJECT_NAME]``.
``--os-project-domain-id ``
Defaults to ``env[OS_PROJECT_DOMAIN_ID]``.
``--os-project-domain-name ``
Defaults to ``env[OS_PROJECT_DOMAIN_NAME]``.
``--os-auth-token ``
Defaults to ``env[OS_AUTH_TOKEN]``.
``--os-watcher-api-version ``
Defaults to ``env[OS_WATCHER_API_VERSION]``.
``--os-endpoint-type OS_ENDPOINT_TYPE``
Defaults to ``env[OS_ENDPOINT_TYPE]`` or "publicURL"
``--os-endpoint-override ``
Use this API endpoint instead of the Service Catalog.
.. _watcher_action_list:
watcher action list
-------------------
.. code-block:: console
usage: watcher action list [-h] [-f {csv,html,json,table,value,yaml}]
[-c COLUMN] [--max-width ] [--fit-width]
[--print-empty] [--noindent]
[--quote {all,minimal,none,nonnumeric}]
[--action-plan ] [--audit ]
[--detail] [--limit ] [--sort-key ]
[--sort-dir ] [--marker ]
List information on retrieved actions.
**Optional arguments:**
``-h, --help``
show this help message and exit
``--action-plan ``
UUID of the action plan used for filtering.
``--audit ``
UUID of the audit used for filtering.
``--detail``
Show detailed information about actions.
``--limit ``
Maximum number of actions to return per request, 0 for
no limit. Default is the maximum number used by the
Watcher API Service.
``--sort-key ``
Action field that will be used for sorting.
``--sort-dir ``
Sort direction: "asc" (the default) or "desc".
``--marker ``
UUID of the last action in the previous page; displays
list of actions after "marker".
.. _watcher_action_show:
watcher action show
-------------------
.. code-block:: console
usage: watcher action show [-h] [-f {html,json,shell,table,value,yaml}]
[-c COLUMN] [--max-width ] [--fit-width]
[--print-empty] [--noindent] [--prefix PREFIX]
Show detailed information about a given action.
**Positional arguments:**
````
UUID of the action
**Optional arguments:**
``-h, --help``
show this help message and exit
.. _watcher_actionplan_cancel:
watcher actionplan cancel
-------------------------
.. code-block:: console
usage: watcher actionplan cancel [-h] [-f {html,json,shell,table,value,yaml}]
[-c COLUMN] [--max-width ]
[--fit-width] [--print-empty] [--noindent]
[--prefix PREFIX]
Cancel action plan command.
**Positional arguments:**
````
UUID of the action_plan.
**Optional arguments:**
``-h, --help``
show this help message and exit
.. _watcher_actionplan_create:
watcher actionplan create
-------------------------
.. code-block:: console
usage: watcher actionplan create [-h] [-f {html,json,shell,table,value,yaml}]
[-c COLUMN] [--max-width ]
[--fit-width] [--print-empty] [--noindent]
[--prefix PREFIX] -a
[-t ]
Create new audit.
**Optional arguments:**
``-h, --help``
show this help message and exit
``-a , --audit-template ``
Audit template used for this audit (name or uuid).
``-t