diff --git a/muranodashboard/environments/tables.py b/muranodashboard/environments/tables.py index 75b55f86a..3ff79a5ab 100644 --- a/muranodashboard/environments/tables.py +++ b/muranodashboard/environments/tables.py @@ -48,6 +48,16 @@ def _get_environment_status_and_version(request, table): return status, version +def _check_row_actions_allowed(action, request): + envs = action.table.data + if not envs: + return False + for env in envs: + if action.allowed(request, env): + return True + return False + + class AddApplication(tables.LinkAction): name = 'AddApplication' verbose_name = _('Add Component') @@ -107,10 +117,13 @@ class DeleteEnvironment(tables.DeleteAction): ) def allowed(self, request, environment): - if environment: - return environment.status not in (consts.STATUS_ID_DEPLOYING, - consts.STATUS_ID_DELETING) - return True + # table action case: action allowed if any row action allowed + if not environment: + return _check_row_actions_allowed(self, request) + + # row action case + return environment.status not in (consts.STATUS_ID_DEPLOYING, + consts.STATUS_ID_DELETING) def action(self, request, environment_id): try: @@ -152,6 +165,12 @@ class AbandonEnvironment(tables.DeleteAction): * environment is new * app added to env, but not deploy is not started """ + + # table action case: action allowed if any row action allowed + if not environment: + return _check_row_actions_allowed(self, request) + + # row action case status = getattr(environment, 'status', None) if status in [consts.STATUS_ID_NEW, consts.STATUS_ID_PENDING]: return False @@ -234,6 +253,12 @@ class DeployEnvironment(tables.BatchAction): * no new services added to the environment (after env creation or successful deploy or delete failure) """ + + # table action case: action allowed if any row action allowed + if not environment: + return _check_row_actions_allowed(self, request) + + # row action case status = getattr(environment, 'status', None) if (status != consts.STATUS_ID_DEPLOY_FAILURE and not environment.has_new_services): @@ -371,10 +396,10 @@ class EnvironmentsTable(tables.DataTable): row_class = UpdateEnvironmentRow status_columns = ['status'] no_data_message = _('NO ENVIRONMENTS') - table_actions = (CreateEnvironment,) + table_actions = (CreateEnvironment, DeployEnvironment, + DeleteEnvironment, AbandonEnvironment) row_actions = (ShowEnvironmentServices, DeployEnvironment, DeleteEnvironment, AbandonEnvironment) - multi_select = False def get_service_details_link(service): diff --git a/muranodashboard/static/muranodashboard/js/environments-in-place.js b/muranodashboard/static/muranodashboard/js/environments-in-place.js index 114b9fd8e..15e8e25d9 100644 --- a/muranodashboard/static/muranodashboard/js/environments-in-place.js +++ b/muranodashboard/static/muranodashboard/js/environments-in-place.js @@ -46,7 +46,7 @@ $(function() { } var $newEnvTr = $('' + - '' + + '' + 'New' + '' + '
' + diff --git a/muranodashboard/tests/functional/consts.py b/muranodashboard/tests/functional/consts.py index 67f766cc3..22b4d1459 100644 --- a/muranodashboard/tests/functional/consts.py +++ b/muranodashboard/tests/functional/consts.py @@ -17,6 +17,7 @@ DeleteImageMeta = TestImage + "//td//button[contains(text(), 'Delete Metadata')] ImageMeta = "//dl[dt[contains(text(), 'murano_image_info')]]/dd" More = "//tr[contains(@id, '{0}__row__{1}')]//a[contains(@class, dropdown-toggle) and @href='#']" # noqa Status = "//td[contains(text(), '{0}')]" +EnvStatus = "//tr[contains(@data-display, '{0}')]/td[contains(text(), '{1}')]" CellStatus = "//td[contains(@class, 'status_{0}')]" Row = "//tr[contains(@id, 'services__row__{0}')]" ErrorMessage = '//span[contains(@class, "help-block") and contains(text(), "{0}")]' # noqa @@ -31,11 +32,15 @@ HotFlavorField = '//div[contains(@class, "has-error")]//input' ButtonSubmit = ".//*[@name='wizard_goto_step'][2]" InputSubmit = "//input[@type='submit']" ConfirmDeletion = "//div[@class='modal-footer']//a[contains(text(), 'Delete')]" # noqa +ConfirmAbandon = "//div[@class='modal-footer']//a[contains(text(), 'Abandon')]" # noqa UploadPackage = 'packages__action_upload_package' ImportBundle = 'packages__action_import_bundle' CreateEnvironment = ".add_env .btn" DeployEnvironment = "services__action_deploy_env" DeleteEnvironment = "//button[contains(@id, 'action_delete')]" +DeployEnvironments = ".btn#environments__action_deploy" +DeleteEnvironments = ".btn#environments__action_delete" +AbandonEnvironments = ".btn#environments__action_abandon" ConfirmCreateEnvironment = 'confirm_create_env' AddComponent = "services__action_AddApplication" AddCategory = "categories__action_add_category" diff --git a/muranodashboard/tests/functional/sanity_check.py b/muranodashboard/tests/functional/sanity_check.py index da5414c52..eaa7b4730 100644 --- a/muranodashboard/tests/functional/sanity_check.py +++ b/muranodashboard/tests/functional/sanity_check.py @@ -2071,3 +2071,81 @@ class TestSuiteCategoriesPagination(base.PackageTestCase): self.check_element_on_page(by.By.XPATH, c.Status.format(name)) if i != len(pages_itself): self.driver.find_element_by_xpath(c.PrevBtn).click() + + +class TestSuiteMultipleEnvironments(base.ApplicationTestCase): + def test_create_two_environments_and_delete_them_at_once(self): + """Test check ability to create and delete multiple environments + + Scenario: + 1. Create two environments + 2. Navigate to environment list + 3. Check created environments + 4. Delete created environments at once + """ + self.go_to_submenu('Environments') + self.create_environment('test_create_del_env_1') + self.go_to_submenu('Environments') + self.create_environment('test_create_del_env_2', by_id=True) + self.go_to_submenu('Environments') + self.driver.find_element_by_css_selector( + "label[for=ui-id-1]").click() + self.driver.find_element_by_css_selector( + c.DeleteEnvironments).click() + self.driver.find_element_by_xpath(c.ConfirmDeletion).click() + self.wait_for_alert_message() + self.check_element_not_on_page(by.By.LINK_TEXT, + 'test_create_del_env_1') + self.check_element_not_on_page(by.By.LINK_TEXT, + 'test_create_del_env_2') + + def test_deploy_two_environments_at_once(self): + """Test check ability to deploy multiple environments + + Scenario: + 1. Add two apps to different environments + 2. Navigate to environment list + 3. Check created environments + 4. Deploy created environments at once + """ + self.add_app_to_env(self.mockapp_id) + self.add_app_to_env(self.mockapp_id) + self.go_to_submenu('Environments') + self.driver.find_element_by_css_selector( + "label[for=ui-id-1]").click() + self.driver.find_element_by_css_selector( + c.DeployEnvironments).click() + # check statuses of two environments + self.check_element_on_page(by.By.XPATH, + c.EnvStatus.format('quick-env-1', 'Ready'), + sec=90) + self.check_element_on_page(by.By.XPATH, + c.EnvStatus.format('quick-env-2', 'Ready'), + sec=90) + + def test_abandon_two_environments_at_once(self): + """Test check ability to abandon multiple environments + + Scenario: + 1. Add two apps to different environments + 2. Navigate to environment list + 3. Check created environments + 4. Deploy created environments at once + 5. Abandon environments before they are deployed + """ + self.add_app_to_env(self.mockapp_id) + self.add_app_to_env(self.mockapp_id) + self.go_to_submenu('Environments') + self.driver.find_element_by_css_selector( + "label[for=ui-id-1]").click() + self.driver.find_element_by_css_selector( + c.DeployEnvironments).click() + self.go_to_submenu('Environments') + self.driver.find_element_by_css_selector( + "label[for=ui-id-1]").click() + self.driver.find_element_by_css_selector( + c.AbandonEnvironments).click() + self.driver.find_element_by_xpath(c.ConfirmAbandon).click() + self.wait_for_alert_message() + self.check_element_not_on_page(by.By.LINK_TEXT, 'quick-env-1') + self.check_element_not_on_page(by.By.LINK_TEXT, 'quick-env-2') diff --git a/releasenotes/notes/manage-multiple-envs-e587c2e9432e39d7.yaml b/releasenotes/notes/manage-multiple-envs-e587c2e9432e39d7.yaml new file mode 100644 index 000000000..39713c2ad --- /dev/null +++ b/releasenotes/notes/manage-multiple-envs-e587c2e9432e39d7.yaml @@ -0,0 +1,6 @@ +--- + +features: + - Added possibility for user to select several environments and execute + one of the three actions to all of them at once (delete, abandon or + deploy).