Skip to content

Commit 48682df

Browse files
committed
[FAB-7132] Add couch indexes to chaincode install pkg
Allow indexes that support chaincode queries to be defined alongside chaincode. Any index defined in chaincode directory /statedb/couchdb/indexes will get added to the chaincode deployment spec code package, so that when the chaincode is both installed on a peer and instantiated on a channel, the indexes can be automatically deployed to couchdb. Change-Id: Iaf33a436e76998ae74608d3605acab5643a52f9f Signed-off-by: David Enyeart <enyeart@us.ibm.com>
1 parent 81af16e commit 48682df

File tree

4 files changed

+70
-4
lines changed

4 files changed

+70
-4
lines changed

core/chaincode/platforms/golang/package.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ func getCode(spec *pb.ChaincodeSpec) (*CodeDescriptor, error) {
8787

8888
type SourceDescriptor struct {
8989
Name, Path string
90+
IsMetadata bool
9091
Info os.FileInfo
9192
}
9293
type SourceMap map[string]SourceDescriptor
@@ -115,13 +116,20 @@ func findSource(gopath, pkg string) (SourceMap, error) {
115116
}
116117

117118
if info.IsDir() {
119+
120+
// Allow import of the top level chaincode directory into chaincode code package
118121
if path == tld {
119-
// We dont want to import any directories, but we don't want to stop processing
120-
// at the TLD either.
121122
return nil
122123
}
123124

124-
// Do not recurse
125+
// Allow import of META-INF metadata directories into chaincode code package tar.
126+
// META-INF directories contain chaincode metadata artifacts such as statedb index definitions
127+
if isMetadataDir(path, tld) {
128+
logger.Debug("Files in META-INF directory will be included in code package tar:", path)
129+
return nil
130+
}
131+
132+
// Do not import any other directories into chaincode code package
125133
logger.Debugf("skipping dir: %s", path)
126134
return filepath.SkipDir
127135
}
@@ -137,7 +145,7 @@ func findSource(gopath, pkg string) (SourceMap, error) {
137145
return fmt.Errorf("error obtaining relative path for %s: %s", path, err)
138146
}
139147

140-
sources[name] = SourceDescriptor{Name: name, Path: path, Info: info}
148+
sources[name] = SourceDescriptor{Name: name, Path: path, IsMetadata: isMetadataDir(path, tld), Info: info}
141149

142150
return nil
143151
}
@@ -148,3 +156,8 @@ func findSource(gopath, pkg string) (SourceMap, error) {
148156

149157
return sources, nil
150158
}
159+
160+
// isMetadataDir checks to see if the current path is in the META-INF directory at the root of the chaincode directory
161+
func isMetadataDir(path, tld string) bool {
162+
return strings.HasPrefix(path, filepath.Join(tld, "META-INF"))
163+
}

core/chaincode/platforms/golang/platform.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,23 @@ func (goPlatform *Platform) GetDeploymentPayload(spec *pb.ChaincodeSpec) ([]byte
426426
tw := tar.NewWriter(gw)
427427

428428
for _, file := range files {
429+
430+
// If the file is metadata rather than golang code, remove the leading go code path, for example:
431+
// file.Name: src/github.com/hyperledger/fabric/examples/chaincode/go/marbles02/META-INF/statedb/couchdb/indexes/indexOwner.json
432+
// tar file: META-INF/statedb/couchdb/indexes/indexOwner.json
433+
if file.IsMetadata {
434+
435+
// Ensure META-INF directory can be found, then grab the META-INF relative path to use for packaging
436+
if !strings.HasPrefix(file.Name, filepath.Join("src", code.Pkg, "META-INF")) {
437+
return nil, fmt.Errorf("Could not find META-INF directory in metadata file %s.", file.Name)
438+
}
439+
file.Name, err = filepath.Rel(filepath.Join("src", code.Pkg), file.Name)
440+
if err != nil {
441+
return nil, fmt.Errorf("Could not get relative path for META-INF directory %s. Error:%s", file.Name, err)
442+
}
443+
}
444+
445+
logger.Debug("Writing file to chaincode code package tarball:", file.Name)
429446
err = cutil.WriteFileToPackage(file.Path, file.Name, tw)
430447
if err != nil {
431448
return nil, fmt.Errorf("Error writing %s to tar: %s", file.Name, err)

core/chaincode/platforms/golang/platform_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,41 @@ func Test_DeploymentPayload(t *testing.T) {
165165
}
166166
}
167167

168+
func Test_DeploymentPayloadWithStateDBArtifacts(t *testing.T) {
169+
platform := &Platform{}
170+
spec := &pb.ChaincodeSpec{
171+
ChaincodeId: &pb.ChaincodeID{
172+
Path: "github.com/hyperledger/fabric/examples/chaincode/go/marbles02",
173+
},
174+
}
175+
176+
payload, err := platform.GetDeploymentPayload(spec)
177+
assert.NoError(t, err)
178+
179+
t.Logf("payload size: %d", len(payload))
180+
181+
is := bytes.NewReader(payload)
182+
gr, err := gzip.NewReader(is)
183+
if err == nil {
184+
tr := tar.NewReader(gr)
185+
186+
var foundIndexArtifact bool
187+
for {
188+
header, err := tr.Next()
189+
if err != nil {
190+
// We only get here if there are no more entries to scan
191+
break
192+
}
193+
194+
t.Logf("%s (%d)", header.Name, header.Size)
195+
if header.Name == "META-INF/statedb/couchdb/indexes/indexOwner.json" {
196+
foundIndexArtifact = true
197+
}
198+
}
199+
assert.Equal(t, true, foundIndexArtifact, "should have found statedb index artifact in marbles02 META-INF directory")
200+
}
201+
}
202+
168203
func Test_decodeUrl(t *testing.T) {
169204
cs := &pb.ChaincodeSpec{
170205
ChaincodeId: &pb.ChaincodeID{
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"index":{"fields":["chaincodeid","data.owner"]},"name":"indexOwner","type":"json"}

0 commit comments

Comments
 (0)