Skip to content

Commit 8ce1073

Browse files
committed
[FAB-3160] Provide config-relative path feature
Introduction ====================== The primary goal of this patch is to create the notion of a "config-relative" path reference. For example, a configuration file "/etc/foo/bar.yaml" that contains a key "bat" with a value "baz/blaz/blamo" can be used to specify that "baz/blaz/blamo" should be considered relative to the configuration file itself. In this case, it would be expected to be found at /etc/foo/baz/blaz/blamo. FAB-2037 does a much more thorough job of explaining the rationale on why config-relative is considered important/good-form. This is in stark contrast to what we have today, which is a jumbled mess of assumed GOPATH relative, CWD relative, ENVVAR absolute and sometimes even ENVVAR relative. Therefore, an additional positive side-effect of this endeavor is that this patch also substantially cleans up some technical debt that had been accumulating in the tree for some time related to ad-hoc pathing, DRY violations, and just general inconsistencies in how configuration files were managed. Design Details ========================== This patch refactors the basic configuration system into the notion of a tree rooted at a configuration-path. By default, this path is $GOROOT/..../fabric/sampleconfig during dev/test and /etc/hyperledger/fabric during runtime. The root may be overridden at any time by specifying the environment variable FABRIC_CFG_PATH. (Note that this variable unifies and replaces the former PEER_CFG_PATH and ORDERER_CFG_PATH). The dev/test environment will operate out of the ./fabric/sampleconfig configuration root. The build-system will package that root into /etc/hyperledger/fabric in the runtime context with the intention of the end-user/admin/deployer replacing parts or all of the sampleconfig to suit their application. Since configuration-relative paths are now possible, the configuration files may reference other relative files and they will behave appropriately regardless of the context in which they are executed. For example, consider the files ./sampleconfig/tls/server.[crt|key]. A configuration file may contain a key "tls/server.key" and the system will properly resolve this relative file even at runtime. This is (IMO) far more natural than assuming a path is relative to the CWD of where the command is executed, which is how most of the system behaves today (or requires awkward and very specific ENVVAR overrides). This will be conducive to something like a package-installer (e.g. RPM/DEB) or a docker environment to augment/replace elements of the configuration root and to freely move the configuration around as the package/deployer sees fit. As an example, a deployment on Kubernetes might opt to volume mount /etc/hyperledger/fabric to replace the entire config, or it might just use a secrets mount on /etc/hyperledger/fabric/peer/tls. An RPM packager might opt to install the configuration files in the default /etc/hyperledger/fabric, whereas an unprivledged user might install them in ~/hyperledger. The point is, it shouldn't matter where they are and the user shouldn't need a PhD in CORE_* variables to get it to work. This is part of an overall effort to improve the user-experience as we march towards a v1.0 release. Fixes FAB-3169 as part of FAB-2037 Change-Id: I5f47f554c2f956ec2e1afebd9bd82b0bbb62892a Signed-off-by: Greg Haskins <[email protected]>
1 parent 6ab1799 commit 8ce1073

File tree

98 files changed

+542
-510
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+542
-510
lines changed

Makefile

