-
Notifications
You must be signed in to change notification settings - Fork 8.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FAB-16937] complete by hooking CC fwork with ext. CC
With the external builder and chaincode support prepared for chaincode-as-server model this task finally fills in the remaining pieces to complete the model . adjust chaincode support for client gRPC stream . fork runtime to connect to cc server if server info is provided FAB-16937 Change-Id: I09ecb17fcc762e2cb5e706176bec9b6fa738962e Signed-off-by: muralisr <[email protected]>
- Loading branch information
1 parent
4bde8c4
commit 1b8be06
Showing
13 changed files
with
751 additions
and
100 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
/* | ||
Copyright IBM Corp. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package extcc | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/hyperledger/fabric/common/flogging" | ||
"github.com/hyperledger/fabric/core/comm" | ||
"github.com/hyperledger/fabric/core/container/ccintf" | ||
"github.com/pkg/errors" | ||
|
||
pb "github.com/hyperledger/fabric-protos-go/peer" | ||
|
||
"google.golang.org/grpc" | ||
) | ||
|
||
var extccLogger = flogging.MustGetLogger("extcc") | ||
|
||
// StreamHandler handles the `Chaincode` gRPC service with peer as client | ||
type StreamHandler interface { | ||
HandleChaincodeStream(stream ccintf.ChaincodeStream) error | ||
} | ||
|
||
type ExternalChaincodeRuntime struct { | ||
} | ||
|
||
// createConnection - standard grpc client creating using ClientConfig info (surprised there isn't | ||
// a helper method for this) | ||
func (i *ExternalChaincodeRuntime) createConnection(ccid string, ccinfo *ccintf.ChaincodeServerInfo) (*grpc.ClientConn, error) { | ||
grpcClient, err := comm.NewGRPCClient(ccinfo.ClientConfig) | ||
if err != nil { | ||
return nil, errors.WithMessagef(err, "error creating grpc client to %s", ccid) | ||
} | ||
|
||
conn, err := grpcClient.NewConnection(ccinfo.Address) | ||
if err != nil { | ||
return nil, errors.WithMessagef(err, "error creating grpc connection to %s", ccinfo.Address) | ||
} | ||
|
||
extccLogger.Debugf("Created external chaincode connection: %s", ccid) | ||
|
||
return conn, nil | ||
} | ||
|
||
func (i *ExternalChaincodeRuntime) Stream(ccid string, ccinfo *ccintf.ChaincodeServerInfo, sHandler StreamHandler) error { | ||
extccLogger.Debugf("Starting external chaincode connection: %s", ccid) | ||
conn, err := i.createConnection(ccid, ccinfo) | ||
if err != nil { | ||
return errors.WithMessagef(err, "error cannot create connection for %s", ccid) | ||
} | ||
|
||
defer conn.Close() | ||
|
||
//create the client and start streaming | ||
client := pb.NewChaincodeClient(conn) | ||
|
||
stream, err := client.Connect(context.Background()) | ||
if err != nil { | ||
return errors.WithMessagef(err, "error creating grpc client connection to %s", ccid) | ||
} | ||
|
||
//peer as client has to initiate the stream. Rest of the process is unchanged | ||
sHandler.HandleChaincodeStream(stream) | ||
|
||
extccLogger.Debugf("External chaincode %s client exited", ccid) | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
/* | ||
Copyright IBM Corp. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package extcc_test | ||
|
||
import ( | ||
"net" | ||
"time" | ||
|
||
"github.com/hyperledger/fabric/core/chaincode/extcc" | ||
"github.com/hyperledger/fabric/core/chaincode/extcc/mock" | ||
"github.com/hyperledger/fabric/core/comm" | ||
"github.com/hyperledger/fabric/core/container/ccintf" | ||
|
||
"google.golang.org/grpc" | ||
|
||
. "github.com/onsi/ginkgo" | ||
. "github.com/onsi/gomega" | ||
) | ||
|
||
var _ = Describe("Extcc", func() { | ||
var ( | ||
i *extcc.ExternalChaincodeRuntime | ||
shandler *mock.StreamHandler | ||
) | ||
|
||
BeforeEach(func() { | ||
shandler = &mock.StreamHandler{} | ||
i = &extcc.ExternalChaincodeRuntime{} | ||
}) | ||
|
||
Context("Run", func() { | ||
When("chaincode is running", func() { | ||
var ( | ||
cclist net.Listener | ||
ccserv *grpc.Server | ||
) | ||
BeforeEach(func() { | ||
var err error | ||
cclist, err = net.Listen("tcp", "127.0.0.1:0") | ||
Expect(err).To(BeNil()) | ||
Expect(cclist).To(Not(BeNil())) | ||
ccserv = grpc.NewServer([]grpc.ServerOption{}...) | ||
go ccserv.Serve(cclist) | ||
}) | ||
|
||
AfterEach(func() { | ||
if ccserv != nil { | ||
ccserv.Stop() | ||
} | ||
if cclist != nil { | ||
cclist.Close() | ||
} | ||
}) | ||
|
||
It("runs to completion", func() { | ||
ccinfo := &ccintf.ChaincodeServerInfo{ | ||
Address: cclist.Addr().String(), | ||
ClientConfig: comm.ClientConfig{ | ||
KaOpts: comm.DefaultKeepaliveOptions, | ||
Timeout: 10 * time.Second, | ||
}, | ||
} | ||
err := i.Stream("ccid", ccinfo, shandler) | ||
Expect(err).To(BeNil()) | ||
Expect(shandler.HandleChaincodeStreamCallCount()).To(Equal(1)) | ||
|
||
streamArg := shandler.HandleChaincodeStreamArgsForCall(0) | ||
Expect(streamArg).To(Not(BeNil())) | ||
}) | ||
}) | ||
Context("chaincode info incorrect", func() { | ||
var ( | ||
ccinfo *ccintf.ChaincodeServerInfo | ||
) | ||
BeforeEach(func() { | ||
ccinfo = &ccintf.ChaincodeServerInfo{ | ||
Address: "ccaddress:12345", | ||
ClientConfig: comm.ClientConfig{ | ||
SecOpts: comm.SecureOptions{ | ||
UseTLS: true, | ||
RequireClientCert: true, | ||
Certificate: []byte("fake-cert"), | ||
Key: []byte("fake-key"), | ||
ServerRootCAs: [][]byte{[]byte("fake-root-cert")}, | ||
}, | ||
Timeout: 10 * time.Second, | ||
}, | ||
} | ||
}) | ||
When("address is bad", func() { | ||
BeforeEach(func() { | ||
ccinfo.ClientConfig.SecOpts.UseTLS = false | ||
ccinfo.Address = "<badaddress>" | ||
}) | ||
It("returns an error", func() { | ||
err := i.Stream("ccid", ccinfo, shandler) | ||
Expect(err).To(MatchError(ContainSubstring("error creating grpc connection to <badaddress>"))) | ||
}) | ||
}) | ||
When("unspecified client spec", func() { | ||
BeforeEach(func() { | ||
ccinfo.ClientConfig.SecOpts.Key = nil | ||
}) | ||
It("returns an error", func() { | ||
err := i.Stream("ccid", ccinfo, shandler) | ||
Expect(err).To(MatchError(ContainSubstring("both Key and Certificate are required when using mutual TLS"))) | ||
}) | ||
}) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* | ||
Copyright IBM Corp. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package extcc_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/hyperledger/fabric/core/chaincode/extcc" | ||
. "github.com/onsi/ginkgo" | ||
. "github.com/onsi/gomega" | ||
) | ||
|
||
func TestExtcc(t *testing.T) { | ||
RegisterFailHandler(Fail) | ||
RunSpecs(t, "Chaincode Suite") | ||
} | ||
|
||
//go:generate counterfeiter -o mock/ccstreamhandler.go --fake-name StreamHandler . StreamHandler | ||
type chaincodeStreamHandler interface { | ||
extcc.StreamHandler | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.