From a9572d6b7d34d18ccf5011c40b50b36d7d65234e Mon Sep 17 00:00:00 2001 From: muralisr Date: Wed, 13 Nov 2019 23:00:57 -0500 Subject: [PATCH] [FAB-16890] move build out of container runtime The build process is common to both container and connector models and decides which model applies (based on if build specifies chaincode connection properties). We need to extract the build out of container runtime. Change-Id: I3db0cbb98f9d595a2653a042d5e40306b9540d8f Signed-off-by: muralisr --- core/chaincode/chaincode_support.go | 3 +- core/chaincode/chaincode_support_test.go | 17 ++-- core/chaincode/container_runtime.go | 45 +++-------- core/chaincode/container_runtime_test.go | 31 +++++--- core/chaincode/exectransaction_test.go | 4 +- core/chaincode/mock/runtime.go | 98 ++++++++++++++++++++++-- core/chaincode/runtime_launcher.go | 54 ++++++++++++- core/chaincode/runtime_launcher_test.go | 73 +++++++++++++++++- internal/peer/node/start.go | 16 ++-- 9 files changed, 264 insertions(+), 77 deletions(-) diff --git a/core/chaincode/chaincode_support.go b/core/chaincode/chaincode_support.go index e93a13dd9a9..b592daf6dc0 100644 --- a/core/chaincode/chaincode_support.go +++ b/core/chaincode/chaincode_support.go @@ -34,7 +34,8 @@ const ( // Runtime is used to manage chaincode runtime instances. type Runtime interface { - Start(ccid string) error + Build(ccid string) (*ccintf.ChaincodeServerInfo, error) + Start(ccid string, ccinfo *ccintf.PeerConnection) error Stop(ccid string) error Wait(ccid string) (int, error) } diff --git a/core/chaincode/chaincode_support_test.go b/core/chaincode/chaincode_support_test.go index 7d9f3a50bcc..ef56cd3141d 100644 --- a/core/chaincode/chaincode_support_test.go +++ b/core/chaincode/chaincode_support_test.go @@ -42,6 +42,7 @@ import ( "github.com/hyperledger/fabric/core/common/ccprovider" "github.com/hyperledger/fabric/core/config" "github.com/hyperledger/fabric/core/container" + "github.com/hyperledger/fabric/core/container/ccintf" "github.com/hyperledger/fabric/core/container/dockercontroller" "github.com/hyperledger/fabric/core/ledger" ledgermock "github.com/hyperledger/fabric/core/ledger/mock" @@ -231,14 +232,9 @@ func initMockPeer(channelIDs ...string) (*peer.Peer, *ChaincodeSupport, func(), } containerRuntime := &ContainerRuntime{ - CACert: ca.CertBytes(), - CertGenerator: certGenerator, BuildRegistry: buildRegistry, ContainerRouter: containerRouter, } - if !globalConfig.TLSEnabled { - containerRuntime.CertGenerator = nil - } userRunsCC := true metricsProviders := &disabled.Provider{} chaincodeHandlerRegistry := NewHandlerRegistry(userRunsCC) @@ -247,6 +243,11 @@ func initMockPeer(channelIDs ...string) (*peer.Peer, *ChaincodeSupport, func(), Runtime: containerRuntime, Registry: chaincodeHandlerRegistry, StartupTimeout: globalConfig.StartupTimeout, + CACert: ca.CertBytes(), + CertGenerator: certGenerator, + } + if !globalConfig.TLSEnabled { + chaincodeLauncher.CertGenerator = nil } chaincodeSupport := &ChaincodeSupport{ ACLProvider: mockAclProvider, @@ -903,7 +904,7 @@ func getHistory(t *testing.T, chainID, ccname string, ccSide *mockpeer.MockCCCom func TestStartAndWaitSuccess(t *testing.T) { handlerRegistry := NewHandlerRegistry(false) fakeRuntime := &mock.Runtime{} - fakeRuntime.StartStub = func(_ string) error { + fakeRuntime.StartStub = func(_ string, _ *ccintf.PeerConnection) error { handlerRegistry.Ready("testcc:0") return nil } @@ -925,7 +926,7 @@ func TestStartAndWaitSuccess(t *testing.T) { //test timeout error func TestStartAndWaitTimeout(t *testing.T) { fakeRuntime := &mock.Runtime{} - fakeRuntime.StartStub = func(_ string) error { + fakeRuntime.StartStub = func(_ string, _ *ccintf.PeerConnection) error { time.Sleep(time.Second) return nil } @@ -947,7 +948,7 @@ func TestStartAndWaitTimeout(t *testing.T) { //test container return error func TestStartAndWaitLaunchError(t *testing.T) { fakeRuntime := &mock.Runtime{} - fakeRuntime.StartStub = func(_ string) error { + fakeRuntime.StartStub = func(_ string, _ *ccintf.PeerConnection) error { return errors.New("Bad lunch; upset stomach") } diff --git a/core/chaincode/container_runtime.go b/core/chaincode/container_runtime.go index 2f53126ab26..fe9874f2948 100644 --- a/core/chaincode/container_runtime.go +++ b/core/chaincode/container_runtime.go @@ -7,19 +7,11 @@ SPDX-License-Identifier: Apache-2.0 package chaincode import ( - "github.com/hyperledger/fabric/core/chaincode/accesscontrol" "github.com/hyperledger/fabric/core/container" "github.com/hyperledger/fabric/core/container/ccintf" "github.com/pkg/errors" ) -// CertGenerator generates client certificates for chaincode. -type CertGenerator interface { - // Generate returns a certificate and private key and associates - // the hash of the certificates with the given chaincode name - Generate(ccName string) (*accesscontrol.CertAndPrivKeyPair, error) -} - // ContainerRouter is a poor abstraction used for building, and running chaincode processes. // This management probably does not belong in this package, chaincode process lifecycle should // be driven by what chaincodes are defined, what chaincodes are instantiated, and not driven by @@ -35,29 +27,13 @@ type ContainerRouter interface { // ContainerRuntime is responsible for managing containerized chaincode. type ContainerRuntime struct { - CertGenerator CertGenerator ContainerRouter ContainerRouter - CACert []byte - PeerAddress string BuildRegistry *container.BuildRegistry } -// Start launches chaincode in a runtime environment. -func (c *ContainerRuntime) Start(ccid string) error { - var tlsConfig *ccintf.TLSConfig - if c.CertGenerator != nil { - certKeyPair, err := c.CertGenerator.Generate(string(ccid)) - if err != nil { - return errors.WithMessagef(err, "failed to generate TLS certificates for %s", ccid) - } - - tlsConfig = &ccintf.TLSConfig{ - ClientCert: certKeyPair.Cert, - ClientKey: certKeyPair.Key, - RootCert: c.CACert, - } - } - +// Build builds the chaincode if necessary and returns ChaincodeServerInfo if +// the chaincode is a server +func (c *ContainerRuntime) Build(ccid string) (*ccintf.ChaincodeServerInfo, error) { buildStatus, ok := c.BuildRegistry.BuildStatus(ccid) if !ok { err := c.ContainerRouter.Build(ccid) @@ -66,18 +42,17 @@ func (c *ContainerRuntime) Start(ccid string) error { <-buildStatus.Done() if err := buildStatus.Err(); err != nil { - return errors.WithMessage(err, "error building image") + return nil, errors.WithMessage(err, "error building image") } + return c.ContainerRouter.ChaincodeServerInfo(ccid) +} + +// Start launches chaincode in a runtime environment. +func (c *ContainerRuntime) Start(ccid string, ccinfo *ccintf.PeerConnection) error { chaincodeLogger.Debugf("start container: %s", ccid) - if err := c.ContainerRouter.Start( - ccid, - &ccintf.PeerConnection{ - Address: c.PeerAddress, - TLSConfig: tlsConfig, - }, - ); err != nil { + if err := c.ContainerRouter.Start(ccid, ccinfo); err != nil { return errors.WithMessage(err, "error starting container") } diff --git a/core/chaincode/container_runtime_test.go b/core/chaincode/container_runtime_test.go index 7cee3f5e064..c9eb7c6cb2a 100644 --- a/core/chaincode/container_runtime_test.go +++ b/core/chaincode/container_runtime_test.go @@ -13,25 +13,39 @@ import ( "github.com/hyperledger/fabric/core/chaincode" "github.com/hyperledger/fabric/core/chaincode/mock" "github.com/hyperledger/fabric/core/container" + "github.com/hyperledger/fabric/core/container/ccintf" "github.com/pkg/errors" "github.com/stretchr/testify/assert" ) -func TestContainerRuntimeStart(t *testing.T) { +func TestContainerRuntimeBuild(t *testing.T) { fakeRouter := &mock.ContainerRouter{} + fakeRouter.ChaincodeServerInfoReturns(&ccintf.ChaincodeServerInfo{Address: "ccaddress:12345"}, nil) cr := &chaincode.ContainerRuntime{ ContainerRouter: fakeRouter, - PeerAddress: "peer-address", BuildRegistry: &container.BuildRegistry{}, } - err := cr.Start("chaincode-name:chaincode-version") + ccinfo, err := cr.Build("chaincode-name:chaincode-version") assert.NoError(t, err) + assert.Equal(t, &ccintf.ChaincodeServerInfo{Address: "ccaddress:12345"}, ccinfo) assert.Equal(t, 1, fakeRouter.BuildCallCount()) packageID := fakeRouter.BuildArgsForCall(0) assert.Equal(t, "chaincode-name:chaincode-version", packageID) +} + +func TestContainerRuntimeStart(t *testing.T) { + fakeRouter := &mock.ContainerRouter{} + + cr := &chaincode.ContainerRuntime{ + ContainerRouter: fakeRouter, + BuildRegistry: &container.BuildRegistry{}, + } + + err := cr.Start("chaincode-name:chaincode-version", &ccintf.PeerConnection{Address: "peer-address"}) + assert.NoError(t, err) assert.Equal(t, 1, fakeRouter.StartCallCount()) ccid, peerConnection := fakeRouter.StartArgsForCall(0) @@ -41,27 +55,22 @@ func TestContainerRuntimeStart(t *testing.T) { // Try starting a second time, to ensure build is not invoked again // as the BuildRegistry already holds it - err = cr.Start("chaincode-name:chaincode-version") + err = cr.Start("chaincode-name:chaincode-version", &ccintf.PeerConnection{Address: "fake-address"}) assert.NoError(t, err) - assert.Equal(t, 1, fakeRouter.BuildCallCount()) assert.Equal(t, 2, fakeRouter.StartCallCount()) } func TestContainerRuntimeStartErrors(t *testing.T) { tests := []struct { chaincodeType string - buildErr error startErr error errValue string }{ - {pb.ChaincodeSpec_GOLANG.String(), nil, errors.New("process-failed"), "error starting container: process-failed"}, - {pb.ChaincodeSpec_GOLANG.String(), errors.New("build-failed"), nil, "error building image: build-failed"}, - {pb.ChaincodeSpec_GOLANG.String(), errors.New("build-failed"), nil, "error building image: build-failed"}, + {pb.ChaincodeSpec_GOLANG.String(), errors.New("process-failed"), "error starting container: process-failed"}, } for _, tc := range tests { fakeRouter := &mock.ContainerRouter{} - fakeRouter.BuildReturns(tc.buildErr) fakeRouter.StartReturns(tc.startErr) cr := &chaincode.ContainerRuntime{ @@ -69,7 +78,7 @@ func TestContainerRuntimeStartErrors(t *testing.T) { BuildRegistry: &container.BuildRegistry{}, } - err := cr.Start("ccid") + err := cr.Start("ccid", &ccintf.PeerConnection{Address: "fake-address"}) assert.EqualError(t, err, tc.errValue) } } diff --git a/core/chaincode/exectransaction_test.go b/core/chaincode/exectransaction_test.go index a1e79da028d..2ec9a48a7b2 100644 --- a/core/chaincode/exectransaction_test.go +++ b/core/chaincode/exectransaction_test.go @@ -175,9 +175,7 @@ func initPeer(channelIDs ...string) (*cm.Lifecycle, net.Listener, *ChaincodeSupp } containerRuntime := &ContainerRuntime{ BuildRegistry: buildRegistry, - CACert: ca.CertBytes(), ContainerRouter: containerRouter, - PeerAddress: peerAddress, } userRunsCC := false metricsProviders := &disabled.Provider{} @@ -187,6 +185,8 @@ func initPeer(channelIDs ...string) (*cm.Lifecycle, net.Listener, *ChaincodeSupp Registry: chaincodeHandlerRegistry, Runtime: containerRuntime, StartupTimeout: globalConfig.StartupTimeout, + CACert: ca.CertBytes(), + PeerAddress: peerAddress, } chaincodeSupport := &ChaincodeSupport{ ACLProvider: aclmgmt.NewACLProvider( diff --git a/core/chaincode/mock/runtime.go b/core/chaincode/mock/runtime.go index 196f74f5133..f15bb4ec87d 100644 --- a/core/chaincode/mock/runtime.go +++ b/core/chaincode/mock/runtime.go @@ -3,13 +3,29 @@ package mock import ( "sync" + + "github.com/hyperledger/fabric/core/container/ccintf" ) type Runtime struct { - StartStub func(string) error + BuildStub func(string) (*ccintf.ChaincodeServerInfo, error) + buildMutex sync.RWMutex + buildArgsForCall []struct { + arg1 string + } + buildReturns struct { + result1 *ccintf.ChaincodeServerInfo + result2 error + } + buildReturnsOnCall map[int]struct { + result1 *ccintf.ChaincodeServerInfo + result2 error + } + StartStub func(string, *ccintf.PeerConnection) error startMutex sync.RWMutex startArgsForCall []struct { arg1 string + arg2 *ccintf.PeerConnection } startReturns struct { result1 error @@ -45,16 +61,80 @@ type Runtime struct { invocationsMutex sync.RWMutex } -func (fake *Runtime) Start(arg1 string) error { +func (fake *Runtime) Build(arg1 string) (*ccintf.ChaincodeServerInfo, error) { + fake.buildMutex.Lock() + ret, specificReturn := fake.buildReturnsOnCall[len(fake.buildArgsForCall)] + fake.buildArgsForCall = append(fake.buildArgsForCall, struct { + arg1 string + }{arg1}) + fake.recordInvocation("Build", []interface{}{arg1}) + fake.buildMutex.Unlock() + if fake.BuildStub != nil { + return fake.BuildStub(arg1) + } + if specificReturn { + return ret.result1, ret.result2 + } + fakeReturns := fake.buildReturns + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *Runtime) BuildCallCount() int { + fake.buildMutex.RLock() + defer fake.buildMutex.RUnlock() + return len(fake.buildArgsForCall) +} + +func (fake *Runtime) BuildCalls(stub func(string) (*ccintf.ChaincodeServerInfo, error)) { + fake.buildMutex.Lock() + defer fake.buildMutex.Unlock() + fake.BuildStub = stub +} + +func (fake *Runtime) BuildArgsForCall(i int) string { + fake.buildMutex.RLock() + defer fake.buildMutex.RUnlock() + argsForCall := fake.buildArgsForCall[i] + return argsForCall.arg1 +} + +func (fake *Runtime) BuildReturns(result1 *ccintf.ChaincodeServerInfo, result2 error) { + fake.buildMutex.Lock() + defer fake.buildMutex.Unlock() + fake.BuildStub = nil + fake.buildReturns = struct { + result1 *ccintf.ChaincodeServerInfo + result2 error + }{result1, result2} +} + +func (fake *Runtime) BuildReturnsOnCall(i int, result1 *ccintf.ChaincodeServerInfo, result2 error) { + fake.buildMutex.Lock() + defer fake.buildMutex.Unlock() + fake.BuildStub = nil + if fake.buildReturnsOnCall == nil { + fake.buildReturnsOnCall = make(map[int]struct { + result1 *ccintf.ChaincodeServerInfo + result2 error + }) + } + fake.buildReturnsOnCall[i] = struct { + result1 *ccintf.ChaincodeServerInfo + result2 error + }{result1, result2} +} + +func (fake *Runtime) Start(arg1 string, arg2 *ccintf.PeerConnection) error { fake.startMutex.Lock() ret, specificReturn := fake.startReturnsOnCall[len(fake.startArgsForCall)] fake.startArgsForCall = append(fake.startArgsForCall, struct { arg1 string - }{arg1}) - fake.recordInvocation("Start", []interface{}{arg1}) + arg2 *ccintf.PeerConnection + }{arg1, arg2}) + fake.recordInvocation("Start", []interface{}{arg1, arg2}) fake.startMutex.Unlock() if fake.StartStub != nil { - return fake.StartStub(arg1) + return fake.StartStub(arg1, arg2) } if specificReturn { return ret.result1 @@ -69,17 +149,17 @@ func (fake *Runtime) StartCallCount() int { return len(fake.startArgsForCall) } -func (fake *Runtime) StartCalls(stub func(string) error) { +func (fake *Runtime) StartCalls(stub func(string, *ccintf.PeerConnection) error) { fake.startMutex.Lock() defer fake.startMutex.Unlock() fake.StartStub = stub } -func (fake *Runtime) StartArgsForCall(i int) string { +func (fake *Runtime) StartArgsForCall(i int) (string, *ccintf.PeerConnection) { fake.startMutex.RLock() defer fake.startMutex.RUnlock() argsForCall := fake.startArgsForCall[i] - return argsForCall.arg1 + return argsForCall.arg1, argsForCall.arg2 } func (fake *Runtime) StartReturns(result1 error) { @@ -231,6 +311,8 @@ func (fake *Runtime) WaitReturnsOnCall(i int, result1 int, result2 error) { func (fake *Runtime) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() + fake.buildMutex.RLock() + defer fake.buildMutex.RUnlock() fake.startMutex.RLock() defer fake.startMutex.RUnlock() fake.stopMutex.RLock() diff --git a/core/chaincode/runtime_launcher.go b/core/chaincode/runtime_launcher.go index fe911ed094e..5fe0667e55d 100644 --- a/core/chaincode/runtime_launcher.go +++ b/core/chaincode/runtime_launcher.go @@ -10,6 +10,8 @@ import ( "strconv" "time" + "github.com/hyperledger/fabric/core/chaincode/accesscontrol" + "github.com/hyperledger/fabric/core/container/ccintf" "github.com/pkg/errors" ) @@ -25,6 +27,37 @@ type RuntimeLauncher struct { Registry LaunchRegistry StartupTimeout time.Duration Metrics *LaunchMetrics + PeerAddress string + CACert []byte + CertGenerator CertGenerator +} + +// CertGenerator generates client certificates for chaincode. +type CertGenerator interface { + // Generate returns a certificate and private key and associates + // the hash of the certificates with the given chaincode name + Generate(ccName string) (*accesscontrol.CertAndPrivKeyPair, error) +} + +func (r *RuntimeLauncher) ChaincodeClientInfo(ccid string) (*ccintf.PeerConnection, error) { + var tlsConfig *ccintf.TLSConfig + if r.CertGenerator != nil { + certKeyPair, err := r.CertGenerator.Generate(string(ccid)) + if err != nil { + return nil, errors.WithMessagef(err, "failed to generate TLS certificates for %s", ccid) + } + + tlsConfig = &ccintf.TLSConfig{ + ClientCert: certKeyPair.Cert, + ClientKey: certKeyPair.Key, + RootCert: r.CACert, + } + } + + return &ccintf.PeerConnection{ + Address: r.PeerAddress, + TLSConfig: tlsConfig, + }, nil } func (r *RuntimeLauncher) Launch(ccid string) error { @@ -38,7 +71,26 @@ func (r *RuntimeLauncher) Launch(ccid string) error { timeoutCh = time.NewTimer(r.StartupTimeout).C go func() { - if err := r.Runtime.Start(ccid); err != nil { + var ccservinfo *ccintf.ChaincodeServerInfo + ccservinfo, err := r.Runtime.Build(ccid) + if err != nil { + startFailCh <- errors.WithMessage(err, "error building chaincode") + return + } + if ccservinfo != nil { + startFailCh <- errors.New("peer as client to be implemented") + return + } + ccinfo, err := r.ChaincodeClientInfo(ccid) + if err != nil { + startFailCh <- errors.WithMessage(err, "could not get connection info") + return + } + if ccinfo == nil { + startFailCh <- errors.New("could not get connection info") + return + } + if err = r.Runtime.Start(ccid, ccinfo); err != nil { startFailCh <- errors.WithMessage(err, "error starting container") return } diff --git a/core/chaincode/runtime_launcher_test.go b/core/chaincode/runtime_launcher_test.go index 1f4894077fe..9bc36069782 100644 --- a/core/chaincode/runtime_launcher_test.go +++ b/core/chaincode/runtime_launcher_test.go @@ -11,8 +11,10 @@ import ( "github.com/hyperledger/fabric/common/metrics/metricsfakes" "github.com/hyperledger/fabric/core/chaincode" + "github.com/hyperledger/fabric/core/chaincode/accesscontrol" "github.com/hyperledger/fabric/core/chaincode/fake" "github.com/hyperledger/fabric/core/chaincode/mock" + "github.com/hyperledger/fabric/core/container/ccintf" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/pkg/errors" @@ -26,6 +28,7 @@ var _ = Describe("RuntimeLauncher", func() { fakeLaunchDuration *metricsfakes.Histogram fakeLaunchFailures *metricsfakes.Counter fakeLaunchTimeouts *metricsfakes.Counter + fakeCertGenerator *mock.CertGenerator exitedCh chan int runtimeLauncher *chaincode.RuntimeLauncher @@ -37,7 +40,7 @@ var _ = Describe("RuntimeLauncher", func() { fakeRegistry.LaunchingReturns(launchState, false) fakeRuntime = &mock.Runtime{} - fakeRuntime.StartStub = func(string) error { + fakeRuntime.StartStub = func(string, *ccintf.PeerConnection) error { launchState.Notify(nil) return nil } @@ -59,11 +62,15 @@ var _ = Describe("RuntimeLauncher", func() { LaunchFailures: fakeLaunchFailures, LaunchTimeouts: fakeLaunchTimeouts, } + fakeCertGenerator = &mock.CertGenerator{} + fakeCertGenerator.GenerateReturns(&accesscontrol.CertAndPrivKeyPair{Cert: []byte("cert"), Key: []byte("key")}, nil) runtimeLauncher = &chaincode.RuntimeLauncher{ Runtime: fakeRuntime, Registry: fakeRegistry, StartupTimeout: 5 * time.Second, Metrics: launchMetrics, + PeerAddress: "peer-address", + CertGenerator: fakeCertGenerator, } }) @@ -80,13 +87,73 @@ var _ = Describe("RuntimeLauncher", func() { Expect(cname).To(Equal("chaincode-name:chaincode-version")) }) + Context("build does not return external chaincode info", func() { + BeforeEach(func() { + fakeRuntime.BuildReturns(nil, nil) + }) + + It("chaincode is launched", func() { + err := runtimeLauncher.Launch("chaincode-name:chaincode-version") + Expect(err).NotTo(HaveOccurred()) + + Expect(fakeRuntime.BuildCallCount()).To(Equal(1)) + ccciArg := fakeRuntime.BuildArgsForCall(0) + Expect(ccciArg).To(Equal("chaincode-name:chaincode-version")) + + Expect(fakeRuntime.StartCallCount()).To(Equal(1)) + }) + }) + + Context("build returns external chaincode info", func() { + BeforeEach(func() { + fakeRuntime.BuildReturns(&ccintf.ChaincodeServerInfo{Address: "ccaddress:12345"}, nil) + }) + + It("chaincode is not launched", func() { + err := runtimeLauncher.Launch("chaincode-name:chaincode-version") + Expect(err).To(MatchError("peer as client to be implemented")) + + Expect(fakeRuntime.BuildCallCount()).To(Equal(1)) + ccciArg := fakeRuntime.BuildArgsForCall(0) + Expect(ccciArg).To(Equal("chaincode-name:chaincode-version")) + + Expect(fakeRuntime.StartCallCount()).To(Equal(0)) + }) + }) + It("starts the runtime for the chaincode", func() { err := runtimeLauncher.Launch("chaincode-name:chaincode-version") Expect(err).NotTo(HaveOccurred()) + Expect(fakeRuntime.BuildCallCount()).To(Equal(1)) + ccciArg := fakeRuntime.BuildArgsForCall(0) + Expect(ccciArg).To(Equal("chaincode-name:chaincode-version")) Expect(fakeRuntime.StartCallCount()).To(Equal(1)) - ccciArg := fakeRuntime.StartArgsForCall(0) + ccciArg, ccinfoArg := fakeRuntime.StartArgsForCall(0) Expect(ccciArg).To(Equal("chaincode-name:chaincode-version")) + + Expect(ccinfoArg).To(Equal(&ccintf.PeerConnection{Address: "peer-address", TLSConfig: &ccintf.TLSConfig{ClientCert: []byte("cert"), ClientKey: []byte("key"), RootCert: nil}})) + }) + + Context("tls is not enabled", func() { + BeforeEach(func() { + runtimeLauncher.CertGenerator = nil + }) + + It("starts the runtime for the chaincode with no TLS", func() { + + err := runtimeLauncher.Launch("chaincode-name:chaincode-version") + Expect(err).NotTo(HaveOccurred()) + + Expect(fakeRuntime.BuildCallCount()).To(Equal(1)) + ccciArg := fakeRuntime.BuildArgsForCall(0) + Expect(ccciArg).To(Equal("chaincode-name:chaincode-version")) + Expect(fakeRuntime.StartCallCount()).To(Equal(1)) + ccciArg, ccinfoArg := fakeRuntime.StartArgsForCall(0) + Expect(ccciArg).To(Equal("chaincode-name:chaincode-version")) + + Expect(ccinfoArg).To(Equal(&ccintf.PeerConnection{Address: "peer-address"})) + }) }) It("waits for the launch to complete", func() { @@ -195,7 +262,7 @@ var _ = Describe("RuntimeLauncher", func() { Context("when handler registration fails", func() { BeforeEach(func() { - fakeRuntime.StartStub = func(string) error { + fakeRuntime.StartStub = func(string, *ccintf.PeerConnection) error { launchState.Notify(errors.New("papaya")) return nil } diff --git a/internal/peer/node/start.go b/internal/peer/node/start.go index 3ee1c00c6b2..69aa105a541 100644 --- a/internal/peer/node/start.go +++ b/internal/peer/node/start.go @@ -572,9 +572,6 @@ func serve(args []string) error { containerRuntime := &chaincode.ContainerRuntime{ BuildRegistry: buildRegistry, - CACert: ca.CertBytes(), - CertGenerator: authenticator, - PeerAddress: ccEndpoint, ContainerRouter: containerRouter, } @@ -598,16 +595,19 @@ func serve(args []string) error { ACLProvider: aclProvider, } - // Keep TestQueries working - if !chaincodeConfig.TLSEnabled { - containerRuntime.CertGenerator = nil - } - chaincodeLauncher := &chaincode.RuntimeLauncher{ Metrics: chaincode.NewLaunchMetrics(opsSystem.Provider), Registry: chaincodeHandlerRegistry, Runtime: containerRuntime, StartupTimeout: chaincodeConfig.StartupTimeout, + CertGenerator: authenticator, + CACert: ca.CertBytes(), + PeerAddress: ccEndpoint, + } + + // Keep TestQueries working + if !chaincodeConfig.TLSEnabled { + chaincodeLauncher.CertGenerator = nil } go chaincodeCustodian.Work(buildRegistry, containerRouter, chaincodeLauncher)