Compare commits

..

6 Commits
1.5.0 ... 1.3.1

Author SHA1 Message Date
Nguyen Hai
4a8cf8445e import zuul job settings from project-config
This is a mechanically generated patch to complete step 1 of moving
the zuul job settings out of project-config and into each project
repository.

Because there will be a separate patch on each branch, the branch
specifiers for branch-specific jobs have been removed.

Because this patch is generated by a script, there may be some
cosmetic changes to the layout of the YAML file(s) as the contents are
normalized.

See the python3-first goal document for details:
https://governance.openstack.org/tc/goals/stein/python3-first.html

Change-Id: I6e15638497fc016dca98189dc15397d61d268433
Story: #2002586
Task: #24344
2018-08-19 00:58:47 +09:00
OpenStack Proposal Bot
e28f0e7ee2 Updated from global requirements
Change-Id: I7236e4ba660824d4ae8b72f0c2f79a49ae36861b
2017-09-15 07:45:58 +00:00
zte-hanrong
b45c813d9a Add the filed of description to shell command for action.
blueprint dynamic-action-description

Change-Id: I927cf966530059d9c7af1e6e60a8d75dd3e6b812
(cherry picked from commit 08fbccc684)
2017-08-24 08:45:20 +00:00
Alexander Chadin
4a47b7886d Fix Audit Update functional test
Change-Id: Iffd70302d0b1d7a919db3e6e44bd3bbebcb1e7ce
(cherry picked from commit d6b68dc819)
2017-08-24 07:49:35 +00:00
f5eae02253 Update UPPER_CONSTRAINTS_FILE for stable/pike
Change-Id: I933e0a2cc99083aefae75648578800af7047c343
2017-07-28 21:08:25 +00:00
b6fe5c9261 Update .gitreview for stable/pike
Change-Id: I0ef7e43614425d4f88a2f3b5c2d90dfe3bb7f6c2
2017-07-28 21:08:24 +00:00
29 changed files with 146 additions and 1300 deletions

View File

@@ -2,3 +2,4 @@
host=review.openstack.org
port=29418
project=openstack/python-watcherclient.git
defaultbranch=stable/pike

View File

@@ -1,8 +1,12 @@
- project:
name: openstack/python-watcherclient
templates:
- openstack-python-jobs
- openstack-python35-jobs
- publish-openstack-sphinx-docs
- check-requirements
- openstackclient-plugin-jobs
check:
jobs:
- watcherclient-tempest-functional
gate:
jobs:
- watcherclient-tempest-functional
- openstack-tox-cover:
voting: false

View File

@@ -1,13 +1,13 @@
If you would like to contribute to the development of OpenStack,
you must follow the steps in this page:
https://docs.openstack.org/infra/manual/developers.html
http://docs.openstack.org/infra/manual/developers.html
Once those steps have been completed, changes to OpenStack
should be submitted for review via the Gerrit tool, following
the workflow documented at:
https://docs.openstack.org/infra/manual/developers.html#development-workflow
http://docs.openstack.org/infra/manual/developers.html#development-workflow
Pull requests submitted through GitHub will be ignored.

View File

@@ -1,4 +1,4 @@
python-watcherclient Style Commandments
=======================================
Read the OpenStack Style Commandments https://docs.openstack.org/hacking/latest/
Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/

View File

@@ -23,9 +23,9 @@ 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
* Wiki: http://wiki.openstack.org/wiki/Watcher
* Source: http://git.openstack.org/cgit/openstack/python-watcher
* Bugs: http://bugs.launchpad.net/watcher
Installation
============
@@ -61,7 +61,7 @@ You can install the Watcher CLI with the following command:
sudo pip install python-watcherclient
You can also use the `OpenStack client <https://docs.openstack.org/python-openstackclient/latest/>`_
You can also use the `OpenStack client <http://docs.openstack.org/cli-reference/overview.html>`_
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:

File diff suppressed because it is too large Load Diff

View File

@@ -29,4 +29,3 @@ Once you've configured your authentication parameters, you can run
watcher
openstack_cli
details

View File

@@ -55,7 +55,7 @@ fill partially typed commands. To use this feature, source the below file
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
$ source 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

View File

