Skip to content

Commit 362c5a3

Browse files
committed
Peer CLI queryinstalled JSON output with flag
FAB-14932 Change-Id: Id2bedd4063c60744601087717c9d55180470d708 Signed-off-by: Will Lahti <wtlahti@us.ibm.com>
1 parent 1c323e7 commit 362c5a3

File tree

5 files changed

+84
-8
lines changed

5 files changed

+84
-8
lines changed

integration/nwo/commands/peer.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ func (c ChaincodeQueryInstalled) SessionName() string {
386386
func (c ChaincodeQueryInstalled) Args() []string {
387387
return []string{
388388
"lifecycle", "chaincode", "queryinstalled",
389+
"--output", "json",
389390
}
390391
}
391392

integration/nwo/deploy.go

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/hyperledger/fabric/common/util"
1919
"github.com/hyperledger/fabric/integration/nwo/commands"
2020
"github.com/hyperledger/fabric/protos/common"
21+
"github.com/hyperledger/fabric/protos/peer/lifecycle"
2122
"github.com/hyperledger/fabric/protoutil"
2223
"github.com/onsi/gomega/gbytes"
2324
"github.com/onsi/gomega/gexec"
@@ -166,10 +167,7 @@ func InstallChaincode(n *Network, chaincode Chaincode, peers ...*Peer) {
166167
Expect(err).NotTo(HaveOccurred())
167168
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
168169

169-
sess, err = n.PeerAdminSession(p, commands.ChaincodeQueryInstalled{})
170-
Expect(err).NotTo(HaveOccurred())
171-
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
172-
Expect(sess).To(gbytes.Say(fmt.Sprintf("Package ID: %s, Label: %s", chaincode.PackageID, chaincode.Label)))
170+
EnsureInstalled(n, chaincode.Label, chaincode.PackageID, p)
173171
}
174172
}
175173

@@ -375,6 +373,32 @@ func UpgradeChaincodeLegacy(n *Network, channel string, orderer *Orderer, chainc
375373
EnsureInstantiatedLegacy(n, channel, chaincode.Name, chaincode.Version, peers...)
376374
}
377375

376+
func EnsureInstalled(n *Network, label, packageID string, peers ...*Peer) {
377+
for _, p := range peers {
378+
Eventually(queryInstalled(n, p), n.EventuallyTimeout).Should(
379+
ContainElement(&lifecycle.QueryInstalledChaincodesResult_InstalledChaincode{
380+
Label: label,
381+
PackageId: packageID,
382+
}))
383+
}
384+
}
385+
386+
type queryInstalledOutput struct {
387+
InstalledChaincodes []*lifecycle.QueryInstalledChaincodesResult_InstalledChaincode `json:"installed_chaincodes"`
388+
}
389+
390+
func queryInstalled(n *Network, peer *Peer) func() []*lifecycle.QueryInstalledChaincodesResult_InstalledChaincode {
391+
return func() []*lifecycle.QueryInstalledChaincodesResult_InstalledChaincode {
392+
sess, err := n.PeerAdminSession(peer, commands.ChaincodeQueryInstalled{})
393+
Expect(err).NotTo(HaveOccurred())
394+
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
395+
output := &queryInstalledOutput{}
396+
err = json.Unmarshal(sess.Out.Contents(), output)
397+
Expect(err).NotTo(HaveOccurred())
398+
return output.InstalledChaincodes
399+
}
400+
}
401+
378402
type simulateCommitOutput struct {
379403
Approved map[string]bool
380404
}

