Tempest API tests on /actions
Following the blueprint tempest-basic-set-up which implemented a first batch of tests, this one adds a new set of API tests on actions. I also added extra check on actions within the dummy strategy scenario. Change-Id: Ib9bf093d0ed457ecba32e8251c019d2cf5c98128 Closes-Bug: #1538074
This commit is contained in:
		@@ -54,25 +54,6 @@ class InfraOptimClientJSON(base.BaseInfraOptimClient):
 | 
			
		||||
        """
 | 
			
		||||
        return self._show_request('audit_templates', audit_template_uuid)
 | 
			
		||||
 | 
			
		||||
    @base.handle_errors
 | 
			
		||||
    def filter_audit_template_by_host_aggregate(self, host_aggregate):
 | 
			
		||||
        """Gets an audit template associated with given host agregate ID.
 | 
			
		||||
 | 
			
		||||
        :param host_aggregate: Unique identifier of the host aggregate
 | 
			
		||||
        :return: Serialized audit template as a dictionary.
 | 
			
		||||
        """
 | 
			
		||||
        return self._list_request('/audit_templates',
 | 
			
		||||
                                  host_aggregate=host_aggregate)
 | 
			
		||||
 | 
			
		||||
    @base.handle_errors
 | 
			
		||||
    def filter_audit_template_by_goal(self, goal):
 | 
			
		||||
        """Gets an audit template associated with given goal.
 | 
			
		||||
 | 
			
		||||
        :param goal: goal identifier
 | 
			
		||||
        :return: Serialized audit template as a dictionary.
 | 
			
		||||
        """
 | 
			
		||||
        return self._list_request('/audit_templates', goal=goal)
 | 
			
		||||
 | 
			
		||||
    @base.handle_errors
 | 
			
		||||
    def create_audit_template(self, **kwargs):
 | 
			
		||||
        """Creates an audit template with the specified parameters.
 | 
			
		||||
@@ -139,12 +120,6 @@ class InfraOptimClientJSON(base.BaseInfraOptimClient):
 | 
			
		||||
        """Lists details of all existing audit templates."""
 | 
			
		||||
        return self._list_request('/audits/detail', **kwargs)
 | 
			
		||||
 | 
			
		||||
    @base.handle_errors
 | 
			
		||||
    def list_audit_by_audit_template(self, audit_template_uuid):
 | 
			
		||||
        """Lists all audits associated with an audit template."""
 | 
			
		||||
        return self._list_request(
 | 
			
		||||
            '/audits', audit_template=audit_template_uuid)
 | 
			
		||||
 | 
			
		||||
    @base.handle_errors
 | 
			
		||||
    def show_audit(self, audit_uuid):
 | 
			
		||||
        """Gets a specific audit template.
 | 
			
		||||
@@ -254,3 +229,24 @@ class InfraOptimClientJSON(base.BaseInfraOptimClient):
 | 
			
		||||
        :return: Serialized goal as a dictionary
 | 
			
		||||
        """
 | 
			
		||||
        return self._show_request('/goals', goal)
 | 
			
		||||
 | 
			
		||||
    # ### ACTIONS ### #
 | 
			
		||||
 | 
			
		||||
    @base.handle_errors
 | 
			
		||||
    def list_actions(self, **kwargs):
 | 
			
		||||
        """List all existing actions"""
 | 
			
		||||
        return self._list_request('/actions', **kwargs)
 | 
			
		||||
 | 
			
		||||
    @base.handle_errors
 | 
			
		||||
    def list_actions_detail(self, **kwargs):
 | 
			
		||||
        """Lists details of all existing actions"""
 | 
			
		||||
        return self._list_request('/actions/detail', **kwargs)
 | 
			
		||||
 | 
			
		||||
    @base.handle_errors
 | 
			
		||||
    def show_action(self, action_uuid):
 | 
			
		||||
        """Gets a specific action
 | 
			
		||||
 | 
			
		||||
        :param action_uuid: Unique identifier of the action
 | 
			
		||||
        :return: Serialized action as a dictionary
 | 
			
		||||
        """
 | 
			
		||||
        return self._show_request('/actions', action_uuid)
 | 
			
		||||
 
 | 
			
		||||
