Skip to content

Commit

Permalink
[FAB-8845] WithTargetURLs option
Browse files Browse the repository at this point in the history
This option adds a WithTargetURLs option. This new options is
similar to WithTargets, but only a URL is required. The peer
object is created from the InfraProvider based on configuration
associated to the URL.

Change-Id: I188c8b8726e8bbc224ea23c1bd6a62333edc9efd
Signed-off-by: Troy Ronda <[email protected]>
  • Loading branch information
troyronda committed Mar 13, 2018
1 parent cc87976 commit 92a48d0
Show file tree
Hide file tree
Showing 11 changed files with 312 additions and 32 deletions.
8 changes: 4 additions & 4 deletions pkg/client/ledger/ledger.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,10 +279,10 @@ func (c *Client) QueryConfig(options ...RequestOption) (fab.ChannelCfg, error) {
}

//prepareRequestOpts Reads Opts from Option array
func (c *Client) prepareRequestOpts(options ...RequestOption) (Opts, error) {
opts := Opts{}
func (c *Client) prepareRequestOpts(options ...RequestOption) (requestOptions, error) {
opts := requestOptions{}
for _, option := range options {
err := option(&opts)
err := option(c.context, &opts)
if err != nil {
return opts, errors.WithMessage(err, "Failed to read request opts")
}
Expand All @@ -306,7 +306,7 @@ func (c *Client) prepareRequestOpts(options ...RequestOption) (Opts, error) {
}

// calculateTargets calculates targets based on targets and filter
func (c *Client) calculateTargets(opts Opts) ([]fab.Peer, error) {
func (c *Client) calculateTargets(opts requestOptions) ([]fab.Peer, error) {

if opts.Targets != nil && opts.TargetFilter != nil {
return nil, errors.New("If targets are provided, filter cannot be provided")
Expand Down
50 changes: 41 additions & 9 deletions pkg/client/ledger/opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ SPDX-License-Identifier: Apache-2.0

package ledger

import "github.com/hyperledger/fabric-sdk-go/pkg/context/api/fab"
import (
"github.com/hyperledger/fabric-sdk-go/pkg/common/context"
"github.com/hyperledger/fabric-sdk-go/pkg/context/api/fab"
"github.com/hyperledger/fabric-sdk-go/pkg/core/config"
"github.com/pkg/errors"
)

const (
minTargets = 1
Expand All @@ -24,17 +29,17 @@ func WithDefaultTargetFilter(filter TargetFilter) ClientOption {
}
}

//RequestOption func for each Opts argument
type RequestOption func(opts *Opts) error
//RequestOption func for each requestOptions argument
type RequestOption func(ctx context.Client, opts *requestOptions) error

// TargetFilter allows for filtering target peers
type TargetFilter interface {
// Accept returns true if peer should be included in the list of target peers
Accept(peer fab.Peer) bool
}

//Opts contains options for operations performed by LedgerClient
type Opts struct {
//requestOptions contains options for operations performed by LedgerClient
type requestOptions struct {
Targets []fab.Peer // target peers
TargetFilter TargetFilter // target filter
MaxTargets int // maximum number of targets to select
Expand All @@ -43,31 +48,58 @@ type Opts struct {

//WithTargets encapsulates fab.Peer targets to ledger RequestOption
func WithTargets(targets ...fab.Peer) RequestOption {
return func(opts *Opts) error {
return func(ctx context.Client, opts *requestOptions) error {
opts.Targets = targets
return nil
}
}

// WithTargetURLs allows overriding of the target peers for the request.
// Targets are specified by URL, and the SDK will create the underlying peer
// objects.
func WithTargetURLs(urls ...string) RequestOption {
return func(ctx context.Client, opts *requestOptions) error {

var targets []fab.Peer

for _, url := range urls {

peerCfg, err := config.NetworkPeerConfigFromURL(ctx.Config(), url)
if err != nil {
return err
}

peer, err := ctx.InfraProvider().CreatePeerFromConfig(peerCfg)
if err != nil {
return errors.WithMessage(err, "creating orderer from config failed")
}

targets = append(targets, peer)
}

return WithTargets(targets...)(ctx, opts)
}
}

//WithTargetFilter encapsulates TargetFilter targets to ledger RequestOption
func WithTargetFilter(targetFilter TargetFilter) RequestOption {
return func(opts *Opts) error {
return func(ctx context.Client, opts *requestOptions) error {
opts.TargetFilter = targetFilter
return nil
}
}

//WithMaxTargets encapsulates max targets to ledger RequestOption
func WithMaxTargets(maxTargets int) RequestOption {
return func(opts *Opts) error {
return func(ctx context.Client, opts *requestOptions) error {
opts.MaxTargets = maxTargets
return nil
}
}

//WithMinTargets encapsulates min targets to ledger RequestOption
func WithMinTargets(minTargets int) RequestOption {
return func(opts *Opts) error {
return func(ctx context.Client, opts *requestOptions) error {
opts.MinTargets = minTargets
return nil
}
Expand Down
76 changes: 76 additions & 0 deletions pkg/client/ledger/opts_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package ledger

import (
"testing"

"github.com/hyperledger/fabric-sdk-go/pkg/context/api/core"
fcmocks "github.com/hyperledger/fabric-sdk-go/pkg/fab/mocks"
"github.com/stretchr/testify/assert"
)

func TestWithTargetURLsInvalid(t *testing.T) {
ctx := setupTestContext("test", "Org1MSP")
opt := WithTargetURLs("invalid")

mockConfig := &fcmocks.MockConfig{}

oConfig := &core.PeerConfig{
URL: "127.0.0.1:7050",
}

mockConfig.SetCustomPeerCfg(oConfig)
ctx.SetConfig(mockConfig)

opts := requestOptions{}
err := opt(ctx, &opts)
assert.NotNil(t, err, "Should have failed for invalid target peer")
}

func TestWithTargetURLsValid(t *testing.T) {
ctx := setupTestContext("test", "Org1MSP")
opt := WithTargetURLs("127.0.0.1:7050")

mockConfig := &fcmocks.MockConfig{}

pConfig1 := core.PeerConfig{
URL: "127.0.0.1:7050",
}

npConfig1 := core.NetworkPeer{
PeerConfig: pConfig1,
MspID: "MYMSP",
}

pConfig2 := core.PeerConfig{
URL: "127.0.0.1:7051",
}

npConfig2 := core.NetworkPeer{
PeerConfig: pConfig2,
MspID: "OTHERMSP",
}

mockConfig.SetCustomPeerCfg(&pConfig1)
mockConfig.SetCustomNetworkPeerCfg([]core.NetworkPeer{npConfig2, npConfig1})
ctx.SetConfig(mockConfig)

opts := requestOptions{}
err := opt(ctx, &opts)
assert.Nil(t, err, "Should have failed for invalid target peer")

assert.Equal(t, 1, len(opts.Targets), "should have one peer")
assert.Equal(t, pConfig1.URL, opts.Targets[0].URL(), "", "Wrong URL")
assert.Equal(t, npConfig1.MspID, opts.Targets[0].MSPID(), "", "Wrong MSP")
}

func setupTestContext(userName string, mspID string) *fcmocks.MockContext {
user := fcmocks.NewMockUserWithMSPID(userName, mspID)
ctx := fcmocks.NewMockContext(user)
return ctx
}
47 changes: 34 additions & 13 deletions pkg/client/resmgmt/opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,48 +11,69 @@ import (

"github.com/hyperledger/fabric-sdk-go/pkg/common/context"
"github.com/hyperledger/fabric-sdk-go/pkg/context/api/fab"
"github.com/hyperledger/fabric-sdk-go/pkg/core/config"
"github.com/pkg/errors"
)

//WithTargets encapsulates fab.Peer targets to resmgmtclient RequestOption
// WithTargetURLs allows overriding of the target peers for the request.
func WithTargets(targets ...fab.Peer) RequestOption {
return func(ctx context.Client, opts *requestOptions) error {
opts.Targets = targets
return nil
}
}

//WithTarget encapsulates fab.Peer target to RequestOption
func WithTarget(target fab.Peer) RequestOption {
// WithTargetURLs allows overriding of the target peers for the request.
// Targets are specified by URL, and the SDK will create the underlying peer
// objects.
func WithTargetURLs(urls ...string) RequestOption {
return func(ctx context.Client, opts *requestOptions) error {
opts.Targets = []fab.Peer{target}
return nil

var targets []fab.Peer

for _, url := range urls {

peerCfg, err := config.NetworkPeerConfigFromURL(ctx.Config(), url)
if err != nil {
return err
}

peer, err := ctx.InfraProvider().CreatePeerFromConfig(peerCfg)
if err != nil {
return errors.WithMessage(err, "creating orderer from config failed")
}

targets = append(targets, peer)
}

return WithTargets(targets...)(ctx, opts)
}
}

//WithTargetFilter encapsulates resmgmtclient TargetFilter targets to resmgmtclient RequestOption
// WithTargetFilter enables a target filter for the request.
func WithTargetFilter(targetFilter TargetFilter) RequestOption {
return func(ctx context.Client, opts *requestOptions) error {
opts.TargetFilter = targetFilter
return nil
}
}

//WithTimeout encapsulates time.Duration to resmgmtclient RequestOption
// WithTimeout specifies the timeout for the request. If not specified,
// a default timeout from configuration is used.
func WithTimeout(timeout time.Duration) RequestOption {
return func(ctx context.Client, opts *requestOptions) error {
opts.Timeout = timeout
return nil
}
}

//WithOrdererURL allows an orderer to be specified for the request.
//The orderer will be looked-up based on the url argument.
//A default orderer implementation will be used.
func WithOrdererURL(ordererID string) RequestOption {
// WithOrdererURL allows an orderer to be specified for the request.
// The orderer will be looked-up based on the url argument.
// A default orderer implementation will be used.
func WithOrdererURL(url string) RequestOption {
return func(ctx context.Client, opts *requestOptions) error {

ordererCfg, err := ctx.Config().OrdererConfig(ordererID)
ordererCfg, err := ctx.Config().OrdererConfig(url)
if err != nil {
return errors.WithMessage(err, "orderer not found")
}
Expand All @@ -69,7 +90,7 @@ func WithOrdererURL(ordererID string) RequestOption {
}
}

//WithOrderer allows an orderer to be specified for the request.
// WithOrderer allows an orderer to be specified for the request.
func WithOrderer(orderer fab.Orderer) RequestOption {
return func(ctx context.Client, opts *requestOptions) error {
opts.Orderer = orderer
Expand Down
70 changes: 70 additions & 0 deletions pkg/client/resmgmt/opts_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package resmgmt

import (
"testing"

"github.com/hyperledger/fabric-sdk-go/pkg/context/api/core"
fcmocks "github.com/hyperledger/fabric-sdk-go/pkg/fab/mocks"
"github.com/stretchr/testify/assert"
)

func TestWithTargetURLsInvalid(t *testing.T) {
ctx := setupTestContext("test", "Org1MSP")
opt := WithTargetURLs("invalid")

mockConfig := &fcmocks.MockConfig{}

oConfig := &core.PeerConfig{
URL: "127.0.0.1:7050",
}

mockConfig.SetCustomPeerCfg(oConfig)
ctx.SetConfig(mockConfig)

opts := requestOptions{}
err := opt(ctx, &opts)
assert.NotNil(t, err, "Should have failed for invalid target peer")
}

func TestWithTargetURLsValid(t *testing.T) {
ctx := setupTestContext("test", "Org1MSP")
opt := WithTargetURLs("127.0.0.1:7050")

mockConfig := &fcmocks.MockConfig{}

pConfig1 := core.PeerConfig{
URL: "127.0.0.1:7050",
}

npConfig1 := core.NetworkPeer{
PeerConfig: pConfig1,
MspID: "MYMSP",
}

pConfig2 := core.PeerConfig{
URL: "127.0.0.1:7051",
}

npConfig2 := core.NetworkPeer{
PeerConfig: pConfig2,
MspID: "OTHERMSP",
}

mockConfig.SetCustomPeerCfg(&pConfig1)
mockConfig.SetCustomNetworkPeerCfg([]core.NetworkPeer{npConfig2, npConfig1})
ctx.SetConfig(mockConfig)

opts := requestOptions{}
err := opt(ctx, &opts)
assert.Nil(t, err, "Should have failed for invalid target peer")

assert.Equal(t, 1, len(opts.Targets), "should have one peer")
assert.Equal(t, pConfig1.URL, opts.Targets[0].URL(), "", "Wrong URL")
assert.Equal(t, npConfig1.MspID, opts.Targets[0].MSPID(), "", "Wrong MSP")
}
4 changes: 2 additions & 2 deletions pkg/client/resmgmt/resmgmt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ func TestInstallCCWithOpts(t *testing.T) {
Status: http.StatusOK, MockRoles: []string{}, MockCert: nil, MockMSP: "Org1MSP", Payload: responseBytes}

req = InstallCCRequest{Name: "error", Version: "v0", Path: "", Package: &api.CCPackage{Type: 1, Code: []byte("code")}}
_, err = rc.InstallCC(req, WithTarget(&peer))
_, err = rc.InstallCC(req, WithTargets(&peer))
if err == nil {
t.Fatalf("Should have failed since install cc returns an error in the client")
}
Expand All @@ -540,7 +540,7 @@ func TestInstallCC(t *testing.T) {

// Chaincode that is not installed already (it will be installed)
req := InstallCCRequest{Name: "ID", Version: "v0", Path: "path", Package: &api.CCPackage{Type: 1, Code: []byte("code")}}
responses, err := rc.InstallCC(req, WithTarget(&peer))
responses, err := rc.InstallCC(req, WithTargets(&peer))
if err != nil {
t.Fatal(err)
}
Expand Down
Loading

0 comments on commit 92a48d0

Please sign in to comment.