Skip to content

Commit

Permalink
Implement 'osnadmin channel info' subcommand and update tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Priyansurout committed Jun 13, 2024
1 parent aec91f8 commit 8306268
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 43 deletions.
15 changes: 10 additions & 5 deletions cmd/osnadmin/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ func executeForArgs(args []string) (output string, exit int, err error) {
configBlockPath := join.Flag("config-block", "Path to the file containing an up-to-date config block for the channel").Short('b').Required().String()

list := channel.Command("list", "List channel information for an Ordering Service Node (OSN). If the channelID flag is set, more detailed information will be provided for that channel.")
listChannelID := list.Flag("channelID", "Channel ID").Short('c').String()
// listChannelID := list.Flag("channelID", "Channel ID").Short('c').String()
// Define the new info subcommand
info := channel.Command("info", "Get detailed information about a specific channel.")
infoChannelID := info.Flag("channelID", "Channel ID").Short('c').Required().String()

remove := channel.Command("remove", "Remove a channel from an Ordering Service Node (OSN).")
removeChannelID := remove.Flag("channelID", "Channel ID").Short('c').Required().String()
Expand Down Expand Up @@ -113,11 +116,13 @@ func executeForArgs(args []string) (output string, exit int, err error) {
case join.FullCommand():
resp, err = osnadmin.Join(osnURL, marshaledConfigBlock, caCertPool, tlsClientCert)
case list.FullCommand():
if *listChannelID != "" {
resp, err = osnadmin.ListSingleChannel(osnURL, *listChannelID, caCertPool, tlsClientCert)
break
}
// if *listChannelID != "" {
// resp, err = osnadmin.ListSingleChannel(osnURL, *listChannelID, caCertPool, tlsClientCert)
// break
// }
resp, err = osnadmin.ListAllChannels(osnURL, caCertPool, tlsClientCert)
case info.FullCommand():
resp, err = osnadmin.ListSingleChannel(osnURL, *infoChannelID, caCertPool, tlsClientCert)
case remove.FullCommand():
resp, err = osnadmin.Remove(osnURL, *removeChannelID, caCertPool, tlsClientCert)
}
Expand Down
185 changes: 147 additions & 38 deletions cmd/osnadmin/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,20 @@ var _ = Describe("osnadmin", func() {
Name: "fight-the-system",
},
})
})

mockChannelManagement.ChannelInfoReturns(types.ChannelInfo{
Name: "asparagus",
ConsensusRelation: "broccoli",
Status: "carrot",
Height: 987,
}, nil)
It("returns an error when channelID flag is not provided", func() {
args := []string{
"channel",
"info",
"--orderer-address", ordererURL,
"--ca-file", ordererCACert,
"--client-cert", clientCert,
"--client-key", clientKey,
}
output, exit, err := executeForArgs(args)
expectedErrorMessage := "required flag(s) \"channelID\" not set"
checkCLIError(output, exit, err, expectedErrorMessage)
})

It("uses the channel participation API to list all application channels and the system channel (when it exists)", func() {
Expand Down Expand Up @@ -156,10 +163,70 @@ var _ = Describe("osnadmin", func() {
checkStatusOutput(output, exit, err, 200, expectedOutput)
})

Context("when TLS is disabled", func() {
BeforeEach(func() {
tlsConfig = nil
})

It("uses the channel participation API to list all channels", func() {
args := []string{
"channel",
"list",
"--orderer-address", ordererURL,
}
output, exit, err := executeForArgs(args)
Expect(err).NotTo(HaveOccurred())
Expect(exit).To(Equal(0))

expectedOutput := types.ChannelList{
Channels: []types.ChannelInfoShort{
{
Name: "participation-trophy",
URL: "/participation/v1/channels/participation-trophy",
},
{
Name: "another-participation-trophy",
URL: "/participation/v1/channels/another-participation-trophy",
},
},
SystemChannel: &types.ChannelInfoShort{
Name: "fight-the-system",
URL: "/participation/v1/channels/fight-the-system",
},
}
checkStatusOutput(output, exit, err, 200, expectedOutput)
})
})
})

