@@ -44,7 +44,10 @@ const (
4444
4545 defaultDBPort = "5433"
4646 configFlag = "--config"
47+ timeoutFlag = "--timeout"
4748 containerRootUser = "0:0"
49+
50+ dbinit = "dbinit"
4851)
4952
5053// enforcePostgresSSLAndReloadConfigScript enforces SSL-only client connections to a PostgreSQL
@@ -67,14 +70,8 @@ func TestCommitterReleaseImagesWithTLS(t *testing.T) {
6770 ctx := t .Context ()
6871
6972 t .Log ("creating config-block" )
70- v := config .NewViperWithLoadGenDefaults ()
71- c , _ , err := config .ReadLoadGenYamlAndSetupLogging (v , filepath .Join (localConfigPath , "loadgen.yaml" ))
72- require .NoError (t , err )
73- c .LoadProfile .Policy .ArtifactsPath = t .TempDir ()
74- _ , err = workload .CreateOrExtendConfigBlockWithCrypto (& c .LoadProfile .Policy )
75- require .NoError (t , err )
73+ artifactsPath := generateArtifactsPath (t )
7674
77- dbInitNode := "dbinit"
7875 committerNodes := []string {verifierService , vcService , queryService , coordinatorService , sidecarService }
7976
8077 for _ , dbType := range []string {testdb .YugaDBType , testdb .PostgresDBType } {
@@ -93,8 +90,9 @@ func TestCommitterReleaseImagesWithTLS(t *testing.T) {
9390 params := startNodeParameters {
9491 networkName : networkName ,
9592 tlsMode : mode ,
96- artifactsPath : c . LoadProfile . Policy . ArtifactsPath ,
93+ artifactsPath : artifactsPath ,
9794 dbType : dbType ,
95+ dbInitTimeout : "30s" ,
9896 }
9997
10098 for _ , node := range append (committerNodes , dbService , ordererService , loadgenService ) {
@@ -107,7 +105,8 @@ func TestCommitterReleaseImagesWithTLS(t *testing.T) {
107105 // start a secured database node and return the db password.
108106 params .dbPassword = startSecuredDatabaseNode (ctx , t , params .asNode (dbService ))
109107 // init the state DB and verify the operation succeeded.
110- runDatabaseInitWithReleaseImage (ctx , t , params .asNode (dbInitNode ))
108+ statusChannel , errChannel := runDatabaseInitWithReleaseImage (ctx , t , params .asNode (dbinit ))
109+ requireSuccessfulExecution (t , statusChannel , errChannel )
111110 // start the orderer node.
112111 startCommitterNodeWithTestImage (ctx , t , params .asNode (ordererService ))
113112 // start the committer nodes.
@@ -121,9 +120,7 @@ func TestCommitterReleaseImagesWithTLS(t *testing.T) {
121120 // start the load generator node.
122121 startLoadgenNodeWithReleaseImage (ctx , t , params .asNode (loadgenService ))
123122
124- metricsClientTLSConfig := test .NewServiceTLSConfig (
125- c .LoadProfile .Policy .ArtifactsPath , "loadgen" , mode ,
126- )
123+ metricsClientTLSConfig := test .NewServiceTLSConfig (artifactsPath , "loadgen" , mode )
127124
128125 monitorMetric (
129126 t ,
@@ -137,6 +134,29 @@ func TestCommitterReleaseImagesWithTLS(t *testing.T) {
137134 }
138135}
139136
137+ // TestDatabaseInitFailureWithoutActiveDB tests that database initialization fails gracefully
138+ // when the database is not available, using a short timeout.
139+ func TestDatabaseInitFailureWithoutActiveDB (t * testing.T ) {
140+ t .Parallel ()
141+
142+ params := startNodeParameters {
143+ tlsMode : connection .NoneTLSMode ,
144+ dbType : "none_activated_database" ,
145+ dbInitTimeout : "10s" ,
146+ artifactsPath : generateArtifactsPath (t ),
147+ }
148+ statusCh , errorCh := runDatabaseInitWithReleaseImage (t .Context (), t , params .asNode (dbinit ))
149+
150+ // Expect the container to fail since there's no database available.
151+ select {
152+ case status := <- statusCh :
153+ t .Logf ("exited with status code: %v" , status .StatusCode )
154+ require .NotZero (t , status .StatusCode , "container should have failed but exited with code 0" )
155+ case err := <- errorCh :
156+ require .Error (t , err , "container should have failed but exited with no error" )
157+ }
158+ }
159+
140160// CreateAndStartSecuredDatabaseNode creates a containerized YugabyteDB or PostgreSQL
141161// database instance in a secure mode.
142162func startSecuredDatabaseNode (ctx context.Context , t * testing.T , params startNodeParameters ) string {
@@ -185,17 +205,25 @@ func startSecuredDatabaseNode(ctx context.Context, t *testing.T, params startNod
185205}
186206
187207// runDatabaseInitWithReleaseImage runs init-db command in a temporary container.
188- func runDatabaseInitWithReleaseImage (ctx context.Context , t * testing.T , params startNodeParameters ) {
208+ func runDatabaseInitWithReleaseImage (
209+ ctx context.Context , t * testing.T , params startNodeParameters ,
210+ ) (<- chan container.WaitResponse , <- chan error ) {
189211 t .Helper ()
190212
191213 dbInitConfigPath := filepath .Join (containerConfigPath , params .node )
192214 t .Logf ("Starting %s as container with user %s.\n " , committerReleaseImage , containerRootUser )
193215
194- runContainerToCompletion (ctx , t , createAndStartContainerParameters {
216+ statusCh , errCh := createAndStartContainerAndItsLogs (ctx , t , createAndStartContainerParameters {
195217 config : & container.Config {
196218 Image : committerReleaseImage ,
197- Cmd : []string {initDBCommand , configFlag , fmt .Sprintf ("%s.yaml" , dbInitConfigPath )},
198- User : containerRootUser ,
219+ Cmd : []string {
220+ initDBCommand ,
221+ configFlag ,
222+ fmt .Sprintf ("%s.yaml" , dbInitConfigPath ),
223+ timeoutFlag ,
224+ params .dbInitTimeout ,
225+ },
226+ User : containerRootUser ,
199227 Env : []string {
200228 "SC_DBINIT_DATABASE_PASSWORD=" + params .dbPassword ,
201229 "SC_DBINIT_DATABASE_USERNAME=" + params .dbUsername (),
@@ -208,14 +236,15 @@ func runDatabaseInitWithReleaseImage(ctx context.Context, t *testing.T, params s
208236 Binds : []string {
209237 fmt .Sprintf (
210238 "%s.yaml:/%s.yaml" ,
211- filepath .Join (mustGetWD (t ), localConfigPath , "dbinit" ), dbInitConfigPath ,
239+ filepath .Join (mustGetWD (t ), localConfigPath , params . node ), dbInitConfigPath ,
212240 ),
213241 fmt .Sprintf ("%s:%s" , params .artifactsPath , containerArtifactsPath ),
214242 },
215243 AutoRemove : true ,
216244 },
217245 name : assembleContainerName (initDBCommand , params .tlsMode , params .dbType ),
218246 })
247+ return statusCh , errCh
219248}
220249
221250// startCommitterNodeWithReleaseImage starts a committer node using the release image.
@@ -365,10 +394,40 @@ func startCommitterNodeWithTestImage(
365394 })
366395}
367396
397+ // generateArtifactsPath loads a loadgen config, create crypto materials and return their path.
398+ func generateArtifactsPath (t * testing.T ) string {
399+ t .Helper ()
400+ t .Log ("creating config-block" )
401+ v := config .NewViperWithLoadGenDefaults ()
402+ c , _ , err := config .ReadLoadGenYamlAndSetupLogging (v , filepath .Join (localConfigPath , "loadgen.yaml" ))
403+ require .NoError (t , err )
404+ c .LoadProfile .Policy .ArtifactsPath = t .TempDir ()
405+ _ , err = workload .CreateOrExtendConfigBlockWithCrypto (& c .LoadProfile .Policy )
406+ require .NoError (t , err )
407+ return c .LoadProfile .Policy .ArtifactsPath
408+ }
409+
368410// mustGetWD returns the current working directory.
369411func mustGetWD (t * testing.T ) string {
370412 t .Helper ()
371413 wd , err := os .Getwd ()
372414 require .NoError (t , err )
373415 return wd
374416}
417+
418+ func requireSuccessfulExecution (
419+ t * testing.T , statusCh <- chan container.WaitResponse , errCh <- chan error ,
420+ ) {
421+ t .Helper ()
422+ select {
423+ case err := <- errCh :
424+ require .NoError (t , err )
425+ case status := <- statusCh :
426+ require .Zero (
427+ t ,
428+ status .StatusCode ,
429+ "container failed with exit code %d" ,
430+ status .StatusCode ,
431+ )
432+ }
433+ }
0 commit comments