@@ -19,8 +19,8 @@ signed OpenStack's contributor's agreement.
.. seealso::
* https://docs.openstack.org/infra/manual/developers.html
* https://wiki.openstack.org/CLA
* http://docs.openstack.org/infra/manual/developers.html
* http://wiki.openstack.org/CLA
LaunchPad Project
-----------------
@@ -41,7 +41,7 @@ Project Hosting Details
-------------------------
Bug tracker
https://launchpad.net/python-watcherclient
http://launchpad.net/python-watcherclient
Mailing list (prefix subjects with ``[watcher]`` for faster responses)
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev

View File

@@ -68,7 +68,7 @@ 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
>>> watcher.audit.get(audit_uuid) # information about a particular audit
When the `Client`_ needs to propagate an exception, it will usually
raise an instance subclassed from

View File

@@ -3,12 +3,12 @@
# process, which may cause wedges in the gate later.
Babel!=2.4.0,>=2.3.4 # BSD
cliff!=2.9.0,>=2.8.0 # Apache-2.0
cliff>=2.8.0 # Apache-2.0
osc-lib>=1.7.0 # Apache-2.0
oslo.i18n>=3.15.3 # Apache-2.0
oslo.utils>=3.31.0 # Apache-2.0
oslo.i18n!=3.15.2,>=2.1.0 # Apache-2.0
oslo.utils>=3.20.0 # Apache-2.0
pbr!=2.1.0,>=2.0.0 # Apache-2.0
PrettyTable<0.8,>=0.7.1 # BSD
keystoneauth1>=3.3.0 # Apache-2.0
six>=1.10.0 # MIT
PyYAML>=3.10 # MIT
keystoneauth1>=3.1.0 # Apache-2.0
six>=1.9.0 # MIT
PyYAML>=3.10.0 # MIT

View File

@@ -5,7 +5,7 @@ description-file =
README.rst
author = OpenStack
author-email = openstack-dev@lists.openstack.org
home-page = https://docs.openstack.org/python-watcherclient/latest/
home-page = http://docs.openstack.org/developer/python-watcherclient
classifier =
Environment :: OpenStack
Intended Audience :: Information Technology

View File

@@ -5,15 +5,15 @@
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.17.0 # Apache-2.0
mock>=2.0 # BSD
openstackdocstheme>=1.16.0 # Apache-2.0
oslotest>=1.10.0 # Apache-2.0
python-subunit>=1.0.0 # Apache-2.0/BSD
python-subunit>=0.0.18 # Apache-2.0/BSD
sphinx>=1.6.2 # BSD
testrepository>=0.0.18 # Apache-2.0/BSD
testscenarios>=0.4 # Apache-2.0/BSD
testtools>=2.2.0 # MIT
tempest>=17.1.0 # Apache-2.0
testtools>=1.4.0 # MIT
tempest>=16.1.0 # Apache-2.0
# Needed for pypi packaging
wheel>=0.24.0 # MIT
wheel # MIT

View File

@@ -6,7 +6,7 @@ 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}
constraints: pip install -U --force-reinstall -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt?h=stable/pike} {opts} {packages}
pip install -U {opts} {packages}
setenv =
VIRTUAL_ENV={envdir}

View File

