Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion agent/grpc-external/services/resource/write.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ func (s *Server) Write(ctx context.Context, req *pbresource.WriteRequest) (*pbre
//
// - CAS failures will be retried by retryCAS anyway. So the read-modify-write
// cycle should eventually succeed.
var mismatchError storage.GroupVersionMismatchError
existing, err := s.Backend.Read(ctx, storage.EventualConsistency, input.Id)
switch {
// Create path.
Expand Down Expand Up @@ -146,7 +147,11 @@ func (s *Server) Write(ctx context.Context, req *pbresource.WriteRequest) (*pbre
// TODO(spatel): Revisit owner<->resource tenancy rules post-1.16

// Update path.
case err == nil:
case err == nil || errors.As(err, &mismatchError):
// Allow writes that update GroupVersion.
if mismatchError.Stored != nil {
existing = mismatchError.Stored
}
// Use the stored ID because it includes the Uid.
//
// Generally, users won't provide the Uid but controllers will, because
Expand Down
31 changes: 31 additions & 0 deletions agent/grpc-external/services/resource/write_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/hashicorp/consul/internal/resource/demo"
"github.com/hashicorp/consul/internal/storage"
"github.com/hashicorp/consul/proto-public/pbresource"
pbdemov1 "github.com/hashicorp/consul/proto/private/pbdemo/v1"
pbdemov2 "github.com/hashicorp/consul/proto/private/pbdemo/v2"
)

Expand Down Expand Up @@ -392,6 +393,36 @@ func TestWrite_Update_NoUid(t *testing.T) {
require.NoError(t, err)
}

func TestWrite_Update_GroupVersion(t *testing.T) {
server := testServer(t)
client := testClient(t, server)

demo.RegisterTypes(server.Registry)

res, err := demo.GenerateV2Artist()
require.NoError(t, err)

rsp1, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: res})
require.NoError(t, err)

res = rsp1.Resource
res.Id.Type = demo.TypeV1Artist

// translate artistV2 to artistV1
var artistV2 pbdemov2.Artist
require.NoError(t, res.Data.UnmarshalTo(&artistV2))
artistV1 := &pbdemov1.Artist{
Name: artistV2.Name,
Description: "some awesome band",
Genre: pbdemov1.Genre_GENRE_JAZZ,
GroupMembers: int32(len(artistV2.GroupMembers)),
}
res.Data.MarshalFrom(artistV1)

_, err = client.Write(testContext(t), &pbresource.WriteRequest{Resource: res})
require.NoError(t, err)
}

func TestWrite_NonCASUpdate_Success(t *testing.T) {
server := testServer(t)
client := testClient(t, server)
Expand Down