@@ -22,6 +22,7 @@ import (
2222 cb "github.com/hyperledger/fabric-protos-go-apiv2/common"
2323 "github.com/hyperledger/fabric/cmd/osnadmin/mocks"
2424 "github.com/hyperledger/fabric/common/crypto/tlsgen"
25+ . "github.com/hyperledger/fabric/internal/test"
2526 "github.com/hyperledger/fabric/orderer/common/channelparticipation"
2627 "github.com/hyperledger/fabric/orderer/common/localconfig"
2728 "github.com/hyperledger/fabric/orderer/common/types"
@@ -694,7 +695,7 @@ var _ = Describe("osnadmin", func() {
694695 tlsConfig = nil
695696 })
696697
697- It ("uses the channel participation API to join a channel" , func () {
698+ It ("uses the channel participation API to update a channel" , func () {
698699 args := []string {
699700 "channel" ,
700701 "update" ,
@@ -713,6 +714,137 @@ var _ = Describe("osnadmin", func() {
713714 })
714715 })
715716
717+ Describe ("Fetch" , func () {
718+ var (
719+ blockPath string
720+ block * cb.Block
721+ )
722+
723+ BeforeEach (func () {
724+ blockPath = filepath .Join (tempDir , "block.pb" )
725+ block = blockWithGroups (
726+ map [string ]* cb.ConfigGroup {
727+ "Application" : {},
728+ },
729+ "testing123" ,
730+ )
731+ mockChannelManagement .FetchBlockReturns (block , nil )
732+ })
733+
734+ AfterEach (func () {
735+ _ = os .Remove (blockPath )
736+ })
737+
738+ It ("uses the channel participation API to fetch a block" , func () {
739+ args := []string {
740+ "channel" ,
741+ "fetch" ,
742+ "--outputfile" , blockPath ,
743+ "--channelID" , channelID ,
744+ "--blockID" , "100" ,
745+ "--orderer-address" , ordererURL ,
746+ "--ca-file" , ordererCACert ,
747+ "--client-cert" , clientCert ,
748+ "--client-key" , clientKey ,
749+ }
750+ output , exit , err := executeForArgs (args )
751+ Expect (err ).NotTo (HaveOccurred ())
752+ Expect (exit ).To (Equal (0 ))
753+ Expect (output ).To (Equal (fmt .Sprintf ("Status: %d\n " , 200 )))
754+
755+ blockBytes , err := os .ReadFile (blockPath )
756+ Expect (err ).NotTo (HaveOccurred ())
757+
758+ b := & cb.Block {}
759+ err = proto .Unmarshal (blockBytes , b )
760+ Expect (err ).NotTo (HaveOccurred ())
761+ Expect (b ).To (ProtoEqual (block ))
762+ })
763+
764+ Context ("when the block is empty" , func () {
765+ BeforeEach (func () {
766+ block = & cb.Block {}
767+ mockChannelManagement .FetchBlockReturns (block , nil )
768+ })
769+
770+ It ("returns with exit code 1 and prints the error" , func () {
771+ args := []string {
772+ "channel" ,
773+ "fetch" ,
774+ "--outputfile" , blockPath ,
775+ "--channelID" , channelID ,
776+ "--blockID" , "100" ,
777+ "--orderer-address" , ordererURL ,
778+ "--ca-file" , ordererCACert ,
779+ "--client-cert" , clientCert ,
780+ "--client-key" , clientKey ,
781+ }
782+ output , exit , err := executeForArgs (args )
783+ Expect (err ).NotTo (HaveOccurred ())
784+ Expect (exit ).To (Equal (0 ))
785+ Expect (output ).To (Equal (fmt .Sprintf ("Status: %d\n " , 200 )))
786+
787+ blockBytes , err := os .ReadFile (blockPath )
788+ Expect (err ).To (HaveOccurred ())
789+ Expect (blockBytes ).To (BeNil ())
790+ })
791+ })
792+
793+ Context ("when fetch the channel fails" , func () {
794+ BeforeEach (func () {
795+ mockChannelManagement .FetchBlockReturns (nil , types .ErrChannelNotExist )
796+ })
797+
798+ It ("returns 404 does not exist" , func () {
799+ args := []string {
800+ "channel" ,
801+ "fetch" ,
802+ "--outputfile" , blockPath ,
803+ "--channelID" , channelID ,
804+ "--blockID" , "100" ,
805+ "--orderer-address" , ordererURL ,
806+ "--ca-file" , ordererCACert ,
807+ "--client-cert" , clientCert ,
808+ "--client-key" , clientKey ,
809+ }
810+ output , exit , err := executeForArgs (args )
811+ expectedOutput := types.ErrorResponse {
812+ Error : "channel does not exist" ,
813+ }
814+ checkStatusOutput (output , exit , err , 404 , expectedOutput )
815+ })
816+ })
817+
818+ Context ("when TLS is disabled" , func () {
819+ BeforeEach (func () {
820+ tlsConfig = nil
821+ })
822+
823+ It ("uses the channel participation API to fetch a block" , func () {
824+ args := []string {
825+ "channel" ,
826+ "fetch" ,
827+ "--outputfile" , blockPath ,
828+ "--channelID" , channelID ,
829+ "--blockID" , "100" ,
830+ "--orderer-address" , ordererURL ,
831+ }
832+ output , exit , err := executeForArgs (args )
833+ Expect (err ).NotTo (HaveOccurred ())
834+ Expect (exit ).To (Equal (0 ))
835+ Expect (output ).To (Equal (fmt .Sprintf ("Status: %d\n " , 200 )))
836+
837+ blockBytes , err := os .ReadFile (blockPath )
838+ Expect (err ).NotTo (HaveOccurred ())
839+
840+ b := & cb.Block {}
841+ err = proto .Unmarshal (blockBytes , b )
842+ Expect (err ).NotTo (HaveOccurred ())
843+ Expect (b ).To (ProtoEqual (block ))
844+ })
845+ })
846+ })
847+
716848 Describe ("Flags" , func () {
717849 It ("accepts short versions of the --orderer-address, --channelID, and --config-block flags" , func () {
718850 configBlock := blockWithGroups (
@@ -750,6 +882,41 @@ var _ = Describe("osnadmin", func() {
750882 checkStatusOutput (output , exit , err , 201 , expectedOutput )
751883 })
752884
885+ It ("accepts short versions of the --channelID, --blockID, and --outputfile flags" , func () {
886+ blockPath := filepath .Join (tempDir , "block.pb" )
887+ block := blockWithGroups (
888+ map [string ]* cb.ConfigGroup {
889+ "Application" : {},
890+ },
891+ "testing123" ,
892+ )
893+ mockChannelManagement .FetchBlockReturns (block , nil )
894+
895+ args := []string {
896+ "channel" ,
897+ "fetch" ,
898+ "-f" , blockPath ,
899+ "-c" , channelID ,
900+ "-b" , "oldest" ,
901+ "-o" , ordererURL ,
902+ "--ca-file" , ordererCACert ,
903+ "--client-cert" , clientCert ,
904+ "--client-key" , clientKey ,
905+ }
906+ output , exit , err := executeForArgs (args )
907+ Expect (err ).NotTo (HaveOccurred ())
908+ Expect (exit ).To (Equal (0 ))
909+ Expect (output ).To (Equal (fmt .Sprintf ("Status: %d\n " , 200 )))
910+
911+ blockBytes , err := os .ReadFile (blockPath )
912+ Expect (err ).NotTo (HaveOccurred ())
913+
914+ b := & cb.Block {}
915+ err = proto .Unmarshal (blockBytes , b )
916+ Expect (err ).NotTo (HaveOccurred ())
917+ Expect (b ).To (ProtoEqual (block ))
918+ })
919+
753920 Context ("when an unknown flag is used" , func () {
754921 It ("returns an error for long flags" , func () {
755922 _ , _ , err := executeForArgs ([]string {"channel" , "list" , "--bad-flag" })
0 commit comments