Skip to content

Commit 5e2f457

Browse files
authored
Implement metadata api access to the sidecar (#442)
* Add metadata grpc interface Signed-off-by: mikeee <[email protected]> * use errors package Signed-off-by: mikeee <[email protected]> * remove allocations and explicitly populate returns Signed-off-by: mikeee <[email protected]> * remove examples Signed-off-by: mikeee <[email protected]> * lint Signed-off-by: mikeee <[email protected]> --------- Signed-off-by: mikeee <[email protected]>
1 parent 6c9a8c2 commit 5e2f457

File tree

4 files changed

+179
-0
lines changed

4 files changed

+179
-0
lines changed

client/client.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ type Client interface {
7979
// InvokeMethodWithCustomContent invokes app with custom content (struct + content type).
8080
InvokeMethodWithCustomContent(ctx context.Context, appID, methodName, verb string, contentType string, content interface{}) (out []byte, err error)
8181

82+
// GetMetadata returns metadata from the sidecar.
83+
GetMetadata(ctx context.Context) (metadata *GetMetadataResponse, err error)
84+
85+
// SetMetadata sets a key-value pair in the sidecar.
86+
SetMetadata(ctx context.Context, key, value string) error
87+
8288
// PublishEvent publishes data onto topic in specific pubsub component.
8389
PublishEvent(ctx context.Context, pubsubName, topicName string, data interface{}, opts ...PublishEventOption) error
8490

client/client_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,21 @@ func (s *testDaprServer) ExecuteStateTransaction(ctx context.Context, in *pb.Exe
338338
return &empty.Empty{}, nil
339339
}
340340

341+
func (s *testDaprServer) GetMetadata(ctx context.Context, req *empty.Empty) (metadata *pb.GetMetadataResponse, err error) {
342+
resp := &pb.GetMetadataResponse{
343+
Id: uuid.NewString(),
344+
ActiveActorsCount: []*pb.ActiveActorsCount{},
345+
ExtendedMetadata: map[string]string{"test_key": "test_value"},
346+
Subscriptions: []*pb.PubsubSubscription{},
347+
HttpEndpoints: []*pb.MetadataHTTPEndpoint{},
348+
}
349+
return resp, nil
350+
}
351+
352+
func (s *testDaprServer) SetMetadata(ctx context.Context, req *pb.SetMetadataRequest) (*empty.Empty, error) {
353+
return &empty.Empty{}, nil
354+
}
355+
341356
func (s *testDaprServer) PublishEvent(ctx context.Context, req *pb.PublishEventRequest) (*empty.Empty, error) {
342357
return &empty.Empty{}, nil
343358
}

client/metadata.go

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package client
2+
3+
import (
4+
"context"
5+
"errors"
6+
"fmt"
7+
8+
"google.golang.org/protobuf/types/known/emptypb"
9+
10+
pb "github.com/dapr/go-sdk/dapr/proto/runtime/v1"
11+
)
12+
13+
type GetMetadataResponse struct {
14+
ID string
15+
ActiveActorsCount []*MetadataActiveActorsCount
16+
RegisteredComponents []*MetadataRegisteredComponents
17+
ExtendedMetadata map[string]string
18+
Subscriptions []*MetadataSubscription
19+
HTTPEndpoints []*MetadataHTTPEndpoint
20+
}
21+
22+
type MetadataActiveActorsCount struct {
23+
Type string
24+
Count int32
25+
}
26+
27+
type MetadataRegisteredComponents struct {
28+
Name string
29+
Type string
30+
Version string
31+
Capabilities []string
32+
}
33+
34+
type MetadataSubscription struct {
35+
PubsubName string
36+
Topic string
37+
Metadata map[string]string
38+
Rules *PubsubSubscriptionRules
39+
DeadLetterTopic string
40+
}
41+
42+
type PubsubSubscriptionRules struct {
43+
Rules []*PubsubSubscriptionRule
44+
}
45+
46+
type PubsubSubscriptionRule struct {
47+
Match string
48+
Path string
49+
}
50+
51+
type MetadataHTTPEndpoint struct {
52+
Name string
53+
}
54+
55+
// GetMetadata returns the metadata of the sidecar
56+
func (c *GRPCClient) GetMetadata(ctx context.Context) (metadata *GetMetadataResponse, err error) {
57+
resp, err := c.protoClient.GetMetadata(ctx, &emptypb.Empty{})
58+
if err != nil {
59+
return nil, fmt.Errorf("error invoking service: %w", err)
60+
}
61+
if resp != nil {
62+
activeActorsCount := make([]*MetadataActiveActorsCount, len(resp.ActiveActorsCount))
63+
for a := range resp.ActiveActorsCount {
64+
activeActorsCount[a] = &MetadataActiveActorsCount{
65+
Type: resp.ActiveActorsCount[a].Type,
66+
Count: resp.ActiveActorsCount[a].Count,
67+
}
68+
}
69+
registeredComponents := make([]*MetadataRegisteredComponents, len(resp.RegisteredComponents))
70+
for r := range resp.RegisteredComponents {
71+
registeredComponents[r] = &MetadataRegisteredComponents{
72+
Name: resp.RegisteredComponents[r].Name,
73+
Type: resp.RegisteredComponents[r].Type,
74+
Version: resp.RegisteredComponents[r].Version,
75+
Capabilities: resp.RegisteredComponents[r].Capabilities,
76+
}
77+
}
78+
subscriptions := make([]*MetadataSubscription, len(resp.Subscriptions))
79+
for s := range resp.Subscriptions {
80+
rules := &PubsubSubscriptionRules{}
81+
for r := range resp.Subscriptions[s].Rules.Rules {
82+
rules.Rules = append(rules.Rules, &PubsubSubscriptionRule{
83+
Match: resp.Subscriptions[s].Rules.Rules[r].Match,
84+
Path: resp.Subscriptions[s].Rules.Rules[r].Path,
85+
})
86+
}
87+
88+
subscriptions[s] = &MetadataSubscription{
89+
PubsubName: resp.Subscriptions[s].PubsubName,
90+
Topic: resp.Subscriptions[s].Topic,
91+
Metadata: resp.Subscriptions[s].Metadata,
92+
Rules: rules,
93+
DeadLetterTopic: resp.Subscriptions[s].DeadLetterTopic,
94+
}
95+
}
96+
httpEndpoints := make([]*MetadataHTTPEndpoint, len(resp.HttpEndpoints))
97+
for e := range resp.HttpEndpoints {
98+
httpEndpoints[e] = &MetadataHTTPEndpoint{
99+
Name: resp.HttpEndpoints[e].Name,
100+
}
101+
}
102+
metadata = &GetMetadataResponse{
103+
ID: resp.Id,
104+
ActiveActorsCount: activeActorsCount,
105+
RegisteredComponents: registeredComponents,
106+
ExtendedMetadata: resp.GetExtendedMetadata(),
107+
Subscriptions: subscriptions,
108+
HTTPEndpoints: httpEndpoints,
109+
}
110+
}
111+
112+
return metadata, nil
113+
}
114+
115+
// SetMetadata sets a value in the extended metadata of the sidecar
116+
func (c *GRPCClient) SetMetadata(ctx context.Context, key, value string) error {
117+
if len(key) == 0 {
118+
return errors.New("a key is required")
119+
}
120+
req := &pb.SetMetadataRequest{
121+
Key: key,
122+
Value: value,
123+
}
124+
_, err := c.protoClient.SetMetadata(ctx, req)
125+
if err != nil {
126+
return fmt.Errorf("error setting metadata: %w", err)
127+
}
128+
return nil
129+
}

client/metadata_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package client
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
// Test GetMetadata returns
11+
func TestGetMetadata(t *testing.T) {
12+
ctx := context.Background()
13+
t.Run("get meta", func(t *testing.T) {
14+
metadata, err := testClient.GetMetadata(ctx)
15+
assert.NoError(t, err)
16+
assert.NotNil(t, metadata)
17+
})
18+
}
19+
20+
func TestSetMetadata(t *testing.T) {
21+
ctx := context.Background()
22+
t.Run("set meta", func(t *testing.T) {
23+
err := testClient.SetMetadata(ctx, "test_key", "test_value")
24+
assert.NoError(t, err)
25+
metadata, err := testClient.GetMetadata(ctx)
26+
assert.NoError(t, err)
27+
assert.Equal(t, "test_value", metadata.ExtendedMetadata["test_key"])
28+
})
29+
}

0 commit comments

Comments
 (0)