Skip to content

Commit 9280d69

Browse files
author
Chris Elder
committed
[FAB-3094] CouchDB Errors if system databases missing
CouchDB log fills with errors if its system databases are not created. The system databases should be created upon peer startup, if they do not yet exist. This change makes a simple check on creating the state database to check if the system database exist as well. If they are missing, then the system databases are created. Change-Id: I6dacb8ceefcda8fd0f14a0ef55da921b9160343d Signed-off-by: Chris Elder <[email protected]>
1 parent 7f336b9 commit 9280d69

File tree

3 files changed

+94
-8
lines changed

3 files changed

+94
-8
lines changed

core/ledger/util/couchdb/couchdb.go

+20-5
Original file line numberDiff line numberDiff line change
@@ -321,8 +321,11 @@ func (dbclient *CouchDatabase) GetDatabaseInfo() (*DBInfo, *DBReturn, error) {
321321

322322
}
323323

324-
//VerifyConnection method provides function to verify the connection information
325-
func (couchInstance *CouchInstance) VerifyConnection() (*ConnectionInfo, *DBReturn, error) {
324+
//VerifyCouchConfig method provides function to verify the connection information
325+
func (couchInstance *CouchInstance) VerifyCouchConfig() (*ConnectionInfo, *DBReturn, error) {
326+
327+
logger.Debugf("Entering VerifyCouchConfig()")
328+
defer logger.Debugf("Exiting VerifyCouchConfig()")
326329

327330
connectURL, err := url.Parse(couchInstance.conf.URL)
328331
if err != nil {
@@ -334,16 +337,18 @@ func (couchInstance *CouchInstance) VerifyConnection() (*ConnectionInfo, *DBRetu
334337
//get the number of retries for startup
335338
maxRetriesOnStartup := couchInstance.conf.MaxRetriesOnStartup
336339

337-
resp, couchDBReturn, err := couchInstance.handleRequest(http.MethodGet, connectURL.String(), nil, "", "", maxRetriesOnStartup)
340+
resp, couchDBReturn, err := couchInstance.handleRequest(http.MethodGet, connectURL.String(), nil,
341+
couchInstance.conf.Username, couchInstance.conf.Password, maxRetriesOnStartup)
342+
338343
if err != nil {
339-
return nil, couchDBReturn, err
344+
return nil, couchDBReturn, fmt.Errorf("Unable to connect to CouchDB, check the hostname and port: %s", err.Error())
340345
}
341346
defer resp.Body.Close()
342347

343348
dbResponse := &ConnectionInfo{}
344349
errJSON := json.NewDecoder(resp.Body).Decode(&dbResponse)
345350
if errJSON != nil {
346-
return nil, nil, errJSON
351+
return nil, nil, fmt.Errorf("Unable to connect to CouchDB, check the hostname and port: %s", errJSON.Error())
347352
}
348353

349354
// trace the database info response
@@ -354,6 +359,16 @@ func (couchInstance *CouchInstance) VerifyConnection() (*ConnectionInfo, *DBRetu
354359
}
355360
}
356361

362+
//check to see if the system databases exist
363+
//Verifying the existence of the system database accomplishes two steps
364+
//1. Ensures the system databases are created
365+
//2. Verifies the username password provided in the CouchDB config are valid for system admin
366+
err = CreateSystemDatabasesIfNotExist(*couchInstance)
367+
if err != nil {
368+
logger.Errorf("Unable to connect to CouchDB, error: %s Check the admin username and password.\n", err.Error())
369+
return nil, nil, fmt.Errorf("Unable to connect to CouchDB, error: %s Check the admin username and password.\n", err.Error())
370+
}
371+
357372
return dbResponse, couchDBReturn, nil
358373

359374
}

core/ledger/util/couchdb/couchdbutil.go

+33-2
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ func CreateCouchInstance(couchDBConnectURL, id, pw string, maxRetries,
4141
//Create the CouchDB instance
4242
couchInstance := &CouchInstance{conf: *couchConf}
4343

44-
connectInfo, retVal, verifyErr := couchInstance.VerifyConnection()
44+
connectInfo, retVal, verifyErr := couchInstance.VerifyCouchConfig()
4545
if verifyErr != nil {
46-
return nil, fmt.Errorf("Unable to connect to CouchDB, check the hostname and port: %s", verifyErr.Error())
46+
return nil, verifyErr
4747
}
4848

4949
//return an error if the http return value is not 200
@@ -96,6 +96,37 @@ func CreateCouchDatabase(couchInstance CouchInstance, dbName string) (*CouchData
9696
return &couchDBDatabase, nil
9797
}
9898

99+
//CreateSystemDatabasesIfNotExist - creates the system databases if they do not exist
100+
func CreateSystemDatabasesIfNotExist(couchInstance CouchInstance) error {
101+
102+
dbName := "_users"
103+
systemCouchDBDatabase := CouchDatabase{CouchInstance: couchInstance, DBName: dbName}
104+
_, err := systemCouchDBDatabase.CreateDatabaseIfNotExist()
105+
if err != nil {
106+
logger.Errorf("Error during CouchDB CreateDatabaseIfNotExist() for system dbName: %s error: %s\n", dbName, err.Error())
107+
return err
108+
}
109+
110+
dbName = "_replicator"
111+
systemCouchDBDatabase = CouchDatabase{CouchInstance: couchInstance, DBName: dbName}
112+
_, err = systemCouchDBDatabase.CreateDatabaseIfNotExist()
113+
if err != nil {
114+
logger.Errorf("Error during CouchDB CreateDatabaseIfNotExist() for system dbName: %s error: %s\n", dbName, err.Error())
115+
return err
116+
}
117+
118+
dbName = "_global_changes"
119+
systemCouchDBDatabase = CouchDatabase{CouchInstance: couchInstance, DBName: dbName}
120+
_, err = systemCouchDBDatabase.CreateDatabaseIfNotExist()
121+
if err != nil {
122+
logger.Errorf("Error during CouchDB CreateDatabaseIfNotExist() for system dbName: %s error: %s\n", dbName, err.Error())
123+
return err
124+
}
125+
126+
return nil
127+
128+
}
129+
99130
//mapAndValidateDatabaseName checks to see if the database name contains illegal characters
100131
//CouchDB Rules: Only lowercase characters (a-z), digits (0-9), and any of the characters
101132
//_, $, (, ), +, -, and / are allowed. Must begin with a letter.

core/ledger/util/couchdb/couchdbutil_test.go

+41-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import (
2626

2727
//Unit test of couch db util functionality
2828
func TestCreateCouchDBConnectionAndDB(t *testing.T) {
29-
if ledgerconfig.IsCouchDBEnabled() == true {
29+
if ledgerconfig.IsCouchDBEnabled() {
3030

3131
database := "testcreatecouchdbconnectionanddb"
3232
cleanup(database)
@@ -41,6 +41,46 @@ func TestCreateCouchDBConnectionAndDB(t *testing.T) {
4141

4242
}
4343

44+
//Unit test of couch db util functionality
45+
func TestCreateCouchDBSystemDBs(t *testing.T) {
46+
if ledgerconfig.IsCouchDBEnabled() {
47+
48+
database := "testcreatecouchdbsystemdb"
49+
cleanup(database)
50+
defer cleanup(database)
51+
52+
//create a new connection
53+
couchInstance, err := CreateCouchInstance(connectURL, "", "", maxRetries,
54+
maxRetriesOnStartup, requestTimeout)
55+
testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to CreateCouchInstance"))
56+
57+
err = CreateSystemDatabasesIfNotExist(*couchInstance)
58+
testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to create system databases"))
59+
60+
db := CouchDatabase{CouchInstance: *couchInstance, DBName: "_users"}
61+
62+
//Retrieve the info for the new database and make sure the name matches
63+
dbResp, _, errdb := db.GetDatabaseInfo()
64+
testutil.AssertNoError(t, errdb, fmt.Sprintf("Error when trying to retrieve _users database information"))
65+
testutil.AssertEquals(t, dbResp.DbName, "_users")
66+
67+
db = CouchDatabase{CouchInstance: *couchInstance, DBName: "_replicator"}
68+
69+
//Retrieve the info for the new database and make sure the name matches
70+
dbResp, _, errdb = db.GetDatabaseInfo()
71+
testutil.AssertNoError(t, errdb, fmt.Sprintf("Error when trying to retrieve _replicator database information"))
72+
testutil.AssertEquals(t, dbResp.DbName, "_replicator")
73+
74+
db = CouchDatabase{CouchInstance: *couchInstance, DBName: "_global_changes"}
75+
76+
//Retrieve the info for the new database and make sure the name matches
77+
dbResp, _, errdb = db.GetDatabaseInfo()
78+
testutil.AssertNoError(t, errdb, fmt.Sprintf("Error when trying to retrieve _global_changes database information"))
79+
testutil.AssertEquals(t, dbResp.DbName, "_global_changes")
80+
81+
}
82+
83+
}
4484
func TestDatabaseMapping(t *testing.T) {
4585

4686
//create a new instance and database object using a database name mixed case

0 commit comments

Comments
 (0)