Skip to content

Commit 0a960e9

Browse files
committed
* addressed Liran's comments.
Signed-off-by: Dean Amar <Dean.Amar@ibm.com>
1 parent 783a1d4 commit 0a960e9

12 files changed

Lines changed: 135 additions & 132 deletions

File tree

cmd/cliutil/flags.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,10 @@ SPDX-License-Identifier: Apache-2.0
77
package cliutil
88

99
import (
10-
"time"
11-
1210
"github.com/spf13/cobra"
1311
)
1412

1513
// SetDefaultFlags registers the --config flag on the given command.
1614
func SetDefaultFlags(cmd *cobra.Command, configPath *string) {
1715
cmd.PersistentFlags().StringVarP(configPath, "config", "c", "", "set the config file path")
1816
}
19-
20-
// SetDurationFlag registers a duration flag with the given name on the given command.
21-
func SetDurationFlag(cmd *cobra.Command, name string, duration *time.Duration) {
22-
cmd.Flags().DurationVar(duration, name, 5*time.Minute, "Timeout for the initialization operation")
23-
}

cmd/committer/db_init_cmd.go

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,33 +37,23 @@ func databaseInitializationCMD() *cobra.Command {
3737
},
3838
}
3939
cliutil.SetDefaultFlags(cmd, &configPath)
40-
cliutil.SetDurationFlag(cmd, "timeout", &timeout)
40+
// registers a duration flag for database initialization.
41+
cmd.Flags().DurationVar(&timeout, "timeout", 5*time.Minute, "Timeout for the initialization operation")
4142
return cmd
4243
}
4344

