@@ -22,7 +22,6 @@ 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/orderer/common/channelparticipation"
2625 "github.com/hyperledger/fabric/orderer/common/localconfig"
2726 "github.com/hyperledger/fabric/orderer/common/types"
2827 "github.com/hyperledger/fabric/protoutil"
@@ -63,7 +62,7 @@ var _ = Describe("osnadmin", func() {
6362 }
6463 mockChannelManagement = & mocks.ChannelManagement {}
6564
66- h := channelparticipation .NewHTTPHandler (config , mockChannelManagement )
65+ h := nwo .NewHTTPHandler (config , mockChannelManagement )
6766 Expect (h ).NotTo (BeNil ())
6867 testServer = httptest .NewUnstartedServer (h )
6968
@@ -532,134 +531,183 @@ var _ = Describe("osnadmin", func() {
532531 })
533532 })
534533
535- Describe ("Flags" , func () {
536- It ("accepts short versions of the --orderer-address, --channelID, and --config-block flags" , func () {
537- configBlock := blockWithGroups (
538- map [string ]* cb.ConfigGroup {
539- "Application" : {},
540- },
541- "testing123" ,
542- )
543- blockPath := createBlockFile (tempDir , configBlock )
544- mockChannelManagement .JoinChannelReturns (types.ChannelInfo {
545- Name : "apple" ,
546- ConsensusRelation : "banana" ,
547- Status : "orange" ,
548- Height : 123 ,
534+ Describe ("Update" , func () {
535+ var envelopePath string
536+
537+ BeforeEach (func () {
538+ configEnvelope := envelopeUpdateConfigWithGroups ("testing123" )
539+ envelopePath = createEnvelopeFile (tempDir , configEnvelope )
540+
541+ mockChannelManagement .UpdateChannelReturns (types.ChannelInfo {
542+ Name : "apple" ,
543+ Height : 123 ,
549544 }, nil )
545+ })
550546
547+ It ("uses the channel participation API to update a channel" , func () {
551548 args := []string {
552549 "channel" ,
553- "join " ,
554- "-o " , ordererURL ,
555- "-c " , channelID ,
556- "-b " , blockPath ,
550+ "update " ,
551+ "--orderer-address " , ordererURL ,
552+ "--channelID " , channelID ,
553+ "--config-update-envelope " , envelopePath ,
557554 "--ca-file" , ordererCACert ,
558555 "--client-cert" , clientCert ,
559556 "--client-key" , clientKey ,
560557 }
561558 output , exit , err := executeForArgs (args )
562559 expectedOutput := types.ChannelInfo {
563- Name : "apple" ,
564- URL : "/participation/v1/channels/apple" ,
565- ConsensusRelation : "banana" ,
566- Status : "orange" ,
567- Height : 123 ,
560+ Name : "apple" ,
561+ URL : "/participation/v1/channels/apple" ,
562+ Height : 123 ,
568563 }
569564 checkStatusOutput (output , exit , err , 201 , expectedOutput )
570565 })
571566
572- Context ("when an unknown flag is used" , func () {
573- It ("returns an error for long flags" , func () {
574- _ , _ , err := executeForArgs ([]string {"channel" , "list" , "--bad-flag" })
575- Expect (err ).To (MatchError ("unknown long flag '--bad-flag'" ))
567+ Context ("when the envelope is empty" , func () {
568+ BeforeEach (func () {
569+ envelopePath = createEnvelopeFile (tempDir , & cb.Envelope {})
576570 })
577571
578- It ("returns an error for short flags" , func () {
579- _ , _ , err := executeForArgs ([]string {"channel" , "list" , "-z" })
580- Expect (err ).To (MatchError ("unknown short flag '-z'" ))
572+ It ("returns with exit code 1 and prints the error" , func () {
573+ args := []string {
574+ "channel" ,
575+ "update" ,
576+ "--orderer-address" , ordererURL ,
577+ "--channelID" , channelID ,
578+ "--config-update-envelope" , envelopePath ,
579+ "--ca-file" , ordererCACert ,
580+ "--client-cert" , clientCert ,
581+ "--client-key" , clientKey ,
582+ }
583+ output , exit , err := executeForArgs (args )
584+
585+ checkFlagError (output , exit , err , "failed to retrieve channel id - payload header is empty" )
581586 })
582587 })
583588
584- Context ("when the ca cert cannot be read " , func () {
589+ Context ("when the --channelID does not match the channel ID in the envelope " , func () {
585590 BeforeEach (func () {
586- ordererCACert = "not-the-ca-cert -youre-looking-for"
591+ channelID = "not-the-channel -youre-looking-for"
587592 })
588593
589594 It ("returns with exit code 1 and prints the error" , func () {
590595 args := []string {
591596 "channel" ,
592- "list " ,
597+ "update " ,
593598 "--orderer-address" , ordererURL ,
594599 "--channelID" , channelID ,
600+ "--config-update-envelope" , envelopePath ,
595601 "--ca-file" , ordererCACert ,
596602 "--client-cert" , clientCert ,
597603 "--client-key" , clientKey ,
598604 }
599605 output , exit , err := executeForArgs (args )
600- checkFlagError (output , exit , err , "reading orderer CA certificate: open not-the-ca-cert-youre-looking-for: no such file or directory" )
606+
607+ checkFlagError (output , exit , err , "specified --channelID not-the-channel-youre-looking-for does not match channel ID testing123 in config update envelope" )
601608 })
602609 })
603610
604- Context ("when the ca-file contains a private key instead of certificate(s) " , func () {
611+ Context ("when the envelope isn't a valid config update " , func () {
605612 BeforeEach (func () {
606- ordererCACert = clientKey
613+ envelope := & cb.Envelope {
614+ Payload : protoutil .MarshalOrPanic (& cb.Payload {
615+ Header : & cb.Header {
616+ ChannelHeader : protoutil .MarshalOrPanic (& cb.ChannelHeader {
617+ Type : int32 (cb .HeaderType_ENDORSER_TRANSACTION ),
618+ ChannelId : channelID ,
619+ }),
620+ },
621+ }),
622+ }
623+ envelopePath = createEnvelopeFile (tempDir , envelope )
607624 })
608625
609- It ("returns with exit code 1 and prints the error " , func () {
626+ It ("returns 405 bad request " , func () {
610627 args := []string {
611628 "channel" ,
612- "remove " ,
629+ "update " ,
613630 "--orderer-address" , ordererURL ,
614631 "--channelID" , channelID ,
632+ "--config-update-envelope" , envelopePath ,
615633 "--ca-file" , ordererCACert ,
616634 "--client-cert" , clientCert ,
617635 "--client-key" , clientKey ,
618636 }
619637 output , exit , err := executeForArgs (args )
620- checkFlagError (output , exit , err , "failed to add ca-file PEM to cert pool" )
638+ Expect (err ).NotTo (HaveOccurred ())
639+ Expect (exit ).To (Equal (0 ))
640+
641+ expectedOutput := types.ErrorResponse {
642+ Error : "invalid config update envelope: bad type" ,
643+ }
644+ checkStatusOutput (output , exit , err , 400 , expectedOutput )
621645 })
622646 })
623647
624- Context ("when the client cert/key pair fail to load " , func () {
648+ Context ("when updating the channel fails " , func () {
625649 BeforeEach (func () {
626- clientKey = "brussel-sprouts"
650+ mockChannelManagement . UpdateChannelReturns (types. ChannelInfo {}, types . ErrChannelNotExist )
627651 })
628652
629- It ("returns with exit code 1 and prints the error " , func () {
653+ It ("returns 405 not allowed " , func () {
630654 args := []string {
631655 "channel" ,
632- "list " ,
656+ "update " ,
633657 "--orderer-address" , ordererURL ,
658+ "--channelID" , channelID ,
659+ "--config-update-envelope" , envelopePath ,
634660 "--ca-file" , ordererCACert ,
635661 "--client-cert" , clientCert ,
636662 "--client-key" , clientKey ,
637663 }
638664 output , exit , err := executeForArgs (args )
639- checkFlagError (output , exit , err , "loading client cert/key pair: open brussel-sprouts: no such file or directory" )
665+ expectedOutput := types.ErrorResponse {
666+ Error : "cannot update: channel does not exist" ,
667+ }
668+ checkStatusOutput (output , exit , err , 405 , expectedOutput )
640669 })
641- })
642670
643- Context ("when the config block cannot be read" , func () {
644- var configBlockPath string
671+ It ("returns 405 not allowed (without status)" , func () {
672+ args := []string {
673+ "channel" ,
674+ "update" ,
675+ "--orderer-address" , ordererURL ,
676+ "--channelID" , channelID ,
677+ "--config-update-envelope" , envelopePath ,
678+ "--ca-file" , ordererCACert ,
679+ "--client-cert" , clientCert ,
680+ "--client-key" , clientKey ,
681+ "--no-status" ,
682+ }
683+ output , exit , err := executeForArgs (args )
684+ expectedOutput := types.ErrorResponse {
685+ Error : "cannot update: channel does not exist" ,
686+ }
687+ checkOutput (output , exit , err , expectedOutput )
688+ })
689+ })
645690
691+ Context ("when TLS is disabled" , func () {
646692 BeforeEach (func () {
647- configBlockPath = "not-the-config-block-youre-looking-for"
693+ tlsConfig = nil
648694 })
649695
650- It ("returns with exit code 1 and prints the error " , func () {
696+ It ("uses the channel participation API to join a channel " , func () {
651697 args := []string {
652698 "channel" ,
653- "join " ,
699+ "update " ,
654700 "--orderer-address" , ordererURL ,
655701 "--channelID" , channelID ,
656- "--ca-file" , ordererCACert ,
657- "--client-cert" , clientCert ,
658- "--client-key" , clientKey ,
659- "--config-block" , configBlockPath ,
702+ "--config-update-envelope" , envelopePath ,
660703 }
661704 output , exit , err := executeForArgs (args )
662- checkFlagError (output , exit , err , "reading config block: open not-the-config-block-youre-looking-for: no such file or directory" )
705+ expectedOutput := types.ChannelInfo {
706+ Name : "apple" ,
707+ URL : "/participation/v1/channels/apple" ,
708+ Height : 123 ,
709+ }
710+ checkStatusOutput (output , exit , err , 201 , expectedOutput )
663711 })
664712 })
665713 })
@@ -834,3 +882,34 @@ func createBlockFile(tempDir string, configBlock *cb.Block) string {
834882 Expect (err ).NotTo (HaveOccurred ())
835883 return blockPath
836884}
885+
886+ func envelopeUpdateConfigWithGroups (channelID string ) * cb.Envelope {
887+ data := & cb.Envelope {
888+ Payload : protoutil .MarshalOrPanic (& cb.Payload {
889+ Data : protoutil .MarshalOrPanic (& cb.ConfigUpdateEnvelope {
890+ ConfigUpdate : protoutil .MarshalOrPanic (& cb.ConfigUpdate {
891+ ChannelId : channelID ,
892+ ReadSet : & cb.ConfigGroup {},
893+ WriteSet : & cb.ConfigGroup {},
894+ }),
895+ }),
896+ Header : & cb.Header {
897+ ChannelHeader : protoutil .MarshalOrPanic (& cb.ChannelHeader {
898+ Type : int32 (cb .HeaderType_CONFIG_UPDATE ),
899+ ChannelId : channelID ,
900+ }),
901+ },
902+ }),
903+ }
904+
905+ return data
906+ }
907+
908+ func createEnvelopeFile (tempDir string , configEnvelope * cb.Envelope ) string {
909+ envelopeBytes , err := proto .Marshal (configEnvelope )
910+ Expect (err ).NotTo (HaveOccurred ())
911+ envelopePath := filepath .Join (tempDir , "envelope.pb" )
912+ err = os .WriteFile (envelopePath , envelopeBytes , 0o644 )
913+ Expect (err ).NotTo (HaveOccurred ())
914+ return envelopePath
915+ }
0 commit comments