Describe("Info", func() {
BeforeEach(func() {
mockChannelManagement.ChannelListReturns(types.ChannelList{
Channels: []types.ChannelInfoShort{
{
Name: "participation-trophy",
},
{
Name: "another-participation-trophy",
},
},
SystemChannel: &types.ChannelInfoShort{
Name: "fight-the-system",
},
})

mockChannelManagement.ChannelInfoReturns(types.ChannelInfo{
Name: "asparagus",
ConsensusRelation: "broccoli",
Status: "carrot",
Height: 987,
}, nil)
})

It("uses the channel participation API to list the details of a single channel", func() {
args := []string{
"channel",
"list",
"info",
"--orderer-address", ordererURL,
"--channelID", "tell-me-your-secrets",
"--ca-file", ordererCACert,
Expand All @@ -185,7 +252,7 @@ var _ = Describe("osnadmin", func() {
It("returns 404 not found", func() {
args := []string{
"channel",
"list",
"info",
"--orderer-address", ordererURL,
"--channelID", "tell-me-your-secrets",
"--ca-file", ordererCACert,
Expand All @@ -205,39 +272,10 @@ var _ = Describe("osnadmin", func() {
tlsConfig = nil
})

It("uses the channel participation API to list all channels", func() {
args := []string{
"channel",
"list",
"--orderer-address", ordererURL,
}
output, exit, err := executeForArgs(args)
Expect(err).NotTo(HaveOccurred())
Expect(exit).To(Equal(0))

expectedOutput := types.ChannelList{
Channels: []types.ChannelInfoShort{
{
Name: "participation-trophy",
URL: "/participation/v1/channels/participation-trophy",
},
{
Name: "another-participation-trophy",
URL: "/participation/v1/channels/another-participation-trophy",
},
},
SystemChannel: &types.ChannelInfoShort{
Name: "fight-the-system",
URL: "/participation/v1/channels/fight-the-system",
},
}
checkStatusOutput(output, exit, err, 200, expectedOutput)
})

It("uses the channel participation API to list the details of a single channel", func() {
args := []string{
"channel",
"list",
"info",
"--orderer-address", ordererURL,
"--channelID", "tell-me-your-secrets",
}
Expand All @@ -254,6 +292,26 @@ var _ = Describe("osnadmin", func() {
}
checkStatusOutput(output, exit, err, 200, expectedOutput)
})
Context("when the channel does not exist", func() {
BeforeEach(func() {
mockChannelManagement.ChannelInfoReturns(types.ChannelInfo{}, errors.New("eat-your-peas"))
})

It("returns 404 not found with the info subcommand", func() {
args := []string{
"channel",
"info",
"--orderer-address", ordererURL,
"--channelID", "tell-me-your-secrets",
}
output, exit, err := executeForArgs(args)
expectedOutput := types.ErrorResponse{
Error: "eat-your-peas",
}
checkStatusOutput(output, exit, err, 404, expectedOutput)
})
})

})
})

Expand Down Expand Up @@ -581,6 +639,18 @@ var _ = Describe("osnadmin", func() {
})
})

Context("when an unknown flag is used with the info subcommand", func() {
It("returns an error for long flags", func() {
_, _, err := executeForArgs([]string{"channel", "info", "--bad-flag"})
Expect(err).To(MatchError("unknown long flag '--bad-flag'"))
})

It("returns an error for short flags", func() {
_, _, err := executeForArgs([]string{"channel", "info", "-z"})
Expect(err).To(MatchError("unknown short flag '-z'"))
})
})

Context("when the ca cert cannot be read", func() {
BeforeEach(func() {
ordererCACert = "not-the-ca-cert-youre-looking-for"
Expand All @@ -591,6 +661,25 @@ var _ = Describe("osnadmin", func() {
"channel",
"list",
"--orderer-address", ordererURL,
"--ca-file", ordererCACert,
"--client-cert", clientCert,
"--client-key", clientKey,
}
output, exit, err := executeForArgs(args)
checkFlagError(output, exit, err, "reading orderer CA certificate: open not-the-ca-cert-youre-looking-for: no such file or directory")
})
})

Context("when the ca cert cannot be read with the info subcommand", func() {
BeforeEach(func() {
ordererCACert = "not-the-ca-cert-youre-looking-for"
})

It("returns with exit code 1 and prints the error with the info subcommand", func() {
args := []string{
"channel",
"info",
"--orderer-address", ordererURL,
"--channelID", channelID,
"--ca-file", ordererCACert,
"--client-cert", clientCert,
Expand Down Expand Up @@ -640,6 +729,26 @@ var _ = Describe("osnadmin", func() {
})
})

Context("when the client cert/key pair fail to load with the info subcommand", func() {
BeforeEach(func() {
clientKey = "brussel-sprouts"
})

It("returns with exit code 1 and prints the error with the info subcommand", func() {
args := []string{
"channel",
"info",
"--orderer-address", ordererURL,
"--channelID", channelID,
"--ca-file", ordererCACert,
"--client-cert", clientCert,
"--client-key", clientKey,
}
output, exit, err := executeForArgs(args)
checkFlagError(output, exit, err, "loading client cert/key pair: open brussel-sprouts: no such file or directory")
})
})

Context("when the config block cannot be read", func() {
var configBlockPath string

Expand Down

0 comments on commit 8306268

Please sign in to comment.