@@ -161,21 +161,17 @@ def common_params_for_list(args, fields, field_labels):
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):
def common_filters(limit=None, sort_key=None, sort_dir=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 = []
@@ -185,8 +181,6 @@ def common_filters(limit=None, sort_key=None, sort_dir=None, marker=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

View File

@@ -26,7 +26,7 @@ You need to install virtualenv, create a virtual environment and activate it::
$ pip install virtualenv
$ virtualenv watcher-env
$ . watcher-env/bin/activate
$ source watcher-env/bin/activate
Then, to install Tempest you can issue the following commands::

View File

@@ -24,14 +24,14 @@ function generate_testr_results {
sudo /usr/os-testr-env/bin/subunit2html $BASE/logs/testrepository.subunit $BASE/logs/testr_results.html
sudo gzip -9 $BASE/logs/testrepository.subunit
sudo gzip -9 $BASE/logs/testr_results.html
sudo chown $USER:$USER $BASE/logs/testrepository.subunit.gz $BASE/logs/testr_results.html.gz
sudo chown jenkins:jenkins $BASE/logs/testrepository.subunit.gz $BASE/logs/testr_results.html.gz
sudo chmod a+r $BASE/logs/testrepository.subunit.gz $BASE/logs/testr_results.html.gz
fi
}
export WATCHERCLIENT_DIR="$BASE/new/python-watcherclient"
sudo chown -R $USER:stack $WATCHERCLIENT_DIR
sudo chown -R jenkins:stack $WATCHERCLIENT_DIR
# Get admin credentials
cd $STACK_DIR
@@ -44,7 +44,7 @@ cd $WATCHERCLIENT_DIR
echo "Running watcherclient functional test suite"
set +e
# Preserve env for OS_ credentials
sudo -E -H -u $USER tox -efunctional
sudo -E -H -u jenkins tox -efunctional
EXIT_CODE=$?
set -e

View File

@@ -10,8 +10,6 @@
# License for the specific language governing permissions and limitations
# under the License.
import os
import re
import shlex
import subprocess
@@ -22,24 +20,9 @@ from tempest.lib.cli import output_parser
from tempest.lib import exceptions
def credentials():
creds = {
'--os-username': os.environ.get('OS_USERNAME', 'admin'),
'--os-password': os.environ.get('OS_PASSWORD', 'secretadmin'),
'--os-project-name': os.environ.get('OS_PROJECT_NAME', 'admin'),
'--os-auth-url': os.environ.get('OS_AUTH_URL',
'http://10.0.1.94/identity'),
'--os-project-domain-id': os.environ.get('OS_PROJECT_DOMAIN_ID',
'default'),
'--os-user-domain-id': os.environ.get('OS_USER_DOMAIN_ID', 'default'),
}
return [x for sub in creds.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)

View File

@@ -22,7 +22,7 @@ class AuditTests(base.TestCase):
"""Functional tests for audit."""
dummy_name = 'dummy'
list_fields = ['UUID', 'Name', 'Audit Type', 'State', 'Goal', 'Strategy']
list_fields = ['UUID', 'Audit Type', 'State', 'Goal', 'Strategy']
detailed_list_fields = list_fields + ['Created At', 'Updated At',
'Deleted At', 'Parameters',
'Interval', 'Audit Scope',
@@ -71,7 +71,7 @@ class AuditTests(base.TestCase):
class AuditActiveTests(base.TestCase):
list_fields = ['UUID', 'Name', 'Audit Type', 'State', 'Goal', 'Strategy']
list_fields = ['UUID', 'Audit Type', 'State', 'Goal', 'Strategy']
detailed_list_fields = list_fields + ['Created At', 'Updated At',
'Deleted At', 'Parameters',
'Interval', 'Audit Scope']

View File

@@ -97,8 +97,7 @@ class UtilsTest(test_utils.BaseTestCase):
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 = mock.Mock(limit=None, sort_key=None, sort_dir=None)
self.args.detail = False
self.expected_params = {'detail': False}
@@ -118,13 +117,6 @@ class CommonParamsForListTest(test_utils.BaseTestCase):
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'

View File

@@ -94,13 +94,6 @@ fake_responses_pagination = {
{"action_plans": [ACTION_PLAN2]}
),
},
'/v1/action_plans/?marker=f8e47706-efcf-49a4-a5c4-af604eb492f2':
{
'GET': (
{},
{"action_plans": [ACTION_PLAN2]}
),
},
}
fake_responses_sorting = {
@@ -165,19 +158,6 @@ class ActionPlanManagerTest(testtools.TestCase):
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)

View File

@@ -33,16 +33,12 @@ ACTION_PLAN_1 = {
'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"}
],
'global_efficacy': {
"value": 99,
"unit": "%",
"name": "dummy_global_efficacy",
"description": "Dummy Global Efficacy",
},
'deleted_at': None,
}
@@ -56,12 +52,12 @@ ACTION_PLAN_2 = {
'name': 'indicator2',
'unit': '%'}],
'updated_at': None,
'global_efficacy': [{
'global_efficacy': {
"value": 87,
"unit": "%",
"name": "dummy_global_efficacy",
"description": "Dummy Global Efficacy",
}],
},
'deleted_at': None,
}
@@ -73,7 +69,6 @@ class ActionPlanShellTest(base.CommandTestCase):
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()
@@ -119,11 +114,6 @@ class ActionPlanShellTest(base.CommandTestCase):
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):
@@ -141,10 +131,6 @@ class ActionPlanShellTest(base.CommandTestCase):
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)
@@ -179,8 +165,6 @@ class ActionPlanShellTest(base.CommandTestCase):
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')

