def _update_broker_config(self, svc, config): """ Retrieve the latest broker configuration from the management service and update it in the supplied `config`. :param dxlclient._cli._management_service.ManagementService svc: the management service to query for the new broker cert chain :param dxlclient._cli._provision_config.DxlProvisionConfig config: object representing the dxl client configuration """ broker_response = svc.invoke_command(self._BROKER_LIST_COMMAND) try: brokers = json.loads(broker_response)["brokers"] config.brokers = [ Broker(broker["hostName"], broker["guid"], broker["ipAddress"], broker["port"]) for broker in brokers ] websocket_brokers = json.loads(broker_response)["webSocketBrokers"] config.websocket_brokers = [ Broker(broker["hostName"], broker["guid"], broker["ipAddress"], broker["port"]) for broker in websocket_brokers ] except Exception as ex: logger.error("Failed to process broker list. Message: %s", ex) raise
def test_client_retries_defines_how_many_times_the_client_retries_connection(self, retries, connect_count): # Client wont' connect ;) self.client._client.connect = Mock(side_effect=Exception('Could not connect')) # No delay between retries (faster unit tests) self.client.config.reconnect_delay = 0 self.client._wait_for_policy_delay = 0 broker = Broker(host_name='localhost') broker._parse(UuidGenerator.generate_id_as_string() + ";9999;localhost;127.0.0.1") self.client.config.brokers = [broker] self.client.config.connect_retries = retries with self.assertRaises(DxlException): self.client.connect() self.assertEqual(self.client._client.connect.call_count, connect_count)
def test_write_modified_config(self): initial_data = os.linesep.join([ "# mycerts", "[Certs]", "BrokerCertChain = abundle.crt", "CertFile = acertfile.crt", "# pk file", "PrivateKey = akey.key", "{}[Brokers]".format(os.linesep), "# broker 7", "myid7 = myid7;8007;myhost7;10.10.100.7", "# broker 8", "myid8 = myid8;8008;myhost8;10.10.100.8{}".format(os.linesep) ]) expected_data_after_mods = os.linesep.join([ "# mycerts", "[Certs]", "BrokerCertChain = newbundle.pem", "CertFile = acertfile.crt", "# pk file", "PrivateKey = newkey.pem", "{}[Brokers]".format(os.linesep), "# broker 8", "myid8 = myid8;8008;myhost8;10.10.100.8", "myid9 = myid9;8009;myhost9;10.10.100.9{}".format(os.linesep) ]) with patch.object(builtins, 'open', return_value=io.BytesIO(initial_data.encode())), \ patch.object(os.path, 'isfile', return_value=True): config = DxlClientConfig.create_dxl_config_from_file( "mock_file.cfg") del config.brokers[0] config.broker_ca_bundle = "newbundle.pem" config.private_key = "newkey.pem" config.brokers.append(Broker("myhost9", "myid9", "10.10.100.9", 8009)) byte_stream = self.CapturedBytesIO() with patch.object(builtins, 'open', return_value=byte_stream) as mock_open: config.write("newfile.txt") self.assertEqual(expected_data_after_mods.encode(), byte_stream.bytes_captured) mock_open.assert_called_with("newfile.txt", "wb")
def test_client_raises_exception_when_cannot_sync_connect_to_broker(self): with self.create_client() as client: broker = Broker("localhost", UuidGenerator.generate_id_as_string(), "127.0.0.1") client._config.brokers = [broker] with self.assertRaises(DxlException): client.connect()
def test_write_in_memory_config(self): expected_data = os.linesep.join([ "[Certs]", "BrokerCertChain = mycabundle.pem", "CertFile = mycertfile.pem", "PrivateKey = myprivatekey.pem", "{}[Brokers]".format(os.linesep), "myid1 = myid1;8001;myhost1;10.10.100.1", "myid2 = myid2;8002;myhost2;10.10.100.2{}".format(os.linesep) ]) byte_stream = self.CapturedBytesIO() with patch.object(builtins, 'open', return_value=byte_stream) as mock_open: config = DxlClientConfig( "mycabundle.pem", "mycertfile.pem", "myprivatekey.pem", [ Broker("myhost1", "myid1", "10.10.100.1", 8001), Broker("myhost2", "myid2", "10.10.100.2", 8002) ]) config.write("myfile.txt") self.assertEqual(expected_data.encode(), byte_stream.bytes_captured) mock_open.assert_called_with("myfile.txt", "wb")
def test_get_sorted_broker_list_returns_all_brokers(self): # Create config config = DxlClientConfig(broker_ca_bundle=get_ca_bundle_pem(), cert_file=get_cert_file_pem(), private_key=get_dxl_private_key(), brokers=[]) # Create mocked brokers broker1 = Broker('b1host') broker2 = Broker('b2host') broker1._connect_to_broker = broker2._connect_to_broker = Mock( return_value=True) # Add them to config config.brokers.append(broker1) config.brokers.append(broker2) # Get all brokers broker_list = config._get_sorted_broker_list() # Check all brokers are in the list self.assertTrue(broker1 in broker_list) self.assertTrue(broker2 in broker_list)
def _brokers_for_config(broker_lines): """ Convert the supplied broker configuration, a `list` of strings - one for each broker - into a list of :class:`Broker` objects. Each string in the input list represents a key/value pair, delimited by an equal sign. This method uses :meth:`Broker._parse` as a constructor, raising an `Exception` any broker configuration lines are syntactically invalid. :param broker_lines: collection of configuration info for each broker :type broker_lines: list(str) or tuple(str) or set(str) :return: `list` of broker info :rtype: list(Broker) """ brokers = [] for broker_line in broker_lines: try: broker_key, broker_value = broker_line.split("=") except Exception: logger.error("Invalid key value pair for broker entry: %s", broker_line) raise broker = Broker(host_name="none") try: broker._parse(broker_value) except Exception as ex: logger.error("Failed to process broker value: %s. Message: %s", broker_value, ex) raise if not broker.unique_id: raise Exception("No guid for broker: {}".format(broker_value)) if broker.unique_id != broker_key: raise Exception("{}{}{}{}. Broker line: {}".format( "guid for broker key ", broker_key, " did not match guid for broker value: ", broker.unique_id, broker_line)) brokers.append(broker) return brokers
def test_parse_url_valid_with_host_name(self): broker = Broker.parse("mybroker") self.assertIsInstance(broker, Broker) self.assertEqual("mybroker", broker.host_name)
def setUp(self): self.socket_mock = patch('socket.socket').start() self.connection_mock = patch('socket.create_connection').start() self.connection_mock.return_value = self.socket_mock self.broker = Broker(host_name='localhost')
class BrokerTest(unittest.TestCase): def setUp(self): self.socket_mock = patch('socket.socket').start() self.connection_mock = patch('socket.create_connection').start() self.connection_mock.return_value = self.socket_mock self.broker = Broker(host_name='localhost') def tearDown(self): patch.stopall() @parameterized.expand([ ("", ), ("a ; "), ]) @raises(MalformedBrokerUriException) def test_parse_string_with_invalid_port_raises_exception(self, unique_id): self.broker._parse(unique_id + "b; [c] ") @parameterized.expand([ ("", ), ("a ; "), ]) @raises(MalformedBrokerUriException) def test_parse_string_without_hostname_raises_exception(self, unique_id): self.broker._parse(unique_id + "b") @parameterized.expand([ ("", ), ("a ; "), ]) @raises(MalformedBrokerUriException) def test_parse_string_with_empty_hostname_raises_exception( self, unique_id): self.broker._parse(unique_id + "b;") @parameterized.expand([ ("", ), ("a ;"), ]) @raises(MalformedBrokerUriException) def test_parse_string_with_port_out_of_range_raises_exception( self, unique_id): self.broker._parse(unique_id + "65536; [c] ") def test_parse_string_valid_with_unique_id_but_no_ip_address(self): self.broker._parse("a ; 8883; [c] ") self.assertEqual("a", self.broker.unique_id) self.assertEqual(8883, self.broker.port) self.assertEqual("c", self.broker.host_name) self.assertIsNone(self.broker.ip_address) def test_parse_string_valid_with_unique_id_and_ip_address(self): self.broker._parse("a ; 8883; [c];10.0.0.1 ") self.assertEqual("a", self.broker.unique_id) self.assertEqual(8883, self.broker.port) self.assertEqual("c", self.broker.host_name) self.assertEqual("10.0.0.1", self.broker.ip_address) def test_parse_string_valid_without_unique_id_or_ip_address(self): self.broker._parse("8883; [c] ") self.assertEqual("", self.broker.unique_id) self.assertEqual(8883, self.broker.port) self.assertEqual("c", self.broker.host_name) self.assertIsNone(self.broker.ip_address) def test_parse_string_valid_with_ip_address_but_no_unique_id(self): self.broker._parse("8883; [c];10.0.0.1 ") self.assertEqual("", self.broker.unique_id) self.assertEqual(8883, self.broker.port) self.assertEqual("c", self.broker.host_name) self.assertEqual("10.0.0.1", self.broker.ip_address) def test_parse_url_valid_with_host_name(self): broker = Broker.parse("mybroker") self.assertIsInstance(broker, Broker) self.assertEqual("mybroker", broker.host_name) def test_parse_url_valid_with_host_name_and_port(self): broker = Broker.parse("mybroker:8993") self.assertIsInstance(broker, Broker) self.assertEqual("mybroker", broker.host_name) self.assertEqual(8993, broker.port) def test_parse_url_valid_with_protocol_and_host_name(self): broker = Broker.parse("ssl://mybroker") self.assertIsInstance(broker, Broker) self.assertEqual("mybroker", broker.host_name) self.assertEqual(8883, broker.port) def test_parse_url_valid_with_protocol_host_name_and_port(self): broker = Broker.parse("ssl://mybroker:8993") self.assertIsInstance(broker, Broker) self.assertEqual("mybroker", broker.host_name) self.assertEqual(8993, broker.port) def test_parse_url_generates_id(self): broker = Broker.parse("mybroker") self.assertIsInstance(broker, Broker) self.assertIsNotNone(broker.unique_id) self.assertIsNot("", broker.unique_id.strip()) def test_parse_url_valid_with_ipv6_hostname_but_no_port(self): broker = Broker.parse("[ff02::1]") self.assertIsInstance(broker, Broker) self.assertEqual("ff02::1", broker.host_name) self.assertEqual(8883, broker.port) def test_parse_url_valid_with_ipv6_hostname_and_port(self): broker = Broker.parse("[ff02::1]:8993") self.assertIsInstance(broker, Broker) self.assertEqual("ff02::1", broker.host_name) self.assertEqual(8993, broker.port) def test_attributes(self): self.assertEqual("", self.broker.unique_id) self.assertEqual("localhost", self.broker.host_name) self.assertIsNone(self.broker.ip_address) self.assertEqual(8883, self.broker.port) self.assertIsNone(self.broker._response_from_ip_address) self.assertIsNone(self.broker._response_time) def test_connect_tries_first_using_hostname(self): self.broker._parse("broker_guid;8883;broker.fake.com;1.2.3.4") self.broker._connect_to_broker() self.assertFalse(self.broker._response_from_ip_address) self.assertIsNotNone(self.broker._response_time) self.connection_mock.assert_called_with(('broker.fake.com', 8883), timeout=ANY) def test_connect_uses_ip_address_when_connect_to_hostname_fails(self): self.connection_mock.side_effect = [socket.error, self.socket_mock] self.broker._parse("broker_guid;8883;broker.fake.com;1.2.3.4") self.broker._connect_to_broker() self.assertEqual(2, self.connection_mock.call_count) self.assertTrue(self.broker._response_from_ip_address) self.assertIsNotNone(self.broker._response_time) self.connection_mock.assert_called_with(('1.2.3.4', 8883), timeout=ANY) def test_close_once(self): self.broker._parse("broker_guid;8883;broker.fake.com;1.2.3.4") self.broker._connect_to_broker() self.assertEqual(1, self.socket_mock.close.call_count) def test_close_once_when_errors(self): self.connection_mock.side_effect = [socket.error, self.socket_mock] self.broker._parse("broker_guid;8883;broker.fake.com;1.2.3.4") self.broker._connect_to_broker() self.assertEqual(1, self.socket_mock.close.call_count)
def test_parse_url_valid_with_ipv6_hostname_and_port(self): broker = Broker.parse("[ff02::1]:8993") self.assertIsInstance(broker, Broker) self.assertEqual("ff02::1", broker.host_name) self.assertEqual(8993, broker.port)
def test_parse_url_generates_id(self): broker = Broker.parse("mybroker") self.assertIsInstance(broker, Broker) self.assertIsNotNone(broker.unique_id) self.assertIsNot("", broker.unique_id.strip())
def test_parse_url_valid_with_protocol_host_name_and_port(self): broker = Broker.parse("ssl://mybroker:8993") self.assertIsInstance(broker, Broker) self.assertEqual("mybroker", broker.host_name) self.assertEqual(8993, broker.port)
class BrokerTest(unittest.TestCase): def setUp(self): self.socket_mock = patch('socket.socket', autospec=True).start() self.connection_mock = patch('socket.create_connection').start() self.connection_mock.return_value = self.socket_mock self.broker = Broker(host_name='localhost') def tearDown(self): patch.stopall() @raises(MalformedBrokerUriException) def test_parse_invalid_port(self): self.broker._parse("a ; b; [c] ") @raises(MalformedBrokerUriException) def test_parse_missing_hostname(self): self.broker._parse("a ; b;") @raises(MalformedBrokerUriException) def test_parse_port_out_of_range(self): self.broker._parse("a ; 65536; [c] ") def test_parse_valid_without_ip_address(self): self.broker._parse("a ; 8883; [c] ") self.assertTrue(self.broker.unique_id == "a") self.assertTrue(self.broker.port == 8883) self.assertTrue(self.broker.host_name == "c") @raises(MalformedBrokerUriException) def test_parse_valid_with_invalid_ip_address(self): self.broker._parse("a ; 8883; [c];[d] ") def test_parse_valid_with_iPv4_address(self): self.broker._parse("a ; 8883; [c];10.0.0.1 ") self.assertTrue(self.broker.unique_id == "a") self.assertTrue(self.broker.port == 8883) self.assertTrue(self.broker.host_name == "c") self.assertTrue(self.broker.ip_address == "10.0.0.1") def test_parse_valid_with_iPv6_address(self): self.broker._parse("a ; 8883; [c];[::1] ") self.assertTrue(self.broker.unique_id == "a") self.assertTrue(self.broker.port == 8883) self.assertTrue(self.broker.host_name == "c") self.assertTrue(self.broker.ip_address == "::1") def test_attributes(self): self.assertEqual(self.broker.unique_id, "") self.assertEqual(self.broker.host_name, "localhost") self.assertEqual(self.broker.ip_address, None) self.assertEqual(self.broker.port, 8883) self.assertEqual(self.broker._response_from_ip_address, None) self.assertEqual(self.broker._response_time, None) def test_connect_tries_first_using_hostname(self): self.broker._parse("broker_guid;8883;broker.fake.com;1.2.3.4") self.broker._connect_to_broker() self.assertEqual(self.broker._response_from_ip_address, False) self.assertIsNotNone(self.broker._response_time) self.connection_mock.assert_called_with(('broker.fake.com', 8883), timeout=ANY) def test_connect_uses_ip_address_when_connect_to_hostname_fails(self): self.connection_mock.side_effect = [socket.error, self.socket_mock] self.broker._parse("broker_guid;8883;broker.fake.com;1.2.3.4") self.broker._connect_to_broker() self.assertEquals(self.connection_mock.call_count, 2) self.assertEqual(self.broker._response_from_ip_address, True) self.assertIsNotNone(self.broker._response_time) self.connection_mock.assert_called_with(('1.2.3.4', 8883), timeout=ANY) def test_close_once(self): self.broker._parse("broker_guid;8883;broker.fake.com;1.2.3.4") self.broker._connect_to_broker() self.assertEquals(self.socket_mock.close.call_count, 1) def test_close_once_when_errors(self): self.connection_mock.side_effect = [socket.error, self.socket_mock] self.broker._parse("broker_guid;8883;broker.fake.com;1.2.3.4") self.broker._connect_to_broker() self.assertEquals(self.socket_mock.close.call_count, 1)