validating reference properties in translate_input.py

added some validation checks for hosting_server
 in hot_resource.py

Added unit testcases for translate_input.py

Change-Id: Ibad2b5b231ac7f119df6d2c5e1eb6949cf9b0be2
Closes-bug: #1321996
This commit is contained in:
srinivas_tadepalli 2015-03-17 18:12:34 +05:30
parent 01f85e17b8
commit 23c1e9709d
4 changed files with 220 additions and 14 deletions

View File

@ -100,9 +100,13 @@ class HotResource(object):
self.properties = {'config': {'get_resource': config_name}}
deploy_lookup[interface.name] = self
else:
# hosting_server is None if requirements is None
hosting_on_server = (hosting_server.name if
hosting_server else None)
sd_config = {'config': {'get_resource': config_name},
'server': {'get_resource':
hosting_server.name}}
hosting_on_server}}
deploy_resource = \
HotResource(self.nodetemplate,
deploy_name,
@ -144,12 +148,13 @@ class HotResource(object):
if self.type == 'OS::Heat::SoftwareDeployment':
# skip if already have hosting
# If type is NodeTemplate, look up corresponding HotResrouce
host_server = self.properties.get('server')['get_resource']
if host_server is None:
host_server = self.properties.get('server')
if host_server is None or not host_server['get_resource']:
raise Exception(_("Internal Error: expecting host "
"in software deployment"))
elif isinstance(host_server, NodeTemplate):
self.properties['server']['get_resource'] = host_server.name
elif isinstance(host_server['get_resource'], NodeTemplate):
self.properties['server']['get_resource'] = \
host_server['get_resource'].name
def top_of_chain(self):
dependent = self.group_dependencies.get(self)

View File

View File

@ -0,0 +1,193 @@
# 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.
from translator.hot.translate_inputs import TranslateInputs
from translator.toscalib.parameters import Input
from translator.toscalib.tests.base import TestCase
import translator.toscalib.utils.yamlparser
class ToscaTemplateInputValidationTest(TestCase):
def _translate_input_test(self, tpl_snippet, input_params,
expectedmessage=None):
inputs_dict = (translator.toscalib.utils.yamlparser.
simple_parse(tpl_snippet)['inputs'])
inputs = []
for name, attrs in inputs_dict.items():
input = Input(name, attrs)
inputs.append(input)
translateinput = TranslateInputs(inputs, input_params)
try:
translateinput.translate()
except ValueError:
pass
except Exception as err:
self.assertEqual(expectedmessage, err.__str__())
def test_invalid_input_type(self):
tpl_snippet = '''
inputs:
cpus:
type: integer
description: Number of CPUs for the server.
constraints:
- valid_values: [ 1, 2, 4, 8 ]
'''
input_params = {'cpus': 'string'}
expectedmessage = ('could not convert string to float: string')
self._translate_input_test(tpl_snippet, input_params,
expectedmessage)
def test_invalid_input_constraints_for_equal(self):
tpl_snippet = '''
inputs:
num_cpus:
type: integer
description: Number of CPUs for the server.
constraints:
- equal: 1
'''
input_params = {'num_cpus': '0'}
expectedmessage = ('num_cpus: 0 is not equal to "1".')
self._translate_input_test(tpl_snippet, input_params, expectedmessage)
def test_invalid_input_constraints_for_greater_or_equal(self):
tpl_snippet = '''
inputs:
num_cpus:
type: integer
description: Number of CPUs for the server.
constraints:
- greater_or_equal: 1
'''
input_params = {'num_cpus': '0'}
expectedmessage = ('num_cpus: 0 must be greater or equal to "1".')
self._translate_input_test(tpl_snippet, input_params, expectedmessage)
def test_invalid_input_constraints_for_greater_than(self):
tpl_snippet = '''
inputs:
num_cpus:
type: integer
description: Number of CPUs for the server.
constraints:
- greater_than: 1
'''
input_params = {'num_cpus': '0'}
expectedmessage = ('num_cpus: 0 must be greater than "1".')
self._translate_input_test(tpl_snippet, input_params, expectedmessage)
def test_invalid_input_constraints_for_less_than(self):
tpl_snippet = '''
inputs:
num_cpus:
type: integer
description: Number of CPUs for the server.
constraints:
- less_than: 8
'''
input_params = {'num_cpus': '8'}
expectedmessage = ('num_cpus: 8 must be less than "8".')
self._translate_input_test(tpl_snippet, input_params, expectedmessage)
def test_invalid_input_constraints_for_less_or_equal(self):
tpl_snippet = '''
inputs:
num_cpus:
type: integer
description: Number of CPUs for the server.
constraints:
- less_or_equal: 8
'''
input_params = {'num_cpus': '9'}
expectedmessage = ('num_cpus: 9 must be less or equal to "8".')
self._translate_input_test(tpl_snippet, input_params, expectedmessage)
def test_invalid_input_constraints_for_valid_values(self):
tpl_snippet = '''
inputs:
num_cpus:
type: integer
description: Number of CPUs for the server.
constraints:
- valid_values: [ 1, 2, 4, 8 ]
'''
input_params = {'num_cpus': '3'}
expectedmessage = ('num_cpus: 3 is not an valid value "[1, 2, 4, 8]".')
self._translate_input_test(tpl_snippet, input_params, expectedmessage)
def test_invalid_input_constraints_for_in_range(self):
tpl_snippet = '''
inputs:
num_cpus:
type: integer
description: Number of CPUs for the server.
constraints:
- in_range: [ 1, 8 ]
'''
input_params = {'num_cpus': '10'}
expectedmessage = ('num_cpus: 10 is out of range (min:1, max:8).')
self._translate_input_test(tpl_snippet, input_params, expectedmessage)
def test_invalid_input_constraints_for_min_length(self):
tpl_snippet = '''
inputs:
user_name:
type: string
description: Name of the user.
constraints:
- min_length: 8
'''
input_params = {'user_name': 'abcd'}
expectedmessage = ('length of user_name: abcd must be at least "8".')
self._translate_input_test(tpl_snippet, input_params, expectedmessage)
def test_invalid_input_constraints_for_max_length(self):
tpl_snippet = '''
inputs:
user_name:
type: string
description: Name of the user.
constraints:
- max_length: 6
'''
input_params = {'user_name': 'abcdefg'}
expectedmessage = ('length of user_name: '
'abcdefg must be no greater than "6".')
self._translate_input_test(tpl_snippet, input_params, expectedmessage)
def test_invalid_input_constraints_for_pattern(self):
tpl_snippet = '''
inputs:
user_name:
type: string
description: Name of the user.
constraints:
- pattern: '^\w+$'
'''
input_params = {'user_name': '1-abc'}
expectedmessage = ('user_name: "1-abc" does '
'not match pattern "^\\w+$".')
self._translate_input_test(tpl_snippet, input_params, expectedmessage)

View File

@ -12,6 +12,7 @@
# under the License.
from translator.hot.syntax.hot_parameter import HotParameter
from translator.toscalib.dataentity import DataEntity
from translator.toscalib.utils.gettextutils import _
@ -60,22 +61,29 @@ class TranslateInputs():
def _translate_inputs(self):
hot_inputs = []
hot_default = None
for input in self.inputs:
hot_input_type = TOSCA_TO_HOT_INPUT_TYPES[input.type]
hot_constraints = []
if input.constraints:
for constraint in input.constraints:
hc, hvalue = self._translate_constraints(
constraint.constraint_key, constraint.constraint_value)
hot_constraints.append({hc: hvalue})
if input.name in self.parsed_params:
DataEntity.validate_datatype(hot_input_type,
self.parsed_params[input.name])
hot_default = self.parsed_params[input.name]
elif input.default is not None:
hot_default = input.default
else:
raise Exception(_("Need to specify a value "
"for input {0}").format(input.name))
hot_constraints = []
if input.constraints:
for constraint in input.constraints:
constraint.validate(
int(hot_default) if hot_input_type == "number"
else hot_default)
hc, hvalue = self._translate_constraints(
constraint.constraint_key, constraint.constraint_value)
hot_constraints.append({hc: hvalue})
hot_inputs.append(HotParameter(name=input.name,
type=hot_input_type,
description=input.description,
@ -101,9 +109,9 @@ class TranslateInputs():
elif name == LESS_OR_EQUAL:
hot_value = {"max": value}
elif name == IN_RANGE:
range_values = value.keys()
min_value = min(range_values)
max_value = max(range_values)
# value is list type here
min_value = min(value)
max_value = max(value)
hot_value = {"min": min_value, "max": max_value}
elif name == LENGTH:
hot_value = {"min": value, "max": value}