+6-12
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ K := $(foreach exec,$(EXECUTABLES),\
7575
GOSHIM_DEPS = $(shell ./scripts/goListFiles.sh $(PKGNAME)/core/chaincode/shim)
7676
JAVASHIM_DEPS = $(shell git ls-files core/chaincode/shim/java)
7777
PROTOS = $(shell git ls-files *.proto | grep -v vendor)
78-
MSP_SAMPLECONFIG = $(shell git ls-files msp/sampleconfig/*)
7978
PROJECT_FILES = $(shell git ls-files)
8079
IMAGES = peer orderer ccenv javaenv buildenv testenv zookeeper kafka couchdb
8180
RELEASE_PLATFORMS = windows-amd64 darwin-amd64 linux-amd64 linux-ppc64le linux-s390x
@@ -208,21 +207,14 @@ build/image/javaenv/payload: build/javashim.tar.bz2 \
208207
build/protos.tar.bz2 \
209208
settings.gradle
210209
build/image/peer/payload: build/docker/bin/peer \
211-
peer/core.yaml \
212-
build/msp-sampleconfig.tar.bz2 \
213-
common/configtx/tool/configtx.yaml
210+
build/sampleconfig.tar.bz2
214211
build/image/orderer/payload: build/docker/bin/orderer \
215-
build/msp-sampleconfig.tar.bz2 \
216-
orderer/orderer.yaml \
217-
common/configtx/tool/configtx.yaml
212+
build/sampleconfig.tar.bz2
218213
build/image/buildenv/payload: build/gotools.tar.bz2 \
219214
build/docker/gotools/bin/protoc-gen-go
220215
build/image/testenv/payload: build/docker/bin/orderer \
221-
orderer/orderer.yaml \
222-
common/configtx/tool/configtx.yaml \
223216
build/docker/bin/peer \
224-
peer/core.yaml \
225-
build/msp-sampleconfig.tar.bz2 \
217+
build/sampleconfig.tar.bz2 \
226218
images/testenv/install-softhsm2.sh
227219
build/image/zookeeper/payload: images/zookeeper/docker-entrypoint.sh
228220
build/image/kafka/payload: images/kafka/docker-entrypoint.sh \
@@ -261,9 +253,11 @@ build/goshim.tar.bz2: $(GOSHIM_DEPS)
261253
@echo "Creating $@"
262254
@tar -jhc -C $(GOPATH)/src $(patsubst $(GOPATH)/src/%,%,$(GOSHIM_DEPS)) > $@
263255

256+
build/sampleconfig.tar.bz2:
257+
(cd sampleconfig && tar -jc *) > $@
258+
264259
build/javashim.tar.bz2: $(JAVASHIM_DEPS)
265260
build/protos.tar.bz2: $(PROTOS)
266-
build/msp-sampleconfig.tar.bz2: $(MSP_SAMPLECONFIG)
267261

268262
build/%.tar.bz2:
269263
@echo "Creating $@"

bddtests/docker-compose-next-4.yml

-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ services:
77
file: docker-compose-orderer-solo.yml
88
service: orderer0
99
environment:
10-
- ORDERER_GENERAL_LOCALMSPDIR=${ORDERER0_ORDERER_GENERAL_LOCALMSPDIR}
1110
- ORDERER_GENERAL_LOCALMSPID=${ORDERER0_ORDERER_GENERAL_LOCALMSPID}
1211
- ORDERER_GENERAL_TLS_ENABLED=true
1312
- ORDERER_GENERAL_TLS_PRIVATEKEY=${ORDERER0_ORDERER_GENERAL_TLS_PRIVATEKEY}
@@ -24,7 +23,6 @@ services:
2423
- CORE_PEER_GOSSIP_BOOTSTRAP=peer1:7051
2524
- CORE_PEER_PROFILE_ENABLED=true
2625
- CORE_PEER_COMMITTER_LEDGER_ORDERER=orderer0:7050
27-
- CORE_PEER_MSPCONFIGPATH=${PEER0_CORE_PEER_MSPCFGPATH}
2826
- CORE_PEER_LOCALMSPID=${PEER0_CORE_PEER_LOCALMSPID}
2927
- CORE_PEER_TLS_CERT_FILE=${PEER0_CORE_PEER_TLS_CERT_FILE}
3028
- CORE_PEER_TLS_KEY_FILE=${PEER0_CORE_PEER_TLS_KEY_FILE}
@@ -44,7 +42,6 @@ services:
4442
- CORE_PEER_ID=vp1
4543
- CORE_PEER_GOSSIP_BOOTSTRAP=peer0:7051
4644
- CORE_PEER_COMMITTER_LEDGER_ORDERER=orderer0:7050
47-
- CORE_PEER_MSPCONFIGPATH=${PEER1_CORE_PEER_MSPCFGPATH}
4845
- CORE_PEER_LOCALMSPID=${PEER1_CORE_PEER_LOCALMSPID}
4946
- CORE_PEER_TLS_CERT_FILE=${PEER1_CORE_PEER_TLS_CERT_FILE}
5047
- CORE_PEER_TLS_KEY_FILE=${PEER1_CORE_PEER_TLS_KEY_FILE}
@@ -62,7 +59,6 @@ services:
6259
- CORE_PEER_ID=vp2
6360
- CORE_PEER_GOSSIP_BOOTSTRAP=peer3:7051
6461
- CORE_PEER_COMMITTER_LEDGER_ORDERER=orderer0:7050
65-
- CORE_PEER_MSPCONFIGPATH=${PEER2_CORE_PEER_MSPCFGPATH}
6662
- CORE_PEER_LOCALMSPID=${PEER2_CORE_PEER_LOCALMSPID}
6763
- CORE_PEER_TLS_CERT_FILE=${PEER2_CORE_PEER_TLS_CERT_FILE}
6864
- CORE_PEER_TLS_KEY_FILE=${PEER2_CORE_PEER_TLS_KEY_FILE}
@@ -80,7 +76,6 @@ services:
8076
- CORE_PEER_ID=vp3
8177
- CORE_PEER_GOSSIP_BOOTSTRAP=peer2:7051
8278
- CORE_PEER_COMMITTER_LEDGER_ORDERER=orderer0:7050
83-
- CORE_PEER_MSPCONFIGPATH=${PEER3_CORE_PEER_MSPCFGPATH}
8479
- CORE_PEER_LOCALMSPID=${PEER3_CORE_PEER_LOCALMSPID}
8580
- CORE_PEER_TLS_CERT_FILE=${PEER3_CORE_PEER_TLS_CERT_FILE}
8681
- CORE_PEER_TLS_KEY_FILE=${PEER3_CORE_PEER_TLS_KEY_FILE}

bddtests/orderer-3-kafka-1.yml

-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ services:
55
service: orderer0
66
image: hyperledger/fabric-testenv-orderer
77
environment:
8-
- ORDERER_GENERAL_LOCALMSPDIR=${ORDERER1_ORDERER_GENERAL_LOCALMSPDIR}
98
- ORDERER_GENERAL_LOCALMSPID=${ORDERER1_ORDERER_GENERAL_LOCALMSPID}
109
- ORDERER_GENERAL_TLS_PRIVATEKEY=${ORDERER1_ORDERER_GENERAL_TLS_PRIVATEKEY}
1110
- ORDERER_GENERAL_TLS_CERTIFICATE=${ORDERER1_ORDERER_GENERAL_TLS_CERTIFICATE}
@@ -19,7 +18,6 @@ services:
1918
service: orderer0
2019
image: hyperledger/fabric-testenv-orderer
2120
environment:
22-
- ORDERER_GENERAL_LOCALMSPDIR=${ORDERER2_ORDERER_GENERAL_LOCALMSPDIR}
2321
- ORDERER_GENERAL_LOCALMSPID=${ORDERER2_ORDERER_GENERAL_LOCALMSPID}
2422
- ORDERER_GENERAL_TLS_PRIVATEKEY=${ORDERER2_ORDERER_GENERAL_TLS_PRIVATEKEY}
2523
- ORDERER_GENERAL_TLS_CERTIFICATE=${ORDERER2_ORDERER_GENERAL_TLS_CERTIFICATE}

bddtests/regression/go/ote/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ Check your Docker and Docker-Compose versions with the following commands:
8484
```
8585

8686
### Environment Variables for configuration
87-
Find default values of all variables in hyperledger/fabric/orderer/orderer.yaml
88-
and hyperledger/fabric/peer/core.yaml.
87+
Find default values of all variables in hyperledger/fabric/sampleconfig/orderer.yaml
88+
and hyperledger/fabric/sampleconfig/core.yaml.
8989
```
9090
CONFIGTX_ORDERER_ORDERERTYPE solo
9191
CONFIGTX_ORDERER_BATCHSIZE_MAXMESSAGECOUNT 10

bddtests/regression/go/ote/network.json

-4
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,6 @@
6565
"zookeeper",
6666
"kafka0"
6767
],
68-
"volumes": [
69-
"/opt/gopath/src/github.com/hyperledger/fabric/msp/sampleconfig:/etc/hyperledger/msp/sampleconfig"
70-
],
7168
"container_name": "orderer0",
7269
"networks": [
7370
"bridge"
@@ -110,7 +107,6 @@
110107
},
111108
"working_dir": "/opt/gopath/src/github.com/hyperledger/fabric/peer",
112109
"volumes": [
113-
"/opt/gopath/src/github.com/hyperledger/fabric/msp/sampleconfig:/etc/hyperledger/msp/sampleconfig",
114110
"/var/run:/host/var/run/"
115111
],
116112
"command": "peer node start",

bddtests/regression/go/ote/ote.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ package main
2020
// ======================
2121
//
2222
// This file ote.go contains main(), for executing from command line
23-
// using environment variables to override those in orderer/orderer.yaml
23+
// using environment variables to override those in sampleconfig/orderer.yaml
2424
// or to set OTE test configuration parameters.
2525
//
2626
// Function ote() is called by main after reading environment variables,

bddtests/steps/endorser_util.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ def getExample02ChaincodeSpec():
157157
def _createDeploymentSpecAsFile(ccSpec, outputPath):
158158
'''peer chaincode package -n myCC -c '{"Args":["init","a","100","b","200"]}' -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 --logging-level=DEBUG test.file'''
159159
myEnv = os.environ.copy()
160-
myEnv['CORE_PEER_MSPCONFIGPATH'] = "./../msp/sampleconfig"
160+
myEnv['CORE_PEER_MSPCONFIGPATH'] = "./../sampleconfig/msp"
161161
nameArgs = ["-n", ccSpec.chaincode_id.name]
162162
ctorArgs = ["-c", json.dumps({'Args' : [item for item in ccSpec.input.args]})]
163163
pathArgs = ["-p", ccSpec.chaincode_id.path]

common/config/msp/config_test.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@ package msp
1919
import (
2020
"testing"
2121

22+
"github.com/hyperledger/fabric/core/config"
2223
"github.com/hyperledger/fabric/msp"
2324
mspprotos "github.com/hyperledger/fabric/protos/msp"
2425
"github.com/stretchr/testify/assert"
2526
)
2627

2728
func TestMSPConfigManager(t *testing.T) {
28-
conf, err := msp.GetLocalMspConfig("../../../msp/sampleconfig/", nil, "DEFAULT")
29+
mspDir, err := config.GetDevMspDir()
30+
assert.NoError(t, err)
31+
conf, err := msp.GetLocalMspConfig(mspDir, nil, "DEFAULT")
2932
assert.NoError(t, err)
3033

3134
// test success:

common/configtx/test/helper.go

+5-27
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,14 @@ limitations under the License.
1717
package test
1818

1919
import (
20-
"os"
21-
"path/filepath"
22-
2320
"github.com/hyperledger/fabric/common/config"
2421
configtxmsp "github.com/hyperledger/fabric/common/config/msp"
2522
"github.com/hyperledger/fabric/common/configtx"
2623
genesisconfig "github.com/hyperledger/fabric/common/configtx/tool/localconfig"
2724
"github.com/hyperledger/fabric/common/configtx/tool/provisional"
2825
"github.com/hyperledger/fabric/common/flogging"
2926
"github.com/hyperledger/fabric/common/genesis"
27+
cf "github.com/hyperledger/fabric/core/config"
3028
"github.com/hyperledger/fabric/msp"
3129
cb "github.com/hyperledger/fabric/protos/common"
3230
mspproto "github.com/hyperledger/fabric/protos/msp"
@@ -39,33 +37,13 @@ const (
3937
AcceptAllPolicyKey = "AcceptAllPolicy"
4038
)
4139

42-
func dirExists(path string) bool {
43-
_, err := os.Stat(path)
44-
return err == nil
45-
}
46-
4740
func getConfigDir() string {
48-
mspSampleConfig := "/msp/sampleconfig"
49-
peerPath := filepath.Join(os.Getenv("PEER_CFG_PATH"), mspSampleConfig)
50-
ordererPath := filepath.Join(os.Getenv("ORDERER_CFG_PATH"), mspSampleConfig)
51-
switch {
52-
case dirExists(peerPath):
53-
return peerPath
54-
case dirExists(ordererPath):
55-
return ordererPath
56-
}
57-
58-
gopath := os.Getenv("GOPATH")
59-
for _, p := range filepath.SplitList(gopath) {
60-
samplePath := filepath.Join(p, "src/github.com/hyperledger/fabric", mspSampleConfig)
61-
if !dirExists(samplePath) {
62-
continue
63-
}
64-
return samplePath
41+
mspDir, err := cf.GetDevMspDir()
42+
if err != nil {
43+
logger.Panicf("Could not find genesis.yaml, try setting GOPATH correctly")
6544
}
6645

67-
logger.Panicf("Could not find genesis.yaml, try setting PEER_CFG_PATH, ORDERER_CFG_PATH, or GOPATH correctly")
68-
return ""
46+
return mspDir
6947
}
7048

7149
// MakeGenesisBlock creates a genesis block using the test templates for the given chainID

common/configtx/test/helper_test.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"path/filepath"
2222
"testing"
2323

24+
"github.com/hyperledger/fabric/core/config"
2425
"github.com/hyperledger/fabric/msp"
2526
logging "github.com/op/go-logging"
2627
)
@@ -43,10 +44,15 @@ func TestMakeGenesisBlock(t *testing.T) {
4344

4445
func TestMakeGenesisBlockFromMSPs(t *testing.T) {
4546

47+
mspDir, err := config.GetDevMspDir()
48+
if err != nil {
49+
t.Fatalf("Error getting DevMspDir: %s", err)
50+
}
51+
4652
ordererOrgID := "TestOrdererOrg"
4753
appOrgID := "TestAppOrg"
48-
appMSPConf, err := msp.GetLocalMspConfig("msp/sampleconfig", nil, appOrgID)
49-
ordererMSPConf, err := msp.GetLocalMspConfig("msp/sampleconfig", nil, ordererOrgID)
54+
appMSPConf, err := msp.GetLocalMspConfig(mspDir, nil, appOrgID)
55+
ordererMSPConf, err := msp.GetLocalMspConfig(mspDir, nil, ordererOrgID)
5056
if err != nil {
5157
t.Fatalf("Error making genesis block from MSPs: %s", err)
5258
}

common/configtx/tool/localconfig/config.go

+23-48
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ package localconfig
1818

1919
import (
2020
"fmt"
21-
"os"
22-
"path/filepath"
21+
2322
"strings"
2423
"time"
2524

@@ -28,7 +27,10 @@ import (
2827

2928
"github.com/spf13/viper"
3029

30+
"path/filepath"
31+
3132
bccsp "github.com/hyperledger/fabric/bccsp/factory"
33+
cf "github.com/hyperledger/fabric/core/config"
3234
)
3335

3436
var logger = flogging.MustGetLogger("configtx/tool/localconfig")
@@ -43,16 +45,6 @@ const (
4345
Prefix string = "CONFIGTX"
4446
)
4547

46-
var (
47-
configName string
48-
configFileName string
49-
)
50-
51-
func init() {
52-
configName = strings.ToLower(Prefix)
53-
configFileName = configName + ".yaml"
54-
}
55-
5648
// TopLevel consists of the structs used by the configtxgen tool.
5749
type TopLevel struct {
5850
Profiles map[string]*Profile `yaml:"Profiles"`
@@ -137,7 +129,7 @@ var genesisDefaults = TopLevel{
137129
},
138130
}
139131

140-
func (p *Profile) completeInitialization() {
132+
func (p *Profile) initDefaults() {
141133
for {
142134
switch {
143135
case p.Orderer.OrdererType == "":
@@ -167,46 +159,29 @@ func (p *Profile) completeInitialization() {
167159
}
168160
}
169161

170-
// Load returns the orderer/application config combination that corresponds to a given profile.
171-
func Load(profile string) *Profile {
172-
config := viper.New()
173-
174-
config.SetConfigName(configName)
175-
var cfgPath string
162+
func translatePaths(configDir string, org *Organization) {
163+
cf.TranslatePathInPlace(configDir, &org.MSPDir)
164+
cf.TranslatePathInPlace(configDir, &org.BCCSP.SwOpts.FileKeystore.KeyStorePath)
165+
}
176166

177-
// Candidate paths to look for the config file in, based on GOPATH
178-
searchPath := []string{
179-
os.Getenv("ORDERER_CFG_PATH"),
180-
os.Getenv("PEER_CFG_PATH"),
181-
}
167+
func (p *Profile) completeInitialization(configDir string) {
168+
p.initDefaults()
182169

183-
for _, p := range filepath.SplitList(os.Getenv("GOPATH")) {
184-
searchPath = append(searchPath, filepath.Join(p, "src/github.com/hyperledger/fabric/common/configtx/tool/"))
170+
// Fix up any relative paths
171+
for _, org := range p.Application.Organizations {
172+
translatePaths(configDir, org)
185173
}
186174

187-
for _, path := range searchPath {
188-
if len(path) == 0 {
189-
// No point printing a "checking for" message below for an empty path
190-
continue
191-
}
192-
logger.Infof("Looking for %s in: %s", configFileName, path)
193-
if _, err := os.Stat(filepath.Join(path, configFileName)); err != nil {
194-
// The YAML file does not exist in this component of the path
195-
continue
196-
}
197-
cfgPath = path
198-
logger.Infof("Found %s there", configFileName)
199-
break
175+
for _, org := range p.Orderer.Organizations {
176+
translatePaths(configDir, org)
200177
}
178+
}
201179

202-
if cfgPath == "" {
203-
logger.Fatalf("Could not find %s in paths of %s."+
204-
"Try setting ORDERER_CFG_PATH, PEER_CFG_PATH, or GOPATH correctly.",
205-
configFileName, searchPath)
206-
}
180+
// Load returns the orderer/application config combination that corresponds to a given profile.
181+
func Load(profile string) *Profile {
182+
config := viper.New()
207183

208-
// Path to look for the config file in
209-
config.AddConfigPath(cfgPath)
184+
cf.InitViper(config, "configtx")
210185

211186
// For environment variables
212187
config.SetEnvPrefix(Prefix)
@@ -217,7 +192,7 @@ func Load(profile string) *Profile {
217192

218193
err := config.ReadInConfig()
219194
if err != nil {
220-
logger.Panicf("Error reading configuration from %s in %s: %s", configFileName, cfgPath, err)
195+
logger.Panicf("Error reading configuration: %s", err)
221196
}
222197

223198
var uconf TopLevel
@@ -231,7 +206,7 @@ func Load(profile string) *Profile {
231206
logger.Panicf("Could not find profile %s", profile)
232207
}
233208

234-
result.completeInitialization()
209+
result.completeInitialization(filepath.Dir(config.ConfigFileUsed()))
235210

236211
return result
237212
}

0 commit comments

Comments
 (0)