Commit 6e8d5564 authored by Matthew Sykes's avatar Matthew Sykes
Browse files

[FAB-11053] extract config block helpers to nwo



Change-Id: I4159e84a512a52bdba7917a03200c1614067ee7f
Signed-off-by: default avatarMatthew Sykes <sykesmat@us.ibm.com>
parent 5d808449
......@@ -16,8 +16,7 @@ import (
"time"
docker "github.com/fsouza/go-dockerclient"
"github.com/gogo/protobuf/proto"
"github.com/hyperledger/fabric/common/tools/configtxlator/update"
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/core/aclmgmt/resources"
"github.com/hyperledger/fabric/integration/nwo"
"github.com/hyperledger/fabric/integration/nwo/commands"
......@@ -245,156 +244,30 @@ var _ = Describe("EndToEndACL", func() {
// configuration with Org2's signer, and then submits the config update using
// Org1.
func SetACLPolicy(network *nwo.Network, channel, policyName, policy string) {
tempDir, err := ioutil.TempDir("", "aclconfig")
Expect(err).NotTo(HaveOccurred())
defer os.RemoveAll(tempDir)
orderer := network.Orderer("orderer")
org1AdminPeer := network.Peer("Org1", "peer0")
org2AdminPeer := network.Peer("Org2", "peer0")
outputFile := filepath.Join(tempDir, "updated_config.pb")
GenerateACLConfigUpdate(network, orderer, channel, policyName, policy, outputFile)
sess, err := network.PeerAdminSession(org2AdminPeer, commands.SignConfigTx{File: outputFile})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, time.Minute).Should(gexec.Exit(0))
SendConfigUpdate(network, org1AdminPeer, channel, outputFile)
}
func GenerateACLConfigUpdate(network *nwo.Network, orderer *nwo.Orderer, channel, policyName, policy, outputFile string) {
tempDir, err := ioutil.TempDir("", "aclconfig")
Expect(err).NotTo(HaveOccurred())
defer os.RemoveAll(tempDir)
// fetch the config block
output := filepath.Join(tempDir, "config_block.pb")
channelFetch := commands.ChannelFetch{
ChannelID: channel,
Block: "config",
Orderer: network.OrdererAddress(orderer, nwo.ListenPort),
OutputFile: output,
}
peer := network.Peer("Org1", "peer0")
sess, err := network.PeerAdminSession(peer, channelFetch)
Expect(err).NotTo(HaveOccurred())
Eventually(sess, time.Minute).Should(gexec.Exit(0))
Expect(sess.Err).To(gbytes.Say("Received block: "))
// read the config block file
fileBytes, err := ioutil.ReadFile(output)
Expect(err).NotTo(HaveOccurred())
Expect(fileBytes).NotTo(BeNil())
submitter := network.Peer("Org1", "peer0")
signer := network.Peer("Org2", "peer0")
// unmarshal the config block bytes
configBlock := &common.Block{}
err = proto.Unmarshal(fileBytes, configBlock)
Expect(err).NotTo(HaveOccurred())
// unmarshal the envelope bytes
env := &common.Envelope{}
err = proto.Unmarshal(configBlock.Data.Data[0], env)
Expect(err).NotTo(HaveOccurred())
// unmarshal the payload bytes
payload := &common.Payload{}
err = proto.Unmarshal(env.Payload, payload)
Expect(err).NotTo(HaveOccurred())
// unmarshal the config envelope bytes
configEnv := &common.ConfigEnvelope{}
err = proto.Unmarshal(payload.Data, configEnv)
Expect(err).NotTo(HaveOccurred())
// clone the config
config := configEnv.Config
config := nwo.GetConfigBlock(network, submitter, orderer, channel)
updatedConfig := proto.Clone(config).(*common.Config)
acls := &pb.ACLs{
Acls: make(map[string]*pb.APIResource),
}
// set the policy
apiResource := &pb.APIResource{}
apiResource.PolicyRef = policy
acls.Acls[policyName] = apiResource
cv := &common.ConfigValue{
Value: utils.MarshalOrPanic(acls),
updatedConfig.ChannelGroup.Groups["Application"].Values["ACLs"] = &common.ConfigValue{
ModPolicy: "Admins",
Value: utils.MarshalOrPanic(&pb.ACLs{
Acls: map[string]*pb.APIResource{
policyName: &pb.APIResource{PolicyRef: policy},
},
}),
}
updatedConfig.ChannelGroup.Groups["Application"].Values["ACLs"] = cv
// compute the config update and package it into an envelope
configUpdate, err := update.Compute(config, updatedConfig)
Expect(err).NotTo(HaveOccurred())
configUpdate.ChannelId = channel
configUpdateEnvelope := &common.ConfigUpdateEnvelope{
ConfigUpdate: utils.MarshalOrPanic(configUpdate),
}
signedEnv, err := utils.CreateSignedEnvelope(
common.HeaderType_CONFIG_UPDATE,
channel,
nil,
configUpdateEnvelope,
0,
0,
)
Expect(err).NotTo(HaveOccurred())
Expect(signedEnv).NotTo(BeNil())
// write the config update envelope to the file system
signedEnvelopeBytes := utils.MarshalOrPanic(signedEnv)
err = ioutil.WriteFile(outputFile, signedEnvelopeBytes, 0660)
Expect(err).NotTo(HaveOccurred())
}
func SendConfigUpdate(network *nwo.Network, peer *nwo.Peer, channel, updateFile string) {
tempDir, err := ioutil.TempDir("", "cfgupdate")
Expect(err).NotTo(HaveOccurred())
defer os.RemoveAll(tempDir)
orderer := network.Orderer("orderer")
outputBlock := filepath.Join(tempDir, "config_block.pb")
channelFetch := commands.ChannelFetch{
ChannelID: channel,
Block: "config",
Orderer: network.OrdererAddress(orderer, nwo.ListenPort),
OutputFile: outputBlock,
}
sess, err := network.PeerAdminSession(peer, channelFetch)
Expect(err).NotTo(HaveOccurred())
Eventually(sess, time.Minute).Should(gexec.Exit(0))
Expect(sess.Err).To(gbytes.Say("Received block: "))
prevConfigBlockNumber := GetNumberFromBlockFile(outputBlock)
sess, err = network.PeerAdminSession(peer, commands.ChannelUpdate{
ChannelID: channel,
Orderer: network.OrdererAddress(orderer, nwo.ListenPort),
File: updateFile,
})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, time.Minute).Should(gexec.Exit(0))
Expect(sess.Err).To(gbytes.Say("Successfully submitted channel update"))
getConfigBlockNumber := func() uint64 {
sess, err := network.PeerAdminSession(peer, channelFetch)
Expect(err).NotTo(HaveOccurred())
Eventually(sess, time.Minute).Should(gexec.Exit(0))
Expect(sess.Err).To(gbytes.Say("Received block: "))
blockNumber := GetNumberFromBlockFile(outputBlock)
return blockNumber
}
Eventually(getConfigBlockNumber, time.Minute).Should(BeNumerically(">", prevConfigBlockNumber))
nwo.UpdateConfig(network, signer, submitter, orderer, channel, config, updatedConfig)
}
// GetTxIDFromBlock gets a transaction id from a block that has been
// marshaled and stored on the filesystem
func GetTxIDFromBlockFile(blockFile string) string {
block := UnmarshalBlockFromFile(blockFile)
block := nwo.UnmarshalBlockFromFile(blockFile)
envelope, err := utils.GetEnvelopeFromBlock(block.Data.Data[0])
Expect(err).NotTo(HaveOccurred())
......@@ -408,25 +281,6 @@ func GetTxIDFromBlockFile(blockFile string) string {
return chdr.TxId
}
// GetNumberFromBlockFile gets the number of the block that has been
// marshaled and stored on the filesystem
func GetNumberFromBlockFile(blockFile string) uint64 {
block := UnmarshalBlockFromFile(blockFile)
return block.Header.Number
}
// UnmarshalBlockFromFile unmarshals a block on the filesystem into
// a *common.Block
func UnmarshalBlockFromFile(blockFile string) *common.Block {
blockBytes, err := ioutil.ReadFile(blockFile)
Expect(err).NotTo(HaveOccurred())
block, err := utils.UnmarshalBlock(blockBytes)
Expect(err).NotTo(HaveOccurred())
return block
}
// ToCLIChaincodeArgs converts string args to args for use with chaincode calls
// from the CLI.
func ToCLIChaincodeArgs(args ...string) string {
......
/*
Copyright IBM Corp All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package nwo
import (
"io/ioutil"
"os"
"path/filepath"
"time"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gbytes"
"github.com/onsi/gomega/gexec"
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/common/tools/configtxlator/update"
"github.com/hyperledger/fabric/integration/nwo/commands"
"github.com/hyperledger/fabric/protos/common"
"github.com/hyperledger/fabric/protos/utils"
)
// GetConfigBlock retrieves the current config block for a channel and
// unmarshals it.
func GetConfigBlock(n *Network, peer *Peer, orderer *Orderer, channel string) *common.Config {
tempDir, err := ioutil.TempDir("", "getConfigBlock")
Expect(err).NotTo(HaveOccurred())
defer os.RemoveAll(tempDir)
// fetch the config block
output := filepath.Join(tempDir, "config_block.pb")
sess, err := n.PeerAdminSession(peer, commands.ChannelFetch{
ChannelID: channel,
Block: "config",
Orderer: n.OrdererAddress(orderer, ListenPort),
OutputFile: output,
})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, time.Minute).Should(gexec.Exit(0))
Expect(sess.Err).To(gbytes.Say("Received block: "))
// unmarshal the config block bytes
configBlock := UnmarshalBlockFromFile(output)
// unmarshal the envelope bytes
envelope, err := utils.GetEnvelopeFromBlock(configBlock.Data.Data[0])
Expect(err).NotTo(HaveOccurred())
// unmarshal the payload bytes
payload, err := utils.GetPayload(envelope)
Expect(err).NotTo(HaveOccurred())
// unmarshal the config envelope bytes
configEnv := &common.ConfigEnvelope{}
err = proto.Unmarshal(payload.Data, configEnv)
Expect(err).NotTo(HaveOccurred())
// clone the config
return configEnv.Config
}
// UpdateConfig computes, signs, and submits a configuration update and waits
// for the update to complete.
func UpdateConfig(n *Network, signer, submitter *Peer, orderer *Orderer, channel string, current, updated *common.Config) {
tempDir, err := ioutil.TempDir("", "updateConfig")
Expect(err).NotTo(HaveOccurred())
defer os.RemoveAll(tempDir)
// compute update
configUpdate, err := update.Compute(current, updated)
Expect(err).NotTo(HaveOccurred())
configUpdate.ChannelId = channel
signedEnvelope, err := utils.CreateSignedEnvelope(
common.HeaderType_CONFIG_UPDATE,
channel,
nil, // local signer
&common.ConfigUpdateEnvelope{ConfigUpdate: utils.MarshalOrPanic(configUpdate)},
0, // message version
0, // epoch
)
Expect(err).NotTo(HaveOccurred())
Expect(signedEnvelope).NotTo(BeNil())
updateFile := filepath.Join(tempDir, "update.pb")
err = ioutil.WriteFile(updateFile, utils.MarshalOrPanic(signedEnvelope), 0600)
Expect(err).NotTo(HaveOccurred())
sess, err := n.PeerAdminSession(signer, commands.SignConfigTx{File: updateFile})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, time.Minute).Should(gexec.Exit(0))
// get current configuration block number
currentBlockNumber := CurrentConfigBlockNumber(n, submitter, orderer, channel)
sess, err = n.PeerAdminSession(submitter, commands.ChannelUpdate{
ChannelID: channel,
Orderer: n.OrdererAddress(orderer, ListenPort),
File: updateFile,
})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, time.Minute).Should(gexec.Exit(0))
Expect(sess.Err).To(gbytes.Say("Successfully submitted channel update"))
// wait for the block to be committed
Eventually(func() uint64 { return CurrentConfigBlockNumber(n, submitter, orderer, channel) }).Should(BeNumerically(">", currentBlockNumber))
}
// CurrentConfigBlockNumber retrieves the block number from the header of the
// current config block. This can be used to detect whena configuration change
// has completed.
func CurrentConfigBlockNumber(n *Network, peer *Peer, orderer *Orderer, channel string) uint64 {
tempDir, err := ioutil.TempDir("", "currentConfigBlock")
Expect(err).NotTo(HaveOccurred())
defer os.RemoveAll(tempDir)
// fetch the config block
output := filepath.Join(tempDir, "config_block.pb")
sess, err := n.PeerAdminSession(peer, commands.ChannelFetch{
ChannelID: channel,
Block: "config",
Orderer: n.OrdererAddress(orderer, ListenPort),
OutputFile: output,
})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, time.Minute).Should(gexec.Exit(0))
Expect(sess.Err).To(gbytes.Say("Received block: "))
// unmarshal the config block bytes
configBlock := UnmarshalBlockFromFile(output)
return configBlock.Header.Number
}
// UnmarshalBlockFromFile unmarshals a proto encoded block from a file.
func UnmarshalBlockFromFile(blockFile string) *common.Block {
blockBytes, err := ioutil.ReadFile(blockFile)
Expect(err).NotTo(HaveOccurred())
block, err := utils.UnmarshalBlock(blockBytes)
Expect(err).NotTo(HaveOccurred())
return block
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment