diff --git a/openstack_dashboard/dashboards/admin/rbac_policies/forms.py b/openstack_dashboard/dashboards/admin/rbac_policies/forms.py index ad02a94747..af02a238e1 100644 --- a/openstack_dashboard/dashboards/admin/rbac_policies/forms.py +++ b/openstack_dashboard/dashboards/admin/rbac_policies/forms.py @@ -65,6 +65,7 @@ class CreatePolicyForm(forms.SelfHandlingForm): 'data-switch-on': 'action_object_type', 'data-action_object_type-shared_network': _('Network'), 'data-action_object_type-external_network': _('Network'), + 'data-required-when-shown': 'true', }), required=False) qos_policy_id = forms.ThemableChoiceField( @@ -73,9 +74,22 @@ class CreatePolicyForm(forms.SelfHandlingForm): 'class': 'switched', 'data-switch-on': 'action_object_type', 'data-action_object_type-shared_qos_policy': _('QoS Policy'), + 'data-required-when-shown': 'true', }), required=False) + def clean(self): + cleaned_data = super(CreatePolicyForm, self).clean() + action_object_type = cleaned_data.get("action_object_type") + error_msg = _("This field is required.") + if action_object_type in ["shared_network", "external_network"]: + if not cleaned_data.get("network_id"): + self._errors['network_id'] = self.error_class([error_msg]) + elif action_object_type == "shared_qos_policy": + if not cleaned_data.get("qos_policy_id"): + self._errors['qos_policy_id'] = self.error_class([error_msg]) + return cleaned_data + def __init__(self, request, *args, **kwargs): super(CreatePolicyForm, self).__init__(request, *args, **kwargs) tenant_choices = [('', _("Select a project"))] diff --git a/openstack_dashboard/dashboards/admin/rbac_policies/tests.py b/openstack_dashboard/dashboards/admin/rbac_policies/tests.py index 8e2d53b955..d17cfcf9e0 100644 --- a/openstack_dashboard/dashboards/admin/rbac_policies/tests.py +++ b/openstack_dashboard/dashboards/admin/rbac_policies/tests.py @@ -12,6 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. from django.urls import reverse +import mock from openstack_dashboard import api from openstack_dashboard.test import helpers as test @@ -118,3 +119,63 @@ class RBACPolicyTests(test.BaseAdminViewTests): 'object_id': qos_policy.id} self.mock_rbac_policy_create.assert_called_once_with( test.IsHttpRequest(), **params) + + @test.create_mocks({api.neutron: ('network_list', + 'is_extension_supported',), + api.keystone: ('tenant_list',)}) + def test_rbac_create_post_with_network_type_and_no_network_id(self): + tenants = self.tenants.list() + rbac_policy = self.rbac_policies.first() + + self.mock_tenant_list.return_value = [tenants, False] + self.mock_network_list.return_value = self.networks.list() + self.mock_is_extension_supported.return_value = False + + form_data = {'target_tenant': rbac_policy.target_tenant, + 'action_object_type': 'external_network', + 'network_id': None} + url = reverse('horizon:admin:rbac_policies:create') + res = self.client.post(url, form_data) + + self.assertFormErrors(res, 1) + self.assertContains(res, "This field is required.") + + self.assert_mock_multiple_calls_with_same_arguments( + self.mock_tenant_list, 2, mock.call(test.IsHttpRequest())) + self.assert_mock_multiple_calls_with_same_arguments( + self.mock_network_list, 2, mock.call(test.IsHttpRequest())) + self.assert_mock_multiple_calls_with_same_arguments( + self.mock_is_extension_supported, 2, + mock.call(test.IsHttpRequest(), extension_alias='qos')) + + @test.create_mocks({api.neutron: ('network_list', + 'policy_list', + 'is_extension_supported',), + api.keystone: ('tenant_list',)}) + def test_rbac_create_post_with_qos_policy_type_and_no_qos_policy_id(self): + tenants = self.tenants.list() + rbac_policy = self.rbac_policies.filter(object_type="qos_policy")[0] + + self.mock_tenant_list.return_value = [tenants, False] + self.mock_network_list.return_value = self.networks.list() + self.mock_policy_list.return_value = self.qos_policies.list() + self.mock_is_extension_supported.return_value = True + + form_data = {'target_tenant': rbac_policy.target_tenant, + 'action_object_type': 'shared_qos_policy', + 'qos_policy_id': None} + url = reverse('horizon:admin:rbac_policies:create') + res = self.client.post(url, form_data) + + self.assertFormErrors(res, 1) + self.assertContains(res, "This field is required.") + + self.assert_mock_multiple_calls_with_same_arguments( + self.mock_tenant_list, 2, mock.call(test.IsHttpRequest())) + self.assert_mock_multiple_calls_with_same_arguments( + self.mock_network_list, 2, mock.call(test.IsHttpRequest())) + self.assert_mock_multiple_calls_with_same_arguments( + self.mock_policy_list, 2, mock.call(test.IsHttpRequest())) + self.assert_mock_multiple_calls_with_same_arguments( + self.mock_is_extension_supported, 2, + mock.call(test.IsHttpRequest(), extension_alias='qos'))