Skip to content

Commit

Permalink
add support for etag and bulk secret modifications (dapr#135)
Browse files Browse the repository at this point in the history
  • Loading branch information
yaron2 authored Jan 26, 2021
1 parent ee170a2 commit b972d70
Show file tree
Hide file tree
Showing 17 changed files with 1,485 additions and 731 deletions.
4 changes: 2 additions & 2 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ type Client interface {
GetSecret(ctx context.Context, storeName, key string, meta map[string]string) (data map[string]string, err error)

// GetBulkSecret retrieves all preconfigured secrets for this application.
GetBulkSecret(ctx context.Context, storeName string, meta map[string]string) (data map[string]string, err error)
GetBulkSecret(ctx context.Context, storeName string, meta map[string]string) (data map[string]map[string]string, err error)

// SaveState saves the raw data into store using default state options.
SaveState(ctx context.Context, storeName, key string, data []byte) error
Expand All @@ -79,7 +79,7 @@ type Client interface {
DeleteState(ctx context.Context, storeName, key string) error

// DeleteStateWithETag deletes content from store using provided state options and etag.
DeleteStateWithETag(ctx context.Context, storeName, key, etag string, meta map[string]string, opts *StateOptions) error
DeleteStateWithETag(ctx context.Context, storeName, key string, etag *ETag, meta map[string]string, opts *StateOptions) error

// ExecuteStateTransaction provides way to execute multiple operations on a specified store.
ExecuteStateTransaction(ctx context.Context, storeName string, meta map[string]string, ops []*StateOperation) error
Expand Down
8 changes: 6 additions & 2 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,12 @@ func (s *testDaprServer) GetSecret(ctx context.Context, req *pb.GetSecretRequest
}

func (s *testDaprServer) GetBulkSecret(ctx context.Context, req *pb.GetBulkSecretRequest) (*pb.GetBulkSecretResponse, error) {
d := make(map[string]string)
d["test"] = "value"
d := make(map[string]*pb.SecretResponse)
d["test"] = &pb.SecretResponse{
Secrets: map[string]string{
"test": "value",
},
}
return &pb.GetBulkSecretResponse{
Data: d,
}, nil
Expand Down
12 changes: 10 additions & 2 deletions client/secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func (c *GRPCClient) GetSecret(ctx context.Context, storeName, key string, meta
}

// GetBulkSecret retrieves all preconfigured secrets for this application.
func (c *GRPCClient) GetBulkSecret(ctx context.Context, storeName string, meta map[string]string) (data map[string]string, err error) {
func (c *GRPCClient) GetBulkSecret(ctx context.Context, storeName string, meta map[string]string) (data map[string]map[string]string, err error) {
if storeName == "" {
return nil, errors.New("nil storeName")
}
Expand All @@ -51,7 +51,15 @@ func (c *GRPCClient) GetBulkSecret(ctx context.Context, storeName string, meta m
}

if resp != nil {
data = resp.GetData()
data = map[string]map[string]string{}

for secretName, secretResponse := range resp.Data {
data[secretName] = map[string]string{}

for k, v := range secretResponse.Secrets {
data[secretName][k] = v
}
}
}

return
Expand Down
35 changes: 26 additions & 9 deletions client/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,25 +120,37 @@ type BulkStateItem struct {
type SetStateItem struct {
Key string
Value []byte
Etag string
Etag *ETag
Metadata map[string]string
Options *StateOptions
}

// ETag represents an versioned record information
type ETag struct {
Value string
}

// StateOptions represents the state store persistence policy.
type StateOptions struct {
Concurrency StateConcurrency
Consistency StateConsistency
}

func toProtoSaveStateItem(si *SetStateItem) (item *v1.StateItem) {
return &v1.StateItem{
Etag: si.Etag,
s := &v1.StateItem{
Key: si.Key,
Metadata: si.Metadata,
Value: si.Value,
Options: toProtoStateOptions(si.Options),
}

if si.Etag != nil {
s.Etag = &v1.Etag{
Value: si.Etag.Value,
}
}

return s
}

func toProtoStateOptions(so *StateOptions) (opts *v1.StateOptions) {
Expand Down Expand Up @@ -288,32 +300,37 @@ func (c *GRPCClient) GetStateWithConsistency(ctx context.Context, storeName, key
}

return &StateItem{
Etag: result.Etag,
Key: key,
Value: result.Data,
Etag: result.Etag,
Key: key,
Value: result.Data,
Metadata: result.Metadata,
}, nil
}

// DeleteState deletes content from store using default state options.
func (c *GRPCClient) DeleteState(ctx context.Context, storeName, key string) error {
return c.DeleteStateWithETag(ctx, storeName, key, "", nil, nil)
return c.DeleteStateWithETag(ctx, storeName, key, nil, nil, nil)
}

// DeleteStateWithETag deletes content from store using provided state options and etag.
func (c *GRPCClient) DeleteStateWithETag(ctx context.Context, storeName, key, etag string, meta map[string]string, opts *StateOptions) error {
func (c *GRPCClient) DeleteStateWithETag(ctx context.Context, storeName, key string, etag *ETag, meta map[string]string, opts *StateOptions) error {
if err := hasRequiredStateArgs(storeName, key); err != nil {
return errors.Wrap(err, "missing required arguments")
}

req := &pb.DeleteStateRequest{
StoreName: storeName,
Key: key,
Etag: etag,
Options: toProtoStateOptions(opts),
Metadata: meta,
}

if etag != nil {
req.Etag = &v1.Etag{
Value: etag.Value,
}
}

_, err := c.protoClient.DeleteState(c.withAuthToken(ctx), req)
if err != nil {
return errors.Wrap(err, "error deleting state")
Expand Down
22 changes: 14 additions & 8 deletions client/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ func TestSaveState(t *testing.T) {

t.Run("save data with version", func(t *testing.T) {
item := &SetStateItem{
Etag: "1",
Etag: &ETag{
Value: "1",
},
Key: key,
Value: []byte(data),
}
Expand All @@ -94,7 +96,7 @@ func TestDeleteState(t *testing.T) {
assert.Nil(t, err)
})
t.Run("delete not exist data with etag and meta", func(t *testing.T) {
err := testClient.DeleteStateWithETag(ctx, store, key, "100", map[string]string{"meta1": "value1"},
err := testClient.DeleteStateWithETag(ctx, store, key, &ETag{Value: "100"}, map[string]string{"meta1": "value1"},
&StateOptions{Concurrency: StateConcurrencyFirstWrite, Consistency: StateConsistencyEventual})
assert.Nil(t, err)
})
Expand Down Expand Up @@ -127,9 +129,11 @@ func TestDeleteState(t *testing.T) {

t.Run("save data again with etag, meta", func(t *testing.T) {
err := testClient.SaveBulkState(ctx, store, &SetStateItem{
Key: key,
Value: []byte(data),
Etag: "100",
Key: key,
Value: []byte(data),
Etag: &ETag{
Value: "1",
},
Metadata: map[string]string{"meta1": "value1"},
Options: &StateOptions{Concurrency: StateConcurrencyFirstWrite, Consistency: StateConsistencyEventual},
})
Expand All @@ -145,7 +149,7 @@ func TestDeleteState(t *testing.T) {
})

t.Run("delete exist data with etag and meta", func(t *testing.T) {
err := testClient.DeleteStateWithETag(ctx, store, key, "100", map[string]string{"meta1": "value1"},
err := testClient.DeleteStateWithETag(ctx, store, key, &ETag{Value: "100"}, map[string]string{"meta1": "value1"},
&StateOptions{Concurrency: StateConcurrencyFirstWrite, Consistency: StateConsistencyEventual})
assert.Nil(t, err)
})
Expand Down Expand Up @@ -195,8 +199,10 @@ func TestStateTransactions(t *testing.T) {
op := &StateOperation{
Type: StateOperationTypeUpsert,
Item: &SetStateItem{
Key: item.Key,
Etag: item.Etag,
Key: item.Key,
Etag: &ETag{
Value: item.Etag,
},
Value: item.Value,
},
}
Expand Down
Loading

0 comments on commit b972d70

Please sign in to comment.