4445
// runDatabaseInitialization reads the database-initialization config,
4546
// connects directly to the database, and initializes it.
4647
func runDatabaseInitialization(cmd *cobra.Command, configPath string, timeout time.Duration) error {
47-
dbConfig, _, err := config.ReadDBInitYamlAndSetupLogging(config.NewViperWithDBInitDefaults(), configPath)
48+
dbConfig, err := config.ReadDBInitYamlAndSetupLogging(config.NewViperWithDBInitDefaults(), configPath)
4849
if err != nil {
4950
return err
5051
}
5152

5253
ctx, cancel := context.WithTimeout(cmd.Context(), timeout)
5354
defer cancel()
5455

55-
pool, err := db.NewPool(ctx, dbConfig)
56-
if err != nil {
57-
return errors.Wrap(err, "failed to connect to database")
58-
}
59-
defer pool.Close()
60-
61-
tablePreSplitTablets, err := db.GetTablePreSplitTablets(ctx, pool, dbConfig)
62-
if err != nil {
63-
return errors.Wrap(err, "failed to determine database type")
64-
}
65-
66-
if err := db.SetupSystemTablesAndNamespaces(ctx, pool, dbConfig.Retry, tablePreSplitTablets); err != nil {
56+
if err := db.SetupSystemTablesAndNamespaces(ctx, dbConfig); err != nil {
6757
return errors.Wrap(err, "failed to initialize state database")
6858
}
6959

cmd/config/app_config.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,12 @@ func ReadLoadGenYamlAndSetupLogging(
9494
// ReadDBInitYamlAndSetupLogging reading the YAML config file for database initialization.
9595
func ReadDBInitYamlAndSetupLogging(
9696
v *viper.Viper, configPath string,
97-
) (*db.Config, *serve.Config, error) {
98-
cfg, srvCfg, err := readYamlAndSetupLogging[databaseInitConfig](v, configPath)
97+
) (*db.Config, error) {
98+
cfg, _, err := readYamlAndSetupLogging[databaseInitConfig](v, configPath)
9999
if err != nil {
100-
return nil, nil, err
100+
return nil, err
101101
}
102-
return cfg.Database, srvCfg, nil
102+
return cfg.Database, nil
103103
}
104104

105105
// readYamlAndSetupLogging reading the YAML config file of a service.

cmd/config/samples/dbinit.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,13 @@ database:
2323
ca-cert-path: /root/artifacts/peerOrganizations/peer-org-0.com/msp/tlscacerts/tlspeer-org-0-CA-cert.pem
2424
# Maximum size of the database connection pool. Limits concurrent database operations.
2525
# Should be tuned based on database capacity and expected transaction load.
26+
# For database initialization, a small pool is enough since it only performs schema initialization.
2627
# Default: 20
27-
max-connections: 10
28+
max-connections: 5
2829
# Minimum size of the database connection pool. Keeps connections warm for faster operations.
2930
# Should be less than or equal to max-connections.
3031
# Default: 1
31-
min-connections: 5
32+
min-connections: 1
3233
# Enable load balancing across multiple database endpoints. Should be enabled for
3334
# YugabyteDB clusters to distribute operations across nodes. Set to false for single-node deployments.
3435
load-balance: false

docker/images/test_node/run

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ if [[ $ops == *"db"* ]]; then
4343
docker-entrypoint.sh postgres -p 5433 &
4444
fi
4545

46+
if [[ $ops == *"init-db"* ]]; then
47+
"$BINS_PATH/committer" init-db --config "$CONFIGS_PATH/dbinit.yaml"
48+
fi
49+
4650
if [[ $ops == *"orderer"* ]]; then
4751
"$BINS_PATH/mock" start orderer --config "$CONFIGS_PATH/mock-orderer.yaml" &
4852
fi
@@ -59,10 +63,6 @@ if [[ $ops == *"loadgen"* ]]; then
5963
"$BINS_PATH/loadgen" start --config "$CONFIGS_PATH/loadgen.yaml" &
6064
fi
6165

62-
if [[ $ops == *"init-db"* ]]; then
63-
"$BINS_PATH/committer" init-db --config "$CONFIGS_PATH/dbinit.yaml"
64-
fi
65-
6666
# This just override's the postgres trap.
6767
function cleanup() {
6868
jobs

docker/test/common.go

Lines changed: 16 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ type (
6262
dbType string
6363
dbPassword string
6464
dbEndpointsString string
65+
dbInitTimeout string
6566
cmd []string
6667
additionalEnvs []string
6768
}
@@ -102,44 +103,25 @@ func createAndStartContainerAndItsLogs(
102103
ctx context.Context,
103104
t *testing.T,
104105
params createAndStartContainerParameters,
105-
) {
106+
) (<-chan container.WaitResponse, <-chan error) {
106107
t.Helper()
107-
dockerClient, id := createContainer(ctx, t, params)
108-
require.NoError(t, dockerClient.ContainerStart(ctx, id, container.StartOptions{}))
109-
//nolint:contextcheck // We want to ensure cleanup when the test is done.
110-
t.Cleanup(func() {
111-
stopAndRemoveContainerByID(context.Background(), t, dockerClient, id)
112-
})
113-
logs, err := dockerClient.ContainerLogs(ctx, id, container.LogsOptions{
114-
ShowStdout: true,
115-
ShowStderr: true,
116-
Follow: true,
117-
})
108+
dockerClient := createDockerClient(t)
109+
resp, err := dockerClient.ContainerCreate(
110+
ctx, params.config, params.hostConfig, nil, nil, params.name,
111+
)
118112
require.NoError(t, err)
119-
go func() {
120-
_, err = io.Copy(os.Stdout, logs)
121-
if err != nil {
122-
t.Logf("[%s] logs ended with: %v", params.name, err)
123-
}
124-
}()
125-
}
126-
127-
// runContainerToCompletion creates, starts, and waits for a one-shot container to finish,
128-
// asserting a zero exit code.
129-
func runContainerToCompletion(
130-
ctx context.Context,
131-
t *testing.T,
132-
params createAndStartContainerParameters,
133-
) {
134-
t.Helper()
135-
dockerClient, id := createContainer(ctx, t, params)
136113
// Subscribe before starting.
137114
// If the container finishes and is removed, before
138115
// ContainerWait is called, the container ID no longer exists and the exit status is lost.
139-
statusCh, errCh := dockerClient.ContainerWait(ctx, id, container.WaitConditionNotRunning)
140-
require.NoError(t, dockerClient.ContainerStart(ctx, id, container.StartOptions{}))
141-
142-
logs, err := dockerClient.ContainerLogs(ctx, id, container.LogsOptions{
116+
statusCh, errCh := dockerClient.ContainerWait(ctx, resp.ID, container.WaitConditionNextExit)
117+
require.NoError(t, dockerClient.ContainerStart(ctx, resp.ID, container.StartOptions{}))
118+
if !params.hostConfig.AutoRemove {
119+
//nolint:contextcheck // We want to ensure cleanup when the test is done.
120+
t.Cleanup(func() {
121+
stopAndRemoveContainerByID(context.Background(), t, dockerClient, resp.ID)
122+
})
123+
}
124+
logs, err := dockerClient.ContainerLogs(ctx, resp.ID, container.LogsOptions{
143125
ShowStdout: true,
144126
ShowStderr: true,
145127
Follow: true,
@@ -151,25 +133,7 @@ func runContainerToCompletion(
151133
t.Logf("[%s] logs ended with: %v", params.name, err)
152134
}
153135
}()
154-
155-
select {
156-
case err := <-errCh:
157-
require.NoError(t, err)
158-
case status := <-statusCh:
159-
require.Zero(t, status.StatusCode, "container %s failed with exit code %d", params.name, status.StatusCode)
160-
}
161-
}
162-
163-
func createContainer(
164-
ctx context.Context,
165-
t *testing.T,
166-
params createAndStartContainerParameters,
167-
) (*client.Client, string) {
168-
t.Helper()
169-
dockerClient := createDockerClient(t)
170-
resp, err := dockerClient.ContainerCreate(ctx, params.config, params.hostConfig, nil, nil, params.name)
171-
require.NoError(t, err)
172-
return dockerClient, resp.ID
136+
return statusCh, errCh
173137
}
174138

175139
func monitorMetric(t *testing.T, metricsPort string, metricsTLS *connection.TLSConfig, waitForCount int) {

docker/test/container_release_image_test.go

Lines changed: 76 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
142162
func 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.
369411
func 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+
}

integration/runner/runtime.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,6 @@ func (c *CommitterRuntime) ValidateExpectedResultsInCommittedBlock(t *testing.T,
549549
persistedTxIDsStatus := make([]*committerpb.TxStatus, 0, len(expected.TxIDs))
550550
duplicateTxIDsStatus := make([]*committerpb.TxStatus, 0, len(expected.TxIDs))
551551
for i, tID := range expected.TxIDs {
552-
//nolint:gosec // int -> uint32.
553552
s := committerpb.NewTxStatus(expected.Statuses[i], tID, blk.Header.Number, uint32(i))
554553
if s.Status == committerpb.Status_REJECTED_DUPLICATE_TX_ID {
555554
duplicateTxIDsStatus = append(duplicateTxIDsStatus, s)

service/sidecar/test_exports.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ func RequireNotifications( //nolint:revive // argument-limit.
3939
if !IsStatusStoredInDB(s) {
4040
continue
4141
}
42-
//nolint:gosec // int -> uint32.
4342
expected = append(expected, &committerpb.TxStatus{
4443
Ref: committerpb.NewTxRef(txIDs[i], expectedBlockNumber, uint32(i)),
4544
Status: s,

0 commit comments

Comments
 (0)