Skip to content

Commit

Permalink
Merge pull request #69 from kaleido-io/apiclient
Browse files Browse the repository at this point in the history
Add apiclient command line tools
  • Loading branch information
nguyer authored Mar 10, 2023
2 parents fcfb473 + 14833d1 commit 0b79fa5
Show file tree
Hide file tree
Showing 32 changed files with 1,417 additions and 14 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"go.formatFlags": ["-s"],
"go.lintTool": "golangci-lint",
"cSpell.words": [
"apiclient",
"APIID",
"apitypes",
"badurl",
Expand Down Expand Up @@ -54,6 +55,7 @@
"leveldb",
"loadbalanced",
"logrus",
"metricsmocks",
"mtxs",
"NATS",
"Nowarn",
Expand All @@ -77,7 +79,6 @@
"tekuri",
"tmconfig",
"tmmsgs",
"metricsmocks",
"Tracef",
"txcommon",
"txcommonmocks",
Expand Down
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ lint: ${LINT}
GOGC=20 $(LINT) run -v --timeout 5m

${MOCKERY}:
$(VGO) install github.com/vektra/mockery/cmd/mockery@latest
$(VGO) install github.com/vektra/mockery/v2@latest
${LINT}:
$(VGO) install github.com/golangci/golangci-lint/cmd/[email protected].0
$(VGO) install github.com/golangci/golangci-lint/cmd/[email protected].3


define makemock
Expand All @@ -42,6 +42,7 @@ $(eval $(call makemock, internal/persistence, TransactionPersistence, persiste
$(eval $(call makemock, internal/ws, WebSocketChannels, wsmocks))
$(eval $(call makemock, internal/ws, WebSocketServer, wsmocks))
$(eval $(call makemock, internal/events, Stream, eventsmocks))
$(eval $(call makemock, internal/apiclient, FFTMClient, apiclientmocks))

go-mod-tidy: .ALWAYS
$(VGO) mod tidy
Expand Down
65 changes: 65 additions & 0 deletions cmd/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright © 2023 Kaleido, Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
"context"
"fmt"

"github.com/hyperledger/firefly-common/pkg/config"
"github.com/hyperledger/firefly-common/pkg/httpserver"
"github.com/hyperledger/firefly-transaction-manager/internal/apiclient"
"github.com/hyperledger/firefly-transaction-manager/internal/tmconfig"
"github.com/spf13/cobra"
)

var url string
var nameRegex string
var ignoreNotFound bool

func ClientCommand() *cobra.Command {
return buildClientCommand(createClient)
}

func buildClientCommand(clientFactory func() apiclient.FFTMClient) *cobra.Command {
clientCmd := &cobra.Command{
Use: "client <subcommand>",
Short: "Make API requests to a blockchain connector instance",
}
defaultURL := fmt.Sprintf("http://%s:%s", tmconfig.APIConfig.GetString(httpserver.HTTPConfAddress), tmconfig.APIConfig.GetString(httpserver.HTTPConfPort))

clientCmd.PersistentFlags().BoolVarP(&ignoreNotFound, "ignore-not-found", "", false, "Does not return an error if the resource is not found. Useful for idempotent delete functions.")
clientCmd.PersistentFlags().StringVarP(&url, "url", "", defaultURL, "The URL of the blockchain connector")

clientCmd.AddCommand(clientEventStreamsCommand(clientFactory))
clientCmd.AddCommand(clientListenersCommand(clientFactory))

return clientCmd
}

func createClient() apiclient.FFTMClient {
cfg := config.RootSection("fftm_client")
apiclient.InitConfig(cfg)
if url != "" {
cfg.Set("url", url)
}
return apiclient.NewFFTMClient(context.Background(), cfg)
}

func init() {
tmconfig.Reset()
}
34 changes: 34 additions & 0 deletions cmd/client_eventstreams.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright © 2023 Kaleido, Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
"github.com/hyperledger/firefly-transaction-manager/internal/apiclient"
"github.com/spf13/cobra"
)

var eventStreamID string

func clientEventStreamsCommand(clientFactory func() apiclient.FFTMClient) *cobra.Command {
clientEventStreamsCmd := &cobra.Command{
Use: "eventstreams <subcommand>",
Short: "Make API requests to an blockchain connector instance",
}
clientEventStreamsCmd.AddCommand(clientEventStreamsListCommand(clientFactory))
clientEventStreamsCmd.AddCommand(clientEventStreamsDeleteCommand(clientFactory))
return clientEventStreamsCmd
}
61 changes: 61 additions & 0 deletions cmd/client_eventstreams_delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright © 2023 Kaleido, Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
"context"
"fmt"
"strings"

"github.com/hyperledger/firefly-transaction-manager/internal/apiclient"
"github.com/spf13/cobra"
)

func clientEventStreamsDeleteCommand(clientFactory func() apiclient.FFTMClient) *cobra.Command {
clientEventStreamsDeleteCmd := &cobra.Command{
Use: "delete",
Short: "Delete event streams",
Long: "",
RunE: func(cmd *cobra.Command, args []string) error {
client := clientFactory()
if eventStreamID == "" && nameRegex == "" {
return fmt.Errorf("eventstream or name flag must be set")
}
if eventStreamID != "" && nameRegex != "" {
return fmt.Errorf("eventstream and name flags cannot be combined")
}
if eventStreamID != "" {
err := client.DeleteEventStream(context.Background(), eventStreamID)
if err != nil {
if !(strings.Contains(err.Error(), "FF21046") && ignoreNotFound) {
return err
}
}
}
if nameRegex != "" {
err := client.DeleteEventStreamsByName(context.Background(), nameRegex)
if err != nil {
return err
}
}
return nil
},
}
clientEventStreamsDeleteCmd.Flags().StringVarP(&eventStreamID, "eventstream", "", "", "The ID of the event stream")
clientEventStreamsDeleteCmd.Flags().StringVarP(&nameRegex, "name", "", "", "A regular expression for matching the event stream name")
return clientEventStreamsDeleteCmd
}
83 changes: 83 additions & 0 deletions cmd/client_eventstreams_delete_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright © 2023 Kaleido, Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
"fmt"
"testing"

