summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTatyanaGladysheva <tgladysheva@mirantis.com>2016-01-12 15:37:45 +0300
committerSergei Chipiga <schipiga@mirantis.com>2016-04-20 11:14:02 +0300
commiteda58de3f669abb0991bdaad791158e420615ccb (patch)
treec87331abcc4db9837bd78bd25970c076ad1e3886
parent5d6003971f1c41abecd19c40b1384f9efa5210de (diff)
Added test for check stacks creation and deletion functionality
Test checks that create/delete stacks actions are executed without errors under admin user. Stacks page object was defined similar to other pages. Few other modifications I've made: * horizon.conf - service_available section with new heat option * stack template is added as separate file Depends-On: I1f5dc1220aee39103289a579583095346cce0354 Implements blueprint: horizon-integration-tests-coverage Change-Id: Ibc549f9ae4eac17d8e92d65afe1c5cee9be6e72e
Notes
Notes (review): Code-Review+2: Timur Sufiev <tsufiev@mirantis.com> Workflow+1: Timur Sufiev <tsufiev@mirantis.com> Code-Review+1: Sergei Chipiga <schipiga@mirantis.com> Verified+2: Jenkins Submitted-by: Jenkins Submitted-at: Wed, 20 Apr 2016 10:46:24 +0000 Reviewed-on: https://review.openstack.org/266368 Project: openstack/horizon Branch: refs/heads/master
-rw-r--r--openstack_dashboard/test/integration_tests/config.py2
-rw-r--r--openstack_dashboard/test/integration_tests/horizon.conf2
-rw-r--r--openstack_dashboard/test/integration_tests/pages/project/compute/access_and_security/keypairspage.py11
-rw-r--r--openstack_dashboard/test/integration_tests/pages/project/orchestration/stackspage.py97
-rw-r--r--openstack_dashboard/test/integration_tests/tests/test-data/stack_template11
-rw-r--r--openstack_dashboard/test/integration_tests/tests/test_stacks.py70
-rw-r--r--tools/gate/integration/devstack_exports.sh6
-rw-r--r--tools/gate/integration/devstack_gate_rc4
8 files changed, 197 insertions, 6 deletions
diff --git a/openstack_dashboard/test/integration_tests/config.py b/openstack_dashboard/test/integration_tests/config.py
index c4acee3..c5cfc2f 100644
--- a/openstack_dashboard/test/integration_tests/config.py
+++ b/openstack_dashboard/test/integration_tests/config.py
@@ -70,6 +70,8 @@ NetworkGroup = [
70AvailableServiceGroup = [ 70AvailableServiceGroup = [
71 cfg.BoolOpt('neutron', 71 cfg.BoolOpt('neutron',
72 default=True), 72 default=True),
73 cfg.BoolOpt('heat',
74 default=True),
73] 75]
74 76
75SeleniumGroup = [ 77SeleniumGroup = [
diff --git a/openstack_dashboard/test/integration_tests/horizon.conf b/openstack_dashboard/test/integration_tests/horizon.conf
index 2707381..a570280 100644
--- a/openstack_dashboard/test/integration_tests/horizon.conf
+++ b/openstack_dashboard/test/integration_tests/horizon.conf
@@ -67,6 +67,8 @@ tenant_network_cidr=10.100.0.0/16
67[service_available] 67[service_available]
68# Whether is Neutron expected to be available (boolean value) 68# Whether is Neutron expected to be available (boolean value)
69neutron=True 69neutron=True
70# Whether is Heat expected to be available (boolean value)
71heat=True
70 72
71[scenario] 73[scenario]
72# ssh username for image file (string value) 74# ssh username for image file (string value)
diff --git a/openstack_dashboard/test/integration_tests/pages/project/compute/access_and_security/keypairspage.py b/openstack_dashboard/test/integration_tests/pages/project/compute/access_and_security/keypairspage.py
index 9c24358..2c3a93e 100644
--- a/openstack_dashboard/test/integration_tests/pages/project/compute/access_and_security/keypairspage.py
+++ b/openstack_dashboard/test/integration_tests/pages/project/compute/access_and_security/keypairspage.py
@@ -34,6 +34,11 @@ class KeypairsTable(tables.TableRegion):
34 delete_button.click() 34 delete_button.click()
35 return forms.BaseFormRegion(self.driver, self.conf) 35 return forms.BaseFormRegion(self.driver, self.conf)
36 36
37 @tables.bind_table_action('delete')
38 def delete_keypairs(self, delete_button):
39 delete_button.click()
40 return forms.BaseFormRegion(self.driver, self.conf)
41
37 42
38class KeypairsPage(basepage.BaseNavigationPage): 43class KeypairsPage(basepage.BaseNavigationPage):
39 44
@@ -69,3 +74,9 @@ class KeypairsPage(basepage.BaseNavigationPage):
69 row = self._get_row_with_keypair_name(name) 74 row = self._get_row_with_keypair_name(name)
70 delete_keypair_form = self.keypairs_table.delete_keypair(row) 75 delete_keypair_form = self.keypairs_table.delete_keypair(row)
71 delete_keypair_form.submit() 76 delete_keypair_form.submit()
77
78 def delete_keypairs(self, name):
79 row = self._get_row_with_keypair_name(name)
80 row.mark()
81 delete_keypair_form = self.keypairs_table.delete_keypairs()
82 delete_keypair_form.submit()
diff --git a/openstack_dashboard/test/integration_tests/pages/project/orchestration/stackspage.py b/openstack_dashboard/test/integration_tests/pages/project/orchestration/stackspage.py
new file mode 100644
index 0000000..642a0c7
--- /dev/null
+++ b/openstack_dashboard/test/integration_tests/pages/project/orchestration/stackspage.py
@@ -0,0 +1,97 @@
1# Licensed under the Apache License, Version 2.0 (the "License"); you may
2# not use this file except in compliance with the License. You may obtain
3# a copy of the License at
4#
5# http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10# License for the specific language governing permissions and limitations
11# under the License.
12
13from openstack_dashboard.test.integration_tests import config
14from openstack_dashboard.test.integration_tests.pages import basepage
15from openstack_dashboard.test.integration_tests.regions import forms
16from openstack_dashboard.test.integration_tests.regions import tables
17
18
19class StacksTable(tables.TableRegion):
20 name = "stacks"
21 SELECT_TEMPLATE_FORM_FIELDS = ("template_source", "template_upload",
22 "template_data", "template_url",
23 "environment_source", "environment_upload",
24 "environment_data")
25 LAUNCH_STACK_FORM_FIELDS = ("stack_name", "timeout_mins",
26 "enable_rollback", "password")
27
28 @tables.bind_table_action('launch')
29 def select_template(self, launch_button):
30 launch_button.click()
31 return forms.FormRegion(
32 self.driver, self.conf,
33 field_mappings=self.SELECT_TEMPLATE_FORM_FIELDS)
34
35 def launch_stack(self):
36 return forms.FormRegion(self.driver, self.conf,
37 field_mappings=self.LAUNCH_STACK_FORM_FIELDS)
38
39 @tables.bind_table_action('delete')
40 def delete_stack(self, delete_button):
41 delete_button.click()
42 return forms.BaseFormRegion(self.driver, self.conf)
43
44
45class StacksPage(basepage.BaseNavigationPage):
46 DEFAULT_TEMPLATE_SOURCE = 'raw'
47
48 CONFIG = config.get_config()
49 DEFAULT_PASSWORD = CONFIG.identity.admin_password
50 STACKS_TABLE_NAME_COLUMN = 'name'
51 STACKS_TABLE_STATUS_COLUMN = 'stack_status'
52
53 def __init__(self, driver, conf):
54 super(StacksPage, self).__init__(driver, conf)
55 self._page_title = "Stacks"
56
57 @property
58 def stacks_table(self):
59 return StacksTable(self.driver, self.conf)
60
61 def _get_row_with_stack_name(self, name):
62 return self.stacks_table.get_row(self.STACKS_TABLE_NAME_COLUMN, name)
63
64 def create_stack(self, stack_name, template_data,
65 template_source=DEFAULT_TEMPLATE_SOURCE,
66 environment_source=None,
67 environment_upload=None,
68 timeout_mins=None,
69 enable_rollback=None,
70 password=DEFAULT_PASSWORD):
71 select_template_form = self.stacks_table.select_template()
72 select_template_form.template_source.value = template_source
73 select_template_form.template_data.text = template_data
74 select_template_form.submit()
75 launch_stack_form = self.stacks_table.launch_stack()
76 launch_stack_form.stack_name.text = stack_name
77 launch_stack_form.password.text = password
78 launch_stack_form.submit()
79
80 def delete_stack(self, name):
81 row = self._get_row_with_stack_name(name)
82 row.mark()
83 confirm_delete_stacks_form = self.stacks_table.delete_stack()
84 confirm_delete_stacks_form.submit()
85
86 def is_stack_present(self, name):
87 return bool(self._get_row_with_stack_name(name))
88
89 def is_stack_create_complete(self, name):
90 row = self._get_row_with_stack_name(name)
91 return self.stacks_table.wait_cell_status(
92 lambda: row and row.cells[self.STACKS_TABLE_STATUS_COLUMN],
93 'Create Complete')
94
95 def is_stack_deleted(self, name):
96 return self.stacks_table.is_row_deleted(
97 lambda: self._get_row_with_stack_name(name))
diff --git a/openstack_dashboard/test/integration_tests/tests/test-data/stack_template b/openstack_dashboard/test/integration_tests/tests/test-data/stack_template
new file mode 100644
index 0000000..a86e585
--- /dev/null
+++ b/openstack_dashboard/test/integration_tests/tests/test-data/stack_template
@@ -0,0 +1,11 @@
1heat_template_version: 2013-05-23
2description: Simple template to deploy a single compute instance
3resources:
4 my_instance:
5 type: OS::Nova::Server
6 properties:
7 key_name: {0}
8 image: {1}
9 flavor: m1.tiny
10 networks:
11 - network: {2} \ No newline at end of file
diff --git a/openstack_dashboard/test/integration_tests/tests/test_stacks.py b/openstack_dashboard/test/integration_tests/tests/test_stacks.py
new file mode 100644
index 0000000..b60476b
--- /dev/null
+++ b/openstack_dashboard/test/integration_tests/tests/test_stacks.py
@@ -0,0 +1,70 @@
1# Licensed under the Apache License, Version 2.0 (the "License"); you may
2# not use this file except in compliance with the License. You may obtain
3# a copy of the License at
4#
5# http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10# License for the specific language governing permissions and limitations
11# under the License.
12import os
13
14from openstack_dashboard.test.integration_tests import decorators
15from openstack_dashboard.test.integration_tests import helpers
16from openstack_dashboard.test.integration_tests.regions import messages
17
18
19class TestStacks(helpers.AdminTestCase):
20 KEYPAIR_NAME = 'keypair_for_stack'
21 STACKS_NAME = helpers.gen_random_resource_name('stack', timestamp=False)
22 STACK_TEMPLATE_PATH = os.path.join(
23 os.path.dirname(__file__), 'test-data/stack_template')
24
25 def setUp(self):
26 super(TestStacks, self).setUp()
27 keypair_page = self.home_pg.\
28 go_to_compute_accessandsecurity_keypairspage()
29 keypair_page.create_keypair(self.KEYPAIR_NAME)
30 keypair_page = self.home_pg.\
31 go_to_compute_accessandsecurity_keypairspage()
32 self.assertTrue(keypair_page.is_keypair_present(self.KEYPAIR_NAME))
33
34 @decorators.services_required("heat")
35 def test_create_delete_stack(self):
36 """tests the stack creation and deletion functionality
37 * creates a new stack
38 * verifies the stack appears in the stacks table in Create Complete
39 state
40 * deletes the newly created stack
41 * verifies the stack does not appear in the table after deletion
42 """
43 with open(self.STACK_TEMPLATE_PATH, 'r') as f:
44 template = f.read()
45 input_template = template.format(self.KEYPAIR_NAME,
46 self.CONFIG.image.images_list[0],
47 "public")
48 stacks_page = self.home_pg.go_to_orchestration_stackspage()
49
50 stacks_page.create_stack(self.STACKS_NAME, input_template)
51 self.assertTrue(
52 stacks_page.find_message_and_dismiss(messages.INFO))
53 self.assertFalse(
54 stacks_page.find_message_and_dismiss(messages.ERROR))
55 self.assertTrue(stacks_page.is_stack_present(self.STACKS_NAME))
56 self.assertTrue(stacks_page.is_stack_create_complete(self.STACKS_NAME))
57
58 stacks_page.delete_stack(self.STACKS_NAME)
59 self.assertTrue(
60 stacks_page.find_message_and_dismiss(messages.SUCCESS))
61 self.assertFalse(
62 stacks_page.find_message_and_dismiss(messages.ERROR))
63 self.assertTrue(stacks_page.is_stack_deleted(self.STACKS_NAME))
64
65 def tearDown(self):
66 keypair_page = self.home_pg.\
67 go_to_compute_accessandsecurity_keypairspage()
68 keypair_page.delete_keypairs(self.KEYPAIR_NAME)
69 keypair_page.find_message_and_dismiss(messages.SUCCESS)
70 super(TestStacks, self).tearDown()
diff --git a/tools/gate/integration/devstack_exports.sh b/tools/gate/integration/devstack_exports.sh
deleted file mode 100644
index ce5593e..0000000
--- a/tools/gate/integration/devstack_exports.sh
+++ /dev/null
@@ -1,6 +0,0 @@
1export PYTHONUNBUFFERED=true
2export DEVSTACK_GATE_TIMEOUT=90
3export DEVSTACK_GATE_TEMPEST=0
4export DEVSTACK_GATE_EXERCISES=0
5export DEVSTACK_GATE_INSTALL_TESTONLY=1
6export DEVSTACK_GATE_NEUTRON=1
diff --git a/tools/gate/integration/devstack_gate_rc b/tools/gate/integration/devstack_gate_rc
new file mode 100644
index 0000000..1579b49
--- /dev/null
+++ b/tools/gate/integration/devstack_gate_rc
@@ -0,0 +1,4 @@
1# This file contains various customized Devstack settings that Horizon uses at
2# gate for integration tests job
3
4export ENABLED_SERVICES=heat,h-eng,h-api,h-api-cfn,h-api-cw