@@ -22,11 +22,6 @@ from tempest_lib import exceptions as lib_exc
 | 
			
		||||
 | 
			
		||||
from watcher_tempest_plugin import infra_optim_clients as clients
 | 
			
		||||
 | 
			
		||||
# Resources must be deleted in a specific order, this list
 | 
			
		||||
# defines the resource types to clean up, and the correct order.
 | 
			
		||||
RESOURCE_TYPES = ['audit_template', 'audit', 'action_plan']
 | 
			
		||||
# RESOURCE_TYPES = ['action', 'action_plan', 'audit', 'audit_template']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def creates(resource):
 | 
			
		||||
    """Decorator that adds resources to the appropriate cleanup list."""
 | 
			
		||||
@@ -47,6 +42,8 @@ def creates(resource):
 | 
			
		||||
class BaseInfraOptimTest(test.BaseTestCase):
 | 
			
		||||
    """Base class for Infrastructure Optimization API tests."""
 | 
			
		||||
 | 
			
		||||
    RESOURCE_TYPES = ['audit_template', 'audit']
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def setup_credentials(cls):
 | 
			
		||||
        super(BaseInfraOptimTest, cls).setup_credentials()
 | 
			
		||||
@@ -62,19 +59,18 @@ class BaseInfraOptimTest(test.BaseTestCase):
 | 
			
		||||
        super(BaseInfraOptimTest, cls).resource_setup()
 | 
			
		||||
 | 
			
		||||
        cls.created_objects = {}
 | 
			
		||||
        for resource in RESOURCE_TYPES:
 | 
			
		||||
        for resource in cls.RESOURCE_TYPES:
 | 
			
		||||
            cls.created_objects[resource] = set()
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def resource_cleanup(cls):
 | 
			
		||||
        """Ensure that all created objects get destroyed."""
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            for resource in RESOURCE_TYPES:
 | 
			
		||||
                uuids = cls.created_objects[resource]
 | 
			
		||||
            for resource in cls.RESOURCE_TYPES:
 | 
			
		||||
                obj_uuids = cls.created_objects[resource]
 | 
			
		||||
                delete_method = getattr(cls.client, 'delete_%s' % resource)
 | 
			
		||||
                for u in uuids:
 | 
			
		||||
                    delete_method(u, ignore_errors=lib_exc.NotFound)
 | 
			
		||||
                for obj_uuid in obj_uuids:
 | 
			
		||||
                    delete_method(obj_uuid, ignore_errors=lib_exc.NotFound)
 | 
			
		||||
        finally:
 | 
			
		||||
            super(BaseInfraOptimTest, cls).resource_cleanup()
 | 
			
		||||
 | 
			
		||||
