Skip to content

Commit ea1c53c

Browse files
author
Chris Elder
committed
FAB-827 Add config option in core.yaml for couchDB
Add config option in core.yaml to switch state database from goleveldb to CouchDB Added the following to core.yaml # stateDatabase - options are "goleveldb", "CouchDB" # goleveldb - default state database stored in goleveldb. # CouchDB - store state database in CouchDB stateDatabase: goleveldb couchDBConfig: couchDBAddress: 127.0.0.1:5984 username: password: Changes were also made to couchdb_txmgr to support the config option. Changes were made to couchdb_test.go and marble_example.go to support the config option in core.yaml and environment variables. Marbles example can now be run with couchDb with the following command: CORE_LEDGER_STATE_STATEDATABASE="CouchDB" go run marble_example.go Adding a declaration for CORE_LEDGER_STATE_STATEDATABASE will work for peer, couchdb_test and marbles example. Change-Id: If02ac4f7c1c234d5f4c869875f3c331e35c9a066 Signed-off-by: Chris Elder <chris.elder@us.ibm.com>
1 parent 7e7e23c commit ea1c53c

File tree

10 files changed

+103
-56
lines changed

10 files changed

+103
-56
lines changed

core/ledger/kvledger/example/main/example.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import (
2323
"github.com/hyperledger/fabric/core/ledger"
2424
"github.com/hyperledger/fabric/core/ledger/kvledger"
2525
"github.com/hyperledger/fabric/core/ledger/kvledger/example"
26-
26+
"github.com/hyperledger/fabric/core/ledger/testutil"
2727
pb "github.com/hyperledger/fabric/protos/peer"
2828
)
2929

@@ -40,6 +40,9 @@ var accounts = []string{"account1", "account2", "account3", "account4"}
4040

