Skip to content

Commit c173bd6

Browse files
benluddydinhxuanvu
authored andcommittedApr 16, 2020
Add ListBundles to the client interface.
1 parent 26e32ab commit c173bd6

File tree

3 files changed

+203
-0
lines changed

3 files changed

+203
-0
lines changed
 

‎pkg/client/client.go

+41
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package client
22

33
import (
44
"context"
5+
"io"
56
"time"
67

78
"google.golang.org/grpc"
@@ -16,6 +17,7 @@ type Interface interface {
1617
GetBundleInPackageChannel(ctx context.Context, packageName, channelName string) (*api.Bundle, error)
1718
GetReplacementBundleInPackageChannel(ctx context.Context, currentName, packageName, channelName string) (*api.Bundle, error)
1819
GetBundleThatProvides(ctx context.Context, group, version, kind string) (*api.Bundle, error)
20+
ListBundles(ctx context.Context) (*BundleIterator, error)
1921
HealthCheck(ctx context.Context, reconnectTimeout time.Duration) (bool, error)
2022
Close() error
2123
}
@@ -28,6 +30,37 @@ type Client struct {
2830

2931
var _ Interface = &Client{}
3032

33+
type BundleStream interface {
34+
Recv() (*api.Bundle, error)
35+
}
36+
37+
type BundleIterator struct {
38+
stream BundleStream
39+
error error
40+
}
41+
42+
func NewBundleIterator(stream BundleStream) *BundleIterator {
43+
return &BundleIterator{stream: stream}
44+
}
45+
46+
func (it *BundleIterator) Next() *api.Bundle {
47+
if it.error != nil {
48+
return nil
49+
}
50+
next, err := it.stream.Recv()
51+
if err == io.EOF {
52+
return nil
53+
}
54+
if err != nil {
55+
it.error = err
56+
}
57+
return next
58+
}
59+
60+
func (it *BundleIterator) Error() error {
61+
return it.error
62+
}
63+
3164
func (c *Client) GetBundle(ctx context.Context, packageName, channelName, csvName string) (*api.Bundle, error) {
3265
return c.Registry.GetBundle(ctx, &api.GetBundleRequest{PkgName: packageName, ChannelName: channelName, CsvName: csvName})
3366
}
@@ -44,6 +77,14 @@ func (c *Client) GetBundleThatProvides(ctx context.Context, group, version, kind
4477
return c.Registry.GetDefaultBundleThatProvides(ctx, &api.GetDefaultProviderRequest{Group: group, Version: version, Kind: kind})
4578
}
4679

80+
func (c *Client) ListBundles(ctx context.Context) (*BundleIterator, error) {
81+
stream, err := c.Registry.ListBundles(ctx, &api.ListBundlesRequest{})
82+
if err != nil {
83+
return nil, err
84+
}
85+
return NewBundleIterator(stream), nil
86+
}
87+
4788
func (c *Client) Close() error {
4889
if c.Conn == nil {
4990
return nil

‎pkg/client/client_test.go

+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package client
2+
3+
import (
4+
"context"
5+
"errors"
6+
"testing"
7+
8+
"github.com/operator-framework/operator-registry/pkg/api"
9+
"github.com/operator-framework/operator-registry/pkg/api/grpc_health_v1"
10+
11+
"github.com/stretchr/testify/require"
12+
"google.golang.org/grpc"
13+
)
14+
15+
type RegistryClientStub struct {
16+
ListBundlesClient api.Registry_ListBundlesClient
17+
error error
18+
}
19+
20+
func (s *RegistryClientStub) ListPackages(ctx context.Context, in *api.ListPackageRequest, opts ...grpc.CallOption) (api.Registry_ListPackagesClient, error) {
21+
return nil, nil
22+
}
23+
24+
func (s *RegistryClientStub) GetPackage(ctx context.Context, in *api.GetPackageRequest, opts ...grpc.CallOption) (*api.Package, error) {
25+
return nil, nil
26+
}
27+
28+
func (s *RegistryClientStub) GetBundle(ctx context.Context, in *api.GetBundleRequest, opts ...grpc.CallOption) (*api.Bundle, error) {
29+
return nil, nil
30+
}
31+
32+
func (s *RegistryClientStub) GetBundleForChannel(ctx context.Context, in *api.GetBundleInChannelRequest, opts ...grpc.CallOption) (*api.Bundle, error) {
33+
return nil, nil
34+
}
35+
36+
func (s *RegistryClientStub) GetChannelEntriesThatReplace(ctx context.Context, in *api.GetAllReplacementsRequest, opts ...grpc.CallOption) (api.Registry_GetChannelEntriesThatReplaceClient, error) {
37+
return nil, nil
38+
}
39+
40+
func (s *RegistryClientStub) GetBundleThatReplaces(ctx context.Context, in *api.GetReplacementRequest, opts ...grpc.CallOption) (*api.Bundle, error) {
41+
return nil, nil
42+
}
43+
44+
func (s *RegistryClientStub) GetChannelEntriesThatProvide(ctx context.Context, in *api.GetAllProvidersRequest, opts ...grpc.CallOption) (api.Registry_GetChannelEntriesThatProvideClient, error) {
45+
return nil, nil
46+
}
47+
48+
func (s *RegistryClientStub) GetLatestChannelEntriesThatProvide(ctx context.Context, in *api.GetLatestProvidersRequest, opts ...grpc.CallOption) (api.Registry_GetLatestChannelEntriesThatProvideClient, error) {
49+
return nil, nil
50+
}
51+
52+
func (s *RegistryClientStub) GetDefaultBundleThatProvides(ctx context.Context, in *api.GetDefaultProviderRequest, opts ...grpc.CallOption) (*api.Bundle, error) {
53+
return nil, nil
54+
}
55+
56+
func (s *RegistryClientStub) ListBundles(ctx context.Context, in *api.ListBundlesRequest, opts ...grpc.CallOption) (api.Registry_ListBundlesClient, error) {
57+
return s.ListBundlesClient, s.error
58+
}
59+
60+
func (s *RegistryClientStub) Check(ctx context.Context, in *grpc_health_v1.HealthCheckRequest, opts ...grpc.CallOption) (*grpc_health_v1.HealthCheckResponse, error) {
61+
return nil, nil
62+
}
63+
64+
type BundleReceiverStub struct {
65+
Bundle *api.Bundle
66+
error error
67+
grpc.ClientStream
68+
}
69+
70+
func (s *BundleReceiverStub) Recv() (*api.Bundle, error) {
71+
return s.Bundle, s.error
72+
}
73+
74+
func TestListBundlesError(t *testing.T) {
75+
expected := errors.New("test error")
76+
stub := &RegistryClientStub{
77+
error: expected,
78+
}
79+
c := Client{
80+
Registry: stub,
81+
Health: stub,
82+
}
83+
84+
_, actual := c.ListBundles(context.TODO())
85+
require.Equal(t, expected, actual)
86+
}
87+
88+
func TestListBundlesRecvError(t *testing.T) {
89+
expected := errors.New("test error")
90+
rstub := &BundleReceiverStub{
91+
error: expected,
92+
}
93+
cstub := &RegistryClientStub{
94+
ListBundlesClient: rstub,
95+
}
96+
c := Client{
97+
Registry: cstub,
98+
Health: cstub,
99+
}
100+
101+
it, err := c.ListBundles(context.TODO())
102+
require.NoError(t, err)
103+
104+
require.Nil(t, it.Next())
105+
require.Equal(t, expected, it.Error())
106+
}
107+
108+
func TestListBundlesNext(t *testing.T) {
109+
expected := &api.Bundle{CsvName: "test"}
110+
rstub := &BundleReceiverStub{
111+
Bundle: expected,
112+
}
113+
cstub := &RegistryClientStub{
114+
ListBundlesClient: rstub,
115+
}
116+
c := Client{
117+
Registry: cstub,
118+
Health: cstub,
119+
}
120+
121+
it, err := c.ListBundles(context.TODO())
122+
require.NoError(t, err)
123+
124+
actual := it.Next()
125+
require.NoError(t, it.Error())
126+
require.Equal(t, expected, actual)
127+
}

‎pkg/server/server_test.go

+35
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,41 @@ func TestGetDefaultBundleThatProvides(t *testing.T) {
517517
EqualBundles(t, *expected, *bundle)
518518
}
519519

520+
func TestListBundles(t *testing.T) {
521+
require := require.New(t)
522+
523+
c, conn := client(t)
524+
defer conn.Close()
525+
526+
stream, err := c.ListBundles(context.TODO(), &api.ListBundlesRequest{})
527+
require.NoError(err)
528+
529+
expected := []string{
530+
"etcdoperator.v0.6.1",
531+
"strimzi-cluster-operator.v0.11.1",
532+
"etcdoperator.v0.9.2",
533+
"etcdoperator.v0.9.0",
534+
"prometheusoperator.0.22.2",
535+
"prometheusoperator.0.15.0",
536+
"prometheusoperator.0.14.0",
537+
"strimzi-cluster-operator.v0.11.0",
538+
"strimzi-cluster-operator.v0.12.1",
539+
"strimzi-cluster-operator.v0.12.2",
540+
}
541+
542+
var names []string
543+
for range expected {
544+
bundle, err := stream.Recv()
545+
require.NoError(err)
546+
names = append(names, bundle.CsvName)
547+
}
548+
549+
_, err = stream.Recv()
550+
require.Equal(io.EOF, err)
551+
552+
require.ElementsMatch(expected, names)
553+
}
554+
520555
func EqualBundles(t *testing.T, expected, actual api.Bundle) {
521556
require.ElementsMatch(t, expected.ProvidedApis, actual.ProvidedApis)
522557
require.ElementsMatch(t, expected.RequiredApis, actual.RequiredApis)

0 commit comments

Comments
 (0)
Please sign in to comment.