94
watcherclient/tests/unit/v1/test_audit_shell.py Executable file → Normal file
View File

@@ -17,6 +17,7 @@ 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
@@ -68,7 +69,6 @@ AUDIT_1 = {
'scope': '',
'auto_trigger': False,
'next_run_time': None,
'name': 'my_audit1',
}
AUDIT_2 = {
@@ -87,7 +87,6 @@ AUDIT_2 = {
'scope': '',
'auto_trigger': False,
'next_run_time': None,
'name': 'my_audit2',
}
AUDIT_3 = {
@@ -106,7 +105,6 @@ AUDIT_3 = {
'scope': '',
'auto_trigger': True,
'next_run_time': None,
'name': 'my_audit3',
}
@@ -204,19 +202,14 @@ class AuditShellTest(base.CommandTestCase):
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
def test_do_audit_show_by_not_uuid(self):
self.m_audit_mgr.get.side_effect = exceptions.HTTPNotFound
exit_code, result = self.run_cmd(
'audit show my_audit')
'audit show not_uuid', formatting=None)
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')
self.assertEqual(1, exit_code)
self.assertEqual('', result)
def test_do_audit_delete(self):
self.m_audit_mgr.delete.return_value = ''
@@ -230,18 +223,6 @@ class AuditShellTest(base.CommandTestCase):
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 = ''
@@ -257,6 +238,16 @@ class AuditShellTest(base.CommandTestCase):
self.m_audit_mgr.delete.assert_any_call(
'5b157edd-5a7e-4aaa-b511-f7b33ec86e9f')
def test_do_audit_delete_with_not_uuid(self):
self.m_audit_mgr.delete.return_value = ''
exit_code, result = self.run_cmd(
'audit delete not_uuid',
formatting=None)
self.assertEqual(1, exit_code)
self.assertEqual('', result)
def test_do_audit_update(self):
audit = resource.Audit(mock.Mock(), AUDIT_1)
self.m_audit_mgr.update.return_value = audit
@@ -273,20 +264,14 @@ class AuditShellTest(base.CommandTestCase):
'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
def test_do_audit_update_with_not_uuid(self):
self.m_audit_mgr.update.return_value = ''
exit_code, result = self.run_cmd(
'audit update my_audit replace state=PENDING')
'audit update not_uuid replace state=PENDING', formatting=None)
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'}])
self.assertEqual(1, exit_code)
self.assertEqual('', result)
def test_do_audit_create_with_audit_template_uuid(self):
audit = resource.Audit(mock.Mock(), AUDIT_3)
@@ -303,9 +288,7 @@ class AuditShellTest(base.CommandTestCase):
result)
self.m_audit_mgr.create.assert_called_once_with(
audit_template_uuid='f8e47706-efcf-49a4-a5c4-af604eb492f2',
audit_type='ONESHOT',
auto_trigger=False
)
audit_type='ONESHOT', auto_trigger=False)
def test_do_audit_create_with_audit_template_name(self):
audit = resource.Audit(mock.Mock(), AUDIT_3)
@@ -322,8 +305,7 @@ class AuditShellTest(base.CommandTestCase):
self.m_audit_mgr.create.assert_called_once_with(
audit_template_uuid='f8e47706-efcf-49a4-a5c4-af604eb492f2',
auto_trigger=False,
audit_type='ONESHOT'
)
audit_type='ONESHOT')
def test_do_audit_create_with_goal(self):
audit = resource.Audit(mock.Mock(), AUDIT_1)
@@ -374,9 +356,7 @@ class AuditShellTest(base.CommandTestCase):
result)
self.m_audit_mgr.create.assert_called_once_with(
goal='fc087747-61be-4aad-8126-b701731ae836',
auto_trigger=False,
audit_type='ONESHOT'
)
auto_trigger=False, audit_type='ONESHOT')
def test_do_audit_create_with_parameter(self):
audit = resource.Audit(mock.Mock(), AUDIT_1)
@@ -394,8 +374,7 @@ class AuditShellTest(base.CommandTestCase):
goal='fc087747-61be-4aad-8126-b701731ae836',
audit_type='ONESHOT',
auto_trigger=False,
parameters={'para1': 10, 'para2': 20}
)
parameters={'para1': 10, 'para2': 20})
def test_do_audit_create_with_type_continuous(self):
audit = resource.Audit(mock.Mock(), AUDIT_1)
@@ -413,25 +392,4 @@ class AuditShellTest(base.CommandTestCase):
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'
)
interval='3600')

View File

@@ -31,7 +31,7 @@ class ActionPlanManager(base.Manager):
return '/v1/action_plans/%s' % id if id else '/v1/action_plans'
def list(self, audit=None, limit=None, sort_key=None,
sort_dir=None, detail=False, marker=None):
sort_dir=None, detail=False):
"""Retrieve a list of action plan.
:param audit: Name of the audit
@@ -52,16 +52,13 @@ class ActionPlanManager(base.Manager):
: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)
filters = utils.common_filters(limit, sort_key, sort_dir)
if audit is not None:
filters.append('audit_uuid=%s' % audit)

View File

@@ -26,16 +26,16 @@ from watcherclient.v1 import resource_fields as res_fields
def format_global_efficacy(global_efficacy):
formatted_global_eff = {}
for eff in global_efficacy:
if (eff.get('value') is not None and eff.get('unit')):
eff_name = eff.get('name')
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
formatted_global_efficacy = None
if (global_efficacy.get('value') is not None and
global_efficacy.get('unit')):
formatted_global_efficacy = "%(value).2f %(unit)s" % dict(
unit=global_efficacy.get('unit'),
value=global_efficacy.get('value'))
elif global_efficacy.get('value') is not None:
formatted_global_efficacy = global_efficacy.get('value')
return formatted_global_efficacy
class ShowActionPlan(command.ShowOne):
@@ -64,18 +64,6 @@ class ShowActionPlan(command.ShowOne):
)
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.itervalues()],
stdout=out,
parsed_args=parsed_args,
)
return out.getvalue() or ''
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
@@ -95,8 +83,8 @@ class ShowActionPlan(command.ShowOne):
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)
action_plan.global_efficacy = format_global_efficacy(
action_plan.global_efficacy)
columns = res_fields.ACTION_PLAN_FIELDS
column_headers = res_fields.ACTION_PLAN_FIELD_LABELS
@@ -125,11 +113,6 @@ class ListActionPlan(command.Lister):
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='<actionplan>',
help=_('The last actionplan UUID of the previous page; '
'displays list of actionplans after "marker".'))
parser.add_argument(
'--sort-key',
metavar='<field>',
@@ -156,18 +139,6 @@ class ListActionPlan(command.Lister):
)
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.itervalues()],
stdout=out,
parsed_args=parsed_args,
)
return out.getvalue() or ''
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
@@ -193,8 +164,8 @@ class ListActionPlan(command.Lister):
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)
action_plan.global_efficacy = format_global_efficacy(
action_plan.global_efficacy)
return (field_labels,
(utils.get_item_properties(item, fields) for item in data))

View File

@@ -19,8 +19,7 @@ from watcherclient import exceptions as exc
CREATION_ATTRIBUTES = ['audit_template_uuid', 'audit_type', 'interval',
'parameters', 'goal', 'strategy', 'auto_trigger',
'name']
'parameters', 'goal', 'strategy', 'auto_trigger']
class Audit(base.Resource):
@@ -39,7 +38,8 @@ class AuditManager(base.Manager):
sort_dir=None, detail=False, goal=None, strategy=None):
"""Retrieve a list of audit.
:param audit_template: Name of the audit template
:param audit_template: Name of the audit
:param name: Name of the audit
:param limit: The maximum number of results to return per
request, if:
@@ -92,14 +92,14 @@ class AuditManager(base.Manager):
raise exc.InvalidAttribute()
return self._create(self._path(), new)
def get(self, audit):
def get(self, audit_id):
try:
return self._list(self._path(audit))[0]
return self._list(self._path(audit_id))[0]
except IndexError:
return None
def delete(self, audit):
return self._delete(self._path(audit))
def delete(self, audit_id):
return self._delete(self._path(audit_id))
def update(self, audit, patch):
return self._update(self._path(audit), patch)
def update(self, audit_id, patch):
return self._update(self._path(audit_id), patch)