"github.com/hyperledger/firefly-transaction-manager/internal/apiclient"
"github.com/hyperledger/firefly-transaction-manager/mocks/apiclientmocks"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)

func TestEventStreamsDeleteByID(t *testing.T) {
mc := apiclientmocks.NewFFTMClient(t)
cmd := buildClientCommand(func() apiclient.FFTMClient { return mc })
cmd.SetArgs([]string{"eventstreams", "delete", "--eventstream", "f9506df2-5473-4fd4-9cfb-f835656eaaa7"})
mc.On("DeleteEventStream", mock.Anything, "f9506df2-5473-4fd4-9cfb-f835656eaaa7").Return(nil)
err := cmd.Execute()
assert.NoError(t, err)
mc.AssertExpectations(t)
}

func TestEventStreamsDeleteByName(t *testing.T) {
mc := apiclientmocks.NewFFTMClient(t)
cmd := buildClientCommand(func() apiclient.FFTMClient { return mc })
cmd.SetArgs([]string{"eventstreams", "delete", "--name", "foo"})
mc.On("DeleteEventStreamsByName", mock.Anything, "foo").Return(nil)
err := cmd.Execute()
assert.NoError(t, err)
mc.AssertExpectations(t)
}

func TestEventStreamsDeleteNoID(t *testing.T) {
mc := apiclientmocks.NewFFTMClient(t)
cmd := buildClientCommand(func() apiclient.FFTMClient { return mc })
cmd.SetArgs([]string{"eventstreams", "delete"})
err := cmd.Execute()
assert.Regexp(t, "eventstream or name flag must be set", err)
}

func TestEventStreamsDeleteIDandName(t *testing.T) {
mc := apiclientmocks.NewFFTMClient(t)
cmd := buildClientCommand(func() apiclient.FFTMClient { return mc })
cmd.SetArgs([]string{"eventstreams", "delete", "--eventstream", "f9506df2-5473-4fd4-9cfb-f835656eaaa7", "--name", "foo"})
err := cmd.Execute()
assert.Regexp(t, "eventstream and name flags cannot be combined", err)
}

func TestEventStreamsDeleteByNameError(t *testing.T) {
mc := apiclientmocks.NewFFTMClient(t)
cmd := buildClientCommand(func() apiclient.FFTMClient { return mc })
cmd.SetArgs([]string{"eventstreams", "delete", "--name", "foo"})
mc.On("DeleteEventStreamsByName", mock.Anything, "foo").Return(fmt.Errorf("pop"))
err := cmd.Execute()
assert.Regexp(t, "pop", err)
mc.AssertExpectations(t)
}

func TestEventStreamsDeleteByIDError(t *testing.T) {
mc := apiclientmocks.NewFFTMClient(t)
cmd := buildClientCommand(func() apiclient.FFTMClient { return mc })
cmd.SetArgs([]string{"eventstreams", "delete", "--eventstream", "f9506df2-5473-4fd4-9cfb-f835656eaaa7"})
mc.On("DeleteEventStream", mock.Anything, "f9506df2-5473-4fd4-9cfb-f835656eaaa7").Return(fmt.Errorf("pop"))
err := cmd.Execute()
assert.Regexp(t, "pop", err)
mc.AssertExpectations(t)
}
45 changes: 45 additions & 0 deletions cmd/client_eventstreams_list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright © 2023 Kaleido, Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
"context"
"encoding/json"
"fmt"

"github.com/hyperledger/firefly-transaction-manager/internal/apiclient"
"github.com/spf13/cobra"
)

func clientEventStreamsListCommand(clientFactory func() apiclient.FFTMClient) *cobra.Command {
clientEventStreamsListCmd := &cobra.Command{
Use: "list",
Short: "List event streams",
Long: "",
RunE: func(cmd *cobra.Command, args []string) error {
client := clientFactory()
eventStreams, err := client.GetEventStreams(context.Background())
if err != nil {
return err
}
json, _ := json.MarshalIndent(eventStreams, "", " ")
fmt.Println(string(json))
return nil
},
}
return clientEventStreamsListCmd
}
48 changes: 48 additions & 0 deletions cmd/client_eventstreams_list_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright © 2023 Kaleido, Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
"fmt"
"testing"

"github.com/hyperledger/firefly-transaction-manager/internal/apiclient"
"github.com/hyperledger/firefly-transaction-manager/mocks/apiclientmocks"
"github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)

func TestEventStreamsList(t *testing.T) {
mc := apiclientmocks.NewFFTMClient(t)
cmd := buildClientCommand(func() apiclient.FFTMClient { return mc })
cmd.SetArgs([]string{"eventstreams", "list"})
mc.On("GetEventStreams", mock.Anything).Return([]apitypes.EventStream{}, nil)
err := cmd.Execute()
assert.NoError(t, err)
mc.AssertExpectations(t)
}

func TestEventStreamsListError(t *testing.T) {
mc := apiclientmocks.NewFFTMClient(t)
cmd := buildClientCommand(func() apiclient.FFTMClient { return mc })
cmd.SetArgs([]string{"eventstreams", "list"})
mc.On("GetEventStreams", mock.Anything).Return(nil, fmt.Errorf("pop"))
err := cmd.Execute()
assert.Regexp(t, "pop", err)
mc.AssertExpectations(t)
}
Loading

0 comments on commit 0b79fa5

Please sign in to comment.