Merge "Allow YAQL expressions in task's dependencies"
This commit is contained in:
@@ -18,22 +18,6 @@ from nailgun.consts import NODE_RESOLVE_POLICY
|
||||
from nailgun.consts import ORCHESTRATOR_TASK_TYPES
|
||||
|
||||
|
||||
RELATION_SCHEMA = {
|
||||
'$schema': 'http://json-schema.org/draft-04/schema#',
|
||||
'type': 'object',
|
||||
'required': ['name'],
|
||||
'properties': {
|
||||
'name': {'type': 'string'},
|
||||
'role': {
|
||||
'oneOf': [
|
||||
{'type': 'string'},
|
||||
{'type': 'array'},
|
||||
]
|
||||
},
|
||||
'policy': {'type': 'string', 'enum': list(NODE_RESOLVE_POLICY)},
|
||||
}
|
||||
}
|
||||
|
||||
YAQL_EXP = {
|
||||
'$schema': 'http://json-schema.org/draft-04/schema#',
|
||||
'type': 'object',
|
||||
@@ -43,6 +27,25 @@ YAQL_EXP = {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RELATION_SCHEMA = {
|
||||
'$schema': 'http://json-schema.org/draft-04/schema#',
|
||||
'type': 'object',
|
||||
'required': ['name'],
|
||||
'properties': {
|
||||
'name': {
|
||||
'oneOf': [
|
||||
{'type': 'string'}, YAQL_EXP],
|
||||
},
|
||||
'role': {
|
||||
'oneOf': [
|
||||
{'type': 'string'}, {'type': 'array'}, YAQL_EXP]
|
||||
},
|
||||
'policy': {'type': 'string', 'enum': list(NODE_RESOLVE_POLICY)},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TASK_STRATEGY = {
|
||||
'$schema': 'http://json-schema.org/draft-04/schema#',
|
||||
'type': 'object',
|
||||
@@ -79,8 +82,14 @@ TASK_SCHEMA = {
|
||||
'parameters': TASK_PARAMETERS,
|
||||
'required_for': {'type': 'array'},
|
||||
'requires': {'type': 'array'},
|
||||
'cross-depends': {'type': 'array', 'items': RELATION_SCHEMA},
|
||||
'cross-depended-by': {'type': 'array', 'items': RELATION_SCHEMA}
|
||||
'cross-depends': {
|
||||
'oneOf': [
|
||||
{'type': 'array', 'items': RELATION_SCHEMA}, YAQL_EXP]
|
||||
},
|
||||
'cross-depended-by': {
|
||||
'oneOf': [
|
||||
{'type': 'array', 'items': RELATION_SCHEMA}, YAQL_EXP]
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ from nailgun import consts
|
||||
from nailgun.db.sqlalchemy.models.base import Base
|
||||
from nailgun.db.sqlalchemy.models.fields import JSON
|
||||
from nailgun.db.sqlalchemy.models.mutable import MutableDict
|
||||
from nailgun.db.sqlalchemy.models.mutable import MutableList
|
||||
|
||||
|
||||
class DeploymentGraph(Base):
|
||||
@@ -110,12 +109,12 @@ class DeploymentGraphTask(Base):
|
||||
nullable=False)
|
||||
# cross-depended-by with hypen is deprecated notation
|
||||
cross_depended_by = sa.Column(
|
||||
MutableList.as_mutable(JSON),
|
||||
JSON,
|
||||
default=[],
|
||||
server_default='[]')
|
||||
# cross-depends with hypen is deprecated notation
|
||||
cross_depends = sa.Column(
|
||||
MutableList.as_mutable(JSON),
|
||||
JSON,
|
||||
default=[],
|
||||
server_default='[]')
|
||||
parameters = sa.Column(
|
||||
|
||||
191
nailgun/nailgun/test/unit/test_graph_solver_tasks_validator.py
Normal file
191
nailgun/nailgun/test/unit/test_graph_solver_tasks_validator.py
Normal file
@@ -0,0 +1,191 @@
|
||||
# Copyright 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
import textwrap
|
||||
|
||||
import jsonschema
|
||||
|
||||
from nailgun.api.v1.validators import orchestrator_graph
|
||||
from nailgun.test import base
|
||||
|
||||
|
||||
class TestGraphSolverTasksValidator(base.BaseUnitTest):
|
||||
|
||||
validator = orchestrator_graph.GraphSolverTasksValidator
|
||||
|
||||
def test_task_requires_list(self):
|
||||
self.assertNotRaises(
|
||||
jsonschema.exceptions.ValidationError,
|
||||
self.validator.validate_update,
|
||||
textwrap.dedent('''
|
||||
[{
|
||||
"id": "netconfig",
|
||||
"type": "puppet",
|
||||
"requires": ["tools"]
|
||||
}]
|
||||
'''),
|
||||
instance=None)
|
||||
|
||||
def test_task_required_for_list(self):
|
||||
self.assertNotRaises(
|
||||
jsonschema.exceptions.ValidationError,
|
||||
self.validator.validate_update,
|
||||
textwrap.dedent('''
|
||||
[{
|
||||
"id": "netconfig",
|
||||
"type": "puppet",
|
||||
"required_for": ["tools"]
|
||||
}]
|
||||
'''),
|
||||
instance=None)
|
||||
|
||||
def test_task_cross_depends_list(self):
|
||||
self.assertNotRaises(
|
||||
jsonschema.exceptions.ValidationError,
|
||||
self.validator.validate_update,
|
||||
textwrap.dedent('''
|
||||
[{
|
||||
"id": "netconfig",
|
||||
"type": "puppet",
|
||||
"cross-depends": [{
|
||||
"name": "something"
|
||||
}]
|
||||
}]
|
||||
'''),
|
||||
instance=None)
|
||||
|
||||
def test_task_cross_depends_yaql(self):
|
||||
self.assertNotRaises(
|
||||
jsonschema.exceptions.ValidationError,
|
||||
self.validator.validate_update,
|
||||
textwrap.dedent('''
|
||||
[{
|
||||
"id": "netconfig",
|
||||
"type": "puppet",
|
||||
"cross-depends": {
|
||||
"yaql_exp": "$.do_something()"
|
||||
}
|
||||
}]
|
||||
'''),
|
||||
instance=None)
|
||||
|
||||
def test_task_cross_depends_yaql_inside(self):
|
||||
self.assertNotRaises(
|
||||
jsonschema.exceptions.ValidationError,
|
||||
self.validator.validate_update,
|
||||
textwrap.dedent('''
|
||||
[{
|
||||
"id": "netconfig",
|
||||
"type": "puppet",
|
||||
"cross-depends": [{
|
||||
"name": {
|
||||
"yaql_exp": "$.do_something()"
|
||||
},
|
||||
"role": {
|
||||
"yaql_exp": "$.do_something()"
|
||||
}
|
||||
}]
|
||||
}]
|
||||
'''),
|
||||
instance=None)
|
||||
|
||||
def test_task_cross_depended_by_list(self):
|
||||
self.assertNotRaises(
|
||||
jsonschema.exceptions.ValidationError,
|
||||
self.validator.validate_update,
|
||||
textwrap.dedent('''
|
||||
[{
|
||||
"id": "netconfig",
|
||||
"type": "puppet",
|
||||
"cross-depended-by": [{
|
||||
"name": "something",
|
||||
"role": "something"
|
||||
}]
|
||||
}]
|
||||
'''),
|
||||
instance=None)
|
||||
|
||||
def test_task_cross_depended_by_yaql(self):
|
||||
self.assertNotRaises(
|
||||
jsonschema.exceptions.ValidationError,
|
||||
self.validator.validate_update,
|
||||
textwrap.dedent('''
|
||||
[{
|
||||
"id": "netconfig",
|
||||
"type": "puppet",
|
||||
"cross-depended-by": {
|
||||
"yaql_exp": "$.do_something()"
|
||||
}
|
||||
}]
|
||||
'''),
|
||||
instance=None)
|
||||
|
||||
def test_task_cross_depended_by_yaql_inside(self):
|
||||
self.assertNotRaises(
|
||||
jsonschema.exceptions.ValidationError,
|
||||
self.validator.validate_update,
|
||||
textwrap.dedent('''
|
||||
[{
|
||||
"id": "netconfig",
|
||||
"type": "puppet",
|
||||
"cross-depended-by": [{
|
||||
"name": {
|
||||
"yaql_exp": "$.do_something()"
|
||||
},
|
||||
"role": {
|
||||
"yaql_exp": "$.do_something()"
|
||||
}
|
||||
}]
|
||||
}]
|
||||
'''),
|
||||
instance=None)
|
||||
|
||||
def test_task_strategy_int(self):
|
||||
self.assertNotRaises(
|
||||
jsonschema.exceptions.ValidationError,
|
||||
self.validator.validate_update,
|
||||
textwrap.dedent('''
|
||||
[{
|
||||
"id": "netconfig",
|
||||
"type": "puppet",
|
||||
"parameters": {
|
||||
"strategy": {
|
||||
"type": "parallel",
|
||||
"amount": 42
|
||||
}
|
||||
}
|
||||
}]
|
||||
'''),
|
||||
instance=None)
|
||||
|
||||
def test_task_strategy_yaql(self):
|
||||
self.assertNotRaises(
|
||||
jsonschema.exceptions.ValidationError,
|
||||
self.validator.validate_update,
|
||||
textwrap.dedent('''
|
||||
[{
|
||||
"id": "netconfig",
|
||||
"type": "puppet",
|
||||
"parameters": {
|
||||
"strategy": {
|
||||
"type": "parallel",
|
||||
"amount": {
|
||||
"yaql_exp": "$.do_something()"
|
||||
}
|
||||
}
|
||||
}
|
||||
}]
|
||||
'''),
|
||||
instance=None)
|
||||
Reference in New Issue
Block a user