def setUp(self): ports = [ Ports(internal=80, external=8086, protocol='tcp', ip='0.0.0.0') ] metadata = ContainerMetadata({'name': 'dummyservice_name'}) metadata_with_port = { 80: ContainerMetadata({'name': 'dummyservice_80_name'}) } container_id = 'deadbeef' service_name = 'dummyservice' hostname = 'my_host_name' ip = '127.6.6.6' tags = ['tag1', 'tag2'] self.container_info = ContainerInfo(container_id, service_name, ports, metadata, metadata_with_port, hostname, ip, tags)
def test_names_count_multiple_services(self): self.container_info.metadata = ContainerMetadata() self.container_info.metadata_with_port = { 80: ContainerMetadata({'name': 'dummyservice_80_name'}), 81: ContainerMetadata({'name': 'dummyservice_81_name'}), } self.container_info.ports = [ Ports(internal=80, external=8086, protocol='tcp', ip='0.0.0.0'), Ports(internal=81, external=8087, protocol='tcp', ip='0.0.0.0'), ] counts = self.container_info.names_count() self.assertIn('dummyservice_80_name', counts) self.assertIn('dummyservice_81_name', counts) self.assertEqual(counts['dummyservice_80_name'], 1) self.assertEqual(counts['dummyservice_81_name'], 1)
def test_build_service_ip_metadata_port(self): self.container_info.metadata_with_port = { 80: ContainerMetadata({'ip': '4.3.2.1'}) } port = Ports(internal=80, external=8086, protocol='tcp', ip='0.0.0.0') ip = self.container_info.build_service_ip(port) self.assertEqual(ip, '4.3.2.1')
def test_from_dict(self): a = ContainerMetadata({'tags': ['a', 'b', ''], 'attrs': {'k': 'v'}, 'name': 'x'}) a['tags'] = 'c' a['k2'] = 'v2' a['name'] = 'y' self.assertEqual(set(a['tags']), set(['a', 'b', 'c'])) self.assertEqual(a['attrs'], {'k': 'v', 'k2': 'v2'}) self.assertEqual(a['name'], 'y')
def test_names_count_no_name(self): self.container_info.metadata = ContainerMetadata() self.container_info.ports = [ Ports(internal=81, external=8086, protocol='tcp', ip='0.0.0.0') ] counts = self.container_info.names_count() self.assertNotIn('dummyservice_80_name', counts) self.assertEqual(counts, {})
def test_build_service_attrs_metadata(self): self.container_info.metadata_with_port = { 80: ContainerMetadata({'attrs': { 'k': 'v' }}) } port = Ports(internal=80, external=8086, protocol='tcp', ip='0.0.0.0') attrs = self.container_info.build_service_attrs(port) self.assertEqual(attrs, {'k': 'v'})
def test_build_service_name_multiple_services_same_name_udp(self): self.container_info.metadata = ContainerMetadata( {'name': 'dummyservice_name'}) self.container_info.metadata_with_port = {} self.container_info.ports = [ Ports(internal=80, external=8086, protocol='udp', ip='0.0.0.0'), Ports(internal=81, external=8087, protocol='tcp', ip='0.0.0.0'), ] name = self.container_info.build_service_name( self.container_info.ports[0]) self.assertEqual(name, 'dummyservice_name-8086-udp')
def test_services_multiple(self): self.container_info.metadata = ContainerMetadata( {'name': 'dummyservice_name'}) self.container_info.metadata_with_port = {} self.container_info.ports = [ Ports(internal=80, external=8086, protocol='udp', ip='0.0.0.0'), Ports(internal=81, external=8087, protocol='tcp', ip='0.0.0.0'), ] identifiers = self.container_info.service_identifiers() id1 = self.container_info.SERVICE_ID_SEPARATOR.join( ('my_host_name', 'dummyservice', '8086', 'udp')) id2 = self.container_info.SERVICE_ID_SEPARATOR.join( ('my_host_name', 'dummyservice', '8087')) self.assertIn(id1, identifiers) self.assertIn(id2, identifiers)
def parse_service_key(key, value): log.debug(f"Parsing service key {key}: {value!r}") m = SERVICE_PORT_REGEX.match(key) if m: # matching SERVICE_<port>_ key = m.group('key') port = int(m.group('port')) value = validate_kv(key, value) if value: if port not in metadata_with_port: metadata_with_port[port] = ContainerMetadata() metadata_with_port[port][key] = value else: value = validate_kv(key, value) if value: metadata[key] = value
def test_parse_service_meta(self): metadata, metadata_with_port = ServiceRegistrator.parse_service_meta( self.container) self.assertIsInstance(metadata, ContainerMetadata) self.assertIsInstance(metadata_with_port, dict) self.assertEqual( metadata, ContainerMetadata({ 'attrs': { 'check_interval': '25s', 'check_timeout': '15s' }, 'name': 'dummyservicenoportfromenv', 'tags': ['noporttag'] })) self.assertIn(80, metadata_with_port) self.assertIn(180, metadata_with_port) self.assertEqual( metadata_with_port[80]['attrs'], { 'check_interval': '25s', 'check_timeout': '10s', 'check_tcp': 'true', 'check_script': "date --date='@2147483647'", }) self.assertEqual(metadata_with_port[80]['name'], 'dummyservice') self.assertEqual(set(metadata_with_port[80]['tags']), set(['dummytag', 'prod', 'noporttag'])) self.assertEqual( metadata_with_port[180]['attrs'], { 'check_interval': '25s', 'check_timeout': '15s', 'check_tcp': 'false', 'check_script': "command 'arg=val'" }) self.assertEqual(metadata_with_port[180]['name'], 'dummyservice180') self.assertEqual(metadata_with_port[180]['tags'], ['noporttag'])
def test_get_name_none(self): self.container_info.metadata = ContainerMetadata() port = Ports(internal=81, external=8086, protocol='tcp', ip='0.0.0.0') value = self.container_info.get_name(port) self.assertIsNone(value)
def test_get_attr_no_port_no_metadata(self): self.container_info.metadata = ContainerMetadata() value = self.container_info.get_attr('name', 81) self.assertIsNone(value)
def test_bool_no_metadata(self): self.container_info.metadata_with_port = {} self.container_info.metadata = ContainerMetadata() self.assertFalse(self.container_info)
def test_bool_only_metadata_with_ports(self): self.container_info.metadata = ContainerMetadata() self.assertTrue(self.container_info)
def test_services_no_name(self): self.container_info.metadata = ContainerMetadata({'name': ''}) self.container_info.metadata_with_port = {} services = self.container_info.services self.assertEqual(services, [])
def setUp(self): self.metadata = ContainerMetadata()
def test_build_service_ip_metadata(self): self.container_info.metadata = ContainerMetadata({'ip': '1.2.3.4'}) port = Ports(internal=80, external=8086, protocol='tcp', ip='0.0.0.0') ip = self.container_info.build_service_ip(port) self.assertEqual(ip, '1.2.3.4')
def test_services_tags_metadata_notags(self): self.container_info.tags = [] self.container_info.metadata = ContainerMetadata({'tags': 'tag3,tag4'}) port = Ports(internal=80, external=8086, protocol='tcp', ip='0.0.0.0') tags = self.container_info.build_service_tags(port) self.assertEqual(set(tags), set(['tag4', 'tag3']))
def parse_service_meta(cls, container): # extract SERVICE_* from container env # There are 2 forms: one without port, one with port # SERVICE_80_NAME=thisname # SERVICE_NAME=thisname # when port is specified it will be used for matching internal port service # this is stored in two different dicts # those with ports are stored in metadata_with_port[<port>] # read from env vars kv_from_env = cls.parse_env(container.attrs['Config']['Env']) # read from container labels kv_from_labels = cls.parse_labels(container.labels) metadata = ContainerMetadata() metadata_with_port = dict() def validate_kv(key, value): if key == 'NAME': if not SERVICE_NAME_REGEX.match(value): log.warning( f"{container}: Invalid service name: '{value}', ignoring" ) return None else: return value elif key == 'TAGS': return cls.parse_tags_string(container, value) else: return value def parse_service_key(key, value): log.debug(f"Parsing service key {key}: {value!r}") m = SERVICE_PORT_REGEX.match(key) if m: # matching SERVICE_<port>_ key = m.group('key') port = int(m.group('port')) value = validate_kv(key, value) if value: if port not in metadata_with_port: metadata_with_port[port] = ContainerMetadata() metadata_with_port[port][key] = value else: value = validate_kv(key, value) if value: metadata[key] = value # values from env vars take precedence over the ones from labels for key, value in kv_from_labels.items(): parse_service_key(key, value) for key, value in kv_from_env.items(): parse_service_key(key, value) # default to metadata without port, and concatenate tag lists new_metadata_with_port = dict() for port, meta in metadata_with_port.items(): new_metadata_with_port[port] = copy.deepcopy(metadata) new_metadata_with_port[port].update(meta) return metadata, new_metadata_with_port