[svn] commit: r1959 - in /trunk: ./ src/bin/bindctl/ src/bin/cmdctl/ src/bin/xfrin/ src/lib/cc/ src/lib/config/testdata/ src/lib/dns/ src/lib/dns/rdata/generic/ src/lib/dns/tests/ src/lib/python/isc/cc/ src/lib/python/isc/config/ src/lib/python/isc/config/tests/
BIND 10 source code commits
bind10-changes at lists.isc.org
Fri May 28 03:49:38 UTC 2010
Author: zhanglikun
Date: Fri May 28 03:49:38 2010
New Revision: 1959
Log:
1. Merge branches/likun-value-check to trunk.(for ticket 201: add value/type check for commands sent to cmdctl.)\n 2. Apply the patch for ticket 193:msgq: real type data isn't encoded and decoded properly. \n3. The change had been reviewed by Jelte.
Added:
trunk/src/lib/config/testdata/spec27.spec
- copied unchanged from r1958, branches/likun-value-check/src/lib/config/testdata/spec27.spec
Modified:
trunk/ (props changed)
trunk/src/bin/bindctl/bindcmd.py
trunk/src/bin/bindctl/bindctl-source.py.in
trunk/src/bin/bindctl/moduleinfo.py
trunk/src/bin/cmdctl/cmdctl.py.in
trunk/src/bin/xfrin/ (props changed)
trunk/src/lib/cc/ (props changed)
trunk/src/lib/dns/ (props changed)
trunk/src/lib/dns/rdata/generic/rrsig_46.cc (props changed)
trunk/src/lib/dns/tests/ (props changed)
trunk/src/lib/python/isc/cc/message.py
trunk/src/lib/python/isc/config/config_data.py
trunk/src/lib/python/isc/config/module_spec.py
trunk/src/lib/python/isc/config/tests/config_data_test.py
trunk/src/lib/python/isc/config/tests/module_spec_test.py
Modified: trunk/src/bin/bindctl/bindcmd.py
==============================================================================
--- trunk/src/bin/bindctl/bindcmd.py (original)
+++ trunk/src/bin/bindctl/bindcmd.py Fri May 28 03:49:38 2010
@@ -49,7 +49,7 @@
except ImportError:
my_readline = sys.stdin.readline
-
+CONFIG_MODULE_NAME = 'config'
CONST_BINDCTL_HELP = """
usage: <module name> <command name> [param1 = value1 [, param2 = value2]]
Type Tab character to get the hint of module/command/parameters.
@@ -228,7 +228,8 @@
for arg in command["command_args"]:
param = ParamInfo(name = arg["item_name"],
type = arg["item_type"],
- optional = bool(arg["item_optional"]))
+ optional = bool(arg["item_optional"]),
+ param_spec = arg)
if ("item_default" in arg):
param.default = arg["item_default"]
cmd.add_param(param)
@@ -301,12 +302,20 @@
if not name in params and not param_nr in params:
raise CmdMissParamSyntaxError(cmd.module, cmd.command, name)
param_nr += 1
-
+
+ # Convert parameter value according parameter spec file.
+ # Ignore check for commands belongs to module 'config'
+ if cmd.module != CONFIG_MODULE_NAME:
+ for param_name in cmd.params:
+ param_spec = command_info.get_param_with_name(param_name).param_spec
+ cmd.params[param_name] = isc.config.config_data.convert_type(param_spec, cmd.params[param_name])
+
+
def _handle_cmd(self, cmd):
'''Handle a command entered by the user'''
if cmd.command == "help" or ("help" in cmd.params.keys()):
self._handle_help(cmd)
- elif cmd.module == "config":
+ elif cmd.module == CONFIG_MODULE_NAME:
self.apply_config_cmd(cmd)
else:
self.apply_cmd(cmd)
@@ -357,7 +366,7 @@
else:
hints = self._get_param_startswith(cmd.module, cmd.command,
text)
- if cmd.module == "config":
+ if cmd.module == CONFIG_MODULE_NAME:
# grm text has been stripped of slashes...
my_text = self.location + "/" + cur_line.rpartition(" ")[2]
list = self.config_data.get_config_item_list(my_text.rpartition("/")[0], True)
@@ -433,6 +442,9 @@
self._validate_cmd(cmd)
self._handle_cmd(cmd)
except BindCtlException as e:
+ print("Error! ", e)
+ self._print_correct_usage(e)
+ except isc.cc.data.DataTypeError as e:
print("Error! ", e)
self._print_correct_usage(e)
Modified: trunk/src/bin/bindctl/bindctl-source.py.in
==============================================================================
--- trunk/src/bin/bindctl/bindctl-source.py.in (original)
+++ trunk/src/bin/bindctl/bindctl-source.py.in Fri May 28 03:49:38 2010
@@ -29,7 +29,7 @@
def prepare_config_commands(tool):
'''Prepare fixed commands for local configuration editing'''
- module = ModuleInfo(name = "config", desc = "Configuration commands")
+ module = ModuleInfo(name = CONFIG_MODULE_NAME, desc = "Configuration commands")
cmd = CommandInfo(name = "show", desc = "Show configuration")
param = ParamInfo(name = "identifier", type = "string", optional=True)
cmd.add_param(param)
Modified: trunk/src/bin/bindctl/moduleinfo.py
==============================================================================
--- trunk/src/bin/bindctl/moduleinfo.py (original)
+++ trunk/src/bin/bindctl/moduleinfo.py Fri May 28 03:49:38 2010
@@ -33,17 +33,21 @@
class ParamInfo:
"""One parameter of one command.
- Each command parameter has four attributes:
- parameter name, parameter type, parameter value, and parameter description
+ Each command parameter has five attributes:
+ parameter name, parameter type, parameter value,
+ parameter description and paramter's spec(got from
+ module spec file).
"""
def __init__(self, name, desc = '', type = STRING_TYPE,
- optional = False, value = '', default_value = ''):
+ optional = False, value = '', default_value = '',
+ param_spec = None):
self.name = name
self.type = type
self.value = value
self.default_value = default_value
self.desc = desc
self.is_optional = optional
+ self.param_spec = param_spec
def __str__(self):
return str("\t%s <type: %s> \t(%s)" % (self.name, self.type, self.desc))
Modified: trunk/src/bin/cmdctl/cmdctl.py.in
==============================================================================
--- trunk/src/bin/cmdctl/cmdctl.py.in (original)
+++ trunk/src/bin/cmdctl/cmdctl.py.in Fri May 28 03:49:38 2010
@@ -263,8 +263,6 @@
Return rcode, dict.
rcode = 0: dict is the correct returned value.
rcode > 0: dict is : { 'error' : 'error reason' }
-
- TODO. add check for parameters.
'''
# core module ConfigManager does not have a specification file
@@ -273,18 +271,12 @@
if module_name not in self.module_spec.keys():
return 1, {'error' : 'unknown module'}
-
- cmd_valid = False
- # todo: make validate_command() in ModuleSpec class
- commands = self.module_spec[module_name]["commands"]
- for cmd in commands:
- if cmd['command_name'] == command_name:
- cmd_valid = True
- break
-
- if not cmd_valid:
- return 1, {'error' : 'unknown command'}
-
+
+ spec_obj = isc.config.module_spec.ModuleSpec(self.module_spec[module_name], False)
+ errors = []
+ if not spec_obj.validate_command(command_name, params, errors):
+ return 1, {'error': errors[0]}
+
return self.send_command(module_name, command_name, params)
def send_command(self, module_name, command_name, params = None):
Modified: trunk/src/lib/python/isc/cc/message.py
==============================================================================
--- trunk/src/lib/python/isc/cc/message.py (original)
+++ trunk/src/lib/python/isc/cc/message.py Fri May 28 03:49:38 2010
@@ -26,6 +26,7 @@
_ITEM_NULL = 0x04
_ITEM_BOOL = 0x05
_ITEM_INT = 0x06
+_ITEM_REAL = 0x07
_ITEM_UTF8 = 0x08
_ITEM_MASK = 0x0f
@@ -77,6 +78,10 @@
"""Pack an integer and its type/length prefix."""
return (_encode_length_and_type(bytes(str(item), 'utf-8'), _ITEM_INT))
+def _pack_real(item):
+ """Pack an integer and its type/length prefix."""
+ return (_encode_length_and_type(bytes(str(item), 'utf-8'), _ITEM_REAL))
+
def _pack_array(item):
"""Pack a list (array) and its type/length prefix."""
return (_encode_length_and_type(_encode_array(item), _ITEM_LIST))
@@ -98,6 +103,8 @@
return (_pack_bool(item))
elif type(item) == int:
return (_pack_int(item))
+ elif type(item) == float:
+ return (_pack_real(item))
elif type(item) == dict:
return (_pack_hash(item))
elif type(item) == list:
@@ -186,6 +193,8 @@
value = _decode_bool(item)
elif item_type == _ITEM_INT:
value = _decode_int(item)
+ elif item_type == _ITEM_REAL:
+ value = _decode_real(item)
elif item_type == _ITEM_UTF8:
value = str(item, 'utf-8')
elif item_type == _ITEM_HASH:
@@ -205,6 +214,9 @@
def _decode_int(data):
return int(str(data, 'utf-8'))
+def _decode_real(data):
+ return float(str(data, 'utf-8'))
+
def _decode_hash(data):
ret = {}
while len(data) > 0:
Modified: trunk/src/lib/python/isc/config/config_data.py
==============================================================================
--- trunk/src/lib/python/isc/config/config_data.py (original)
+++ trunk/src/lib/python/isc/config/config_data.py Fri May 28 03:49:38 2010
@@ -52,6 +52,51 @@
elif data_type == "map" and type(value) != dict:
# todo: check types of map contents too
raise isc.cc.data.DataTypeError(str(value) + " is not a map")
+
+def convert_type(spec_part, value):
+ """Convert the give value(type is string) according specification
+ part relevant for the value. Raises an isc.cc.data.DataTypeError
+ exception if conversion failed.
+ """
+ if type(spec_part) == dict and 'item_type' in spec_part:
+ data_type = spec_part['item_type']
+ else:
+ raise isc.cc.data.DataTypeError(str("Incorrect specification part for type convering"))
+
+ try:
+ if data_type == "integer":
+ return int(value)
+ elif data_type == "real":
+ return float(value)
+ elif data_type == "boolean":
+ return str.lower(str(value)) != 'false'
+ elif data_type == "string":
+ return str(value)
+ elif data_type == "list":
+ ret = []
+ if type(value) == list:
+ for item in value:
+ ret.append(convert_type(spec_part['list_item_spec'], item))
+ elif type(value) == str:
+ value = value.split(',')
+ for item in value:
+ sub_value = item.split()
+ for sub_item in sub_value:
+ ret.append(convert_type(spec_part['list_item_spec'], sub_item))
+
+ if ret == []:
+ raise isc.cc.data.DataTypeError(str(value) + " is not a list")
+
+ return ret
+ elif data_type == "map":
+ return dict(value)
+ # todo: check types of map contents too
+ else:
+ return value
+ except ValueError as err:
+ raise isc.cc.data.DataTypeError(str(err))
+ except TypeError as err:
+ raise isc.cc.data.DataTypeError(str(err))
def find_spec_part(element, identifier):
"""find the data definition for the given identifier
Modified: trunk/src/lib/python/isc/config/module_spec.py
==============================================================================
--- trunk/src/lib/python/isc/config/module_spec.py (original)
+++ trunk/src/lib/python/isc/config/module_spec.py Fri May 28 03:49:38 2010
@@ -83,6 +83,27 @@
errors.append("No config_data specification")
return False
+ def validate_command(self, cmd_name, cmd_params, errors = None):
+ '''Check whether the given piece of command conforms to this
+ command definition. If so, it reutrns True. If not, it will
+ return False. If errors is given, and is an array, a string
+ describing the error will be appended to it. The current version
+ stops as soon as there is one error.
+ cmd_name is command name to be validated, cmd_params includes
+ command's parameters needs to be validated. cmd_params must
+ be a map, with the format like:
+ {param1_name: param1_value, param2_name: param2_value}
+ '''
+ cmd_spec = self.get_commands_spec()
+ if not cmd_spec:
+ return False
+
+ for cmd in cmd_spec:
+ if cmd['command_name'] != cmd_name:
+ continue
+ return _validate_spec_list(cmd['command_args'], True, cmd_params, errors)
+
+ return False
def get_module_name(self):
"""Returns a string containing the name of the module as
Modified: trunk/src/lib/python/isc/config/tests/config_data_test.py
==============================================================================
--- trunk/src/lib/python/isc/config/tests/config_data_test.py (original)
+++ trunk/src/lib/python/isc/config/tests/config_data_test.py Fri May 28 03:49:38 2010
@@ -94,6 +94,71 @@
#self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, { "value1": 1 })
self.assertRaises(isc.cc.data.DataTypeError, check_type, config_spec, 1)
+
+ def test_convert_type(self):
+ config_spec = isc.config.module_spec_from_file(self.data_path + os.sep + "spec22.spec").get_config_spec()
+ spec_part = find_spec_part(config_spec, "value1")
+ self.assertEqual(1, convert_type(spec_part, '1'))
+ self.assertEqual(2, convert_type(spec_part, 2.1))
+ self.assertEqual(2, convert_type(spec_part, '2'))
+ self.assertEqual(3, convert_type(spec_part, '3'))
+ self.assertEqual(1, convert_type(spec_part, True))
+
+ self.assertRaises(isc.cc.data.DataTypeError, convert_type, spec_part, "a")
+ self.assertRaises(isc.cc.data.DataTypeError, convert_type, spec_part, [ 1, 2 ])
+ self.assertRaises(isc.cc.data.DataTypeError, convert_type, spec_part, { "a": 1 })
+
+ spec_part = find_spec_part(config_spec, "value2")
+ self.assertEqual(1.1, convert_type(spec_part, '1.1'))
+ self.assertEqual(123.0, convert_type(spec_part, '123'))
+ self.assertEqual(1.0, convert_type(spec_part, True))
+ self.assertRaises(isc.cc.data.DataTypeError, convert_type, spec_part, "a")
+ self.assertRaises(isc.cc.data.DataTypeError, convert_type, spec_part, [ 1, 2 ])
+ self.assertRaises(isc.cc.data.DataTypeError, convert_type, spec_part, { "a": 1 })
+
+ spec_part = find_spec_part(config_spec, "value3")
+ self.assertEqual(True, convert_type(spec_part, 'True'))
+ self.assertEqual(False, convert_type(spec_part, 'False'))
+ self.assertEqual(True, convert_type(spec_part, 1))
+ self.assertEqual(True, convert_type(spec_part, 1.1))
+ self.assertEqual(True, convert_type(spec_part, 'a'))
+ self.assertEqual(True, convert_type(spec_part, [1, 2]))
+ self.assertEqual(True, convert_type(spec_part, {'a' : 1}))
+
+ spec_part = find_spec_part(config_spec, "value4")
+ self.assertEqual('asdf', convert_type(spec_part, "asdf"))
+ self.assertEqual('1', convert_type(spec_part, 1))
+ self.assertEqual('1.1', convert_type(spec_part, 1.1))
+ self.assertEqual('True', convert_type(spec_part, True))
+
+ spec_part = find_spec_part(config_spec, "value5")
+ self.assertEqual([1, 2], convert_type(spec_part, '1, 2'))
+ self.assertEqual([1, 2, 3], convert_type(spec_part, '1 2 3'))
+ self.assertEqual([1, 2, 3,4], convert_type(spec_part, '1 2 3, 4'))
+ self.assertEqual([1], convert_type(spec_part, [1,]))
+ self.assertEqual([1,2], convert_type(spec_part, [1,2]))
+ self.assertEqual([1,2], convert_type(spec_part, ['1', '2']))
+
+ self.assertRaises(isc.cc.data.DataTypeError, convert_type, spec_part, 1.1)
+ self.assertRaises(isc.cc.data.DataTypeError, convert_type, spec_part, True)
+ self.assertRaises(isc.cc.data.DataTypeError, convert_type, spec_part, "a")
+ self.assertRaises(isc.cc.data.DataTypeError, convert_type, spec_part, [ "a", "b" ])
+ self.assertRaises(isc.cc.data.DataTypeError, convert_type, spec_part, [ "1", "b" ])
+ self.assertRaises(isc.cc.data.DataTypeError, convert_type, spec_part, { "a": 1 })
+
+ spec_part = find_spec_part(config_spec, "value7")
+ self.assertEqual(['1', '2'], convert_type(spec_part, '1, 2'))
+ self.assertEqual(['1', '2', '3'], convert_type(spec_part, '1 2 3'))
+ self.assertEqual(['1', '2', '3','4'], convert_type(spec_part, '1 2 3, 4'))
+ self.assertEqual([1], convert_type(spec_part, [1,]))
+ self.assertEqual([1,2], convert_type(spec_part, [1,2]))
+ self.assertEqual(['1','2'], convert_type(spec_part, ['1', '2']))
+
+ self.assertRaises(isc.cc.data.DataTypeError, convert_type, spec_part, 1.1)
+ self.assertRaises(isc.cc.data.DataTypeError, convert_type, spec_part, True)
+ self.assertEqual(['a'], convert_type(spec_part, "a"))
+ self.assertEqual(['a', 'b'], convert_type(spec_part, ["a", "b" ]))
+ self.assertEqual([1, 'b'], convert_type(spec_part, [1, "b" ]))
def test_find_spec_part(self):
config_spec = self.cd.get_module_spec().get_config_spec()
Modified: trunk/src/lib/python/isc/config/tests/module_spec_test.py
==============================================================================
--- trunk/src/lib/python/isc/config/tests/module_spec_test.py (original)
+++ trunk/src/lib/python/isc/config/tests/module_spec_test.py Fri May 28 03:49:38 2010
@@ -94,6 +94,24 @@
self.assertEqual(True, self.validate_data("spec22.spec", "data22_7.data"))
self.assertEqual(False, self.validate_data("spec22.spec", "data22_8.data"))
+ def validate_command_params(self, specfile_name, datafile_name, cmd_name):
+ dd = self.read_spec_file(specfile_name);
+ data_file = open(self.spec_file(datafile_name))
+ data_str = data_file.read()
+ params = isc.cc.data.parse_value_str(data_str)
+ return dd.validate_command(cmd_name, params)
+
+ def test_command_validation(self):
+ self.assertEqual(True, self.validate_command_params("spec27.spec", "data22_1.data", 'cmd1'))
+ self.assertEqual(False, self.validate_command_params("spec27.spec", "data22_2.data",'cmd1'))
+ self.assertEqual(False, self.validate_command_params("spec27.spec", "data22_3.data", 'cmd1'))
+ self.assertEqual(False, self.validate_command_params("spec27.spec", "data22_4.data", 'cmd1'))
+ self.assertEqual(False, self.validate_command_params("spec27.spec", "data22_5.data", 'cmd1'))
+ self.assertEqual(True, self.validate_command_params("spec27.spec", "data22_6.data", 'cmd1'))
+ self.assertEqual(True, self.validate_command_params("spec27.spec", "data22_7.data", 'cmd1'))
+ self.assertEqual(False, self.validate_command_params("spec27.spec", "data22_8.data", 'cmd1'))
+ self.assertEqual(False, self.validate_command_params("spec27.spec", "data22_8.data", 'cmd2'))
+
def test_init(self):
self.assertRaises(ModuleSpecError, ModuleSpec, 1)
module_spec = isc.config.module_spec_from_file(self.spec_file("spec1.spec"), False)
More information about the bind10-changes
mailing list