diff --git a/cmd/serve/serve.go b/cmd/serve/serve.go index 0fc05e5..43a4cee 100644 --- a/cmd/serve/serve.go +++ b/cmd/serve/serve.go @@ -215,6 +215,7 @@ func (c *serveCmd) run(conf *serveConfig) error { opts := server.BlockchainServerOpts{ Address: c.address, MetricsAddress: c.metricsAddress, + ConfigBackend: configBackend, SDK: sdk, GWClient: gwClient, SDKContext: sdkContext, diff --git a/cmd/start/start.go b/cmd/start/start.go index 8636020..a951ba8 100644 --- a/cmd/start/start.go +++ b/cmd/start/start.go @@ -60,6 +60,7 @@ type startCmd struct { signaturePolicy string envFile string tunnelAddress string + channel string } func (c startCmd) validate() error { @@ -131,10 +132,6 @@ hlf-cc-dev listen --forward-to=%s --tunnelAddress="xxx:8082" } chaincodeAddress := tunnelCFGItem.SNI - //chaincodeAddress, _, err := net.SplitHostPort(fullChaincodeAddress) - //if err != nil { - // return errors.Wrapf(err, "failed to parse chaincode address %s", fullChaincodeAddress) - //} pdcContents := "" if c.pdcFile != "" { pdcContentsBytes, err := ioutil.ReadFile(c.pdcFile) @@ -175,6 +172,7 @@ hlf-cc-dev listen --forward-to=%s --tunnelAddress="xxx:8082" } } input := models.DeployChaincodeInput{ + Channel: c.channel, Name: c.chaincode, ChaincodeAddress: chaincodeAddress, Pdc: pdcContents, @@ -313,5 +311,6 @@ func NewStartCmd() *cobra.Command { f.StringVar(&c.metaInf, "metaInf", "", "metadata") f.StringVar(&c.signaturePolicy, "signaturePolicy", "", "Signature policy") f.StringVar(&c.envFile, "env-file", "", "Env file to write the environments") + f.StringVar(&c.channel, "channel", "", "Channel name") return cmd } diff --git a/gql/generated.go b/gql/generated.go index f1cacfb..e70a6f9 100644 --- a/gql/generated.go +++ b/gql/generated.go @@ -74,8 +74,8 @@ type ComplexityRoot struct { } Query struct { - Chaincode func(childComplexity int, name string) int - Chaincodes func(childComplexity int) int + Chaincode func(childComplexity int, channel *string, name string) int + Chaincodes func(childComplexity int, channel *string) int __resolve__service func(childComplexity int) int } @@ -101,8 +101,8 @@ type MutationResolver interface { QueryChaincode(ctx context.Context, input models.QueryChaincodeInput) (*models.QueryChaincodeResponse, error) } type QueryResolver interface { - Chaincodes(ctx context.Context) ([]*models.Chaincode, error) - Chaincode(ctx context.Context, name string) (*models.Chaincode, error) + Chaincodes(ctx context.Context, channel *string) ([]*models.Chaincode, error) + Chaincode(ctx context.Context, channel *string, name string) (*models.Chaincode, error) } type executableSchema struct { @@ -264,14 +264,19 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.Chaincode(childComplexity, args["name"].(string)), true + return e.complexity.Query.Chaincode(childComplexity, args["channel"].(*string), args["name"].(string)), true case "Query.chaincodes": if e.complexity.Query.Chaincodes == nil { break } - return e.complexity.Query.Chaincodes(childComplexity), true + args, err := ec.field_Query_chaincodes_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Chaincodes(childComplexity, args["channel"].(*string)), true case "Query._service": if e.complexity.Query.__resolve__service == nil { @@ -463,8 +468,8 @@ input CouchDBIndex { } `, BuiltIn: false}, {Name: "schema/query.graphql", Input: `type Query { - chaincodes: [Chaincode!] - chaincode(name: String!): Chaincode + chaincodes(channel: String): [Chaincode!] + chaincode(channel: String, name: String!): Chaincode } type Chaincode { @@ -573,15 +578,39 @@ func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs func (ec *executionContext) field_Query_chaincode_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - var arg0 string + var arg0 *string + if tmp, ok := rawArgs["channel"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("channel")) + arg0, err = ec.unmarshalOString2áš–string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["channel"] = arg0 + var arg1 string if tmp, ok := rawArgs["name"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) - arg0, err = ec.unmarshalNString2string(ctx, tmp) + arg1, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err } } - args["name"] = arg0 + args["name"] = arg1 + return args, nil +} + +func (ec *executionContext) field_Query_chaincodes_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 *string + if tmp, ok := rawArgs["channel"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("channel")) + arg0, err = ec.unmarshalOString2áš–string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["channel"] = arg0 return args, nil } @@ -1255,9 +1284,16 @@ func (ec *executionContext) _Query_chaincodes(ctx context.Context, field graphql } ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_chaincodes_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Chaincodes(rctx) + return ec.resolvers.Query().Chaincodes(rctx, args["channel"].(*string)) }) if err != nil { ec.Error(ctx, err) @@ -1296,7 +1332,7 @@ func (ec *executionContext) _Query_chaincode(ctx context.Context, field graphql. fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Chaincode(rctx, args["name"].(string)) + return ec.resolvers.Query().Chaincode(rctx, args["channel"].(*string), args["name"].(string)) }) if err != nil { ec.Error(ctx, err) diff --git a/gql/resolvers/mutation.go b/gql/resolvers/mutation.go index 21f38aa..881c554 100644 --- a/gql/resolvers/mutation.go +++ b/gql/resolvers/mutation.go @@ -10,12 +10,16 @@ import ( "encoding/pem" "fmt" "github.com/gosimple/slug" + "github.com/hyperledger/fabric-config/configtx" "github.com/hyperledger/fabric-gateway/pkg/client" pb "github.com/hyperledger/fabric-protos-go/peer" clientmsp "github.com/hyperledger/fabric-sdk-go/pkg/client/msp" "github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt" + hlfcontext "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab" "github.com/hyperledger/fabric-sdk-go/pkg/fab/ccpackager/lifecycle" + "github.com/hyperledger/fabric-sdk-go/pkg/fab/resource" + "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk" "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/common/policydsl" "github.com/kfsoftware/hlf-cc-dev/gql/models" "github.com/kfsoftware/hlf-cc-dev/log" @@ -167,6 +171,10 @@ func (f *mspFilter) Accept(peer fab.Peer) bool { } func (m mutationResolver) DeployChaincode(ctx context.Context, input models.DeployChaincodeInput) (*models.DeployChaincodeResponse, error) { chaincodeName := slug.Make(input.Name) + channel := m.Channel + if input.Channel != "" { + channel = input.Channel + } address := input.ChaincodeAddress host, _, err := net.SplitHostPort(address) if err != nil { @@ -226,6 +234,30 @@ func (m mutationResolver) DeployChaincode(ctx context.Context, input models.Depl if err != nil { return nil, err } + block, err := resClient.QueryConfigBlockFromOrderer(channel) + if err != nil { + return nil, err + } + cfgBlock, err := resource.ExtractConfigFromBlock(block) + if err != nil { + return nil, err + } + cftxGen := configtx.New(cfgBlock) + appConf, err := cftxGen.Application().Configuration() + if err != nil { + return nil, err + } + mapSdkContext := map[string]hlfcontext.ClientProvider{} + for _, organization := range appConf.Organizations { + sdk, err := fabsdk.New(m.ConfigBackend) + if err != nil { + return nil, err + } + mapSdkContext[organization.Name] = sdk.Context( + fabsdk.WithUser(m.User), + fabsdk.WithOrg(organization.MSP.Name), + ) + } version := "1" sequence := 1 @@ -239,10 +271,7 @@ func (m mutationResolver) DeployChaincode(ctx context.Context, input models.Depl if err != nil { return nil, err } - channel := m.Channel - if input.Channel != "" { - channel = input.Channel - } + committedCCs, err := resClient.LifecycleQueryCommittedCC(channel, resmgmt.LifecycleQueryCommittedCCRequest{Name: chaincodeName}) if err != nil { log.Warnf("Error when getting commited chaincodes: %v", err) @@ -271,8 +300,8 @@ func (m mutationResolver) DeployChaincode(ctx context.Context, input models.Depl InitRequired: false, } var wg sync.WaitGroup - wg.Add(len(m.SDKContextMap)) - for mspID, sdkContext := range m.SDKContextMap { + wg.Add(len(mapSdkContext)) + for mspID, sdkContext := range mapSdkContext { mspID := mspID sdkContext := sdkContext go func() { diff --git a/gql/resolvers/query.go b/gql/resolvers/query.go index 51ce1d2..05d72db 100644 --- a/gql/resolvers/query.go +++ b/gql/resolvers/query.go @@ -6,12 +6,16 @@ import ( "github.com/kfsoftware/hlf-cc-dev/gql/models" ) -func (r *queryResolver) Chaincodes(ctx context.Context) ([]*models.Chaincode, error) { +func (r *queryResolver) Chaincodes(ctx context.Context, channel *string) ([]*models.Chaincode, error) { resClient, err := resmgmt.New(r.SDKContext) if err != nil { return nil, err } - committedCCs, err := resClient.LifecycleQueryCommittedCC(r.Channel, resmgmt.LifecycleQueryCommittedCCRequest{}) + channelName := r.Channel + if channel != nil && *channel != "" { + channelName = *channel + } + committedCCs, err := resClient.LifecycleQueryCommittedCC(channelName, resmgmt.LifecycleQueryCommittedCCRequest{}) if err != nil { return nil, err } @@ -26,12 +30,16 @@ func (r *queryResolver) Chaincodes(ctx context.Context) ([]*models.Chaincode, er return chaincodes, nil } -func (r *queryResolver) Chaincode(ctx context.Context, name string) (*models.Chaincode, error) { +func (r *queryResolver) Chaincode(ctx context.Context, channel *string, name string) (*models.Chaincode, error) { + channelName := r.Channel + if channel != nil && *channel != "" { + channelName = *channel + } resClient, err := resmgmt.New(r.SDKContext) if err != nil { return nil, err } - committedCCs, err := resClient.LifecycleQueryCommittedCC(r.Channel, resmgmt.LifecycleQueryCommittedCCRequest{ + committedCCs, err := resClient.LifecycleQueryCommittedCC(channelName, resmgmt.LifecycleQueryCommittedCCRequest{ Name: name, }) if err != nil { diff --git a/gql/resolvers/resolvers.go b/gql/resolvers/resolvers.go index 4749818..c050aa4 100644 --- a/gql/resolvers/resolvers.go +++ b/gql/resolvers/resolvers.go @@ -6,6 +6,7 @@ import ( "github.com/hyperledger/fabric-gateway/pkg/client" clientmsp "github.com/hyperledger/fabric-sdk-go/pkg/client/msp" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context" + "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk" "github.com/kfsoftware/hlf-cc-dev/gql" @@ -16,6 +17,7 @@ type Resolver struct { GWClient *client.Gateway SDKContext context.ClientProvider SDKContextMap map[string]context.ClientProvider + ConfigBackend core.ConfigProvider Channel string MSPClient *clientmsp.Client CAConfig *msp.CAConfig @@ -32,4 +34,3 @@ func (r *Resolver) Query() gql.QueryResolver { return &queryResolver{r} } type mutationResolver struct{ *Resolver } type queryResolver struct{ *Resolver } - diff --git a/schema/query.graphql b/schema/query.graphql index 6487dd4..3d5d812 100644 --- a/schema/query.graphql +++ b/schema/query.graphql @@ -1,6 +1,6 @@ type Query { - chaincodes: [Chaincode!] - chaincode(name: String!): Chaincode + chaincodes(channel: String): [Chaincode!] + chaincode(channel: String, name: String!): Chaincode } type Chaincode { diff --git a/server/server.go b/server/server.go index 4007f63..f608a48 100644 --- a/server/server.go +++ b/server/server.go @@ -10,6 +10,7 @@ import ( "github.com/hyperledger/fabric-gateway/pkg/client" clientmsp "github.com/hyperledger/fabric-sdk-go/pkg/client/msp" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context" + "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk" "github.com/kfsoftware/hlf-cc-dev/gql" @@ -37,11 +38,12 @@ type BlockchainServerOpts struct { SDKContextMap map[string]context.ClientProvider GWClient *client.Gateway - Channel string - MSPClient *clientmsp.Client - CAConfig *msp.CAConfig - Organization string - User string + Channel string + MSPClient *clientmsp.Client + CAConfig *msp.CAConfig + Organization string + User string + ConfigBackend core.ConfigProvider } type BlockchainAPIServer struct { @@ -82,6 +84,7 @@ func (a *BlockchainAPIServer) setupHttpServer() http.Handler { CAConfig: a.CAConfig, SDKContextMap: a.SDKContextMap, Organization: a.Organization, + ConfigBackend: a.ConfigBackend, User: a.User, GWClient: a.GWClient, },