-
Notifications
You must be signed in to change notification settings - Fork 8.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
FAB-1920 install a chaincode on local peer
https://jira.hyperledger.org/browse/FAB-1920 peer chaincode install -n <name> -p <path> -v <version> This command should be executed on the local peer as opposed to other commands such as "invoke", "query" which are sent to the remote peer. ie, assumes the chaincode is on the peer (like chaincode_example02). Contrast this with the old deploy that can be executed from any CLI/SDK outside of the peer. On successful execution the command will create a chaincode package on the file system of the peer prefixed by the "fileSystemPath" as defined in core.yaml. ------- NOTE ------ -The "package" will eventually have more contents such as policy and will be -signed etc, but for now is just the serialized chaincode deployment spec. This will be used in subsequent CRs to get the mechanics of a chaincode on multiple chains ironed out. ------- NOTE ------ Example ======= With default "fileSystemPath: /var/hyperledger/production", peer chaincode install -n mycc -p my/chain/code -v firstversion will create chaincode package in /var/hyperledger/production/chaincodes/mycc.firstversion using the chaincode defined in my/chain/code. Change-Id: I479834736d816ed522688dacae6e946340debf11 Signed-off-by: Srinivasan Muralidharan <muralisr@us.ibm.com>
- Loading branch information
Srinivasan Muralidharan
committed
Feb 8, 2017
1 parent
f7c19f8
commit ce8bd1e
Showing
6 changed files
with
287 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
/* | ||
Copyright IBM Corp. 2016-2017 All Rights Reserved. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package chaincode | ||
|
||
import ( | ||
"fmt" | ||
"io/ioutil" | ||
"os" | ||
|
||
"github.com/hyperledger/fabric/peer/common" | ||
|
||
"github.com/golang/protobuf/proto" | ||
"github.com/spf13/cobra" | ||
"github.com/spf13/viper" | ||
) | ||
|
||
var chaincodeInstallCmd *cobra.Command | ||
|
||
// installCmd returns the cobra command for Chaincode Deploy | ||
func installCmd(cf *ChaincodeCmdFactory) *cobra.Command { | ||
chaincodeInstallCmd = &cobra.Command{ | ||
Use: "install", | ||
Short: fmt.Sprintf("Package the specified chaincode into a deployment spec and save it on the peer's path."), | ||
Long: fmt.Sprintf(`Package the specified chaincode into a deployment spec and save it on the peer's path.`), | ||
ValidArgs: []string{"1"}, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
return chaincodeInstall(cmd, args, cf) | ||
}, | ||
} | ||
|
||
return chaincodeInstallCmd | ||
} | ||
|
||
func createCCInstallPath(path string) (string, error) { | ||
if _, err := os.Stat(path); err != nil { | ||
return "", err | ||
} | ||
chaincodePath := path + "/chaincodes" | ||
if s, err := os.Stat(chaincodePath); err != nil { | ||
if os.IsNotExist(err) { | ||
if err := os.Mkdir(chaincodePath, 0755); err != nil { | ||
return "", err | ||
} | ||
return chaincodePath, nil | ||
} | ||
return "", err | ||
} else if !s.IsDir() { | ||
return "", fmt.Errorf("chaincode path exists but not a dir: %s", chaincodePath) | ||
} | ||
|
||
return chaincodePath, nil | ||
} | ||
|
||
func packageCC(chaincodeBin []byte) ([]byte, error) { | ||
//TODO create proper, secured package, for now return chaincode binary asis | ||
return chaincodeBin, nil | ||
} | ||
|
||
func installCC(path string, bin []byte) error { | ||
if _, err := os.Stat(path); err == nil || !os.IsNotExist(err) { | ||
return fmt.Errorf("chaincode %s exists", path) | ||
} | ||
|
||
if err := ioutil.WriteFile(path, bin, 0644); err != nil { | ||
logger.Errorf("Failed writing deployment spec to file [%s]: [%s]", path, err) | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// chaincodeInstall deploys the chaincode. On success, the chaincode name | ||
// (hash) is printed to STDOUT for use by subsequent chaincode-related CLI | ||
// commands. | ||
func chaincodeInstall(cmd *cobra.Command, args []string, cf *ChaincodeCmdFactory) error { | ||
if chaincodePath == common.UndefinedParamValue || chaincodeVersion == common.UndefinedParamValue { | ||
return fmt.Errorf("Must supply value for %s path and version parameters.\n", chainFuncName) | ||
} | ||
|
||
peerPath := viper.GetString("peer.fileSystemPath") | ||
if peerPath == "" { | ||
return fmt.Errorf("Peer's environment \"peer.fileSystemPath\" is not set") | ||
} | ||
|
||
var ccpath string | ||
var err error | ||
|
||
//create the chaincodes dir if necessary | ||
if ccpath, err = createCCInstallPath(peerPath); err != nil { | ||
return err | ||
} | ||
|
||
//check if chaincode already exists | ||
fileToWrite := ccpath + "/" + chaincodeName + "." + chaincodeVersion | ||
if _, err := os.Stat(fileToWrite); err == nil || !os.IsNotExist(err) { | ||
return fmt.Errorf("chaincode %s exists", fileToWrite) | ||
} | ||
|
||
spec, err := getChaincodeSpecification(cmd) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
cds, err := getChaincodeBytes(spec) | ||
if err != nil { | ||
return fmt.Errorf("Error getting chaincode code %s: %s", chainFuncName, err) | ||
} | ||
|
||
cdsBytes, err := proto.Marshal(cds) | ||
if err != nil { | ||
return fmt.Errorf("Error marshalling chaincode deployment spec : %s", err) | ||
} | ||
|
||
//TODO - packageCC is just a stub. It needs to be filled out with other items | ||
//such as serialized policy and has to be signed. | ||
pkgBytes, err := packageCC(cdsBytes) | ||
if err != nil { | ||
logger.Errorf("Failed creating package [%s]", err) | ||
return err | ||
} | ||
|
||
err = installCC(fileToWrite, pkgBytes) | ||
if err != nil { | ||
logger.Errorf("Failed writing deployment spec to file [%s]: [%s]", fileToWrite, err) | ||
return err | ||
} | ||
|
||
logger.Debugf("Installed chaincode (%s,%s) of size <%d>", chaincodeName, chaincodeVersion, len(cdsBytes)) | ||
return err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
/* | ||
Copyright IBM Corp. 2016-2017 All Rights Reserved. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package chaincode | ||
|
||
import ( | ||
"os" | ||
"testing" | ||
|
||
"github.com/hyperledger/fabric/peer/common" | ||
|
||
"github.com/spf13/cobra" | ||
"github.com/spf13/viper" | ||
) | ||
|
||
func initInstallTest(fsPath string, t *testing.T) *cobra.Command { | ||
viper.Set("peer.fileSystemPath", fsPath) | ||
finitInstallTest(fsPath) | ||
|
||
//if mkdir fails everthing will fail... but it should not | ||
if err := os.Mkdir(fsPath, 0755); err != nil { | ||
t.Fatalf("could not create install env") | ||
} | ||
|
||
InitMSP() | ||
|
||
signer, err := common.GetDefaultSigner() | ||
if err != nil { | ||
t.Fatalf("Get default signer error: %v", err) | ||
} | ||
|
||
mockCF := &ChaincodeCmdFactory{ | ||
Signer: signer, | ||
} | ||
|
||
cmd := installCmd(mockCF) | ||
AddFlags(cmd) | ||
|
||
return cmd | ||
} | ||
|
||
func finitInstallTest(fsPath string) { | ||
os.RemoveAll(fsPath) | ||
} | ||
|
||
// TestInstallCmd tests generation of install command | ||
func TestInstallCmd(t *testing.T) { | ||
fsPath := "/tmp/installtest" | ||
|
||
cmd := initInstallTest(fsPath, t) | ||
defer finitInstallTest(fsPath) | ||
|
||
args := []string{"-n", "example02", "-p", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "-v", "testversion"} | ||
cmd.SetArgs(args) | ||
|
||
if err := cmd.Execute(); err != nil { | ||
t.Fatalf("Error executing install command %s", err) | ||
} | ||
|
||
if _, err := os.Stat(fsPath + "/chaincodes/example02.testversion"); err != nil { | ||
t.Fatalf("chaincode example02.testversion does not exist %s", err) | ||
} | ||
} | ||
|
||
// TestNonExistentCC non existent chaincode should fail as expected | ||
func TestNonExistentCC(t *testing.T) { | ||
fsPath := "/tmp/installtest" | ||
|
||
cmd := initInstallTest(fsPath, t) | ||
defer finitInstallTest(fsPath) | ||
|
||
args := []string{"-n", "badexample02", "-p", "github.com/hyperledger/fabric/examples/chaincode/go/bad_example02", "-v", "testversion"} | ||
cmd.SetArgs(args) | ||
|
||
if err := cmd.Execute(); err == nil { | ||
t.Fatalf("Expected error executing install command for bad chaincode") | ||
} | ||
|
||
if _, err := os.Stat(fsPath + "/chaincodes/badexample02.testversion"); err == nil { | ||
t.Fatalf("chaincode example02.testversion should not exist") | ||
} | ||
} | ||
|
||
// TestCCExists should fail second time | ||
func TestCCExists(t *testing.T) { | ||
fsPath := "/tmp/installtest" | ||
|
||
cmd := initInstallTest(fsPath, t) | ||
defer finitInstallTest(fsPath) | ||
|
||
args := []string{"-n", "example02", "-p", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "-v", "testversion"} | ||
cmd.SetArgs(args) | ||
|
||
if err := cmd.Execute(); err != nil { | ||
t.Fatalf("Error executing install command %s", err) | ||
} | ||
|
||
if _, err := os.Stat(fsPath + "/chaincodes/example02.testversion"); err != nil { | ||
t.Fatalf("chaincode example02.testversion does not exist %s", err) | ||
} | ||
|
||
if err := cmd.Execute(); err == nil { | ||
t.Fatalf("Expected error reinstall but succeeded") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters