Deploy handlers validation is now custom graph aware
TaskDeployGraph and DeploySelectedNodesWithTasks handlers now validating data using deployment graph type Change-Id: I0f7b19a9695bd2ed608d2bf3b6dd28ae91bc86e2 Partial-Bug: #1567504
This commit is contained in:
parent
513a055ab7
commit
e1882de71c
|
@ -314,8 +314,12 @@ class DeploySelectedNodesWithTasks(BaseDeploySelectedNodes):
|
|||
cluster = self.get_object_or_404(objects.Cluster, cluster_id)
|
||||
data = self.checked_data(
|
||||
self.validator.validate_deployment,
|
||||
cluster=cluster)
|
||||
return self.handle_task(cluster, deployment_tasks=data)
|
||||
cluster=cluster,
|
||||
graph_type=self.get_graph_type())
|
||||
return self.handle_task(
|
||||
cluster,
|
||||
deployment_tasks=data,
|
||||
graph_type=self.get_graph_type())
|
||||
|
||||
|
||||
class TaskDeployGraph(BaseHandler):
|
||||
|
@ -344,7 +348,8 @@ class TaskDeployGraph(BaseHandler):
|
|||
tasks = self.checked_data(
|
||||
self.validator.validate,
|
||||
data=tasks,
|
||||
cluster=cluster)
|
||||
cluster=cluster,
|
||||
graph_type=graph_type)
|
||||
logger.debug('Tasks used in dot graph %s', tasks)
|
||||
|
||||
if parents_for:
|
||||
|
|
|
@ -423,16 +423,18 @@ class NodeDeploymentValidator(TaskDeploymentValidator,
|
|||
DeploySelectedNodesValidator):
|
||||
|
||||
@classmethod
|
||||
def validate_deployment(cls, data, cluster):
|
||||
def validate_deployment(cls, data, cluster, graph_type):
|
||||
"""Used to validate attributes used for validate_deployment_attributes
|
||||
|
||||
:param data: raw json data, usually web.data()
|
||||
:param cluster: cluster instance
|
||||
:param graph_type: deployment graph type
|
||||
:returns: loaded json or empty array
|
||||
"""
|
||||
data = cls.validate_json(data)
|
||||
|
||||
if data:
|
||||
cls.validate_tasks(data, cluster)
|
||||
cls.validate_tasks(data, cluster, graph_type)
|
||||
else:
|
||||
raise errors.InvalidData('Tasks list must be specified.')
|
||||
|
||||
|
|
|
@ -34,16 +34,22 @@ class GraphSolverTasksValidator(BasicValidator):
|
|||
class TaskDeploymentValidator(BasicValidator):
|
||||
|
||||
@classmethod
|
||||
def validate_tasks(cls, tasks, cluster):
|
||||
"""Check that passed tasks are present in deployment graph
|
||||
def validate_tasks(cls, tasks, cluster, graph_type):
|
||||
"""Check that passed tasks are present in deployment graph.
|
||||
|
||||
:param tasks: list of tasks
|
||||
:type tasks: list[dict]
|
||||
:param cluster: Cluster DB object
|
||||
:type cluster: models.Cluster
|
||||
:param graph_type: Deployment graph type
|
||||
:type graph_type: basestring
|
||||
:returns: list of tasks
|
||||
:rtype: list[dict]
|
||||
"""
|
||||
cls.validate_schema(tasks, base_types.STRINGS_ARRAY)
|
||||
|
||||
deployment_tasks = objects.Cluster.get_deployment_tasks(cluster)
|
||||
deployment_tasks = objects.Cluster.get_deployment_tasks(
|
||||
cluster, graph_type)
|
||||
graph = orchestrator_graph.GraphSolver()
|
||||
graph.add_tasks(deployment_tasks)
|
||||
|
||||
|
@ -73,15 +79,21 @@ class TaskDeploymentValidator(BasicValidator):
|
|||
class GraphSolverVisualizationValidator(TaskDeploymentValidator):
|
||||
|
||||
@classmethod
|
||||
def validate(cls, data, cluster):
|
||||
def validate(cls, data, cluster, graph_type):
|
||||
"""Check that passed tasks are present in deployment graph
|
||||
|
||||
:param data: list of tasks in string representation.
|
||||
Example: "hiera,controller"
|
||||
:type data: basestring
|
||||
:param cluster: Cluster DB object
|
||||
:type cluster: models.Cluster
|
||||
:param graph_type: Deployment graph type
|
||||
:type graph_type: basestring
|
||||
:returns: list of tasks
|
||||
:rtype: list[dict]
|
||||
"""
|
||||
tasks = list(set(data.split(',')))
|
||||
return cls.validate_tasks(tasks, cluster)
|
||||
return cls.validate_tasks(tasks, cluster, graph_type)
|
||||
|
||||
@classmethod
|
||||
def validate_task_presence(cls, task, graph):
|
||||
|
|
|
@ -761,6 +761,74 @@ class TestTaskDeployGraph(BaseGraphTasksTests):
|
|||
self.assertIn('Task types nonexistent do not exist', resp.body)
|
||||
|
||||
|
||||
class TestCustomTaskDeployGraph(BaseGraphTasksTests):
|
||||
|
||||
content_type = 'text/vnd.graphviz'
|
||||
|
||||
def test_with_custom_graph(self):
|
||||
self.env.create()
|
||||
cluster = self.env.clusters[-1]
|
||||
|
||||
objects.DeploymentGraph.create_for_model(
|
||||
{
|
||||
'tasks': [
|
||||
{'id': 'pre_deployment', 'type': 'stage'},
|
||||
{'id': 'deploy', 'type': 'stage'},
|
||||
{'id': 'post_deployment', 'type': 'stage'},
|
||||
{'id': 'pre-A', 'required_for': ['pre_deployment'],
|
||||
'type': 'puppet'},
|
||||
{'id': 'pre-B', 'required_for': ['pre_deployment'],
|
||||
'type': 'puppet', 'requires': ['pre-A']},
|
||||
{'id': 'pre-C', 'required_for': ['pre_deployment'],
|
||||
'type': 'puppet', 'requires': ['pre-A', 'pre-D']},
|
||||
{'id': 'pre-D', 'required_for': ['pre_deployment'],
|
||||
'type': 'puppet'},
|
||||
]
|
||||
},
|
||||
cluster,
|
||||
'custom-graph'
|
||||
)
|
||||
|
||||
resp = self.app.get(
|
||||
reverse('TaskDeployGraph', kwargs={
|
||||
'cluster_id': cluster.id,
|
||||
'graph_type': 'custom-graph'
|
||||
}) + '?graph_type=custom-graph',
|
||||
expect_errors=True
|
||||
)
|
||||
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertEqual(resp.content_type, self.content_type)
|
||||
self.assertIn('"pre-A" -> pre_deployment', resp.body)
|
||||
self.assertIn('"pre-A" -> "pre-B"', resp.body)
|
||||
self.assertIn('"pre-A" -> "pre-C"', resp.body)
|
||||
|
||||
def test_with_custom_graph_validator_fail(self):
|
||||
self.env.create()
|
||||
cluster = self.env.clusters[-1]
|
||||
|
||||
objects.DeploymentGraph.create_for_model(
|
||||
{
|
||||
'tasks': []
|
||||
},
|
||||
cluster,
|
||||
'custom-graph'
|
||||
)
|
||||
|
||||
resp = self.app.get(
|
||||
reverse('TaskDeployGraph', kwargs={
|
||||
'cluster_id': cluster.id,
|
||||
'graph_type': 'custom-graph'
|
||||
}) + '?graph_type=custom-graph&parents_for=upload_nodes_info',
|
||||
expect_errors=True
|
||||
)
|
||||
|
||||
self.assertEqual(resp.status_code, 400)
|
||||
self.assertIn(
|
||||
'Task upload_nodes_info is not present in graph',
|
||||
resp.body)
|
||||
|
||||
|
||||
class TestTaskDeployCustomGraph(BaseGraphTasksTests):
|
||||
|
||||
content_type = 'text/vnd.graphviz'
|
||||
|
|
|
@ -263,6 +263,68 @@ class TestSelectedNodesAction(BaseSelectedNodesTest):
|
|||
|
||||
self.check_deployment_call_made([nodes_uids[0]], mcast)
|
||||
|
||||
@patch('nailgun.task.task.rpc.cast')
|
||||
def test_start_sel_nodes_deployment_w_custom_graph(self, mcast):
|
||||
controller_nodes = [
|
||||
n for n in self.cluster.nodes
|
||||
if "controller" in n.roles
|
||||
]
|
||||
objects.DeploymentGraph.create_for_model(
|
||||
{'tasks': [
|
||||
{
|
||||
'id': 'custom-task',
|
||||
'type': 'puppet',
|
||||
'roles': '*',
|
||||
'version': '2.0.0',
|
||||
'requires': ['pre_deployment_start']
|
||||
}
|
||||
]}, self.cluster, 'custom-graph')
|
||||
|
||||
self.emulate_nodes_provisioning(controller_nodes)
|
||||
nodes_uids = [n.uid for n in controller_nodes]
|
||||
controller_to_deploy = nodes_uids[0]
|
||||
deploy_action_url = self.make_action_url(
|
||||
"DeploySelectedNodesWithTasks",
|
||||
[controller_to_deploy]
|
||||
) + '&graph_type=custom-graph'
|
||||
self.send_put(deploy_action_url, ['custom-task'])
|
||||
|
||||
executed_task_ids = [
|
||||
t['id'] for t in
|
||||
mcast.call_args[0][1]['args']['tasks_graph'][controller_to_deploy]
|
||||
]
|
||||
self.check_deployment_call_made([controller_to_deploy], mcast)
|
||||
self.assertItemsEqual(['custom-task'], executed_task_ids)
|
||||
|
||||
@patch('nailgun.task.task.rpc.cast')
|
||||
def test_validator_fail_on_deployment_w_custom_graph(self, mcast):
|
||||
objects.DeploymentGraph.create_for_model(
|
||||
{'tasks': [
|
||||
{
|
||||
'id': 'custom-task',
|
||||
'type': 'puppet',
|
||||
}
|
||||
]}, self.cluster, 'custom-graph')
|
||||
|
||||
deploy_action_url = self.make_action_url(
|
||||
"DeploySelectedNodesWithTasks",
|
||||
[]
|
||||
) + '&graph_type=custom-graph'
|
||||
|
||||
response = self.send_put(
|
||||
deploy_action_url,
|
||||
['upload_nodes_info'] # this task exists in default graph
|
||||
)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertEqual(
|
||||
response.json_body,
|
||||
{
|
||||
"message": "Tasks upload_nodes_info are not present "
|
||||
"in deployment graph",
|
||||
"errors": []
|
||||
}
|
||||
)
|
||||
|
||||
@fake_tasks(fake_rpc=False, mock_rpc=False)
|
||||
@patch('nailgun.task.task.rpc.cast')
|
||||
def test_deployment_of_node_is_forbidden(self, mcast):
|
||||
|
|
Loading…
Reference in New Issue