diff --git a/Makefile b/Makefile index 709c1b50c80..ae4827533a9 100644 --- a/Makefile +++ b/Makefile @@ -133,6 +133,9 @@ behave: behave-deps @echo "Running behave tests" @cd bddtests; behave $(BEHAVE_OPTS) +behave-peer-chaincode: build/bin/peer peer-docker orderer-docker + @cd peer/chaincode && behave + linter: buildenv @echo "LINT: Running code checks.." @$(DRUN) hyperledger/fabric-buildenv:$(DOCKER_TAG) ./scripts/golinter.sh diff --git a/core/chaincode/platforms/java/hash.go b/core/chaincode/platforms/java/hash.go index 1581c365c03..08b58ec7245 100644 --- a/core/chaincode/platforms/java/hash.go +++ b/core/chaincode/platforms/java/hash.go @@ -32,8 +32,11 @@ import ( "github.com/hyperledger/fabric/common/util" ccutil "github.com/hyperledger/fabric/core/chaincode/platforms/util" pb "github.com/hyperledger/fabric/protos/peer" + logging "github.com/op/go-logging" ) +var logger = logging.MustGetLogger("java/hash") + func getCodeFromHTTP(path string) (codegopath string, err error) { codegopath, err = ioutil.TempDir("", "javachaincode") @@ -70,11 +73,6 @@ func collectChaincodeFiles(spec *pb.ChaincodeSpec, tw *tar.Writer) (string, erro return "", errors.New("Cannot collect chaincode files from empty chaincode path") } - input := spec.Input - if input == nil || len(input.Args) == 0 { - return "", errors.New("Cannot collect chaincode files from empty input") - } - codepath := chaincodeID.Path var ishttp bool @@ -103,11 +101,18 @@ func collectChaincodeFiles(spec *pb.ChaincodeSpec, tw *tar.Writer) (string, erro return "", fmt.Errorf("code does not exist %s", err) } - inputbytes, err := proto.Marshal(input) - if err != nil { - return "", fmt.Errorf("Error marshalling constructor: %s", err) + var hash []byte + + //install will not have inputs and we don't have to collect hash for it + if spec.Input == nil || len(spec.Input.Args) == 0 { + logger.Debugf("not using input for hash computation for %v ", chaincodeID) + } else { + inputbytes, err2 := proto.Marshal(spec.Input) + if err2 != nil { + return "", fmt.Errorf("Error marshalling constructor: %s", err) + } + hash = util.GenerateHashFromSignature(codepath, inputbytes) } - hash := util.GenerateHashFromSignature(codepath, inputbytes) hash, err = ccutil.HashFilesInDir("", codepath, hash, tw) if err != nil { diff --git a/peer/chaincode/features/environment.py b/peer/chaincode/features/environment.py new file mode 100644 index 00000000000..0bc9651f89e --- /dev/null +++ b/peer/chaincode/features/environment.py @@ -0,0 +1,24 @@ +from behave import * +import os +import subprocess + +# set the default step matcher +use_step_matcher("re") + +def before_all(context): + # set some handy values + context.go_path = os.environ['GOPATH'] + context.fabric_dir = os.path.join(context.go_path, 'src/github.com/hyperledger/fabric') + context.peer_exe = os.path.join(context.fabric_dir, 'build/bin/peer') + context.sample_chaincode = { + 'golang':'github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02', + 'java':'examples/chaincode/java/SimpleSample' + } + +def after_scenario(context, scenario): + if getattr(context, 'peer_container_id', None): + subprocess.check_output(['docker', 'rm', '--force', '--volumes', context.peer_container_id], stderr=subprocess.STDOUT) + if getattr(context, 'orderer_container_id', None): + subprocess.check_output(['docker', 'rm', '--force', '--volumes', context.orderer_container_id], stderr=subprocess.STDOUT) + if getattr(context, 'network_id', None): + subprocess.check_output(['docker', 'network', 'rm', context.network_id], stderr=subprocess.STDOUT) diff --git a/peer/chaincode/features/install.feature b/peer/chaincode/features/install.feature new file mode 100644 index 00000000000..18188bc261b --- /dev/null +++ b/peer/chaincode/features/install.feature @@ -0,0 +1,26 @@ +Feature: Install chaincode via CLI + +Scenario Outline: Install first version chaincode via CLI + + Given a fabric peer and orderer + When a chaincode is installed via the CLI + Then the chaincode is installed on the peer + + Examples: + | lang | + | go | + | java | + +Scenario Outline: Install chaincode with new version + + Only the first version of a chaincode (identified by chaincode name) can be + installed. Subsequent versions must be upgraded instead. + + Given a fabric peer and orderer + When version one of a chaincode is installed via the CLI + Then installing version two of the same chaincode via the CLI will fail + + Examples: + | lang | + | go | + | java | diff --git a/peer/chaincode/features/steps/steps.py b/peer/chaincode/features/steps/steps.py new file mode 100644 index 00000000000..91ff268ec83 --- /dev/null +++ b/peer/chaincode/features/steps/steps.py @@ -0,0 +1,107 @@ +from behave import * +import os +import random +import subprocess +import tempfile +import time +import socket + +@given(u'a fabric peer and orderer') +def step_impl(context): + + # create network + context.network_name = 'behave_' + ''.join(random.choice('0123456789') for i in xrange(7)) + context.network_id = subprocess.check_output([ + 'docker', 'network', 'create', context.network_name + ]).strip() + + # start orderer + context.orderer_container_id = subprocess.check_output([ + 'docker', 'run', '-d', '-p', '7050', + '--expose', '7050', + '--network', context.network_name, + '--network-alias', 'orderer', + '--env', 'ORDERER_GENERAL_LISTENADDRESS=0.0.0.0', + 'hyperledger/fabric-orderer' + ]).strip() + context.orderer_address = subprocess.check_output(['docker', 'port', context.orderer_container_id, '7050']).strip() + + # start peer + context.peer_container_id = subprocess.check_output([ + 'docker', 'run', '-d', '-p', '7051', + '--network', context.network_name, + '--network-alias', 'vp0', + '--env', 'CORE_PEER_ADDRESSAUTODETECT=true', + '--env', 'CORE_PEER_ID=vp0', + '--env', 'CORE_PEER_COMMITTER_LEDGER_ORDERER=orderer:7050', + '--volume', '/var/run/docker.sock:/var/run/docker.sock', + 'hyperledger/fabric-peer' + ]).strip() + context.peer_address = subprocess.check_output(['docker', 'port', context.peer_container_id, '7051']).strip() + time.sleep(1) + + # setup env for peer cli commands + context.peer_env = os.environ.copy() + context.peer_env['CORE_PEER_ADDRESS'] = context.peer_address + context.peer_env['CORE_PEER_COMMITTER_LEDGER_ORDERER'] = context.orderer_address + +@when(r'a (?Pjava|go|golang|car) chaincode is installed via the CLI') +def step_impl(context, lang): + context.chaincode_lang = 'golang' if lang == 'go' else lang + context.chaincode_id_name = lang + '_cc_' + ''.join(random.choice('0123456789') for i in xrange(7)) + context.chaincode_id_version = '1000' + try: + print(subprocess.check_output([ + context.peer_exe, 'chaincode', 'install', + '--logging-level', 'debug', + '--name', context.chaincode_id_name, + '--path', context.sample_chaincode[context.chaincode_lang], + '--version', context.chaincode_id_version, + '--lang', context.chaincode_lang + ], cwd=context.fabric_dir, stderr=subprocess.STDOUT, env=context.peer_env)) + except subprocess.CalledProcessError as e: + print(e.output) + print('CORE_PEER_ADDRESS = ' + context.peer_env['CORE_PEER_ADDRESS']) + print('CORE_PEER_COMMITTER_LEDGER_ORDERER = ' + context.peer_env['CORE_PEER_COMMITTER_LEDGER_ORDERER']) + raise + +@step(u'the chaincode is installed on the peer') +def step_impl(context): + print(subprocess.check_output([ + 'docker', 'exec', context.peer_container_id, 'ls', '-l', '/var/hyperledger/production/chaincodes/' + context.chaincode_id_name + '.' + context.chaincode_id_version + ])) + +@step(r'version (?P\S+) of a (?Pjava|go|golang|car) chaincode is installed via the CLI') +def step_impl(context, version, lang): + context.chaincode_lang = 'golang' if lang == 'go' else lang + context.chaincode_id_name = lang + '_cc_' + ''.join(random.choice('0123456789') for i in xrange(7)) + context.chaincode_id_version = version + try: + print(subprocess.check_output([ + context.peer_exe, 'chaincode', 'install', + '--logging-level', 'debug', + '--name', context.chaincode_id_name, + '--path', context.sample_chaincode[context.chaincode_lang], + '--version', context.chaincode_id_version, + '--lang', context.chaincode_lang + ], cwd=context.fabric_dir, stderr=subprocess.STDOUT, env=context.peer_env)) + except subprocess.CalledProcessError as e: + print(e.output) + raise + +@step(r'installing version (?P\S+) of the same chaincode via the CLI will fail') +def step_impl(context, version): + assert getattr(context, 'chaincode_id_name', None), 'No chaincode previously installed.' + context.chaincode_id_version = version + try: + print(subprocess.check_output([ + context.peer_exe, 'chaincode', 'install', + '--logging-level', 'debug', + '--name', context.chaincode_id_name, + '--path', context.sample_chaincode[context.chaincode_lang], + '--version', context.chaincode_id_version, + '--lang', context.chaincode_lang + ], cwd=context.fabric_dir, stderr=subprocess.STDOUT, env=context.peer_env)) + except subprocess.CalledProcessError as e: + print(e.output) + raise