internal/peer/lifecycle/chaincode/querycommitted_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ var _ = Describe("QueryCommitted", func() {
8585
BeforeEach(func() {
8686
committedQuerier.Input.OutputFormat = "json"
8787
})
88+
8889
It("queries committed chaincodes and writes the output as JSON", func() {
8990
err := committedQuerier.Query()
9091
Expect(err).NotTo(HaveOccurred())

internal/peer/lifecycle/chaincode/queryinstalled.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ package chaincode
99
import (
1010
"context"
1111
"fmt"
12+
"io"
13+
"os"
14+
"strings"
1215

1316
"github.com/golang/protobuf/proto"
1417
cb "github.com/hyperledger/fabric/protos/common"
@@ -24,8 +27,14 @@ import (
2427
// the installed chaincodes
2528
type InstalledQuerier struct {
2629
Command *cobra.Command
30+
Input *InstalledQueryInput
2731
EndorserClient EndorserClient
2832
Signer Signer
33+
Writer io.Writer
34+
}
35+
36+
type InstalledQueryInput struct {
37+
OutputFormat string
2938
}
3039

3140
// QueryInstalledCmd returns the cobra command for listing
@@ -52,13 +61,19 @@ func QueryInstalledCmd(i *InstalledQuerier) *cobra.Command {
5261
return err
5362
}
5463

64+
iqInput := &InstalledQueryInput{
65+
OutputFormat: output,
66+
}
67+
5568
// queryinstalled only supports one peer connection,
5669
// which is why we only wire in the first endorser
5770
// client
5871
i = &InstalledQuerier{
5972
Command: cmd,
6073
EndorserClient: cc.EndorserClients[0],
74+
Input: iqInput,
6175
Signer: cc.Signer,
76+
Writer: os.Stdout,
6277
}
6378
}
6479
return i.Query()
@@ -69,6 +84,7 @@ func QueryInstalledCmd(i *InstalledQuerier) *cobra.Command {
6984
"peerAddresses",
7085
"tlsRootCertFiles",
7186
"connectionProfile",
87+
"output",
7288
}
7389
attachFlags(chaincodeQueryInstalledCmd, flagList)
7490

@@ -109,6 +125,9 @@ func (i *InstalledQuerier) Query() error {
109125
return errors.Errorf("query failed with status: %d - %s", proposalResponse.Response.Status, proposalResponse.Response.Message)
110126
}
111127

128+
if strings.ToLower(i.Input.OutputFormat) == "json" {
129+
return printResponseAsJSON(proposalResponse, &lb.QueryInstalledChaincodesResult{}, i.Writer)
130+
}
112131
return i.printResponse(proposalResponse)
113132
}
114133

@@ -120,12 +139,11 @@ func (i *InstalledQuerier) printResponse(proposalResponse *pb.ProposalResponse)
120139
if err != nil {
121140
return errors.Wrap(err, "failed to unmarshal proposal response's response payload")
122141
}
123-
fmt.Println("Installed chaincodes on peer:")
142+
fmt.Fprintln(i.Writer, "Installed chaincodes on peer:")
124143
for _, chaincode := range qicr.InstalledChaincodes {
125-
fmt.Printf("Package ID: %s, Label: %s\n", chaincode.PackageId, chaincode.Label)
144+
fmt.Fprintf(i.Writer, "Package ID: %s, Label: %s\n", chaincode.PackageId, chaincode.Label)
126145
}
127146
return nil
128-
129147
}
130148

131149
func (i *InstalledQuerier) createProposal() (*pb.Proposal, error) {

internal/peer/lifecycle/chaincode/queryinstalled_test.go

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ SPDX-License-Identifier: Apache-2.0
77
package chaincode_test
88

99
import (
10+
"encoding/json"
11+
"fmt"
12+
1013
"github.com/golang/protobuf/proto"
1114
"github.com/hyperledger/fabric/internal/peer/lifecycle/chaincode"
1215
"github.com/hyperledger/fabric/internal/peer/lifecycle/chaincode/mock"
@@ -17,6 +20,7 @@ import (
1720

1821
. "github.com/onsi/ginkgo"
1922
. "github.com/onsi/gomega"
23+
"github.com/onsi/gomega/gbytes"
2024
)
2125

2226
var _ = Describe("QueryInstalled", func() {
@@ -25,6 +29,7 @@ var _ = Describe("QueryInstalled", func() {
2529
mockProposalResponse *pb.ProposalResponse
2630
mockEndorserClient *mock.EndorserClient
2731
mockSigner *mock.Signer
32+
input *chaincode.InstalledQueryInput
2833
installedQuerier *chaincode.InstalledQuerier
2934
)
3035

@@ -49,16 +54,43 @@ var _ = Describe("QueryInstalled", func() {
4954
mockEndorserClient.ProcessProposalReturns(mockProposalResponse, nil)
5055

5156
mockSigner = &mock.Signer{}
57+
buffer := gbytes.NewBuffer()
58+
input = &chaincode.InstalledQueryInput{}
5259

5360
installedQuerier = &chaincode.InstalledQuerier{
61+
Input: input,
5462
EndorserClient: mockEndorserClient,
5563
Signer: mockSigner,
64+
Writer: buffer,
5665
}
5766
})
5867

59-
It("queries installed chaincodes", func() {
68+
It("queries installed chaincodes and writes the output as human readable plain-text", func() {
6069
err := installedQuerier.Query()
6170
Expect(err).NotTo(HaveOccurred())
71+
Eventually(installedQuerier.Writer).Should(gbytes.Say("Installed chaincodes on peer:"))
72+
Eventually(installedQuerier.Writer).Should(gbytes.Say("Package ID: packageid1, Label: label1"))
73+
})
74+
75+
Context("when JSON-formatted output is requested", func() {
76+
BeforeEach(func() {
77+
installedQuerier.Input.OutputFormat = "json"
78+
})
79+
80+
It("queries installed chaincodes and writes the output as JSON", func() {
81+
err := installedQuerier.Query()
82+
Expect(err).NotTo(HaveOccurred())
83+
expectedOutput := &lb.QueryInstalledChaincodesResult{
84+
InstalledChaincodes: []*lb.QueryInstalledChaincodesResult_InstalledChaincode{
85+
{
86+
PackageId: "packageid1",
87+
Label: "label1",
88+
},
89+
},
90+
}
91+
json, err := json.MarshalIndent(expectedOutput, "", "\t")
92+
Eventually(installedQuerier.Writer).Should(gbytes.Say(fmt.Sprintf(`\Q%s\E`, string(json))))
93+
})
6294
})
6395

6496
Context("when the signer cannot be serialized", func() {

0 commit comments

Comments
 (0)