View File

@@ -31,7 +31,7 @@ class ShowAudit(command.ShowOne):
parser.add_argument(
'audit',
metavar='<audit>',
help=_('UUID or name of the audit'),
help=_('UUID of the audit'),
)
return parser
@@ -175,19 +175,13 @@ class CreateAudit(command.ShowOne):
default=False,
help=_('Trigger automatically action plan '
'once audit is succeeded.'))
parser.add_argument(
'--name',
dest='name',
metavar='<name>',
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']
'interval', 'goal', 'strategy', 'auto_trigger']
fields = dict((k, v) for (k, v) in vars(parsed_args).items()
if k in field_list and v is not None)
@@ -225,7 +219,7 @@ class UpdateAudit(command.ShowOne):
parser.add_argument(
'audit',
metavar='<audit>',
help=_("UUID or name of the audit."))
help=_("UUID of the audit."))
parser.add_argument(
'op',
metavar='<op>',
@@ -245,6 +239,9 @@ class UpdateAudit(command.ShowOne):
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
if not uuidutils.is_uuid_like(parsed_args.audit):
raise exceptions.ValidationError()
patch = common_utils.args_array_to_patch(
parsed_args.op, parsed_args.attributes[0],
exclude_fields=['/interval'])
@@ -266,7 +263,7 @@ class DeleteAudit(command.Command):
'audits',
metavar='<audit>',
nargs='+',
help=_('UUID or name of the audit'),
help=_('UUID of the audit'),
)
return parser
@@ -274,4 +271,7 @@ class DeleteAudit(command.Command):
client = getattr(self.app.client_manager, "infra-optim")
for audit in parsed_args.audits:
if not uuidutils.is_uuid_like(audit):
raise exceptions.ValidationError()
client.audit.delete(audit)

View File

@@ -162,40 +162,37 @@ class CreateAuditTemplate(command.ShowOne):
"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"
" - 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"
"\n"
"JSON example:\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"
"[{'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"
)
)

View File

@@ -30,20 +30,20 @@ AUDIT_TEMPLATE_SHORT_LIST_FIELDS = [
AUDIT_TEMPLATE_SHORT_LIST_FIELD_LABELS = ['UUID', 'Name', 'Goal', 'Strategy']
# Audit
AUDIT_FIELDS = ['uuid', 'name', 'created_at', 'updated_at', 'deleted_at',
AUDIT_FIELDS = ['uuid', 'created_at', 'updated_at', 'deleted_at',
'state', 'audit_type', 'parameters', 'interval', 'goal_name',
'strategy_name', 'scope', 'auto_trigger', 'next_run_time']
AUDIT_FIELD_LABELS = ['UUID', 'Name', 'Created At', 'Updated At', 'Deleted At',
AUDIT_FIELD_LABELS = ['UUID', 'Created At', 'Updated At', 'Deleted At',
'State', 'Audit Type', 'Parameters', 'Interval', 'Goal',
'Strategy', 'Audit Scope', 'Auto Trigger',
'Next Run Time']
AUDIT_SHORT_LIST_FIELDS = ['uuid', 'name', 'audit_type',
AUDIT_SHORT_LIST_FIELDS = ['uuid', 'audit_type',
'state', 'goal_name', 'strategy_name',
'auto_trigger']
AUDIT_SHORT_LIST_FIELD_LABELS = ['UUID', 'Name', 'Audit Type', 'State', 'Goal',
AUDIT_SHORT_LIST_FIELD_LABELS = ['UUID', 'Audit Type', 'State', 'Goal',
'Strategy', 'Auto Trigger']
# Action Plan
@@ -61,8 +61,6 @@ ACTION_PLAN_SHORT_LIST_FIELDS = ['uuid', 'audit_uuid', 'state',
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',