1+ using System . Collections . Generic ;
2+ using System . Linq ;
3+
14namespace Testcontainers . Kafka ;
25
36/// <inheritdoc cref="ContainerBuilder{TBuilderEntity, TContainerEntity, TConfigurationEntity}" />
@@ -9,11 +12,18 @@ public sealed class KafkaBuilder : ContainerBuilder<KafkaBuilder, KafkaContainer
912 public const ushort KafkaPort = 9092 ;
1013
1114 public const ushort BrokerPort = 9093 ;
15+
16+ public const ushort ControllerPort = 9094 ;
1217
1318 public const ushort ZookeeperPort = 2181 ;
1419
1520 public const string StartupScriptFilePath = "/testcontainers.sh" ;
1621
22+ private HashSet < string > _listeners = [ ] ;
23+ private List < string > _advertisedListeners = [ ] ;
24+
25+ private const string ProtocolPrefix = "TC" ;
26+
1727 /// <summary>
1828 /// Initializes a new instance of the <see cref="KafkaBuilder" /> class.
1929 /// </summary>
@@ -43,6 +53,39 @@ public override KafkaContainer Build()
4353 return new KafkaContainer ( DockerResourceConfiguration ) ;
4454 }
4555
56+ /// <summary>
57+ /// Add a listener in the format host:port.
58+ /// Host will be included as a network alias.
59+ /// Use it to register additional connections to the Kafka within the same container network.
60+ ///
61+ /// Default listeners: PLAINTEXT://0.0.0.0:9092, BROKER://0.0.0.0:9093, CONTROLLER://0.0.0.0:9094
62+ /// </summary>
63+ /// <param name="kafka"></param>
64+ /// <returns></returns>
65+ /// <exception cref="NotImplementedException"></exception>
66+ public KafkaBuilder WithListener ( string kafka )
67+ {
68+ var host = kafka . Split ( ':' ) [ 0 ] ;
69+
70+ var protocol = $ "{ ProtocolPrefix } -{ _listeners . Count } ";
71+ var listener = $ "{ protocol } ://{ kafka } ";
72+ var listenerSecurityProtocolMap = $ "{ protocol } :PLAINTEXT";
73+
74+ _listeners . Add ( listener ) ;
75+ _advertisedListeners . Add ( listener ) ;
76+
77+ var currentListeners = this . DockerResourceConfiguration . Environments [ "KAFKA_LISTENERS" ] ;
78+ var currentListenersSecurityProtocolMap = this . DockerResourceConfiguration . Environments [ "KAFKA_LISTENER_SECURITY_PROTOCOL_MAP" ] ;
79+
80+ return this . Merge ( DockerResourceConfiguration , new KafkaConfiguration ( _advertisedListeners ) )
81+ . WithEnvironment ( new Dictionary < string , string > ( )
82+ {
83+ { "KAFKA_LISTENERS" , $ "{ currentListeners } ,{ string . Join ( "," , listener ) } " } ,
84+ { "KAFKA_LISTENER_SECURITY_PROTOCOL_MAP" , $ "{ currentListenersSecurityProtocolMap } ,{ string . Join ( "," , listenerSecurityProtocolMap ) } " }
85+ } )
86+ . WithNetworkAliases ( host ) ;
87+ }
88+
4689 /// <inheritdoc />
4790 protected override KafkaBuilder Init ( )
4891 {
@@ -51,8 +94,10 @@ protected override KafkaBuilder Init()
5194 . WithPortBinding ( KafkaPort , true )
5295 . WithPortBinding ( BrokerPort , true )
5396 . WithPortBinding ( ZookeeperPort , true )
54- . WithEnvironment ( "KAFKA_LISTENERS" , "PLAINTEXT://0.0.0.0:" + KafkaPort + ",BROKER://0.0.0.0:" + BrokerPort )
55- . WithEnvironment ( "KAFKA_LISTENER_SECURITY_PROTOCOL_MAP" , "BROKER:PLAINTEXT,PLAINTEXT:PLAINTEXT" )
97+ . WithEnvironment ( "KAFKA_LISTENERS" , $ "PLAINTEXT://0.0.0.0:{ KafkaPort } ,BROKER://0.0.0.0:{ BrokerPort } ,CONTROLLER://0.0.0.0:{ ControllerPort } ")
98+ . WithEnvironment ( "KAFKA_LISTENER_SECURITY_PROTOCOL_MAP" , "BROKER:PLAINTEXT,PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT" )
99+ . WithEnvironment ( "KAFKA_NODE_ID" , "1" )
100+ . WithEnvironment ( "KAFKA_CONTROLLER_QUORUM_VOTERS" , "1@localhost:" + ControllerPort )
56101 . WithEnvironment ( "KAFKA_INTER_BROKER_LISTENER_NAME" , "BROKER" )
57102 . WithEnvironment ( "KAFKA_BROKER_ID" , "1" )
58103 . WithEnvironment ( "KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR" , "1" )
@@ -79,7 +124,7 @@ protected override KafkaBuilder Init()
79124 startupScript . Append ( lf ) ;
80125 startupScript . Append ( "zookeeper-server-start zookeeper.properties &" ) ;
81126 startupScript . Append ( lf ) ;
82- startupScript . Append ( "export KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://" + container . Hostname + ":" + container . GetMappedPublicPort ( KafkaPort ) + ",BROKER://" + container . IpAddress + ":" + BrokerPort ) ;
127+ startupScript . Append ( "export KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://" + container . Hostname + ":" + container . GetMappedPublicPort ( KafkaPort ) + ",BROKER://" + container . IpAddress + ":" + BrokerPort + "," + string . Join ( "," , container . AdvertisedListeners ) ) ;
83128 startupScript . Append ( lf ) ;
84129 startupScript . Append ( "echo '' > /etc/confluent/docker/ensure" ) ;
85130 startupScript . Append ( lf ) ;
@@ -105,4 +150,5 @@ protected override KafkaBuilder Merge(KafkaConfiguration oldValue, KafkaConfigur
105150 {
106151 return new KafkaBuilder ( new KafkaConfiguration ( oldValue , newValue ) ) ;
107152 }
153+
108154}
0 commit comments