def test_unset(self): d1 = {'a': 'a', 'b': 1, 'c': {'d': 'd', 'e': [1, 2, 3]}} data.unset(d1, 'a') data.unset(d1, 'c/d') data.unset(d1, 'does/not/exist') self.assertEqual(d1, {'b': 1, 'c': {'e': [1, 2, 3]}}) data.unset(d1, 'c/e[0]') self.assertEqual(d1, {'b': 1, 'c': {'e': [2, 3]}}) data.unset(d1, 'c/e[1]') self.assertEqual(d1, {'b': 1, 'c': {'e': [2]}}) # index 1 should now be out of range self.assertRaises(data.DataNotFoundError, data.unset, d1, 'c/e[1]') d2 = {'a': [{'b': [1, 2]}]} data.unset(d2, 'a[0]/b[1]') self.assertEqual(d2, {'a': [{'b': [1]}]}) d3 = {'a': [[1, 2]]} data.set(d3, "a[0][1]", 3) self.assertEqual(d3, {'a': [[1, 3]]}) data.unset(d3, 'a[0][1]') self.assertEqual(d3, {'a': [[1]]})
def test_unset(self): d1 = { 'a': 'a', 'b': 1, 'c': { 'd': 'd', 'e': [ 1, 2, 3 ] } } data.unset(d1, 'a') data.unset(d1, 'c/d') data.unset(d1, 'does/not/exist') self.assertEqual(d1, { 'b': 1, 'c': { 'e': [ 1, 2, 3 ] } }) data.unset(d1, 'c/e[0]') self.assertEqual(d1, { 'b': 1, 'c': { 'e': [ 2, 3 ] } }) data.unset(d1, 'c/e[1]') self.assertEqual(d1, { 'b': 1, 'c': { 'e': [ 2 ] } }) # index 1 should now be out of range self.assertRaises(data.DataNotFoundError, data.unset, d1, 'c/e[1]') d2 = { 'a': [ { 'b': [ 1, 2 ] } ] } data.unset(d2, 'a[0]/b[1]') self.assertEqual(d2, { 'a': [ { 'b': [ 1 ] } ] }) d3 = { 'a': [ [ 1, 2 ] ] } data.set(d3, "a[0][1]", 3) self.assertEqual(d3, { 'a': [ [ 1, 3 ] ] }) data.unset(d3, 'a[0][1]') self.assertEqual(d3, { 'a': [ [ 1 ] ] })
def test_set(self): d1 = {'a': 'a', 'b': 1, 'c': {'d': 'd', 'e': 2}} d12 = {'b': 1, 'c': {'e': 3, 'f': [1]}} d13 = {'b': 1, 'c': {'e': 3, 'f': [2]}} d14 = {'b': 1, 'c': {'e': 3, 'f': [{'g': [1, 2]}]}} d15 = {'b': 1, 'c': {'e': 3, 'f': [{'g': [1, 3]}]}} data.set(d1, 'a', None) data.set(d1, 'c/d', None) data.set(d1, 'c/e/', 3) data.set(d1, 'c/f', [1]) self.assertEqual(d1, d12) data.set(d1, 'c/f[0]', 2) self.assertEqual(d1, d13) data.set(d1, 'c/f[0]', {'g': [1, 2]}) self.assertEqual(d1, d14) data.set(d1, 'c/f[0]/g[1]', 3) self.assertEqual(d1, d15) self.assertRaises(data.DataTypeError, data.set, d1, 1, 2) self.assertRaises(data.DataTypeError, data.set, 1, "", 2) self.assertRaises(data.DataTypeError, data.set, d1, 'c[1]', 2) self.assertRaises(data.DataTypeError, data.set, d1, 'c[1][2]', 2) self.assertRaises(data.DataNotFoundError, data.set, d1, 'c/f[5]', 2) self.assertRaises(data.DataNotFoundError, data.set, d1, 'c/f[5][2]', 2) d3 = {} e3 = data.set(d3, "does/not/exist", 123) self.assertEqual(d3, {'does': {'not': {'exist': 123}}}) self.assertEqual(e3, {'does': {'not': {'exist': 123}}})
def test_set(self): d1 = { 'a': 'a', 'b': 1, 'c': { 'd': 'd', 'e': 2 } } d12 = { 'b': 1, 'c': { 'e': 3, 'f': [ 1 ] } } d13 = { 'b': 1, 'c': { 'e': 3, 'f': [ 2 ] } } d14 = { 'b': 1, 'c': { 'e': 3, 'f': [ { 'g': [ 1, 2 ] } ] } } d15 = { 'b': 1, 'c': { 'e': 3, 'f': [ { 'g': [ 1, 3 ] } ] } } data.set(d1, 'a', None) data.set(d1, 'c/d', None) data.set(d1, 'c/e/', 3) data.set(d1, 'c/f', [ 1 ] ) self.assertEqual(d1, d12) data.set(d1, 'c/f[0]', 2 ) self.assertEqual(d1, d13) data.set(d1, 'c/f[0]', { 'g': [ 1, 2] } ) self.assertEqual(d1, d14) data.set(d1, 'c/f[0]/g[1]', 3) self.assertEqual(d1, d15) self.assertRaises(data.DataTypeError, data.set, d1, 1, 2) self.assertRaises(data.DataTypeError, data.set, 1, "", 2) self.assertRaises(data.DataTypeError, data.set, d1, 'c[1]', 2) self.assertRaises(data.DataTypeError, data.set, d1, 'c[1][2]', 2) self.assertRaises(data.DataNotFoundError, data.set, d1, 'c/f[5]', 2) self.assertRaises(data.DataNotFoundError, data.set, d1, 'c/f[5][2]', 2) d3 = {} e3 = data.set(d3, "does/not/exist", 123) self.assertEqual(d3, { 'does': { 'not': { 'exist': 123 } } }) self.assertEqual(e3, { 'does': { 'not': { 'exist': 123 } } })
def __handle_set_config_module(self, module_name, cmd): # the answer comes (or does not come) from the relevant module # so we need a variable to see if we got it answer = None # todo: use api (and check the data against the definition?) old_data = copy.deepcopy(self.config.data) conf_part = data.find_no_exc(self.config.data, module_name) update_cmd = None use_part = None if conf_part: data.merge(conf_part, cmd) use_part = conf_part else: conf_part = data.set(self.config.data, module_name, {}) data.merge(conf_part[module_name], cmd) use_part = conf_part[module_name] # The command to send update_cmd = ccsession.create_command(ccsession.COMMAND_CONFIG_UPDATE, use_part) # TODO: This design might need some revisiting. We might want some # polymorphism instead of branching. But it just might turn out it # will get solved by itself when we move everything to virtual modules # (which is possible solution to the offline configuration problem) # or when we solve the incorect behaviour here when a config is # rejected (spying modules don't know it was rejected and some modules # might have been commited already). if module_name in self.virtual_modules: # The module is virtual, so call it to get the answer try: error = self.virtual_modules[module_name](use_part) if error is None: answer = ccsession.create_answer(0) # OK, it is successful, send the notify, but don't wait # for answer seq = self.cc.group_sendmsg(update_cmd, module_name) else: answer = ccsession.create_answer(1, error) # Make sure just a validating plugin don't kill the whole manager except Exception as excp: # Provide answer answer = ccsession.create_answer(1, "Exception: " + str(excp)) else: # Real module, send it over the wire to it # send out changed info and wait for answer seq = self.cc.group_sendmsg(update_cmd, module_name) try: # replace 'our' answer with that of the module answer, env = self.cc.group_recvmsg(False, seq) except isc.cc.SessionTimeout: answer = ccsession.create_answer(1, "Timeout waiting for answer from " + module_name) except isc.cc.SessionError as se: logger.error(CFGMGR_BAD_UPDATE_RESPONSE_FROM_MODULE, module_name, se) answer = ccsession.create_answer(1, "Unable to parse response from " + module_name + ": " + str(se)) if answer: rcode, val = ccsession.parse_answer(answer) if rcode == 0: self.write_config() else: self.config.data = old_data return answer
def __handle_set_config_module(self, module_name, cmd): # the answer comes (or does not come) from the relevant module # so we need a variable to see if we got it answer = None # todo: use api (and check the data against the definition?) old_data = copy.deepcopy(self.config.data) conf_part = data.find_no_exc(self.config.data, module_name) update_cmd = None use_part = None if conf_part: data.merge(conf_part, cmd) use_part = conf_part else: conf_part = data.set(self.config.data, module_name, {}) data.merge(conf_part[module_name], cmd) use_part = conf_part[module_name] # The command to send update_cmd = ccsession.create_command(ccsession.COMMAND_CONFIG_UPDATE, use_part) # TODO: This design might need some revisiting. We might want some # polymorphism instead of branching. But it just might turn out it # will get solved by itself when we move everything to virtual modules # (which is possible solution to the offline configuration problem) # or when we solve the incorrect behaviour here when a config is # rejected (spying modules don't know it was rejected and some modules # might have been committed already). if module_name in self.virtual_modules: # The module is virtual, so call it to get the answer try: error = self.virtual_modules[module_name](use_part) if error is None: answer = ccsession.create_answer(0) # OK, it is successful, send the notify, but don't wait # for answer seq = self.cc.group_sendmsg(update_cmd, module_name) else: answer = ccsession.create_answer(1, error) # Make sure just a validating plugin don't kill the whole manager except Exception as excp: # Provide answer answer = ccsession.create_answer(1, "Exception: " + str(excp)) else: # Real module, send it over the wire to it # send out changed info and wait for answer seq = self.cc.group_sendmsg(update_cmd, module_name) try: # replace 'our' answer with that of the module answer, env = self.cc.group_recvmsg(False, seq) except isc.cc.SessionTimeout: answer = ccsession.create_answer(1, "Timeout waiting for answer from " + module_name) except isc.cc.SessionError as se: logger.error(CFGMGR_BAD_UPDATE_RESPONSE_FROM_MODULE, module_name, se) answer = ccsession.create_answer(1, "Unable to parse response from " + module_name + ": " + str(se)) if answer: rcode, val = ccsession.parse_answer(answer) if rcode == 0: self.write_config() else: self.config.data = old_data return answer