Skip to content

Commit

Permalink
Merge "[FAB-16842] prep for for ext CC config"
Browse files Browse the repository at this point in the history
  • Loading branch information
denyeart authored and Gerrit Code Review committed Nov 21, 2019
2 parents 01a80e4 + fead9d9 commit 78471de
Show file tree
Hide file tree
Showing 9 changed files with 545 additions and 1 deletion.
1 change: 1 addition & 0 deletions core/chaincode/container_runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type CertGenerator interface {
// is removed (or perhaps before), this interface should probably go away entirely.
type ContainerRouter interface {
Build(ccid string) error
ChaincodeServerInfo(ccid string) (*ccintf.ChaincodeServerInfo, error)
Start(ccid string, peerConnection *ccintf.PeerConnection) error
Stop(ccid string) error
Wait(ccid string) (int, error)
Expand Down
78 changes: 78 additions & 0 deletions core/chaincode/mock/container_router.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions core/container/ccintf/ccintf.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ SPDX-License-Identifier: Apache-2.0
package ccintf

import (
"github.com/hyperledger/fabric/core/comm"

pb "github.com/hyperledger/fabric-protos-go/peer"
)

Expand All @@ -30,3 +32,9 @@ type TLSConfig struct {
ClientKey []byte
RootCert []byte
}

// ChaincodeServerInfo provides chaincode connection information
type ChaincodeServerInfo struct {
Address string
ClientConfig comm.ClientConfig
}
9 changes: 9 additions & 0 deletions core/container/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type VM interface {
// 'image' also seemed inappropriate. So, the vague 'Instance' is used here.
type Instance interface {
Start(peerConnection *ccintf.PeerConnection) error
ChaincodeServerInfo() (*ccintf.ChaincodeServerInfo, error)
Stop() error
Wait() (int, error)
}
Expand All @@ -43,6 +44,10 @@ func (UninitializedInstance) Start(peerConnection *ccintf.PeerConnection) error
return errors.Errorf("instance has not yet been built, cannot be started")
}

func (UninitializedInstance) ChaincodeServerInfo() (*ccintf.ChaincodeServerInfo, error) {
return nil, errors.Errorf("instance has not yet been built, cannot get chaincode server info")
}

func (UninitializedInstance) Stop() error {
return errors.Errorf("instance has not yet been built, cannot be stopped")
}
Expand Down Expand Up @@ -122,6 +127,10 @@ func (r *Router) Build(ccid string) error {
return nil
}

func (r *Router) ChaincodeServerInfo(ccid string) (*ccintf.ChaincodeServerInfo, error) {
return r.getInstance(ccid).ChaincodeServerInfo()
}

func (r *Router) Start(ccid string, peerConnection *ccintf.PeerConnection) error {
return r.getInstance(ccid).Start(peerConnection)
}
Expand Down
4 changes: 4 additions & 0 deletions core/container/dockercontroller/dockercontroller.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ func (ci *ContainerInstance) Start(peerConnection *ccintf.PeerConnection) error
return ci.DockerVM.Start(ci.CCID, ci.Type, peerConnection)
}

func (ci *ContainerInstance) ChaincodeServerInfo() (*ccintf.ChaincodeServerInfo, error) {
return nil, nil
}

func (ci *ContainerInstance) Stop() error {
return ci.DockerVM.Stop(ci.CCID)
}
Expand Down
5 changes: 4 additions & 1 deletion core/container/externalbuilder/externalbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ func (d *Detector) CachedBuild(ccid string) (*Instance, error) {
PackageID: ccid,
Builder: builder,
BldDir: filepath.Join(durablePath, "bld"),
ReleaseDir: filepath.Join(durablePath, "release"),
TermTimeout: 5 * time.Second,
}, nil
}
Expand Down Expand Up @@ -150,7 +151,8 @@ func (d *Detector) Build(ccid string, md *persistence.ChaincodePackageMetadata,
return nil, errors.WithMessage(err, "could not write build-info.json")
}

err = os.Rename(buildContext.ReleaseDir, filepath.Join(durablePath, "release"))
durableReleaseDir := filepath.Join(durablePath, "release")
err = os.Rename(buildContext.ReleaseDir, durableReleaseDir)
if err != nil {
os.RemoveAll(durablePath)
return nil, errors.WithMessagef(err, "could not move build context release to persistent location '%s'", durablePath)
Expand All @@ -167,6 +169,7 @@ func (d *Detector) Build(ccid string, md *persistence.ChaincodePackageMetadata,
PackageID: ccid,
Builder: builder,
BldDir: durableBldDir,
ReleaseDir: durableReleaseDir,
TermTimeout: 5 * time.Second,
}, nil
}
Expand Down
136 changes: 136 additions & 0 deletions core/container/externalbuilder/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,158 @@ SPDX-License-Identifier: Apache-2.0
package externalbuilder

import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"syscall"
"time"