4141
func init() {
4242

43+
//call a helper method to load the core.yaml
44+
testutil.SetupCoreYAMLConfig("./../../../../../peer")
45+
4346
// Initialization will get a handle to the ledger at the specified path
4447
// Note, if subledgers are supported in the future,
4548
// the various ledgers could be created/managed at this level

core/ledger/kvledger/kv_ledger.go

+8-6
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,15 @@ func NewKVLedger(conf *Conf) (*KVLedger, error) {
7979
if kvledgerconfig.IsCouchDBEnabled() == true {
8080
//By default we can talk to CouchDB with empty id and pw (""), or you can add your own id and password to talk to a secured CouchDB
8181
logger.Debugf("===COUCHDB=== NewKVLedger() Using CouchDB instead of RocksDB...hardcoding and passing connection config for now")
82-
//TODO Hardcoding and passing connection config for now, eventually this will be passed from external config
82+
83+
couchDBDef := kvledgerconfig.GetCouchDBDefinition()
84+
85+
//create new transaction manager based on couchDB
8386
txmgmt := couchdbtxmgmt.NewCouchDBTxMgr(&couchdbtxmgmt.Conf{DBPath: conf.txMgrDBPath},
84-
"127.0.0.1", //couchDB host
85-
5984, //couchDB port
86-
"system", //couchDB db name matches ledger name, TODO for now use system ledger, eventually allow passing in subledger name
87-
"", //enter couchDB id here
88-
"") //enter couchDB pw here
87+
couchDBDef.URL, //couchDB connection URL
88+
"system", //couchDB db name matches ledger name, TODO for now use system ledger, eventually allow passing in subledger name
89+
couchDBDef.Username, //enter couchDB id here
90+
couchDBDef.Password) //enter couchDB pw here
8991
return &KVLedger{blockStore, txmgmt, nil}, nil
9092
}
9193

core/ledger/kvledger/kvledgerconfig/kv_ledger_config.go

+28-5
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,35 @@ limitations under the License.
1616

1717
package kvledgerconfig
1818

19-
// Change this feature toggle to true to use CouchDB for state database
20-
// TODO Eventually this feature toggle will be externalized via a real
21-
// config option on the peer
22-
var useCouchDB = false
19+
import "github.com/spf13/viper"
20+
21+
var stateDatabase = "goleveldb"
22+
var couchDBAddress = "127.0.0.1:5984"
23+
var username = ""
24+
var password = ""
25+
26+
// CouchDBDef contains parameters
27+
type CouchDBDef struct {
28+
URL string
29+
Username string
30+
Password string
31+
}
2332

2433
//IsCouchDBEnabled exposes the useCouchDB variable
2534
func IsCouchDBEnabled() bool {
26-
return useCouchDB
35+
stateDatabase = viper.GetString("ledger.state.stateDatabase")
36+
if stateDatabase == "CouchDB" {
37+
return true
38+
}
39+
return false
40+
}
41+
42+
//GetCouchDBDefinition exposes the useCouchDB variable
43+
func GetCouchDBDefinition() *CouchDBDef {
44+
45+
couchDBAddress = viper.GetString("ledger.state.couchDBConfig.couchDBAddress")
46+
username = viper.GetString("ledger.state.couchDBConfig.username")
47+
password = viper.GetString("ledger.state.couchDBConfig.password")
48+
49+
return &CouchDBDef{couchDBAddress, username, password}
2750
}

core/ledger/kvledger/marble_example/main/marble_example.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,9 @@ import (
2323
"github.com/hyperledger/fabric/core/ledger"
2424
"github.com/hyperledger/fabric/core/ledger/kvledger"
2525
"github.com/hyperledger/fabric/core/ledger/kvledger/example"
26-
27-
logging "github.com/op/go-logging"
28-
26+
"github.com/hyperledger/fabric/core/ledger/testutil"
2927
pb "github.com/hyperledger/fabric/protos/peer"
28+
logging "github.com/op/go-logging"
3029
)
3130

3231
var logger = logging.MustGetLogger("main")
@@ -47,6 +46,9 @@ func init() {
4746
// the various ledgers could be created/managed at this level
4847
logger.Debugf("===COUCHDB=== Marble Example main init()")
4948

49+
//call a helper method to load the core.yaml
50+
testutil.SetupCoreYAMLConfig("./../../../../../peer")
51+
5052
os.RemoveAll(ledgerPath)
5153
ledgerConf := kvledger.NewConf(ledgerPath, 0)
5254
var err error

core/ledger/kvledger/txmgmt/couchdbtxmgmt/couchdb/couchdb.go

+3-11
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import (
3030
"net/textproto"
3131
"net/url"
3232
"regexp"
33-
"strconv"
3433
"strings"
3534

3635
logging "github.com/op/go-logging"
@@ -104,21 +103,14 @@ type FileDetails struct {
104103
}
105104

106105
//CreateConnectionDefinition for a new client connection
107-
func CreateConnectionDefinition(host string, port int, databaseName, username, password string) (*CouchDBConnectionDef, error) {
106+
func CreateConnectionDefinition(couchDBAddress string, databaseName, username, password string) (*CouchDBConnectionDef, error) {
108107

109108
logger.Debugf("===COUCHDB=== Entering CreateConnectionDefinition()")
110109

111-
connectURI := []string{}
112-
connectURI = append(connectURI, "http://")
113-
connectURI = append(connectURI, host)
114-
connectURI = append(connectURI, ":")
115-
116-
connectURI = append(connectURI, strconv.Itoa(port))
117-
118-
urlConcat := strings.Join(connectURI, "")
110+
connectURL := fmt.Sprintf("%s//%s", "http:", couchDBAddress)
119111

120112
//parse the constructed URL to verify no errors
121-
finalURL, err := url.Parse(urlConcat)
113+
finalURL, err := url.Parse(connectURL)
122114
if err != nil {
123115
logger.Errorf("===COUCHDB=== URL parse error: %s", err.Error())
124116
return nil, err

core/ledger/kvledger/txmgmt/couchdbtxmgmt/couchdb/couchdb_test.go

+18-15
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import (
2121
"fmt"
2222
"testing"
2323

24-
kvledgerconfig "github.com/hyperledger/fabric/core/ledger/kvledger/kvledgerconfig"
24+
"github.com/hyperledger/fabric/core/ledger/kvledger/kvledgerconfig"
2525
"github.com/hyperledger/fabric/core/ledger/testutil"
2626
)
2727

@@ -34,8 +34,8 @@ type Asset struct {
3434
Owner string `json:"owner"`
3535
}
3636

37-
var hostname = "localhost"
38-
var port = 5984
37+
var connectURL = "localhost:5984"
38+
var badConnectURL = "localhost:5990"
3939
var database = "testdb1"
4040
var username = ""
4141
var password = ""
@@ -44,16 +44,19 @@ var assetJSON = []byte(`{"asset_name":"marble1","color":"blue","size":"35","owne
4444

4545
func TestDBConnectionDef(t *testing.T) {
4646

47+
//call a helper method to load the core.yaml
48+
testutil.SetupCoreYAMLConfig("./../../../../../../peer")
49+
4750
//create a new connection
48-
_, err := CreateConnectionDefinition("localhost", 5984, "database", "", "")
51+
_, err := CreateConnectionDefinition(connectURL, "database", "", "")
4952
testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to create database connection definition"))
5053

5154
}
5255

5356
func TestDBBadConnectionDef(t *testing.T) {
5457

5558
//create a new connection
56-
_, err := CreateConnectionDefinition("^^^localhost", 5984, "database", "", "")
59+
_, err := CreateConnectionDefinition("^^^localhost:5984", "database", "", "")
5760
testutil.AssertError(t, err, fmt.Sprintf("Did not receive error when trying to create database connection definition with a bad hostname"))
5861

5962
}
@@ -66,7 +69,7 @@ func TestDBCreateSaveWithoutRevision(t *testing.T) {
6669
defer cleanup()
6770

6871
//create a new connection
69-
db, err := CreateConnectionDefinition(hostname, port, database, username, password)
72+
db, err := CreateConnectionDefinition(connectURL, database, username, password)
7073
testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to create database connection definition"))
7174

7275
//create a new database
@@ -85,7 +88,7 @@ func TestDBBadConnection(t *testing.T) {
8588
if kvledgerconfig.IsCouchDBEnabled() == true {
8689

8790
//create a new connection
88-
db, err := CreateConnectionDefinition(hostname, port+5, database, username, password)
91+
db, err := CreateConnectionDefinition(badConnectURL, database, username, password)
8992
testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to create database connection definition"))
9093

9194
//create a new database
@@ -110,7 +113,7 @@ func TestDBCreateDatabaseAndPersist(t *testing.T) {
110113
cleanup()
111114

112115
//create a new connection
113-
db, err := CreateConnectionDefinition(hostname, port, database, username, password)
116+
db, err := CreateConnectionDefinition(connectURL, database, username, password)
114117
testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to create database connection definition"))
115118

116119
//create a new database
@@ -177,7 +180,7 @@ func TestDBBadJSON(t *testing.T) {
177180
cleanup()
178181

179182
//create a new connection
180-
db, err := CreateConnectionDefinition(hostname, port, database, username, password)
183+
db, err := CreateConnectionDefinition(connectURL, database, username, password)
181184
testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to create database connection definition"))
182185

183186
//create a new database
@@ -216,7 +219,7 @@ func TestDBSaveAttachment(t *testing.T) {
216219
attachments = append(attachments, attachment)
217220

218221
//create a new connection
219-
db, err := CreateConnectionDefinition(hostname, port, database, username, password)
222+
db, err := CreateConnectionDefinition(connectURL, database, username, password)
220223
testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to create database connection definition"))
221224

222225
//create a new database
@@ -242,7 +245,7 @@ func TestDBRetrieveNonExistingDocument(t *testing.T) {
242245
defer cleanup()
243246

244247
//create a new connection
245-
db, err := CreateConnectionDefinition(hostname, port, database, username, password)
248+
db, err := CreateConnectionDefinition(connectURL, database, username, password)
246249
testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to create database connection definition"))
247250

248251
//create a new database
@@ -264,7 +267,7 @@ func TestDBTestExistingDB(t *testing.T) {
264267
defer cleanup()
265268

266269
//create a new connection
267-
db, err := CreateConnectionDefinition(hostname, port, database, username, password)
270+
db, err := CreateConnectionDefinition(connectURL, database, username, password)
268271
testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to create database connection definition"))
269272

270273
//create a new database
@@ -286,7 +289,7 @@ func TestDBTestDropNonExistDatabase(t *testing.T) {
286289
defer cleanup()
287290

288291
//create a new connection
289-
db, err := CreateConnectionDefinition(hostname, port, database, username, password)
292+
db, err := CreateConnectionDefinition(connectURL, database, username, password)
290293
testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to create database connection definition"))
291294

292295
//Attempt to drop the database without creating first
@@ -304,7 +307,7 @@ func TestDBTestDropDatabaseBadConnection(t *testing.T) {
304307
defer cleanup()
305308

306309
//create a new connection
307-
db, err := CreateConnectionDefinition(hostname, port+4, database, username, password)
310+
db, err := CreateConnectionDefinition(badConnectURL, database, username, password)
308311
testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to create database connection definition"))
309312

310313
//Attempt to drop the database without creating first
@@ -317,7 +320,7 @@ func TestDBTestDropDatabaseBadConnection(t *testing.T) {
317320
func cleanup() {
318321

319322
//create a new connection
320-
db, _ := CreateConnectionDefinition(hostname, port, database, username, password)
323+
db, _ := CreateConnectionDefinition(connectURL, database, username, password)
321324

322325
//drop the test database
323326
db.DropDatabase()

core/ledger/kvledger/txmgmt/couchdbtxmgmt/couchdb_txmgmt_test.go

+13-11
Original file line numberDiff line numberDiff line change
@@ -28,31 +28,35 @@ import (
2828

2929
type testEnv struct {
3030
conf *Conf
31-
couchHost string
32-
couchPort int
31+
couchDBAddress string
3332
couchDatabaseName string
3433
couchUsername string
3534
couchPassword string
3635
}
3736

3837
func newTestEnv(t testing.TB) *testEnv {
38+
39+
//call a helper method to load the core.yaml
40+
testutil.SetupCoreYAMLConfig("./../../../../../peer")
41+
42+
couchDBDef := kvledgerconfig.GetCouchDBDefinition()
43+
3944
conf := &Conf{"/tmp/tests/ledger/kvledger/txmgmt/couchdbtxmgmt"}
4045
os.RemoveAll(conf.DBPath)
4146
return &testEnv{
4247
conf: conf,
43-
couchHost: "127.0.0.1",
44-
couchPort: 5984,
48+
couchDBAddress: couchDBDef.URL,
4549
couchDatabaseName: "system_test",
46-
couchUsername: "",
47-
couchPassword: "",
50+
couchUsername: couchDBDef.Username,
51+
couchPassword: couchDBDef.Password,
4852
}
4953
}
5054

5155
func (env *testEnv) Cleanup() {
5256
os.RemoveAll(env.conf.DBPath)
5357

5458
//create a new connection
55-
couchDB, _ := couchdb.CreateConnectionDefinition(env.couchHost, env.couchPort, env.couchDatabaseName, env.couchUsername, env.couchPassword)
59+
couchDB, _ := couchdb.CreateConnectionDefinition(env.couchDBAddress, env.couchDatabaseName, env.couchUsername, env.couchPassword)
5660

5761
//drop the test database if it already existed
5862
couchDB.DropDatabase()
@@ -72,8 +76,7 @@ func TestDatabaseAutoCreate(t *testing.T) {
7276
defer env.Cleanup() //and cleanup at the end
7377

7478
txMgr := NewCouchDBTxMgr(env.conf,
75-
env.couchHost, //couchDB host
76-
env.couchPort, //couchDB port
79+
env.couchDBAddress, //couchDB Address
7780
env.couchDatabaseName, //couchDB db name
7881
env.couchUsername, //enter couchDB id
7982
env.couchPassword) //enter couchDB pw
@@ -88,8 +91,7 @@ func TestDatabaseAutoCreate(t *testing.T) {
8891

8992
//Call NewCouchDBTxMgr again, this time the database will already exist from last time
9093
txMgr2 := NewCouchDBTxMgr(env.conf,
91-
env.couchHost, //couchDB host
92-
env.couchPort, //couchDB port
94+
env.couchDBAddress, //couchDB Address
9395
env.couchDatabaseName, //couchDB db name
9496
env.couchUsername, //enter couchDB id
9597
env.couchPassword) //enter couchDB pw

core/ledger/kvledger/txmgmt/couchdbtxmgmt/couchdb_txmgr.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,13 @@ type CouchConnection struct {
8282
}
8383

8484
// NewCouchDBTxMgr constructs a `CouchDBTxMgr`
85-
func NewCouchDBTxMgr(conf *Conf, host string, port int, dbName string, id string, pw string) *CouchDBTxMgr {
85+
func NewCouchDBTxMgr(conf *Conf, couchDBConnectURL string, dbName string, id string, pw string) *CouchDBTxMgr {
8686

8787
// TODO cleanup this RocksDB handle
8888
db := db.CreateDB(&db.Conf{DBPath: conf.DBPath})
8989
db.Open()
9090

91-
couchDB, err := couchdb.CreateConnectionDefinition(host,
92-
port,
91+
couchDB, err := couchdb.CreateConnectionDefinition(couchDBConnectURL,
9392
dbName,
9493
id,
9594
pw)

core/ledger/testutil/test_util.go

+13
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,19 @@ func SetupTestConfig() {
7272
logging.SetFormatter(formatter)
7373
}
7474

75+
// SetupCoreYAMLConfig sets up configurations for tetsing
76+
func SetupCoreYAMLConfig(coreYamlPath string) {
77+
viper.SetConfigName("core")
78+
viper.SetEnvPrefix("CORE")
79+
viper.AddConfigPath(coreYamlPath)
80+
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
81+
viper.AutomaticEnv()
82+
err := viper.ReadInConfig()
83+
if err != nil { // Handle errors reading the config file
84+
panic(fmt.Errorf("Fatal error config file: %s \n", err))
85+
}
86+
}
87+
7588
// SetLogLevel sets up log level
7689
func SetLogLevel(level logging.Level, module string) {
7790
logging.SetLevel(level, module)

peer/core.yaml

+9-1
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ chaincode:
343343
# A value <= 0 turns keepalive off
344344
keepalive: 0
345345

346-
# system chaincodes whitelist. To add system chaincode "myscc" to the
346+
# system chaincodes whitelist. To add system chaincode "myscc" to the
347347
# whitelist, add "myscc: enable" to the list
348348
system:
349349
lccc: enable
@@ -397,6 +397,14 @@ ledger:
397397
# configurations for 'trie'
398398
# 'tire' has no additional configurations exposed as yet
399399

400+
# stateDatabase - options are "goleveldb", "CouchDB"
401+
# goleveldb - default state database stored in goleveldb.
402+
# CouchDB - store state database in CouchDB
403+
stateDatabase: goleveldb
404+
couchDBConfig:
405+
couchDBAddress: 127.0.0.1:5984
406+
username:
407+
password:
400408

401409
###############################################################################
402410
#

0 commit comments

Comments
 (0)