Skip to content

Commit

Permalink
integration: backport chaincode_server_test
Browse files Browse the repository at this point in the history
Signed-off-by: Matthew Sykes <sykesmat@us.ibm.com>
  • Loading branch information
sykesm authored and mastersingh24 committed Mar 11, 2021
1 parent 8843223 commit 6adcbce
Show file tree
Hide file tree
Showing 5 changed files with 264 additions and 5 deletions.
61 changes: 61 additions & 0 deletions integration/chaincode/server/main.go
@@ -0,0 +1,61 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package main

import (
"encoding/json"
"fmt"
"io/ioutil"
"os"

"github.com/hyperledger/fabric-chaincode-go/shim"
"github.com/hyperledger/fabric/integration/chaincode/simple"
)

type config struct {
ListenAddress string `json:"listen_address,omitempty"`
Key string `json:"key,omitempty"` // PEM encoded key
Cert string `json:"cert,omitempty"` // PEM encoded certificate
CA string `json:"ca,omitempty"` // PEM encode CA certificate
}

func main() {
if len(os.Args) < 2 {
fmt.Println("usage: <package-id>")
os.Exit(1)
}

configData, err := ioutil.ReadFile("config.json")
if err != nil {
fmt.Fprintf(os.Stderr, "Cannot read config file: %s", err)
os.Exit(2)
}

var config config
if err := json.Unmarshal(configData, &config); err != nil {
fmt.Fprintf(os.Stderr, "Cannot read config file: %s", err)
os.Exit(2)
}

server := &shim.ChaincodeServer{
CCID: os.Args[1],
Address: config.ListenAddress,
CC: new(simple.SimpleChaincode),
TLSProps: shim.TLSProperties{
Key: []byte(config.Key),
Cert: []byte(config.Cert),
ClientCACerts: []byte(config.CA),
},
}

// do not modify - needed for integration test
fmt.Printf("Starting chaincode %s at %s\n", server.CCID, server.Address)
err = server.Start()
if err != nil {
fmt.Printf("Error starting Simple chaincode: %s", err)
}
}
183 changes: 183 additions & 0 deletions integration/e2e/chaincode_server_test.go
@@ -0,0 +1,183 @@
/*
Copyright IBM Corp All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package e2e

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

"github.com/hyperledger/fabric/common/crypto/tlsgen"
"github.com/hyperledger/fabric/core/container/externalbuilder"
"github.com/hyperledger/fabric/integration/nwo"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/tedsuo/ifrit"
"github.com/tedsuo/ifrit/ginkgomon"
)

var _ = Describe("ChaincodeAsExternalServer", func() {
var (
testDir string
network *nwo.Network
chaincode nwo.Chaincode
chaincodeServerAddress string
assetDir string
process ifrit.Process
ccserver ifrit.Process
)

BeforeEach(func() {
var err error
testDir, err = ioutil.TempDir("", "external-chaincode-server")
Expect(err).NotTo(HaveOccurred())

network = nwo.New(nwo.BasicSolo(), testDir, nil, StartPort(), components)
network.GenerateConfigTree()
network.Bootstrap()

// Create the configuration
chaincodeServerAddress = fmt.Sprintf("127.0.0.1:%d", network.ReservePort())
connData, serverKeyPair := generateChaincodeConfig(chaincodeServerAddress)

// Create directory for configuration files
assetDir, err = ioutil.TempDir(testDir, "assets")
Expect(err).NotTo(HaveOccurred())

// Write the config files
connJSON, err := json.Marshal(connData)
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(filepath.Join(assetDir, "connection.json"), connJSON, 0o644)
Expect(err).NotTo(HaveOccurred())

configJSON, err := json.Marshal(serverKeyPair)
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(filepath.Join(assetDir, "config.json"), configJSON, 0o644)
Expect(err).NotTo(HaveOccurred())

// Setup the network
networkRunner := network.NetworkGroupRunner()
process = ifrit.Invoke(networkRunner)
Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed())

network.CreateAndJoinChannel(network.Orderer("orderer"), "testchannel")
nwo.EnableCapabilities(
network,
"testchannel",
"Application", "V2_0",
network.Orderer("orderer"),
network.Peer("Org1", "peer0"), network.Peer("Org2", "peer0"),
)

chaincode = nwo.Chaincode{
Name: "mycc",
Version: "0.0",
Path: components.Build("github.com/hyperledger/fabric/integration/chaincode/server"),
Lang: "binary",
PackageFile: filepath.Join(testDir, "server.tar.gz"),
Ctor: `{"Args":["init","a","100","b","200"]}`,
InitRequired: true,
SignaturePolicy: `AND ('Org1MSP.member','Org2MSP.member')`,
Sequence: "1",
Label: "my_server_chaincode",
CodeFiles: map[string]string{
filepath.Join(assetDir, "connection.json"): "connection.json",
filepath.Join(assetDir, "config.json"): "config.json",
},
}
})

AfterEach(func() {
if ccserver != nil {
ccserver.Signal(syscall.SIGTERM)
Eventually(ccserver.Wait(), network.EventuallyTimeout).Should(Receive())
}

if process != nil {
process.Signal(syscall.SIGTERM)
Eventually(process.Wait(), network.EventuallyTimeout).Should(Receive())
}
if network != nil {
network.Cleanup()
}
os.RemoveAll(testDir)
})

It("executes a basic solo network with 2 orgs and external chaincode server", func() {
orderer := network.Orderer("orderer")
peer := network.Peer("Org1", "peer0")
peers := network.PeersWithChannel("testchannel")

By("packaging and installing the chaincode")
nwo.PackageAndInstallChaincode(network, chaincode, peers...)
chaincode.SetPackageIDFromPackageFile()

By("approving and committing the chaincode")
nwo.ApproveChaincodeForMyOrg(network, "testchannel", orderer, chaincode, peers...)
nwo.CheckCommitReadinessUntilReady(network, "testchannel", chaincode, network.PeerOrgs(), peers...)
nwo.CommitChaincode(network, "testchannel", orderer, chaincode, peer, peers...)

By("starting the chaincode server")
ccserver = ifrit.Invoke(ginkgomon.New(ginkgomon.Config{
Name: chaincode.PackageID,
Command: &exec.Cmd{
Path: chaincode.Path,
Args: []string{chaincode.Path, chaincode.PackageID, chaincodeServerAddress},
Dir: assetDir,
},
StartCheck: `Starting chaincode ` + chaincode.PackageID + ` at ` + chaincodeServerAddress,
StartCheckTimeout: 15 * time.Second,
}))
Eventually(ccserver.Ready(), network.EventuallyTimeout).Should(BeClosed())

By("exercising the chaincode")
nwo.InitChaincode(network, "testchannel", orderer, chaincode, network.PeersWithChannel("testchannel")...)
RunQueryInvokeQuery(network, orderer, peer, "testchannel")
RunRespondWith(network, orderer, peer, "testchannel")
})
})

type chaincodeConfig struct {
ListenAddress string `json:"listen_address,omitempty"`
Key string `json:"key,omitempty"` // PEM encoded key
Cert string `json:"cert,omitempty"` // PEM encoded certificate
CA string `json:"ca,omitempty"` // PEM encode CA certificate
}

func generateChaincodeConfig(chaincodeAddress string) (externalbuilder.ChaincodeServerUserData, chaincodeConfig) {
tlsCA, err := tlsgen.NewCA()
Expect(err).NotTo(HaveOccurred())

serverPair, err := tlsCA.NewServerCertKeyPair("127.0.0.1")
Expect(err).NotTo(HaveOccurred())
clientPair, err := tlsCA.NewClientCertKeyPair()
Expect(err).NotTo(HaveOccurred())

config := chaincodeConfig{
ListenAddress: chaincodeAddress,
Key: string(serverPair.Key),
Cert: string(serverPair.Cert),
CA: string(tlsCA.CertBytes()),
}

connData := externalbuilder.ChaincodeServerUserData{
Address: chaincodeAddress,
DialTimeout: externalbuilder.Duration(10 * time.Second),
TLSRequired: true,
ClientAuthRequired: true,
ClientKey: string(clientPair.Key),
ClientCert: string(clientPair.Cert),
RootCert: string(tlsCA.CertBytes()),
}

return connData, config
}
8 changes: 6 additions & 2 deletions integration/externalbuilders/binary/bin/build
Expand Up @@ -16,7 +16,11 @@ META="$2"
BLD="$3"

if [ -e "$SRC/metadata" ] ; then
cp -a "$SRC/metadata" "$BLD"
cp -a "$SRC/metadata" "$BLD"
fi

cp "$(jq -r .path "$META/metadata.json")" "$BLD/chaincode"
if [ -f "$SRC/connection.json" ]; then
cp "$SRC/connection.json" "$BLD/connection.json"
else
cp "$(jq -r .path "$META/metadata.json")" "$BLD/chaincode"
fi
7 changes: 6 additions & 1 deletion integration/externalbuilders/binary/bin/release
Expand Up @@ -15,5 +15,10 @@ BLD="$1"
RELEASE="$2"

if [ -d "$BLD/metadata" ] ; then
cp -a "$BLD/metadata/"* "$RELEASE"
cp -a "$BLD/metadata/"* "$RELEASE"
fi

if [ -f "$BLD/connection.json" ]; then
mkdir -p "$RELEASE/chaincode/server"
cp "$BLD/connection.json" "$RELEASE/chaincode/server/"
fi
10 changes: 8 additions & 2 deletions integration/externalbuilders/binary/bin/run
Expand Up @@ -17,7 +17,7 @@ ARTIFACTS=$2
# when set, keep track of the artifacts directories to verify
# proper cleanup in integration test
if [ -n "${RUN_ARTIFACTS_FILE+1}" ]; then
echo $ARTIFACTS >> $RUN_ARTIFACTS_FILE
echo "$ARTIFACTS" >> "$RUN_ARTIFACTS_FILE"
fi

# shellcheck disable=SC2155
Expand All @@ -26,7 +26,8 @@ export CORE_PEER_TLS_ENABLED="true"
export CORE_TLS_CLIENT_CERT_FILE="$ARTIFACTS/client.crt"
export CORE_TLS_CLIENT_KEY_FILE="$ARTIFACTS/client.key"
export CORE_PEER_TLS_ROOTCERT_FILE="$ARTIFACTS/root.crt"
export CORE_PEER_LOCALMSPID="$(jq -r .mspid "$ARTIFACTS/chaincode.json")"
CORE_PEER_LOCALMSPID="$(jq -r .mspid "$ARTIFACTS/chaincode.json")"
export CORE_PEER_LOCALMSPID

jq -r .client_cert "$ARTIFACTS/chaincode.json" > "$CORE_TLS_CLIENT_CERT_FILE"
jq -r .client_key "$ARTIFACTS/chaincode.json" > "$CORE_TLS_CLIENT_KEY_FILE"
Expand All @@ -36,4 +37,9 @@ if [ -z "$(jq -r .client_cert "$ARTIFACTS/chaincode.json")" ]; then
export CORE_PEER_TLS_ENABLED="false"
fi

if [ ! -x "$OUTPUT/chaincode" ]; then
>&2 echo "Expected executable chaincode at $OUTPUT/chaincode"
exit 1
fi

exec "$OUTPUT/chaincode" -peer.address="$(jq -r .peer_address "$ARTIFACTS/chaincode.json")"

0 comments on commit 6adcbce

Please sign in to comment.