"github.com/hyperledger/fabric/core/comm"
"github.com/hyperledger/fabric/core/container/ccintf"
"github.com/pkg/errors"
)

const (
DialTimeout = 3 * time.Second
CCServerReleaseDir = "chaincode/server"
)

type Instance struct {
PackageID string
BldDir string
ReleaseDir string
Builder *Builder
Session *Session
TermTimeout time.Duration
}

// Duration used for the DialTimeout property
type Duration struct {
time.Duration
}

func (d Duration) MarshalJSON() ([]byte, error) {
return json.Marshal(d.Seconds())
}

func (d *Duration) UnmarshalJSON(b []byte) error {
var v interface{}
if err := json.Unmarshal(b, &v); err != nil {
return err
}

switch value := v.(type) {
case float64:
d.Duration = time.Duration(value)
return nil
case string:
var err error
if d.Duration, err = time.ParseDuration(value); err != nil {
return err
}
return nil
default:
return errors.New("invalid duration")
}
}

// ChaincodeServerUserData holds "connection.json" information
type ChaincodeServerUserData struct {
Address string `json:"address"`
DialTimeout Duration `json:"dial_timeout"`
TlsRequired bool `json:"tls_required"`
ClientAuthRequired bool `json:"client_auth_required"`
KeyPath string `json:"key_path"`
CertPath string `json:"cert_path"`
RootCertPath string `json:"root_cert_path"`
}

func (ccdata *ChaincodeServerUserData) ChaincodeServerInfo(cryptoDir string) (*ccintf.ChaincodeServerInfo, error) {
if ccdata.Address == "" {
return nil, errors.New("chaincode address not provided")
}
connInfo := &ccintf.ChaincodeServerInfo{Address: ccdata.Address}

if ccdata.DialTimeout == (Duration{}) {
connInfo.ClientConfig.Timeout = DialTimeout
} else {
connInfo.ClientConfig.Timeout = ccdata.DialTimeout.Duration
}

// we can expose this if necessary
connInfo.ClientConfig.KaOpts = comm.DefaultKeepaliveOptions

if !ccdata.TlsRequired {
return connInfo, nil
}
if ccdata.ClientAuthRequired && ccdata.KeyPath == "" {
return nil, errors.New("chaincode tls key not provided")
}
if ccdata.ClientAuthRequired && ccdata.CertPath == "" {
return nil, errors.New("chaincode tls cert not provided")
}
if ccdata.RootCertPath == "" {
return nil, errors.New("chaincode tls root cert not provided")
}

connInfo.ClientConfig.SecOpts.UseTLS = true

if ccdata.ClientAuthRequired {
connInfo.ClientConfig.SecOpts.RequireClientCert = true
b, err := ioutil.ReadFile(filepath.Join(cryptoDir, ccdata.CertPath))
if err != nil {
return nil, errors.WithMessage(err, fmt.Sprintf("error reading cert file %s", ccdata.CertPath))
}
connInfo.ClientConfig.SecOpts.Certificate = b

b, err = ioutil.ReadFile(filepath.Join(cryptoDir, ccdata.KeyPath))
if err != nil {
return nil, errors.WithMessage(err, fmt.Sprintf("error reading key file %s", ccdata.KeyPath))
}
connInfo.ClientConfig.SecOpts.Key = b
}

b, err := ioutil.ReadFile(filepath.Join(cryptoDir, ccdata.RootCertPath))
if err != nil {
return nil, errors.WithMessage(err, fmt.Sprintf("error reading root cert file %s", ccdata.RootCertPath))
}
connInfo.ClientConfig.SecOpts.ServerRootCAs = [][]byte{b}

return connInfo, nil
}

func (i *Instance) ChaincodeServerReleaseDir() string {
return filepath.Join(i.ReleaseDir, CCServerReleaseDir)
}

func (i *Instance) ChaincodeServerInfo() (*ccintf.ChaincodeServerInfo, error) {
ccinfoPath := filepath.Join(i.ChaincodeServerReleaseDir(), "connection.json")

_, err := os.Stat(ccinfoPath)

if os.IsNotExist(err) {
return nil, nil
}

if err != nil {
return nil, errors.WithMessage(err, "connection information not provided")
}
b, err := ioutil.ReadFile(ccinfoPath)
if err != nil {
return nil, errors.WithMessagef(err, "could not read '%s' for chaincode info", ccinfoPath)
}
ccdata := &ChaincodeServerUserData{}
err = json.Unmarshal(b, &ccdata)
if err != nil {
return nil, errors.WithMessagef(err, "malformed chaincode info at '%s'", ccinfoPath)
}

return ccdata.ChaincodeServerInfo(i.ChaincodeServerReleaseDir())
}

func (i *Instance) Start(peerConnection *ccintf.PeerConnection) error {
sess, err := i.Builder.Run(i.PackageID, i.BldDir, peerConnection)
if err != nil {
Expand Down
Loading

0 comments on commit 78471de

Please sign in to comment.