Add util for action validation to standardise use

Adding a validation util function to help with standardising
how we do action validation, so that validation doesn't continue
after one failure.

Change-Id: I4b46fbfa1382ca94b0821a76439675120be5af60
This commit is contained in:
Adrian Turjak 2018-06-14 15:33:43 +12:00
parent fbe6067bdc
commit 4ee2820ebc
4 changed files with 88 additions and 60 deletions

View File

@ -8,6 +8,25 @@ from django.template import loader
from django.conf import settings
def validate_steps(validation_steps):
"""Helper function for validation in actions
Takes a list of validation functions or validation function results.
If function, will call it first, otherwise checks if valid. Will break
and return False on first validation failure, or return True if all valid.
It is best to pass in the functions and let this call them so that it
doesn't keep validating after the first invalid result.
"""
for step in validation_steps:
if callable(step):
if not step():
return False
if not step:
return False
return True
def send_email(to_addresses, context, conf, task):
"""
Function for sending emails from actions

View File

@ -18,6 +18,7 @@ from django.utils import timezone
from adjutant.common import user_store
from adjutant.common.utils import str_datetime
from adjutant.actions.utils import validate_steps
from adjutant.actions.v1.base import (
BaseAction, UserNameAction, UserMixin, ProjectMixin)
@ -40,10 +41,11 @@ class NewProjectAction(BaseAction, ProjectMixin, UserMixin):
super(NewProjectAction, self).__init__(*args, **kwargs)
def _validate(self):
self.action.valid = (
self._validate_domain_id() and
self._validate_parent_project() and
self._validate_project_absent())
self.action.valid = validate_steps([
self._validate_domain_id,
self._validate_parent_project,
self._validate_project_absent,
])
self.action.save()
def _validate_domain_id(self):
@ -137,11 +139,12 @@ class NewProjectWithUserAction(UserNameAction, ProjectMixin, UserMixin):
super(NewProjectWithUserAction, self).__init__(*args, **kwargs)
def _validate(self):
self.action.valid = (
self._validate_domain_id() and
self._validate_parent_project() and
self._validate_project_absent() and
self._validate_user())
self.action.valid = validate_steps([
self._validate_domain_id,
self._validate_parent_project,
self._validate_project_absent,
self._validate_user,
])
self.action.save()
def _validate_user(self):
@ -420,14 +423,16 @@ class AddDefaultUsersToProjectAction(BaseAction, ProjectMixin, UserMixin):
return all_found
def _pre_validate(self):
self.action.valid = self._validate_users()
self.action.valid = validate_steps([
self._validate_users,
])
self.action.save()
def _validate(self):
self.action.valid = (
self._validate_users() and
self._validate_project_id()
)
self.action.valid = validate_steps([
self._validate_users,
self._validate_project_id,
])
self.action.save()
def _pre_approve(self):

View File

@ -13,6 +13,7 @@
# under the License.
from adjutant.actions.v1.base import BaseAction, ProjectMixin, QuotaMixin
from adjutant.actions.utils import validate_steps
from adjutant.common import openstack_clients, user_store
from adjutant.api import models
from adjutant.common.quota import QuotaManager
@ -70,12 +71,12 @@ class NewDefaultNetworkAction(BaseAction, ProjectMixin):
return True
def _validate(self):
self.action.valid = (
self._validate_region() and
self._validate_project_id() and
self._validate_defaults() and
self._validate_keystone_user()
)
self.action.valid = validate_steps([
self._validate_region,
self._validate_project_id,
self._validate_defaults,
self._validate_keystone_user,
])
self.action.save()
def _create_network(self):
@ -199,18 +200,18 @@ class NewProjectDefaultNetworkAction(NewDefaultNetworkAction):
def _pre_validate(self):
# Note: Don't check project here as it doesn't exist yet.
self.action.valid = (
self._validate_region() and
self._validate_defaults()
)
self.action.valid = validate_steps([
self._validate_region,
self._validate_defaults,
])
self.action.save()
def _validate(self):
self.action.valid = (
self._validate_region() and
self._validate_project_id() and
self._validate_defaults()
)
self.action.valid = validate_steps([
self._validate_region,
self._validate_project_id,
self._validate_defaults,
])
self.action.save()
def _pre_approve(self):
@ -347,12 +348,12 @@ class UpdateProjectQuotasAction(BaseAction, QuotaMixin):
def _validate(self):
# Make sure the project id is valid and can be used
self.action.valid = (
self._validate_project_id() and
self._validate_quota_size_exists() and
self._validate_regions_exist() and
self._validate_usage_lower_than_quota()
)
self.action.valid = validate_steps([
self._validate_project_id,
self._validate_quota_size_exists,
self._validate_regions_exist,
self._validate_usage_lower_than_quota,
])
self.action.save()
def _pre_approve(self):
@ -393,9 +394,9 @@ class SetProjectQuotaAction(UpdateProjectQuotasAction):
def _validate(self):
# Make sure the project id is valid and can be used
self.action.valid = (
self._validate_project_id()
)
self.action.valid = validate_steps([
self._validate_project_id,
])
self.action.save()
def _pre_approve(self):

View File

@ -18,6 +18,7 @@ from django.db import models
from adjutant.common import user_store
from adjutant.actions.v1.base import (
UserNameAction, UserIdAction, UserMixin, ProjectMixin)
from adjutant.actions.utils import validate_steps
class NewUserAction(UserNameAction, ProjectMixin, UserMixin):
@ -91,13 +92,13 @@ class NewUserAction(UserNameAction, ProjectMixin, UserMixin):
return True
def _validate(self):
self.action.valid = (
self._validate_role_permissions() and
self._validate_keystone_user() and
self._validate_domain_id() and
self._validate_project_id() and
self._validate_target_user()
)
self.action.valid = validate_steps([
self._validate_role_permissions,
self._validate_keystone_user,
self._validate_domain_id,
self._validate_project_id,
self._validate_target_user,
])
self.action.save()
def _pre_approve(self):
@ -203,11 +204,11 @@ class ResetUserPasswordAction(UserNameAction, UserMixin):
def _validate(self):
# Here, the order of validation matters
# as each one adds new class variables
self.action.valid = all([
self._validate_domain_name(),
self._validate_username_exists(),
self._validate_user_roles(),
self._validate_user_email(),
self.action.valid = validate_steps([
self._validate_domain_name,
self._validate_username_exists,
self._validate_user_roles,
self._validate_user_email,
])
self.action.save()
@ -311,14 +312,14 @@ class EditUserRolesAction(UserIdAction, ProjectMixin, UserMixin):
return new_roles_manageable and current_roles_manageable
def _validate(self):
self.action.valid = (
self._validate_keystone_user() and
self._validate_role_permissions() and
self._validate_domain_id() and
self._validate_project_id() and
self._validate_target_user() and
self._validate_user_roles()
)
self.action.valid = validate_steps([
self._validate_keystone_user,
self._validate_role_permissions,
self._validate_domain_id,
self._validate_project_id,
self._validate_target_user,
self._validate_user_roles,
])
self.action.save()
def _pre_approve(self):
@ -384,8 +385,10 @@ class UpdateUserEmailAction(UserIdAction, UserMixin):
return self.new_email
def _validate(self):
self.action.valid = (self._validate_user() and
self._validate_email_not_in_use())
self.action.valid = validate_steps([
self._validate_user,
self._validate_email_not_in_use,
])
self.action.save()
def _validate_user(self):