@@ -62,7 +62,7 @@ func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomize
6262func Run (ctx context.Context , img string , opts ... testcontainers.ContainerCustomizer ) (* Container , error ) {
6363 tmpDir , err := os .MkdirTemp ("" , "redpanda" )
6464 if err != nil {
65- return nil , fmt .Errorf ("failed to create directory: %w" , err )
65+ return nil , fmt .Errorf ("create temporary directory: %w" , err )
6666 }
6767 defer os .RemoveAll (tmpDir )
6868
@@ -121,24 +121,24 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom
121121 // the Kafka API.
122122 entrypointPath := filepath .Join (tmpDir , entrypointFile )
123123 if err := os .WriteFile (entrypointPath , entrypoint , 0o700 ); err != nil {
124- return nil , fmt .Errorf ("failed to create entrypoint file: %w" , err )
124+ return nil , fmt .Errorf ("write entrypoint file: %w" , err )
125125 }
126126
127127 // 4. Register extra kafka listeners if provided, network aliases will be
128128 // set
129129 if err := registerListeners (settings , req ); err != nil {
130- return nil , fmt .Errorf ("failed to register listeners: %w" , err )
130+ return nil , fmt .Errorf ("register listeners: %w" , err )
131131 }
132132
133133 // Bootstrap config file contains cluster configurations which will only be considered
134134 // the very first time you start a cluster.
135135 bootstrapConfigPath := filepath .Join (tmpDir , bootstrapConfigFile )
136136 bootstrapConfig , err := renderBootstrapConfig (settings )
137137 if err != nil {
138- return nil , fmt . Errorf ( "failed to create bootstrap config file: %w" , err )
138+ return nil , err
139139 }
140140 if err := os .WriteFile (bootstrapConfigPath , bootstrapConfig , 0o600 ); err != nil {
141- return nil , fmt .Errorf ("failed to create bootstrap config file : %w" , err )
141+ return nil , fmt .Errorf ("write bootstrap config: %w" , err )
142142 }
143143
144144 req .Files = append (req .Files ,
@@ -158,11 +158,11 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom
158158 if settings .EnableTLS {
159159 certPath := filepath .Join (tmpDir , certFile )
160160 if err := os .WriteFile (certPath , settings .cert , 0o600 ); err != nil {
161- return nil , fmt .Errorf ("failed to create certificate file: %w" , err )
161+ return nil , fmt .Errorf ("write certificate file: %w" , err )
162162 }
163163 keyPath := filepath .Join (tmpDir , keyFile )
164164 if err := os .WriteFile (keyPath , settings .key , 0o600 ); err != nil {
165- return nil , fmt .Errorf ("failed to create key file: %w" , err )
165+ return nil , fmt .Errorf ("write key file: %w" , err )
166166 }
167167
168168 req .Files = append (req .Files ,
@@ -192,34 +192,54 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom
192192 // the Redpanda config with the advertised Kafka address.
193193 hostIP , err := ctr .Host (ctx )
194194 if err != nil {
195- return c , fmt .Errorf ("failed to get container host: %w" , err )
195+ return c , fmt .Errorf ("host: %w" , err )
196196 }
197197
198198 kafkaPort , err := ctr .MappedPort (ctx , nat .Port (defaultKafkaAPIPort ))
199199 if err != nil {
200- return c , fmt .Errorf ("failed to get mapped Kafka port: %w" , err )
200+ return c , fmt .Errorf ("mapped kafka port: %w" , err )
201201 }
202202
203203 // 7. Render redpanda.yaml config and mount it.
204204 nodeConfig , err := renderNodeConfig (settings , hostIP , kafkaPort .Int ())
205205 if err != nil {
206- return c , fmt . Errorf ( "failed to render node config: %w" , err )
206+ return c , err
207207 }
208208
209- err = ctr .CopyToContainer (ctx , nodeConfig , filepath .Join (redpandaDir , "redpanda.yaml" ), 600 )
209+ err = ctr .CopyToContainer (ctx , nodeConfig , filepath .Join (redpandaDir , "redpanda.yaml" ), 0o600 )
210210 if err != nil {
211- return c , fmt .Errorf ("failed to copy redpanda.yaml into container: %w" , err )
211+ return c , fmt .Errorf ("copy to container: %w" , err )
212212 }
213213
214214 // 8. Wait until Redpanda is ready to serve requests.
215+ waitHTTP := wait .ForHTTP (defaultAdminAPIPort ).
216+ WithStatusCodeMatcher (func (status int ) bool {
217+ // Redpanda's admin API returns 404 for requests to "/".
218+ return status == http .StatusNotFound
219+ })
220+
221+ var tlsConfig * tls.Config
222+ if settings .EnableTLS {
223+ cert , err := tls .X509KeyPair (settings .cert , settings .key )
224+ if err != nil {
225+ return c , fmt .Errorf ("create admin cert: %w" , err )
226+ }
227+ caCertPool := x509 .NewCertPool ()
228+ caCertPool .AppendCertsFromPEM (settings .cert )
229+ tlsConfig = & tls.Config {
230+ Certificates : []tls.Certificate {cert },
231+ RootCAs : caCertPool ,
232+ }
233+ waitHTTP = waitHTTP .WithTLS (true , tlsConfig )
234+ }
215235 err = wait .ForAll (
216236 wait .ForListeningPort (defaultKafkaAPIPort ),
217- wait . ForListeningPort ( defaultAdminAPIPort ) ,
237+ waitHTTP ,
218238 wait .ForListeningPort (defaultSchemaRegistryPort ),
219239 wait .ForLog ("Successfully started Redpanda!" ),
220240 ).WaitUntilReady (ctx , ctr )
221241 if err != nil {
222- return c , fmt .Errorf ("failed to wait for Redpanda readiness: %w" , err )
242+ return c , fmt .Errorf ("wait for readiness: %w" , err )
223243 }
224244
225245 c .urlScheme = "http"
@@ -231,34 +251,25 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom
231251 if len (settings .ServiceAccounts ) > 0 {
232252 adminAPIPort , err := ctr .MappedPort (ctx , nat .Port (defaultAdminAPIPort ))
233253 if err != nil {
234- return c , fmt .Errorf ("failed to get mapped Admin API port: %w" , err )
254+ return c , fmt .Errorf ("mapped admin port: %w" , err )
235255 }
236256
237257 adminAPIUrl := fmt .Sprintf ("%s://%v:%d" , c .urlScheme , hostIP , adminAPIPort .Int ())
238258 adminCl := NewAdminAPIClient (adminAPIUrl )
239259 if settings .EnableTLS {
240- cert , err := tls .X509KeyPair (settings .cert , settings .key )
241- if err != nil {
242- return c , fmt .Errorf ("failed to create admin client with cert: %w" , err )
243- }
244- caCertPool := x509 .NewCertPool ()
245- caCertPool .AppendCertsFromPEM (settings .cert )
246260 adminCl = adminCl .WithHTTPClient (& http.Client {
247261 Timeout : 5 * time .Second ,
248262 Transport : & http.Transport {
249263 ForceAttemptHTTP2 : true ,
250264 TLSHandshakeTimeout : 10 * time .Second ,
251- TLSClientConfig : & tls.Config {
252- Certificates : []tls.Certificate {cert },
253- RootCAs : caCertPool ,
254- },
265+ TLSClientConfig : tlsConfig ,
255266 },
256267 })
257268 }
258269
259270 for username , password := range settings .ServiceAccounts {
260271 if err := adminCl .CreateUser (ctx , username , password ); err != nil {
261- return c , fmt .Errorf ("failed to create service account with username %q: %w" , username , err )
272+ return c , fmt .Errorf ("create user %q: %w" , username , err )
262273 }
263274 }
264275 }
@@ -299,12 +310,12 @@ func renderBootstrapConfig(settings options) ([]byte, error) {
299310
300311 tpl , err := template .New ("bootstrap.yaml" ).Parse (bootstrapConfigTpl )
301312 if err != nil {
302- return nil , fmt .Errorf ("failed to parse redpanda config file template: %w" , err )
313+ return nil , fmt .Errorf ("parse bootstrap template: %w" , err )
303314 }
304315
305316 var bootstrapConfig bytes.Buffer
306317 if err := tpl .Execute (& bootstrapConfig , bootstrapTplParams ); err != nil {
307- return nil , fmt .Errorf ("failed to render redpanda bootstrap config template: %w" , err )
318+ return nil , fmt .Errorf ("render bootstrap template: %w" , err )
308319 }
309320
310321 return bootstrapConfig .Bytes (), nil
@@ -353,12 +364,12 @@ func renderNodeConfig(settings options, hostIP string, advertisedKafkaPort int)
353364
354365 ncTpl , err := template .New ("redpanda.yaml" ).Parse (nodeConfigTpl )
355366 if err != nil {
356- return nil , fmt .Errorf ("failed to parse redpanda config file template: %w" , err )
367+ return nil , fmt .Errorf ("parse node config template: %w" , err )
357368 }
358369
359370 var redpandaYaml bytes.Buffer
360371 if err := ncTpl .Execute (& redpandaYaml , tplParams ); err != nil {
361- return nil , fmt .Errorf ("failed to render redpanda node config template: %w" , err )
372+ return nil , fmt .Errorf ("render node config template: %w" , err )
362373 }
363374
364375 return redpandaYaml .Bytes (), nil
0 commit comments