mirror of
https://github.com/ansible/awx.git
synced 2026-03-18 01:17:35 -02:30
Basic verification architecture added.
This commit is contained in:
@@ -370,6 +370,9 @@ class SubListCreateAttachDetachAPIView(SubListCreateAPIView):
|
|||||||
# Base class for a sublist view that allows for creating subobjects and
|
# Base class for a sublist view that allows for creating subobjects and
|
||||||
# attaching/detaching them from the parent.
|
# attaching/detaching them from the parent.
|
||||||
|
|
||||||
|
def is_valid_relation(self, parent, sub):
|
||||||
|
return None
|
||||||
|
|
||||||
def get_description_context(self):
|
def get_description_context(self):
|
||||||
d = super(SubListCreateAttachDetachAPIView, self).get_description_context()
|
d = super(SubListCreateAttachDetachAPIView, self).get_description_context()
|
||||||
d.update({
|
d.update({
|
||||||
@@ -406,6 +409,11 @@ class SubListCreateAttachDetachAPIView(SubListCreateAPIView):
|
|||||||
skip_sub_obj_read_check=created):
|
skip_sub_obj_read_check=created):
|
||||||
raise PermissionDenied()
|
raise PermissionDenied()
|
||||||
|
|
||||||
|
# Verify that the relationship to be added is valid.
|
||||||
|
attach_errors = self.is_valid_relation(parent, sub)
|
||||||
|
if attach_errors is not None:
|
||||||
|
return Response(attach_errors, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
# Attach the object to the collection.
|
# Attach the object to the collection.
|
||||||
if sub not in relationship.all():
|
if sub not in relationship.all():
|
||||||
relationship.add(sub)
|
relationship.add(sub)
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ from awx.api.renderers import * # noqa
|
|||||||
from awx.api.serializers import * # noqa
|
from awx.api.serializers import * # noqa
|
||||||
from awx.api.metadata import RoleMetadata
|
from awx.api.metadata import RoleMetadata
|
||||||
from awx.main.consumers import emit_channel_notification
|
from awx.main.consumers import emit_channel_notification
|
||||||
|
from awx.main.scheduler.dag_simple import SimpleDAG
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger('awx.api.views')
|
logger = logging.getLogger('awx.api.views')
|
||||||
|
|
||||||
@@ -2656,6 +2658,29 @@ class WorkflowJobTemplateNodeChildrenBaseList(EnforceParentRelationshipMixin, Su
|
|||||||
self.check_parent_access(parent)
|
self.check_parent_access(parent)
|
||||||
return getattr(parent, self.relationship).all()
|
return getattr(parent, self.relationship).all()
|
||||||
|
|
||||||
|
def is_valid_relation(self, parent, sub):
|
||||||
|
workflow_nodes = parent.workflow_job_template.workflow_job_template_nodes.all()
|
||||||
|
graph = SimpleDAG()
|
||||||
|
for workflow_node in workflow_nodes:
|
||||||
|
graph.add_node(workflow_node)
|
||||||
|
|
||||||
|
find = False
|
||||||
|
for node_type in ['success_nodes', 'failure_nodes', 'always_nodes']:
|
||||||
|
for workflow_node in workflow_nodes:
|
||||||
|
related_nodes = getattr(workflow_node, node_type).all()
|
||||||
|
for related_node in related_nodes:
|
||||||
|
graph.add_edge(workflow_node, related_node, node_type)
|
||||||
|
if not find and parent == workflow_node and\
|
||||||
|
sub == related_node and self.relationship == node_type:
|
||||||
|
find = True
|
||||||
|
if not find:
|
||||||
|
graph.add_edge(parent, sub, self.relationship)
|
||||||
|
|
||||||
|
if graph.cycle_detected():
|
||||||
|
return {"Error": "cycle detected!"}
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
class WorkflowJobTemplateNodeSuccessNodesList(WorkflowJobTemplateNodeChildrenBaseList):
|
class WorkflowJobTemplateNodeSuccessNodesList(WorkflowJobTemplateNodeChildrenBaseList):
|
||||||
relationship = 'success_nodes'
|
relationship = 'success_nodes'
|
||||||
|
|
||||||
|
|||||||
@@ -138,3 +138,6 @@ class SimpleDAG(object):
|
|||||||
roots.append(n)
|
roots.append(n)
|
||||||
return roots
|
return roots
|
||||||
|
|
||||||
|
# TODO
|
||||||
|
def cycle_detected(self):
|
||||||
|
return False
|
||||||
|
|||||||
Reference in New Issue
Block a user