@@ -178,21 +174,6 @@ class BaseInfraOptimTest(test.BaseTestCase):
 | 
			
		||||
 | 
			
		||||
    # ### ACTION PLANS ### #
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    @creates('action_plan')
 | 
			
		||||
    def start_action_plan(cls, audit_uuid, type='ONESHOT',
 | 
			
		||||
                          state='PENDING', deadline=None):
 | 
			
		||||
        """Wrapper utility for creating a test action plan
 | 
			
		||||
 | 
			
		||||
        :param audit_uuid: Audit Template UUID this action plan will use
 | 
			
		||||
        :param type: Audit type (either ONESHOT or CONTINUOUS)
 | 
			
		||||
        :return: A tuple with The HTTP response and its body
 | 
			
		||||
        """
 | 
			
		||||
        resp, body = cls.client.create_action_plan(
 | 
			
		||||
            audit_uuid=audit_uuid, type=type,
 | 
			
		||||
            state=state, deadline=deadline)
 | 
			
		||||
        return resp, body
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def delete_action_plan(cls, action_plan_uuid):
 | 
			
		||||
        """Deletes an action plan having the specified UUID
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										102
									
								
								watcher_tempest_plugin/tests/api/admin/test_action.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								watcher_tempest_plugin/tests/api/admin/test_action.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,102 @@
 | 
			
		||||
# -*- encoding: utf-8 -*-
 | 
			
		||||
# 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 __future__ import unicode_literals
 | 
			
		||||
 | 
			
		||||
import collections
 | 
			
		||||
import functools
 | 
			
		||||
 | 
			
		||||
from tempest import test
 | 
			
		||||
 | 
			
		||||
from watcher_tempest_plugin.tests.api.admin import base
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestShowListAction(base.BaseInfraOptimTest):
 | 
			
		||||
    """Tests for actions"""
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def resource_setup(cls):
 | 
			
		||||
        super(TestShowListAction, cls).resource_setup()
 | 
			
		||||
        _, cls.audit_template = cls.create_audit_template()
 | 
			
		||||
        _, cls.audit = cls.create_audit(cls.audit_template['uuid'])
 | 
			
		||||
 | 
			
		||||
        assert test.call_until_true(
 | 
			
		||||
            func=functools.partial(cls.has_audit_succeeded, cls.audit['uuid']),
 | 
			
		||||
            duration=30,
 | 
			
		||||
            sleep_for=.5
 | 
			
		||||
        )
 | 
			
		||||
        _, action_plans = cls.client.list_action_plan_by_audit(
 | 
			
		||||
            cls.audit['uuid'])
 | 
			
		||||
        cls.action_plan = action_plans['action_plans'][0]
 | 
			
		||||
 | 
			
		||||
    @test.attr(type='smoke')
 | 
			
		||||
    def test_show_one_action(self):
 | 
			
		||||
        _, action = self.client.show_action(
 | 
			
		||||
            self.action_plan["first_action_uuid"])
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(action['uuid'], self.action_plan["first_action_uuid"])
 | 
			
		||||
        self.assertEqual(action['action_type'], "nop")
 | 
			
		||||
        self.assertEqual(action['state'], "PENDING")
 | 
			
		||||
 | 
			
		||||
    @test.attr(type='smoke')
 | 
			
		||||
    def test_show_action_with_links(self):
 | 
			
		||||
        _, action = self.client.show_action(
 | 
			
		||||
            self.action_plan["first_action_uuid"])
 | 
			
		||||
        self.assertIn('links', action.keys())
 | 
			
		||||
        self.assertEqual(2, len(action['links']))
 | 
			
		||||
        self.assertIn(action['uuid'], action['links'][0]['href'])
 | 
			
		||||
 | 
			
		||||
    @test.attr(type="smoke")
 | 
			
		||||
    def test_list_actions(self):
 | 
			
		||||
        _, body = self.client.list_actions()
 | 
			
		||||
 | 
			
		||||
        # Verify self links.
 | 
			
		||||
        for action in body['actions']:
 | 
			
		||||
            self.validate_self_link('actions', action['uuid'],
 | 
			
		||||
                                    action['links'][0]['href'])
 | 
			
		||||
 | 
			
		||||
    @test.attr(type="smoke")
 | 
			
		||||
    def test_list_actions_by_action_plan(self):
 | 
			
		||||
        _, body = self.client.list_actions(
 | 
			
		||||
            action_plan_uuid=self.action_plan["uuid"])
 | 
			
		||||
 | 
			
		||||
        for item in body['actions']:
 | 
			
		||||
            self.assertEqual(self.action_plan["uuid"],
 | 
			
		||||
                             item['action_plan_uuid'])
 | 
			
		||||
 | 
			
		||||
        action_counter = collections.Counter(
 | 
			
		||||
            act['action_type'] for act in body['actions'])
 | 
			
		||||
 | 
			
		||||
        # A dummy strategy generates 2 "nop" actions and 1 "sleep" action
 | 
			
		||||
        self.assertEqual(len(body['actions']), 3)
 | 
			
		||||
        self.assertEqual(action_counter.get("nop"), 2)
 | 
			
		||||
        self.assertEqual(action_counter.get("sleep"), 1)
 | 
			
		||||
 | 
			
		||||
    @test.attr(type="smoke")
 | 
			
		||||
    def test_list_actions_by_audit(self):
 | 
			
		||||
        _, body = self.client.list_actions(audit_uuid=self.audit["uuid"])
 | 
			
		||||
 | 
			
		||||
        for item in body['actions']:
 | 
			
		||||
            self.assertEqual(self.action_plan["uuid"],
 | 
			
		||||
                             item['action_plan_uuid'])
 | 
			
		||||
 | 
			
		||||
        action_counter = collections.Counter(
 | 
			
		||||
            act['action_type'] for act in body['actions'])
 | 
			
		||||
 | 
			
		||||
        # A dummy strategy generates 2 "nop" actions and 1 "sleep" action
 | 
			
		||||
        self.assertEqual(len(body['actions']), 3)
 | 
			
		||||
        self.assertEqual(action_counter.get("nop"), 2)
 | 
			
		||||
        self.assertEqual(action_counter.get("sleep"), 1)
 | 
			
		||||
@@ -34,7 +34,7 @@ class TestCreateDeleteExecuteActionPlan(base.BaseInfraOptimTest):
 | 
			
		||||
 | 
			
		||||
        self.assertTrue(test.call_until_true(
 | 
			
		||||
            func=functools.partial(self.has_audit_succeeded, audit['uuid']),
 | 
			
		||||
            duration=10,
 | 
			
		||||
            duration=30,
 | 
			
		||||
            sleep_for=.5
 | 
			
		||||
        ))
 | 
			
		||||
        _, action_plans = self.client.list_action_plan_by_audit(audit['uuid'])
 | 
			
		||||
@@ -52,7 +52,7 @@ class TestCreateDeleteExecuteActionPlan(base.BaseInfraOptimTest):
 | 
			
		||||
 | 
			
		||||
        self.assertTrue(test.call_until_true(
 | 
			
		||||
            func=functools.partial(self.has_audit_succeeded, audit['uuid']),
 | 
			
		||||
            duration=10,
 | 
			
		||||
            duration=30,
 | 
			
		||||
            sleep_for=.5
 | 
			
		||||
        ))
 | 
			
		||||
        _, action_plans = self.client.list_action_plan_by_audit(audit['uuid'])
 | 
			
		||||
@@ -72,7 +72,7 @@ class TestCreateDeleteExecuteActionPlan(base.BaseInfraOptimTest):
 | 
			
		||||
 | 
			
		||||
        self.assertTrue(test.call_until_true(
 | 
			
		||||
            func=functools.partial(self.has_audit_succeeded, audit['uuid']),
 | 
			
		||||
            duration=10,
 | 
			
		||||
            duration=30,
 | 
			
		||||
            sleep_for=.5
 | 
			
		||||
        ))
 | 
			
		||||
        _, action_plans = self.client.list_action_plan_by_audit(audit['uuid'])
 | 
			
		||||
@@ -89,7 +89,7 @@ class TestCreateDeleteExecuteActionPlan(base.BaseInfraOptimTest):
 | 
			
		||||
        self.assertTrue(test.call_until_true(
 | 
			
		||||
            func=functools.partial(
 | 
			
		||||
                self.has_action_plan_finished, action_plan['uuid']),
 | 
			
		||||
            duration=10,
 | 
			
		||||
            duration=30,
 | 
			
		||||
            sleep_for=.5
 | 
			
		||||
        ))
 | 
			
		||||
        _, finished_ap = self.client.show_action_plan(action_plan['uuid'])
 | 
			
		||||
@@ -109,7 +109,7 @@ class TestShowListActionPlan(base.BaseInfraOptimTest):
 | 
			
		||||
 | 
			
		||||
        assert test.call_until_true(
 | 
			
		||||
            func=functools.partial(cls.has_audit_succeeded, cls.audit['uuid']),
 | 
			
		||||
            duration=10,
 | 
			
		||||
            duration=30,
 | 
			
		||||
            sleep_for=.5
 | 
			
		||||
        )
 | 
			
		||||
        _, action_plans = cls.client.list_action_plan_by_audit(
 | 
			
		||||
 
 | 
			
		||||
@@ -179,9 +179,8 @@ class TestShowListAudit(base.BaseInfraOptimTest):
 | 
			
		||||
        self.assertEqual(len(body['audits']), 3)
 | 
			
		||||
        self.assertIn(next_marker, body['next'])
 | 
			
		||||
 | 
			
		||||
    # @decorators.skip_because(bug="1533220")
 | 
			
		||||
    @test.attr(type='smoke')
 | 
			
		||||
    def test_list_audits_related_to_given_audit_template(self):
 | 
			
		||||
        _, body = self.client.list_audit_by_audit_template(
 | 
			
		||||
            self.audit_template['uuid'])
 | 
			
		||||
        _, body = self.client.list_audits(
 | 
			
		||||
            audit_template=self.audit_template['uuid'])
 | 
			
		||||
        self.assertIn(self.audit['uuid'], [n['uuid'] for n in body['audits']])
 | 
			
		||||
 
 | 
			
		||||
@@ -88,8 +88,8 @@ class TestAuditTemplate(base.BaseInfraOptimTest):
 | 
			
		||||
    @decorators.skip_because(bug="1510189")
 | 
			
		||||
    @test.attr(type='smoke')
 | 
			
		||||
    def test_filter_audit_template_by_goal(self):
 | 
			
		||||
        _, audit_template = self.client.\
 | 
			
		||||
            filter_audit_template_by_goal(self.audit_template['goal'])
 | 
			
		||||
        _, audit_template = self.client.list_audit_templates(
 | 
			
		||||
            goal=self.audit_template['goal'])
 | 
			
		||||
 | 
			
		||||
        self.assert_expected(self.audit_template,
 | 
			
		||||
                             audit_template['audit_templates'][0])
 | 
			
		||||
@@ -97,9 +97,8 @@ class TestAuditTemplate(base.BaseInfraOptimTest):
 | 
			
		||||
    @decorators.skip_because(bug="1510189")
 | 
			
		||||
    @test.attr(type='smoke')
 | 
			
		||||
    def test_filter_audit_template_by_host_aggregate(self):
 | 
			
		||||
        _, audit_template = self.client.\
 | 
			
		||||
            filter_audit_template_by_host_aggregate(
 | 
			
		||||
                self.audit_template['host_aggregate'])
 | 
			
		||||
        _, audit_template = self.client.list_audit_templates(
 | 
			
		||||
            host_aggregate=self.audit_template['host_aggregate'])
 | 
			
		||||
 | 
			
		||||
        self.assert_expected(self.audit_template,
 | 
			
		||||
                             audit_template['audit_templates'][0])
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@
 | 
			
		||||
 | 
			
		||||
from __future__ import unicode_literals
 | 
			
		||||
 | 
			
		||||
import collections
 | 
			
		||||
import functools
 | 
			
		||||
 | 
			
		||||
from tempest import test
 | 
			
		||||
@@ -62,6 +63,16 @@ class TestExecuteDummyStrategy(base.BaseInfraOptimScenarioTest):
 | 
			
		||||
            sleep_for=.5
 | 
			
		||||
        ))
 | 
			
		||||
        _, finished_ap = self.client.show_action_plan(action_plan['uuid'])
 | 
			
		||||
        _, action_list = self.client.list_actions(
 | 
			
		||||
            action_plan_uuid=finished_ap["uuid"])
 | 
			
		||||
 | 
			
		||||
        action_counter = collections.Counter(
 | 
			
		||||
            act['action_type'] for act in action_list['actions'])
 | 
			
		||||
 | 
			
		||||
        self.assertIn(updated_ap['state'], ('TRIGGERED', 'ONGOING'))
 | 
			
		||||
        self.assertEqual(finished_ap['state'], 'SUCCEEDED')
 | 
			
		||||
 | 
			
		||||
        # A dummy strategy generates 2 "nop" actions and 1 "sleep" action
 | 
			
		||||
        self.assertEqual(len(action_list['actions']), 3)
 | 
			
		||||
        self.assertEqual(action_counter.get("nop"), 2)
 | 
			
		||||
        self.assertEqual(action_counter.get("sleep"), 1)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user