From 0e578a8ca83d566ee3a9f3fd026af43803e3d2c8 Mon Sep 17 00:00:00 2001 From: Jason Yellick Date: Sun, 3 Jun 2018 21:59:09 -0400 Subject: [PATCH] FAB-10996 Cleanup runtime launcher interface Presently, the runtime launcher has a dependency on lifecycle that doesn't actually need to exist. Instead, the runtime launcher should simply accept a description of the chaincode to launch. Change-Id: Ie9703afa8d7567e188f3e0b4cf59301ef29d6890 Signed-off-by: Jason Yellick --- core/chaincode/chaincode_support.go | 25 ++-- core/chaincode/chaincode_support_test.go | 6 +- core/chaincode/runtime_launcher.go | 38 +----- core/chaincode/runtime_launcher_test.go | 165 +++++------------------ 4 files changed, 53 insertions(+), 181 deletions(-) diff --git a/core/chaincode/chaincode_support.go b/core/chaincode/chaincode_support.go index c7ecad26057..0d0fea74337 100644 --- a/core/chaincode/chaincode_support.go +++ b/core/chaincode/chaincode_support.go @@ -31,8 +31,7 @@ type Runtime interface { // Launcher is used to launch chaincode runtimes. type Launcher interface { - Launch(context context.Context, channelID, chaincodeName string) error - LaunchInit(context context.Context, ccci *lifecycle.ChaincodeContainerInfo) error + Launch(context context.Context, ccci *lifecycle.ChaincodeContainerInfo) error } // Lifecycle provides a way to retrieve chaincode definitions and the packages necessary to run them @@ -61,6 +60,7 @@ type ChaincodeSupport struct { HandlerRegistry *HandlerRegistry Launcher Launcher sccp sysccprovider.SystemChaincodeProvider + Lifecycle Lifecycle } // NewChaincodeSupport creates a new ChaincodeSupport instance. @@ -91,6 +91,11 @@ func NewChaincodeSupport( certGenerator = nil } + cs.Lifecycle = &lifecycle.Lifecycle{ + Executor: cs, + InstantiatedChaincodeStore: chaincodeStore, + } + cs.Runtime = &ContainerRuntime{ CertGenerator: certGenerator, Processor: processor, @@ -108,11 +113,7 @@ func NewChaincodeSupport( Runtime: cs.Runtime, Registry: cs.HandlerRegistry, PackageProvider: packageProvider, - Lifecycle: &lifecycle.Lifecycle{ - Executor: cs, - InstantiatedChaincodeStore: chaincodeStore, - }, - StartupTimeout: config.StartupTimeout, + StartupTimeout: config.StartupTimeout, } return cs @@ -132,7 +133,7 @@ func (cs *ChaincodeSupport) LaunchInit(ctx context.Context, cccid *ccprovider.CC ccci := lifecycle.DeploymentSpecToChaincodeContainerInfo(spec) ccci.Version = cccid.Version - return cs.Launcher.LaunchInit(ctx, ccci) + return cs.Launcher.Launch(ctx, ccci) } // Launch starts executing chaincode if it is not already running. This method @@ -155,8 +156,14 @@ func (cs *ChaincodeSupport) Launch(ctx context.Context, cccid *ccprovider.CCCont // used to support system chaincode. It should really be instantiated with the // appropriate reference to ChaincodeSupport. ctx = context.WithValue(ctx, ccintf.GetCCHandlerKey(), cs) + chaincodeName := spec.GetChaincodeSpec().Name() + + ccci, err := cs.Lifecycle.ChaincodeContainerInfo(cccid.ChainID, chaincodeName) + if err != nil { + return errors.Wrapf(err, "[channel %s] failed to get chaincode container info for %s", cccid.ChainID, chaincodeName) + } - return cs.Launcher.Launch(ctx, cccid.ChainID, spec.ChaincodeSpec.ChaincodeId.Name) + return cs.Launcher.Launch(ctx, ccci) } // Stop stops a chaincode if running. diff --git a/core/chaincode/chaincode_support_test.go b/core/chaincode/chaincode_support_test.go index a1c338117a1..56225c3c6e2 100644 --- a/core/chaincode/chaincode_support_test.go +++ b/core/chaincode/chaincode_support_test.go @@ -1047,7 +1047,7 @@ func TestStartAndWaitSuccess(t *testing.T) { } //actual test - everythings good - err := launcher.start(context.Background(), ccci) + err := launcher.Launch(context.Background(), ccci) if err != nil { t.Fatalf("expected success but failed with error %s", err) } @@ -1080,7 +1080,7 @@ func TestStartAndWaitTimeout(t *testing.T) { } //the actual test - timeout 1000 > 500 - err := launcher.start(context.Background(), ccci) + err := launcher.Launch(context.Background(), ccci) if err == nil { t.Fatalf("expected error but succeeded") } @@ -1112,7 +1112,7 @@ func TestStartAndWaitLaunchError(t *testing.T) { } //actual test - container launch gives error - err := launcher.start(context.Background(), ccci) + err := launcher.Launch(context.Background(), ccci) if err == nil { t.Fatalf("expected error but succeeded") } diff --git a/core/chaincode/runtime_launcher.go b/core/chaincode/runtime_launcher.go index 5616069ae1a..10cabe68938 100644 --- a/core/chaincode/runtime_launcher.go +++ b/core/chaincode/runtime_launcher.go @@ -31,46 +31,11 @@ type RuntimeLauncher struct { Runtime Runtime Registry LaunchRegistry PackageProvider PackageProvider - Lifecycle Lifecycle StartupTimeout time.Duration } -// LaunchInit launches a container which is not yet defined in the LSCC table -// This is only necessary for the pre v1.3 lifecycle -func (r *RuntimeLauncher) LaunchInit(ctx context.Context, ccci *lifecycle.ChaincodeContainerInfo) error { - err := r.start(ctx, ccci) - if err != nil { - chaincodeLogger.Errorf("start failed: %+v", err) - return err - } - - chaincodeLogger.Debug("launch complete") - - return nil -} - -// Launch chaincode with the appropriate runtime. -func (r *RuntimeLauncher) Launch(ctx context.Context, channelID, chaincodeName string) error { - ccci, err := r.Lifecycle.ChaincodeContainerInfo(channelID, chaincodeName) - if err != nil { - return errors.Wrapf(err, "[channel %s] failed to get chaincode container info for %s", channelID, chaincodeName) - } - - err = r.start(ctx, ccci) - if err != nil { - chaincodeLogger.Errorf("start failed: %+v", err) - return err - } - - chaincodeLogger.Debug("launch complete") - - return nil -} - -func (r *RuntimeLauncher) start(ctx context.Context, ccci *lifecycle.ChaincodeContainerInfo) error { +func (r *RuntimeLauncher) Launch(ctx context.Context, ccci *lifecycle.ChaincodeContainerInfo) error { var codePackage []byte - // Note, it is not actually possible for cds.CodePackage to be non-nil in the real world - // But some of the tests rely on the idea that it might be set. if ccci.ContainerType != inproccontroller.ContainerType { var err error codePackage, err = r.PackageProvider.GetChaincodeCodePackage(ccci.Name, ccci.Version) @@ -113,5 +78,6 @@ func (r *RuntimeLauncher) start(ctx context.Context, ccci *lifecycle.ChaincodeCo return err } + chaincodeLogger.Debug("launch complete") return nil } diff --git a/core/chaincode/runtime_launcher_test.go b/core/chaincode/runtime_launcher_test.go index c11a7260e24..50430427098 100644 --- a/core/chaincode/runtime_launcher_test.go +++ b/core/chaincode/runtime_launcher_test.go @@ -13,8 +13,6 @@ import ( "github.com/hyperledger/fabric/core/chaincode/fake" lc "github.com/hyperledger/fabric/core/chaincode/lifecycle" "github.com/hyperledger/fabric/core/chaincode/mock" - "github.com/hyperledger/fabric/core/common/ccprovider" - pb "github.com/hyperledger/fabric/protos/peer" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/pkg/errors" @@ -23,34 +21,17 @@ import ( var _ = Describe("RuntimeLauncher", func() { var ( + fakePackageProvider *mock.PackageProvider fakeRuntime *mock.Runtime fakeRegistry *fake.LaunchRegistry - fakeLifecycle *mock.Lifecycle - fakePackageProvider *mock.PackageProvider launchState *chaincode.LaunchState - cccid *ccprovider.CCContext - signedProp *pb.SignedProposal - proposal *pb.Proposal - chaincodeID *pb.ChaincodeID - deploymentSpec *pb.ChaincodeDeploymentSpec - ccci *lc.ChaincodeContainerInfo + ccci *lc.ChaincodeContainerInfo runtimeLauncher *chaincode.RuntimeLauncher - - ccciReturnValue *lc.ChaincodeContainerInfo ) BeforeEach(func() { - signedProp = &pb.SignedProposal{ProposalBytes: []byte("some-proposal-bytes")} - proposal = &pb.Proposal{Payload: []byte("some-payload-bytes")} - cccid = ccprovider.NewCCContext("chain-id", "context-name", "context-version", "tx-id", false, signedProp, proposal) - chaincodeID = &pb.ChaincodeID{Name: "chaincode-name", Version: "chaincode-version"} - deploymentSpec = &pb.ChaincodeDeploymentSpec{ - ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: chaincodeID}, - CodePackage: []byte("code-package"), - } - launchState = chaincode.NewLaunchState() fakeRegistry = &fake.LaunchRegistry{} fakeRegistry.LaunchingReturns(launchState, nil) @@ -64,82 +45,24 @@ var _ = Describe("RuntimeLauncher", func() { fakePackageProvider = &mock.PackageProvider{} fakePackageProvider.GetChaincodeCodePackageReturns([]byte("code-package"), nil) - ccciReturnValue = &lc.ChaincodeContainerInfo{ - Name: "info-name", - Path: "info-path", - Version: "info-version", - ContainerType: "info-container-type", - Type: "info-type", + ccci = &lc.ChaincodeContainerInfo{ + Name: "chaincode-name", + Path: "chaincode-path", + Version: "chaincode-version", + ContainerType: "chaincode-container-type", + Type: "chaincode-type", } - fakeLifecycle = &mock.Lifecycle{} - fakeLifecycle.ChaincodeContainerInfoReturns(ccciReturnValue, nil) runtimeLauncher = &chaincode.RuntimeLauncher{ Runtime: fakeRuntime, - PackageProvider: fakePackageProvider, Registry: fakeRegistry, - Lifecycle: fakeLifecycle, + PackageProvider: fakePackageProvider, StartupTimeout: 5 * time.Second, } }) - Context("when launch is provided with an invocation spec", func() { - var invocationSpec *pb.ChaincodeInvocationSpec - - BeforeEach(func() { - invocationSpec = &pb.ChaincodeInvocationSpec{ - ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: chaincodeID}, - } - }) - - It("gets the chaincode container info", func() { - err := runtimeLauncher.Launch(context.Background(), cccid.ChainID, invocationSpec.ChaincodeSpec.Name()) - Expect(err).NotTo(HaveOccurred()) - - Expect(fakeLifecycle.ChaincodeContainerInfoCallCount()).To(Equal(1)) - chainID, chaincodeID := fakeLifecycle.ChaincodeContainerInfoArgsForCall(0) - Expect(chainID).To(Equal("chain-id")) - Expect(chaincodeID).To(Equal("chaincode-name")) - }) - - It("uses the chaincode container info when starting the runtime", func() { - err := runtimeLauncher.Launch(context.Background(), cccid.ChainID, invocationSpec.ChaincodeSpec.Name()) - Expect(err).NotTo(HaveOccurred()) - - Expect(fakeRuntime.StartCallCount()).To(Equal(1)) - ctx, ccci, codePackage := fakeRuntime.StartArgsForCall(0) - Expect(ctx).To(Equal(context.Background())) - Expect(ccci).To(Equal(ccciReturnValue)) - Expect(codePackage).To(Equal([]byte("code-package"))) - }) - - Context("when getting the deployment spec fails", func() { - BeforeEach(func() { - fakeLifecycle.ChaincodeContainerInfoReturns(nil, errors.New("king-kong")) - }) - - It("returns a wrapped error", func() { - err := runtimeLauncher.Launch(context.Background(), cccid.ChainID, invocationSpec.ChaincodeSpec.Name()) - Expect(err).To(MatchError("[channel chain-id] failed to get chaincode container info for chaincode-name: king-kong")) - }) - }) - }) - - Context("when launch is provided with a deployment spec", func() { - BeforeEach(func() { - deploymentSpec.CodePackage = []byte("code-package") - ccci = lc.DeploymentSpecToChaincodeContainerInfo(deploymentSpec) - }) - - It("does not get the deployment spec from lifecycle", func() { - err := runtimeLauncher.LaunchInit(context.Background(), ccci) - Expect(err).NotTo(HaveOccurred()) - Expect(fakeLifecycle.ChaincodeContainerInfoCallCount()).To(Equal(0)) - }) - }) - It("registers the chaincode as launching", func() { - err := runtimeLauncher.LaunchInit(context.Background(), ccci) + err := runtimeLauncher.Launch(context.Background(), ccci) Expect(err).NotTo(HaveOccurred()) Expect(fakeRegistry.LaunchingCallCount()).To(Equal(1)) @@ -148,19 +71,13 @@ var _ = Describe("RuntimeLauncher", func() { }) It("starts the runtime for the chaincode", func() { - err := runtimeLauncher.LaunchInit(context.Background(), ccci) + err := runtimeLauncher.Launch(context.Background(), ccci) Expect(err).NotTo(HaveOccurred()) Expect(fakeRuntime.StartCallCount()).To(Equal(1)) - ctx, ccci, codePackage := fakeRuntime.StartArgsForCall(0) + ctx, ccciArg, codePackage := fakeRuntime.StartArgsForCall(0) Expect(ctx).To(Equal(context.Background())) - Expect(ccci).To(Equal(&lc.ChaincodeContainerInfo{ - Name: deploymentSpec.Name(), - Path: deploymentSpec.Path(), - Type: deploymentSpec.CCType(), - Version: deploymentSpec.Version(), - ContainerType: "DOCKER", - })) + Expect(ccciArg).To(Equal(ccci)) Expect(codePackage).To(Equal([]byte("code-package"))) }) @@ -168,7 +85,7 @@ var _ = Describe("RuntimeLauncher", func() { fakeRuntime.StartReturns(nil) errCh := make(chan error, 1) - go func() { errCh <- runtimeLauncher.LaunchInit(context.Background(), ccci) }() + go func() { errCh <- runtimeLauncher.Launch(context.Background(), ccci) }() Consistently(errCh).ShouldNot(Receive()) launchState.Notify(nil) @@ -176,7 +93,7 @@ var _ = Describe("RuntimeLauncher", func() { }) It("does not deregister the chaincode", func() { - err := runtimeLauncher.LaunchInit(context.Background(), ccci) + err := runtimeLauncher.Launch(context.Background(), ccci) Expect(err).NotTo(HaveOccurred()) Expect(fakeRegistry.DeregisterCallCount()).To(Equal(0)) @@ -188,7 +105,7 @@ var _ = Describe("RuntimeLauncher", func() { }) It("returns an error", func() { - err := runtimeLauncher.LaunchInit(context.Background(), ccci) + err := runtimeLauncher.Launch(context.Background(), ccci) Expect(err).To(MatchError("failed to register chaincode-name:chaincode-version as launching: gargoyle")) }) }) @@ -199,27 +116,21 @@ var _ = Describe("RuntimeLauncher", func() { }) It("returns a wrapped error", func() { - err := runtimeLauncher.LaunchInit(context.Background(), ccci) + err := runtimeLauncher.Launch(context.Background(), ccci) Expect(err).To(MatchError("error starting container: banana")) }) It("stops the runtime", func() { - runtimeLauncher.LaunchInit(context.Background(), ccci) + runtimeLauncher.Launch(context.Background(), ccci) Expect(fakeRuntime.StopCallCount()).To(Equal(1)) - ctx, ccci := fakeRuntime.StopArgsForCall(0) + ctx, ccciArg := fakeRuntime.StopArgsForCall(0) Expect(ctx).To(Equal(context.Background())) - Expect(ccci).To(Equal(&lc.ChaincodeContainerInfo{ - Name: deploymentSpec.Name(), - Path: deploymentSpec.Path(), - Type: deploymentSpec.CCType(), - Version: deploymentSpec.Version(), - ContainerType: "DOCKER", - })) + Expect(ccciArg).To(Equal(ccci)) }) It("deregisters the chaincode", func() { - runtimeLauncher.LaunchInit(context.Background(), ccci) + runtimeLauncher.Launch(context.Background(), ccci) Expect(fakeRegistry.DeregisterCallCount()).To(Equal(1)) cname := fakeRegistry.DeregisterArgsForCall(0) @@ -236,27 +147,21 @@ var _ = Describe("RuntimeLauncher", func() { }) It("returns an error", func() { - err := runtimeLauncher.LaunchInit(context.Background(), ccci) + err := runtimeLauncher.Launch(context.Background(), ccci) Expect(err).To(MatchError("chaincode registration failed: papaya")) }) It("stops the runtime", func() { - runtimeLauncher.LaunchInit(context.Background(), ccci) + runtimeLauncher.Launch(context.Background(), ccci) Expect(fakeRuntime.StopCallCount()).To(Equal(1)) - ctx, ccci := fakeRuntime.StopArgsForCall(0) + ctx, ccciArg := fakeRuntime.StopArgsForCall(0) Expect(ctx).To(Equal(context.Background())) - Expect(ccci).To(Equal(&lc.ChaincodeContainerInfo{ - Name: deploymentSpec.Name(), - Path: deploymentSpec.Path(), - Type: deploymentSpec.CCType(), - Version: deploymentSpec.Version(), - ContainerType: "DOCKER", - })) + Expect(ccciArg).To(Equal(ccci)) }) It("deregisters the chaincode", func() { - runtimeLauncher.LaunchInit(context.Background(), ccci) + runtimeLauncher.Launch(context.Background(), ccci) Expect(fakeRegistry.DeregisterCallCount()).To(Equal(1)) cname := fakeRegistry.DeregisterArgsForCall(0) @@ -271,27 +176,21 @@ var _ = Describe("RuntimeLauncher", func() { }) It("returns a meaningful error", func() { - err := runtimeLauncher.LaunchInit(context.Background(), ccci) + err := runtimeLauncher.Launch(context.Background(), ccci) Expect(err).To(MatchError("timeout expired while starting chaincode chaincode-name:chaincode-version for transaction")) }) It("stops the runtime", func() { - runtimeLauncher.LaunchInit(context.Background(), ccci) + runtimeLauncher.Launch(context.Background(), ccci) Expect(fakeRuntime.StopCallCount()).To(Equal(1)) - ctx, ccci := fakeRuntime.StopArgsForCall(0) + ctx, ccciArg := fakeRuntime.StopArgsForCall(0) Expect(ctx).To(Equal(context.Background())) - Expect(ccci).To(Equal(&lc.ChaincodeContainerInfo{ - Name: deploymentSpec.Name(), - Path: deploymentSpec.Path(), - Type: deploymentSpec.CCType(), - Version: deploymentSpec.Version(), - ContainerType: "DOCKER", - })) + Expect(ccciArg).To(Equal(ccci)) }) It("deregisters the chaincode", func() { - runtimeLauncher.LaunchInit(context.Background(), ccci) + runtimeLauncher.Launch(context.Background(), ccci) Expect(fakeRegistry.DeregisterCallCount()).To(Equal(1)) cname := fakeRegistry.DeregisterArgsForCall(0) @@ -306,7 +205,7 @@ var _ = Describe("RuntimeLauncher", func() { }) It("preserves the initial error", func() { - err := runtimeLauncher.LaunchInit(context.Background(), ccci) + err := runtimeLauncher.Launch(context.Background(), ccci) Expect(err).To(MatchError("error starting container: whirled-peas")) Expect(fakeRuntime.StopCallCount()).To(Equal(1)) })