diff --git a/internal/gen/testing/attribute/attribute.pb.go b/internal/gen/testing/attribute/attribute.pb.go index e63f01a09f..21562e13c3 100644 --- a/internal/gen/testing/attribute/attribute.pb.go +++ b/internal/gen/testing/attribute/attribute.pb.go @@ -7,9 +7,12 @@ package attribute import ( + _ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options" _ "github.com/hashicorp/boundary/sdk/pbs/controller/protooptions" + _ "google.golang.org/genproto/googleapis/api/annotations" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + fieldmaskpb "google.golang.org/protobuf/types/known/fieldmaskpb" structpb "google.golang.org/protobuf/types/known/structpb" reflect "reflect" sync "sync" @@ -27,7 +30,9 @@ type TestResource struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` + OtherId string `protobuf:"bytes,3,opt,name=other_id,json=otherId,proto3" json:"other_id,omitempty"` // Types that are assignable to Attrs: // *TestResource_Attributes // *TestResource_SubResourceAttributes @@ -73,6 +78,20 @@ func (x *TestResource) GetId() string { return "" } +func (x *TestResource) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *TestResource) GetOtherId() string { + if x != nil { + return x.OtherId + } + return "" +} + func (m *TestResource) GetAttrs() isTestResource_Attrs { if m != nil { return m.Attrs @@ -162,7 +181,8 @@ type TestNoAttributes struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` } func (x *TestNoAttributes) Reset() { @@ -204,120 +224,1654 @@ func (x *TestNoAttributes) GetId() string { return "" } -var File_testing_attribute_v1_attribute_proto protoreflect.FileDescriptor +func (x *TestNoAttributes) GetType() string { + if x != nil { + return x.Type + } + return "" +} -var file_testing_attribute_v1_attribute_proto_rawDesc = []byte{ - 0x0a, 0x24, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x14, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x1c, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, - 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xec, 0x01, 0x0a, 0x0c, 0x54, 0x65, 0x73, 0x74, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x46, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, - 0x72, 0x75, 0x63, 0x74, 0x42, 0x0b, 0x9a, 0xe3, 0x29, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x48, 0x00, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, - 0x7b, 0x0a, 0x17, 0x73, 0x75, 0x62, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x2f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x62, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x42, 0x10, 0x9a, 0xe3, 0x29, 0x0c, 0x73, 0x75, 0x62, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x48, 0x00, 0x52, 0x15, 0x73, 0x75, 0x62, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x42, 0x07, 0x0a, 0x05, - 0x61, 0x74, 0x74, 0x72, 0x73, 0x22, 0x2f, 0x0a, 0x19, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x62, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x22, 0x0a, 0x10, 0x54, 0x65, 0x73, 0x74, 0x4e, 0x6f, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x42, 0x48, 0x5a, 0x46, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, - 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x3b, 0x61, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +type TestNoOneOf struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` + Attributes *structpb.Struct `protobuf:"bytes,10,opt,name=attributes,proto3" json:"attributes,omitempty"` } -var ( - file_testing_attribute_v1_attribute_proto_rawDescOnce sync.Once - file_testing_attribute_v1_attribute_proto_rawDescData = file_testing_attribute_v1_attribute_proto_rawDesc -) +func (x *TestNoOneOf) Reset() { + *x = TestNoOneOf{} + if protoimpl.UnsafeEnabled { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} -func file_testing_attribute_v1_attribute_proto_rawDescGZIP() []byte { - file_testing_attribute_v1_attribute_proto_rawDescOnce.Do(func() { - file_testing_attribute_v1_attribute_proto_rawDescData = protoimpl.X.CompressGZIP(file_testing_attribute_v1_attribute_proto_rawDescData) - }) - return file_testing_attribute_v1_attribute_proto_rawDescData +func (x *TestNoOneOf) String() string { + return protoimpl.X.MessageStringOf(x) } -var file_testing_attribute_v1_attribute_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_testing_attribute_v1_attribute_proto_goTypes = []interface{}{ - (*TestResource)(nil), // 0: testing.attribute.v1.TestResource - (*TestSubResourceAttributes)(nil), // 1: testing.attribute.v1.TestSubResourceAttributes - (*TestNoAttributes)(nil), // 2: testing.attribute.v1.TestNoAttributes - (*structpb.Struct)(nil), // 3: google.protobuf.Struct +func (*TestNoOneOf) ProtoMessage() {} + +func (x *TestNoOneOf) ProtoReflect() protoreflect.Message { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var file_testing_attribute_v1_attribute_proto_depIdxs = []int32{ - 3, // 0: testing.attribute.v1.TestResource.attributes:type_name -> google.protobuf.Struct - 1, // 1: testing.attribute.v1.TestResource.sub_resource_attributes:type_name -> testing.attribute.v1.TestSubResourceAttributes - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name + +// Deprecated: Use TestNoOneOf.ProtoReflect.Descriptor instead. +func (*TestNoOneOf) Descriptor() ([]byte, []int) { + return file_testing_attribute_v1_attribute_proto_rawDescGZIP(), []int{3} } -func init() { file_testing_attribute_v1_attribute_proto_init() } -func file_testing_attribute_v1_attribute_proto_init() { - if File_testing_attribute_v1_attribute_proto != nil { - return +func (x *TestNoOneOf) GetId() string { + if x != nil { + return x.Id } - if !protoimpl.UnsafeEnabled { - file_testing_attribute_v1_attribute_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TestResource); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } + return "" +} + +func (x *TestNoOneOf) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *TestNoOneOf) GetAttributes() *structpb.Struct { + if x != nil { + return x.Attributes + } + return nil +} + +type TestListResourceRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *TestListResourceRequest) Reset() { + *x = TestListResourceRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestListResourceRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestListResourceRequest) ProtoMessage() {} + +func (x *TestListResourceRequest) ProtoReflect() protoreflect.Message { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) } - file_testing_attribute_v1_attribute_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TestSubResourceAttributes); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestListResourceRequest.ProtoReflect.Descriptor instead. +func (*TestListResourceRequest) Descriptor() ([]byte, []int) { + return file_testing_attribute_v1_attribute_proto_rawDescGZIP(), []int{4} +} + +type TestListResourceResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Items []*TestResource `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` +} + +func (x *TestListResourceResponse) Reset() { + *x = TestListResourceResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestListResourceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestListResourceResponse) ProtoMessage() {} + +func (x *TestListResourceResponse) ProtoReflect() protoreflect.Message { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) } - file_testing_attribute_v1_attribute_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TestNoAttributes); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestListResourceResponse.ProtoReflect.Descriptor instead. +func (*TestListResourceResponse) Descriptor() ([]byte, []int) { + return file_testing_attribute_v1_attribute_proto_rawDescGZIP(), []int{5} +} + +func (x *TestListResourceResponse) GetItems() []*TestResource { + if x != nil { + return x.Items + } + return nil +} + +type TestGetResourceRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *TestGetResourceRequest) Reset() { + *x = TestGetResourceRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestGetResourceRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestGetResourceRequest) ProtoMessage() {} + +func (x *TestGetResourceRequest) ProtoReflect() protoreflect.Message { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) } + return ms } - file_testing_attribute_v1_attribute_proto_msgTypes[0].OneofWrappers = []interface{}{ - (*TestResource_Attributes)(nil), - (*TestResource_SubResourceAttributes)(nil), + return mi.MessageOf(x) +} + +// Deprecated: Use TestGetResourceRequest.ProtoReflect.Descriptor instead. +func (*TestGetResourceRequest) Descriptor() ([]byte, []int) { + return file_testing_attribute_v1_attribute_proto_rawDescGZIP(), []int{6} +} + +func (x *TestGetResourceRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +type TestGetResourceResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Item *TestResource `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` +} + +func (x *TestGetResourceResponse) Reset() { + *x = TestGetResourceResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestGetResourceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestGetResourceResponse) ProtoMessage() {} + +func (x *TestGetResourceResponse) ProtoReflect() protoreflect.Message { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestGetResourceResponse.ProtoReflect.Descriptor instead. +func (*TestGetResourceResponse) Descriptor() ([]byte, []int) { + return file_testing_attribute_v1_attribute_proto_rawDescGZIP(), []int{7} +} + +func (x *TestGetResourceResponse) GetItem() *TestResource { + if x != nil { + return x.Item + } + return nil +} + +type TestCreateResourceRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Item *TestResource `protobuf:"bytes,2,opt,name=item,proto3" json:"item,omitempty"` +} + +func (x *TestCreateResourceRequest) Reset() { + *x = TestCreateResourceRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestCreateResourceRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestCreateResourceRequest) ProtoMessage() {} + +func (x *TestCreateResourceRequest) ProtoReflect() protoreflect.Message { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestCreateResourceRequest.ProtoReflect.Descriptor instead. +func (*TestCreateResourceRequest) Descriptor() ([]byte, []int) { + return file_testing_attribute_v1_attribute_proto_rawDescGZIP(), []int{8} +} + +func (x *TestCreateResourceRequest) GetItem() *TestResource { + if x != nil { + return x.Item + } + return nil +} + +type TestCreateResourceResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Item *TestResource `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` +} + +func (x *TestCreateResourceResponse) Reset() { + *x = TestCreateResourceResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestCreateResourceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestCreateResourceResponse) ProtoMessage() {} + +func (x *TestCreateResourceResponse) ProtoReflect() protoreflect.Message { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestCreateResourceResponse.ProtoReflect.Descriptor instead. +func (*TestCreateResourceResponse) Descriptor() ([]byte, []int) { + return file_testing_attribute_v1_attribute_proto_rawDescGZIP(), []int{9} +} + +func (x *TestCreateResourceResponse) GetItem() *TestResource { + if x != nil { + return x.Item + } + return nil +} + +type TestUpdateResourceRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Item *TestResource `protobuf:"bytes,2,opt,name=item,proto3" json:"item,omitempty"` + UpdateMask *fieldmaskpb.FieldMask `protobuf:"bytes,3,opt,name=update_mask,proto3" json:"update_mask,omitempty"` +} + +func (x *TestUpdateResourceRequest) Reset() { + *x = TestUpdateResourceRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestUpdateResourceRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestUpdateResourceRequest) ProtoMessage() {} + +func (x *TestUpdateResourceRequest) ProtoReflect() protoreflect.Message { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestUpdateResourceRequest.ProtoReflect.Descriptor instead. +func (*TestUpdateResourceRequest) Descriptor() ([]byte, []int) { + return file_testing_attribute_v1_attribute_proto_rawDescGZIP(), []int{10} +} + +func (x *TestUpdateResourceRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *TestUpdateResourceRequest) GetItem() *TestResource { + if x != nil { + return x.Item + } + return nil +} + +func (x *TestUpdateResourceRequest) GetUpdateMask() *fieldmaskpb.FieldMask { + if x != nil { + return x.UpdateMask + } + return nil +} + +type TestUpdateResourceResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Item *TestResource `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` +} + +func (x *TestUpdateResourceResponse) Reset() { + *x = TestUpdateResourceResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestUpdateResourceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestUpdateResourceResponse) ProtoMessage() {} + +func (x *TestUpdateResourceResponse) ProtoReflect() protoreflect.Message { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestUpdateResourceResponse.ProtoReflect.Descriptor instead. +func (*TestUpdateResourceResponse) Descriptor() ([]byte, []int) { + return file_testing_attribute_v1_attribute_proto_rawDescGZIP(), []int{11} +} + +func (x *TestUpdateResourceResponse) GetItem() *TestResource { + if x != nil { + return x.Item + } + return nil +} + +type TestRequestNoItem struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *TestRequestNoItem) Reset() { + *x = TestRequestNoItem{} + if protoimpl.UnsafeEnabled { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestRequestNoItem) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestRequestNoItem) ProtoMessage() {} + +func (x *TestRequestNoItem) ProtoReflect() protoreflect.Message { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestRequestNoItem.ProtoReflect.Descriptor instead. +func (*TestRequestNoItem) Descriptor() ([]byte, []int) { + return file_testing_attribute_v1_attribute_proto_rawDescGZIP(), []int{12} +} + +func (x *TestRequestNoItem) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type TestRequestItemNotMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Item string `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` +} + +func (x *TestRequestItemNotMessage) Reset() { + *x = TestRequestItemNotMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestRequestItemNotMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestRequestItemNotMessage) ProtoMessage() {} + +func (x *TestRequestItemNotMessage) ProtoReflect() protoreflect.Message { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestRequestItemNotMessage.ProtoReflect.Descriptor instead. +func (*TestRequestItemNotMessage) Descriptor() ([]byte, []int) { + return file_testing_attribute_v1_attribute_proto_rawDescGZIP(), []int{13} +} + +func (x *TestRequestItemNotMessage) GetItem() string { + if x != nil { + return x.Item + } + return "" +} + +type TestItemNoType struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *TestItemNoType) Reset() { + *x = TestItemNoType{} + if protoimpl.UnsafeEnabled { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestItemNoType) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestItemNoType) ProtoMessage() {} + +func (x *TestItemNoType) ProtoReflect() protoreflect.Message { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestItemNoType.ProtoReflect.Descriptor instead. +func (*TestItemNoType) Descriptor() ([]byte, []int) { + return file_testing_attribute_v1_attribute_proto_rawDescGZIP(), []int{14} +} + +func (x *TestItemNoType) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +type TestRequestItemNoType struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Item *TestItemNoType `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` +} + +func (x *TestRequestItemNoType) Reset() { + *x = TestRequestItemNoType{} + if protoimpl.UnsafeEnabled { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestRequestItemNoType) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestRequestItemNoType) ProtoMessage() {} + +func (x *TestRequestItemNoType) ProtoReflect() protoreflect.Message { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestRequestItemNoType.ProtoReflect.Descriptor instead. +func (*TestRequestItemNoType) Descriptor() ([]byte, []int) { + return file_testing_attribute_v1_attribute_proto_rawDescGZIP(), []int{15} +} + +func (x *TestRequestItemNoType) GetItem() *TestItemNoType { + if x != nil { + return x.Item + } + return nil +} + +type TestNoItemAttributes struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Types that are assignable to Attrs: + // *TestNoItemAttributes_Attributes + // *TestNoItemAttributes_SubResourceAttributes + Attrs isTestNoItemAttributes_Attrs `protobuf_oneof:"attrs"` +} + +func (x *TestNoItemAttributes) Reset() { + *x = TestNoItemAttributes{} + if protoimpl.UnsafeEnabled { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestNoItemAttributes) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestNoItemAttributes) ProtoMessage() {} + +func (x *TestNoItemAttributes) ProtoReflect() protoreflect.Message { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestNoItemAttributes.ProtoReflect.Descriptor instead. +func (*TestNoItemAttributes) Descriptor() ([]byte, []int) { + return file_testing_attribute_v1_attribute_proto_rawDescGZIP(), []int{16} +} + +func (x *TestNoItemAttributes) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (m *TestNoItemAttributes) GetAttrs() isTestNoItemAttributes_Attrs { + if m != nil { + return m.Attrs + } + return nil +} + +func (x *TestNoItemAttributes) GetAttributes() *structpb.Struct { + if x, ok := x.GetAttrs().(*TestNoItemAttributes_Attributes); ok { + return x.Attributes + } + return nil +} + +func (x *TestNoItemAttributes) GetSubResourceAttributes() *TestSubResourceAttributes { + if x, ok := x.GetAttrs().(*TestNoItemAttributes_SubResourceAttributes); ok { + return x.SubResourceAttributes + } + return nil +} + +type isTestNoItemAttributes_Attrs interface { + isTestNoItemAttributes_Attrs() +} + +type TestNoItemAttributes_Attributes struct { + Attributes *structpb.Struct `protobuf:"bytes,10,opt,name=attributes,proto3,oneof"` +} + +type TestNoItemAttributes_SubResourceAttributes struct { + SubResourceAttributes *TestSubResourceAttributes `protobuf:"bytes,20,opt,name=sub_resource_attributes,json=subResourceAttributes,proto3,oneof"` +} + +func (*TestNoItemAttributes_Attributes) isTestNoItemAttributes_Attrs() {} + +func (*TestNoItemAttributes_SubResourceAttributes) isTestNoItemAttributes_Attrs() {} + +type TestCreateNoOneOfRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Item *TestNoOneOf `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` +} + +func (x *TestCreateNoOneOfRequest) Reset() { + *x = TestCreateNoOneOfRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestCreateNoOneOfRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestCreateNoOneOfRequest) ProtoMessage() {} + +func (x *TestCreateNoOneOfRequest) ProtoReflect() protoreflect.Message { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestCreateNoOneOfRequest.ProtoReflect.Descriptor instead. +func (*TestCreateNoOneOfRequest) Descriptor() ([]byte, []int) { + return file_testing_attribute_v1_attribute_proto_rawDescGZIP(), []int{17} +} + +func (x *TestCreateNoOneOfRequest) GetItem() *TestNoOneOf { + if x != nil { + return x.Item + } + return nil +} + +type TestUpdateNoOneOfRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Item *TestNoOneOf `protobuf:"bytes,2,opt,name=item,proto3" json:"item,omitempty"` +} + +func (x *TestUpdateNoOneOfRequest) Reset() { + *x = TestUpdateNoOneOfRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestUpdateNoOneOfRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestUpdateNoOneOfRequest) ProtoMessage() {} + +func (x *TestUpdateNoOneOfRequest) ProtoReflect() protoreflect.Message { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestUpdateNoOneOfRequest.ProtoReflect.Descriptor instead. +func (*TestUpdateNoOneOfRequest) Descriptor() ([]byte, []int) { + return file_testing_attribute_v1_attribute_proto_rawDescGZIP(), []int{18} +} + +func (x *TestUpdateNoOneOfRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *TestUpdateNoOneOfRequest) GetItem() *TestNoOneOf { + if x != nil { + return x.Item + } + return nil +} + +type TestResponseNoItem struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *TestResponseNoItem) Reset() { + *x = TestResponseNoItem{} + if protoimpl.UnsafeEnabled { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestResponseNoItem) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestResponseNoItem) ProtoMessage() {} + +func (x *TestResponseNoItem) ProtoReflect() protoreflect.Message { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[19] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestResponseNoItem.ProtoReflect.Descriptor instead. +func (*TestResponseNoItem) Descriptor() ([]byte, []int) { + return file_testing_attribute_v1_attribute_proto_rawDescGZIP(), []int{19} +} + +func (x *TestResponseNoItem) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type TestResponseItemNotMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Item string `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` +} + +func (x *TestResponseItemNotMessage) Reset() { + *x = TestResponseItemNotMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestResponseItemNotMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestResponseItemNotMessage) ProtoMessage() {} + +func (x *TestResponseItemNotMessage) ProtoReflect() protoreflect.Message { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[20] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestResponseItemNotMessage.ProtoReflect.Descriptor instead. +func (*TestResponseItemNotMessage) Descriptor() ([]byte, []int) { + return file_testing_attribute_v1_attribute_proto_rawDescGZIP(), []int{20} +} + +func (x *TestResponseItemNotMessage) GetItem() string { + if x != nil { + return x.Item + } + return "" +} + +type TestResponseItemNoType struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Item *TestItemNoType `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` +} + +func (x *TestResponseItemNoType) Reset() { + *x = TestResponseItemNoType{} + if protoimpl.UnsafeEnabled { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestResponseItemNoType) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestResponseItemNoType) ProtoMessage() {} + +func (x *TestResponseItemNoType) ProtoReflect() protoreflect.Message { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[21] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestResponseItemNoType.ProtoReflect.Descriptor instead. +func (*TestResponseItemNoType) Descriptor() ([]byte, []int) { + return file_testing_attribute_v1_attribute_proto_rawDescGZIP(), []int{21} +} + +func (x *TestResponseItemNoType) GetItem() *TestItemNoType { + if x != nil { + return x.Item + } + return nil +} + +type TestCreateNoOneOfResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Item *TestNoOneOf `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` +} + +func (x *TestCreateNoOneOfResponse) Reset() { + *x = TestCreateNoOneOfResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestCreateNoOneOfResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestCreateNoOneOfResponse) ProtoMessage() {} + +func (x *TestCreateNoOneOfResponse) ProtoReflect() protoreflect.Message { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[22] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestCreateNoOneOfResponse.ProtoReflect.Descriptor instead. +func (*TestCreateNoOneOfResponse) Descriptor() ([]byte, []int) { + return file_testing_attribute_v1_attribute_proto_rawDescGZIP(), []int{22} +} + +func (x *TestCreateNoOneOfResponse) GetItem() *TestNoOneOf { + if x != nil { + return x.Item + } + return nil +} + +type TestUpdateNoOneOfResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Item *TestNoOneOf `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` +} + +func (x *TestUpdateNoOneOfResponse) Reset() { + *x = TestUpdateNoOneOfResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestUpdateNoOneOfResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestUpdateNoOneOfResponse) ProtoMessage() {} + +func (x *TestUpdateNoOneOfResponse) ProtoReflect() protoreflect.Message { + mi := &file_testing_attribute_v1_attribute_proto_msgTypes[23] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestUpdateNoOneOfResponse.ProtoReflect.Descriptor instead. +func (*TestUpdateNoOneOfResponse) Descriptor() ([]byte, []int) { + return file_testing_attribute_v1_attribute_proto_rawDescGZIP(), []int{23} +} + +func (x *TestUpdateNoOneOfResponse) GetItem() *TestNoOneOf { + if x != nil { + return x.Item + } + return nil +} + +var File_testing_attribute_v1_attribute_proto protoreflect.FileDescriptor + +var file_testing_attribute_v1_attribute_proto_rawDesc = []byte{ + 0x0a, 0x24, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x14, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, + 0x76, 0x32, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, + 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, + 0x6d, 0x61, 0x73, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa1, 0x02, 0x0a, 0x0c, 0x54, 0x65, 0x73, 0x74, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x08, 0x6f, + 0x74, 0x68, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x04, 0xa0, + 0xe3, 0x29, 0x01, 0x52, 0x07, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x49, 0x64, 0x12, 0x46, 0x0a, 0x0a, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x42, 0x0b, 0x9a, 0xe3, 0x29, 0x07, 0x64, + 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x48, 0x00, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x12, 0x7b, 0x0a, 0x17, 0x73, 0x75, 0x62, 0x5f, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, + 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x73, + 0x74, 0x53, 0x75, 0x62, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x42, 0x10, 0x9a, 0xe3, 0x29, 0x0c, 0x73, 0x75, 0x62, 0x5f, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x00, 0x52, 0x15, 0x73, 0x75, 0x62, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x73, 0x42, 0x07, 0x0a, 0x05, 0x61, 0x74, 0x74, 0x72, 0x73, 0x22, 0x2f, 0x0a, 0x19, 0x54, 0x65, + 0x73, 0x74, 0x53, 0x75, 0x62, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x36, 0x0a, 0x10, 0x54, + 0x65, 0x73, 0x74, 0x4e, 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x22, 0x6a, 0x0a, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x4e, 0x6f, 0x4f, 0x6e, 0x65, + 0x4f, 0x66, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, + 0x75, 0x63, 0x74, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, + 0x19, 0x0a, 0x17, 0x54, 0x65, 0x73, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x54, 0x0a, 0x18, 0x54, 0x65, + 0x73, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x73, + 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, + 0x22, 0x28, 0x0a, 0x16, 0x54, 0x65, 0x73, 0x74, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x51, 0x0a, 0x17, 0x54, 0x65, + 0x73, 0x74, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x53, 0x0a, + 0x19, 0x54, 0x65, 0x73, 0x74, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x04, 0x69, 0x74, + 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, + 0x6e, 0x67, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x04, 0x69, 0x74, + 0x65, 0x6d, 0x22, 0x54, 0x0a, 0x1a, 0x54, 0x65, 0x73, 0x74, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x36, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, + 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0xa1, 0x01, 0x0a, 0x19, 0x54, 0x65, 0x73, + 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x36, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x73, 0x74, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0x3c, + 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, + 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x22, 0x54, 0x0a, 0x1a, + 0x54, 0x65, 0x73, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x69, 0x74, + 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, + 0x6e, 0x67, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x04, 0x69, 0x74, + 0x65, 0x6d, 0x22, 0x27, 0x0a, 0x11, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x4e, 0x6f, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x2f, 0x0a, 0x19, 0x54, + 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x4e, 0x6f, + 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x20, 0x0a, 0x0e, + 0x54, 0x65, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x4e, 0x6f, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x51, + 0x0a, 0x15, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x74, 0x65, + 0x6d, 0x4e, 0x6f, 0x54, 0x79, 0x70, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x73, + 0x74, 0x49, 0x74, 0x65, 0x6d, 0x4e, 0x6f, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x69, 0x74, 0x65, + 0x6d, 0x22, 0xf4, 0x01, 0x0a, 0x14, 0x54, 0x65, 0x73, 0x74, 0x4e, 0x6f, 0x49, 0x74, 0x65, 0x6d, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x46, 0x0a, 0x0a, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x42, 0x0b, 0x9a, 0xe3, 0x29, 0x07, 0x64, 0x65, 0x66, + 0x61, 0x75, 0x6c, 0x74, 0x48, 0x00, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x12, 0x7b, 0x0a, 0x17, 0x73, 0x75, 0x62, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x14, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, + 0x75, 0x62, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x42, 0x10, 0x9a, 0xe3, 0x29, 0x0c, 0x73, 0x75, 0x62, 0x5f, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x00, 0x52, 0x15, 0x73, 0x75, 0x62, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x42, + 0x07, 0x0a, 0x05, 0x61, 0x74, 0x74, 0x72, 0x73, 0x22, 0x51, 0x0a, 0x18, 0x54, 0x65, 0x73, 0x74, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x4f, 0x6e, 0x65, 0x4f, 0x66, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x4e, 0x6f, + 0x4f, 0x6e, 0x65, 0x4f, 0x66, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x61, 0x0a, 0x18, 0x54, + 0x65, 0x73, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x4f, 0x6e, 0x65, 0x4f, 0x66, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x35, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x73, + 0x74, 0x4e, 0x6f, 0x4f, 0x6e, 0x65, 0x4f, 0x66, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x28, + 0x0a, 0x12, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4e, 0x6f, + 0x49, 0x74, 0x65, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x30, 0x0a, 0x1a, 0x54, 0x65, 0x73, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x4e, 0x6f, 0x74, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x52, 0x0a, 0x16, 0x54, 0x65, + 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x4e, 0x6f, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x49, 0x74, + 0x65, 0x6d, 0x4e, 0x6f, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x52, + 0x0a, 0x19, 0x54, 0x65, 0x73, 0x74, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x4f, 0x6e, + 0x65, 0x4f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x04, 0x69, + 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74, 0x65, 0x73, 0x74, + 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x54, 0x65, 0x73, 0x74, 0x4e, 0x6f, 0x4f, 0x6e, 0x65, 0x4f, 0x66, 0x52, 0x04, 0x69, 0x74, + 0x65, 0x6d, 0x22, 0x52, 0x0a, 0x19, 0x54, 0x65, 0x73, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x4e, 0x6f, 0x4f, 0x6e, 0x65, 0x4f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x35, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, + 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x4e, 0x6f, 0x4f, 0x6e, 0x65, 0x4f, 0x66, + 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x32, 0xc1, 0x05, 0x0a, 0x13, 0x54, 0x65, 0x73, 0x74, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x9b, + 0x01, 0x0a, 0x10, 0x54, 0x65, 0x73, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x12, 0x2d, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, 0x2f, + 0x74, 0x65, 0x73, 0x74, 0x2d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x92, 0x41, + 0x0b, 0x12, 0x09, 0x54, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x12, 0xaf, 0x01, 0x0a, + 0x12, 0x54, 0x65, 0x73, 0x74, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x12, 0x2f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x73, 0x74, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22, 0x12, + 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x73, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, + 0x0d, 0x12, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0xb4, + 0x01, 0x0a, 0x12, 0x54, 0x65, 0x73, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x73, + 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, + 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, + 0x73, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, + 0x32, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2d, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, + 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x0d, 0x12, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x20, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0xa2, 0x01, 0x0a, 0x0f, 0x54, 0x65, 0x73, 0x74, 0x47, 0x65, + 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2c, 0x2e, 0x74, 0x65, 0x73, 0x74, + 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x54, 0x65, 0x73, 0x74, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, + 0x67, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, + 0x65, 0x73, 0x74, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x32, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, 0x17, + 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x0a, + 0x12, 0x08, 0x54, 0x65, 0x73, 0x74, 0x20, 0x67, 0x65, 0x74, 0x42, 0x50, 0x5a, 0x46, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, + 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x3b, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0xa2, 0xe3, 0x29, 0x04, 0x74, 0x65, 0x73, 0x74, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_testing_attribute_v1_attribute_proto_rawDescOnce sync.Once + file_testing_attribute_v1_attribute_proto_rawDescData = file_testing_attribute_v1_attribute_proto_rawDesc +) + +func file_testing_attribute_v1_attribute_proto_rawDescGZIP() []byte { + file_testing_attribute_v1_attribute_proto_rawDescOnce.Do(func() { + file_testing_attribute_v1_attribute_proto_rawDescData = protoimpl.X.CompressGZIP(file_testing_attribute_v1_attribute_proto_rawDescData) + }) + return file_testing_attribute_v1_attribute_proto_rawDescData +} + +var file_testing_attribute_v1_attribute_proto_msgTypes = make([]protoimpl.MessageInfo, 24) +var file_testing_attribute_v1_attribute_proto_goTypes = []interface{}{ + (*TestResource)(nil), // 0: testing.attribute.v1.TestResource + (*TestSubResourceAttributes)(nil), // 1: testing.attribute.v1.TestSubResourceAttributes + (*TestNoAttributes)(nil), // 2: testing.attribute.v1.TestNoAttributes + (*TestNoOneOf)(nil), // 3: testing.attribute.v1.TestNoOneOf + (*TestListResourceRequest)(nil), // 4: testing.attribute.v1.TestListResourceRequest + (*TestListResourceResponse)(nil), // 5: testing.attribute.v1.TestListResourceResponse + (*TestGetResourceRequest)(nil), // 6: testing.attribute.v1.TestGetResourceRequest + (*TestGetResourceResponse)(nil), // 7: testing.attribute.v1.TestGetResourceResponse + (*TestCreateResourceRequest)(nil), // 8: testing.attribute.v1.TestCreateResourceRequest + (*TestCreateResourceResponse)(nil), // 9: testing.attribute.v1.TestCreateResourceResponse + (*TestUpdateResourceRequest)(nil), // 10: testing.attribute.v1.TestUpdateResourceRequest + (*TestUpdateResourceResponse)(nil), // 11: testing.attribute.v1.TestUpdateResourceResponse + (*TestRequestNoItem)(nil), // 12: testing.attribute.v1.TestRequestNoItem + (*TestRequestItemNotMessage)(nil), // 13: testing.attribute.v1.TestRequestItemNotMessage + (*TestItemNoType)(nil), // 14: testing.attribute.v1.TestItemNoType + (*TestRequestItemNoType)(nil), // 15: testing.attribute.v1.TestRequestItemNoType + (*TestNoItemAttributes)(nil), // 16: testing.attribute.v1.TestNoItemAttributes + (*TestCreateNoOneOfRequest)(nil), // 17: testing.attribute.v1.TestCreateNoOneOfRequest + (*TestUpdateNoOneOfRequest)(nil), // 18: testing.attribute.v1.TestUpdateNoOneOfRequest + (*TestResponseNoItem)(nil), // 19: testing.attribute.v1.TestResponseNoItem + (*TestResponseItemNotMessage)(nil), // 20: testing.attribute.v1.TestResponseItemNotMessage + (*TestResponseItemNoType)(nil), // 21: testing.attribute.v1.TestResponseItemNoType + (*TestCreateNoOneOfResponse)(nil), // 22: testing.attribute.v1.TestCreateNoOneOfResponse + (*TestUpdateNoOneOfResponse)(nil), // 23: testing.attribute.v1.TestUpdateNoOneOfResponse + (*structpb.Struct)(nil), // 24: google.protobuf.Struct + (*fieldmaskpb.FieldMask)(nil), // 25: google.protobuf.FieldMask +} +var file_testing_attribute_v1_attribute_proto_depIdxs = []int32{ + 24, // 0: testing.attribute.v1.TestResource.attributes:type_name -> google.protobuf.Struct + 1, // 1: testing.attribute.v1.TestResource.sub_resource_attributes:type_name -> testing.attribute.v1.TestSubResourceAttributes + 24, // 2: testing.attribute.v1.TestNoOneOf.attributes:type_name -> google.protobuf.Struct + 0, // 3: testing.attribute.v1.TestListResourceResponse.items:type_name -> testing.attribute.v1.TestResource + 0, // 4: testing.attribute.v1.TestGetResourceResponse.item:type_name -> testing.attribute.v1.TestResource + 0, // 5: testing.attribute.v1.TestCreateResourceRequest.item:type_name -> testing.attribute.v1.TestResource + 0, // 6: testing.attribute.v1.TestCreateResourceResponse.item:type_name -> testing.attribute.v1.TestResource + 0, // 7: testing.attribute.v1.TestUpdateResourceRequest.item:type_name -> testing.attribute.v1.TestResource + 25, // 8: testing.attribute.v1.TestUpdateResourceRequest.update_mask:type_name -> google.protobuf.FieldMask + 0, // 9: testing.attribute.v1.TestUpdateResourceResponse.item:type_name -> testing.attribute.v1.TestResource + 14, // 10: testing.attribute.v1.TestRequestItemNoType.item:type_name -> testing.attribute.v1.TestItemNoType + 24, // 11: testing.attribute.v1.TestNoItemAttributes.attributes:type_name -> google.protobuf.Struct + 1, // 12: testing.attribute.v1.TestNoItemAttributes.sub_resource_attributes:type_name -> testing.attribute.v1.TestSubResourceAttributes + 3, // 13: testing.attribute.v1.TestCreateNoOneOfRequest.item:type_name -> testing.attribute.v1.TestNoOneOf + 3, // 14: testing.attribute.v1.TestUpdateNoOneOfRequest.item:type_name -> testing.attribute.v1.TestNoOneOf + 14, // 15: testing.attribute.v1.TestResponseItemNoType.item:type_name -> testing.attribute.v1.TestItemNoType + 3, // 16: testing.attribute.v1.TestCreateNoOneOfResponse.item:type_name -> testing.attribute.v1.TestNoOneOf + 3, // 17: testing.attribute.v1.TestUpdateNoOneOfResponse.item:type_name -> testing.attribute.v1.TestNoOneOf + 4, // 18: testing.attribute.v1.TestResourceService.TestListResource:input_type -> testing.attribute.v1.TestListResourceRequest + 8, // 19: testing.attribute.v1.TestResourceService.TestCreateResource:input_type -> testing.attribute.v1.TestCreateResourceRequest + 10, // 20: testing.attribute.v1.TestResourceService.TestUpdateResource:input_type -> testing.attribute.v1.TestUpdateResourceRequest + 6, // 21: testing.attribute.v1.TestResourceService.TestGetResource:input_type -> testing.attribute.v1.TestGetResourceRequest + 5, // 22: testing.attribute.v1.TestResourceService.TestListResource:output_type -> testing.attribute.v1.TestListResourceResponse + 9, // 23: testing.attribute.v1.TestResourceService.TestCreateResource:output_type -> testing.attribute.v1.TestCreateResourceResponse + 11, // 24: testing.attribute.v1.TestResourceService.TestUpdateResource:output_type -> testing.attribute.v1.TestUpdateResourceResponse + 7, // 25: testing.attribute.v1.TestResourceService.TestGetResource:output_type -> testing.attribute.v1.TestGetResourceResponse + 22, // [22:26] is the sub-list for method output_type + 18, // [18:22] is the sub-list for method input_type + 18, // [18:18] is the sub-list for extension type_name + 18, // [18:18] is the sub-list for extension extendee + 0, // [0:18] is the sub-list for field type_name +} + +func init() { file_testing_attribute_v1_attribute_proto_init() } +func file_testing_attribute_v1_attribute_proto_init() { + if File_testing_attribute_v1_attribute_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_testing_attribute_v1_attribute_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestResource); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestSubResourceAttributes); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestNoAttributes); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestNoOneOf); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestListResourceRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestListResourceResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestGetResourceRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestGetResourceResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestCreateResourceRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestCreateResourceResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestUpdateResourceRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestUpdateResourceResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestRequestNoItem); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestRequestItemNotMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestItemNoType); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestRequestItemNoType); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestNoItemAttributes); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestCreateNoOneOfRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestUpdateNoOneOfRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestResponseNoItem); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestResponseItemNotMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestResponseItemNoType); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestCreateNoOneOfResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestUpdateNoOneOfResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_testing_attribute_v1_attribute_proto_msgTypes[0].OneofWrappers = []interface{}{ + (*TestResource_Attributes)(nil), + (*TestResource_SubResourceAttributes)(nil), + } + file_testing_attribute_v1_attribute_proto_msgTypes[16].OneofWrappers = []interface{}{ + (*TestNoItemAttributes_Attributes)(nil), + (*TestNoItemAttributes_SubResourceAttributes)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -325,9 +1879,9 @@ func file_testing_attribute_v1_attribute_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_testing_attribute_v1_attribute_proto_rawDesc, NumEnums: 0, - NumMessages: 3, + NumMessages: 24, NumExtensions: 0, - NumServices: 0, + NumServices: 1, }, GoTypes: file_testing_attribute_v1_attribute_proto_goTypes, DependencyIndexes: file_testing_attribute_v1_attribute_proto_depIdxs, diff --git a/internal/gen/testing/attribute/attribute.pb.gw.go b/internal/gen/testing/attribute/attribute.pb.gw.go new file mode 100644 index 0000000000..f0122eb25a --- /dev/null +++ b/internal/gen/testing/attribute/attribute.pb.gw.go @@ -0,0 +1,513 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: testing/attribute/v1/attribute.proto + +/* +Package attribute is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package attribute + +import ( + "context" + "io" + "net/http" + + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = metadata.Join + +func request_TestResourceService_TestListResource_0(ctx context.Context, marshaler runtime.Marshaler, client TestResourceServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq TestListResourceRequest + var metadata runtime.ServerMetadata + + msg, err := client.TestListResource(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_TestResourceService_TestListResource_0(ctx context.Context, marshaler runtime.Marshaler, server TestResourceServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq TestListResourceRequest + var metadata runtime.ServerMetadata + + msg, err := server.TestListResource(ctx, &protoReq) + return msg, metadata, err + +} + +func request_TestResourceService_TestCreateResource_0(ctx context.Context, marshaler runtime.Marshaler, client TestResourceServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq TestCreateResourceRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Item); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.TestCreateResource(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_TestResourceService_TestCreateResource_0(ctx context.Context, marshaler runtime.Marshaler, server TestResourceServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq TestCreateResourceRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Item); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.TestCreateResource(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_TestResourceService_TestUpdateResource_0 = &utilities.DoubleArray{Encoding: map[string]int{"item": 0, "id": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} +) + +func request_TestResourceService_TestUpdateResource_0(ctx context.Context, marshaler runtime.Marshaler, client TestResourceServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq TestUpdateResourceRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Item); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if protoReq.UpdateMask == nil || len(protoReq.UpdateMask.GetPaths()) == 0 { + if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.Item); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } else { + protoReq.UpdateMask = fieldMask + } + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") + } + + protoReq.Id, err = runtime.String(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_TestResourceService_TestUpdateResource_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.TestUpdateResource(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_TestResourceService_TestUpdateResource_0(ctx context.Context, marshaler runtime.Marshaler, server TestResourceServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq TestUpdateResourceRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Item); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if protoReq.UpdateMask == nil || len(protoReq.UpdateMask.GetPaths()) == 0 { + if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.Item); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } else { + protoReq.UpdateMask = fieldMask + } + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") + } + + protoReq.Id, err = runtime.String(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_TestResourceService_TestUpdateResource_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.TestUpdateResource(ctx, &protoReq) + return msg, metadata, err + +} + +func request_TestResourceService_TestGetResource_0(ctx context.Context, marshaler runtime.Marshaler, client TestResourceServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq TestGetResourceRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") + } + + protoReq.Id, err = runtime.String(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) + } + + msg, err := client.TestGetResource(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_TestResourceService_TestGetResource_0(ctx context.Context, marshaler runtime.Marshaler, server TestResourceServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq TestGetResourceRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") + } + + protoReq.Id, err = runtime.String(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) + } + + msg, err := server.TestGetResource(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterTestResourceServiceHandlerServer registers the http handlers for service TestResourceService to "mux". +// UnaryRPC :call TestResourceServiceServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterTestResourceServiceHandlerFromEndpoint instead. +func RegisterTestResourceServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server TestResourceServiceServer) error { + + mux.Handle("GET", pattern_TestResourceService_TestListResource_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/testing.attribute.v1.TestResourceService/TestListResource", runtime.WithHTTPPathPattern("/v1/test-resources")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_TestResourceService_TestListResource_0(ctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_TestResourceService_TestListResource_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_TestResourceService_TestCreateResource_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/testing.attribute.v1.TestResourceService/TestCreateResource", runtime.WithHTTPPathPattern("/v1/test-resources")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_TestResourceService_TestCreateResource_0(ctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_TestResourceService_TestCreateResource_0(ctx, mux, outboundMarshaler, w, req, response_TestResourceService_TestCreateResource_0{resp}, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("PATCH", pattern_TestResourceService_TestUpdateResource_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/testing.attribute.v1.TestResourceService/TestUpdateResource", runtime.WithHTTPPathPattern("/v1/test-resources/{id}")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_TestResourceService_TestUpdateResource_0(ctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_TestResourceService_TestUpdateResource_0(ctx, mux, outboundMarshaler, w, req, response_TestResourceService_TestUpdateResource_0{resp}, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_TestResourceService_TestGetResource_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/testing.attribute.v1.TestResourceService/TestGetResource", runtime.WithHTTPPathPattern("/v1/test-resources/{id}")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_TestResourceService_TestGetResource_0(ctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_TestResourceService_TestGetResource_0(ctx, mux, outboundMarshaler, w, req, response_TestResourceService_TestGetResource_0{resp}, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterTestResourceServiceHandlerFromEndpoint is same as RegisterTestResourceServiceHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterTestResourceServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterTestResourceServiceHandler(ctx, mux, conn) +} + +// RegisterTestResourceServiceHandler registers the http handlers for service TestResourceService to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterTestResourceServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterTestResourceServiceHandlerClient(ctx, mux, NewTestResourceServiceClient(conn)) +} + +// RegisterTestResourceServiceHandlerClient registers the http handlers for service TestResourceService +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "TestResourceServiceClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "TestResourceServiceClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "TestResourceServiceClient" to call the correct interceptors. +func RegisterTestResourceServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client TestResourceServiceClient) error { + + mux.Handle("GET", pattern_TestResourceService_TestListResource_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + ctx, err = runtime.AnnotateContext(ctx, mux, req, "/testing.attribute.v1.TestResourceService/TestListResource", runtime.WithHTTPPathPattern("/v1/test-resources")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_TestResourceService_TestListResource_0(ctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_TestResourceService_TestListResource_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_TestResourceService_TestCreateResource_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + ctx, err = runtime.AnnotateContext(ctx, mux, req, "/testing.attribute.v1.TestResourceService/TestCreateResource", runtime.WithHTTPPathPattern("/v1/test-resources")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_TestResourceService_TestCreateResource_0(ctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_TestResourceService_TestCreateResource_0(ctx, mux, outboundMarshaler, w, req, response_TestResourceService_TestCreateResource_0{resp}, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("PATCH", pattern_TestResourceService_TestUpdateResource_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + ctx, err = runtime.AnnotateContext(ctx, mux, req, "/testing.attribute.v1.TestResourceService/TestUpdateResource", runtime.WithHTTPPathPattern("/v1/test-resources/{id}")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_TestResourceService_TestUpdateResource_0(ctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_TestResourceService_TestUpdateResource_0(ctx, mux, outboundMarshaler, w, req, response_TestResourceService_TestUpdateResource_0{resp}, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_TestResourceService_TestGetResource_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + ctx, err = runtime.AnnotateContext(ctx, mux, req, "/testing.attribute.v1.TestResourceService/TestGetResource", runtime.WithHTTPPathPattern("/v1/test-resources/{id}")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_TestResourceService_TestGetResource_0(ctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_TestResourceService_TestGetResource_0(ctx, mux, outboundMarshaler, w, req, response_TestResourceService_TestGetResource_0{resp}, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +type response_TestResourceService_TestCreateResource_0 struct { + proto.Message +} + +func (m response_TestResourceService_TestCreateResource_0) XXX_ResponseBody() interface{} { + response := m.Message.(*TestCreateResourceResponse) + return response.Item +} + +type response_TestResourceService_TestUpdateResource_0 struct { + proto.Message +} + +func (m response_TestResourceService_TestUpdateResource_0) XXX_ResponseBody() interface{} { + response := m.Message.(*TestUpdateResourceResponse) + return response.Item +} + +type response_TestResourceService_TestGetResource_0 struct { + proto.Message +} + +func (m response_TestResourceService_TestGetResource_0) XXX_ResponseBody() interface{} { + response := m.Message.(*TestGetResourceResponse) + return response.Item +} + +var ( + pattern_TestResourceService_TestListResource_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "test-resources"}, "")) + + pattern_TestResourceService_TestCreateResource_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "test-resources"}, "")) + + pattern_TestResourceService_TestUpdateResource_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "test-resources", "id"}, "")) + + pattern_TestResourceService_TestGetResource_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "test-resources", "id"}, "")) +) + +var ( + forward_TestResourceService_TestListResource_0 = runtime.ForwardResponseMessage + + forward_TestResourceService_TestCreateResource_0 = runtime.ForwardResponseMessage + + forward_TestResourceService_TestUpdateResource_0 = runtime.ForwardResponseMessage + + forward_TestResourceService_TestGetResource_0 = runtime.ForwardResponseMessage +) diff --git a/internal/gen/testing/attribute/attribute_grpc.pb.go b/internal/gen/testing/attribute/attribute_grpc.pb.go new file mode 100644 index 0000000000..120013605c --- /dev/null +++ b/internal/gen/testing/attribute/attribute_grpc.pb.go @@ -0,0 +1,209 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. + +package attribute + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// TestResourceServiceClient is the client API for TestResourceService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type TestResourceServiceClient interface { + TestListResource(ctx context.Context, in *TestListResourceRequest, opts ...grpc.CallOption) (*TestListResourceResponse, error) + TestCreateResource(ctx context.Context, in *TestCreateResourceRequest, opts ...grpc.CallOption) (*TestCreateResourceResponse, error) + TestUpdateResource(ctx context.Context, in *TestUpdateResourceRequest, opts ...grpc.CallOption) (*TestUpdateResourceResponse, error) + TestGetResource(ctx context.Context, in *TestGetResourceRequest, opts ...grpc.CallOption) (*TestGetResourceResponse, error) +} + +type testResourceServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewTestResourceServiceClient(cc grpc.ClientConnInterface) TestResourceServiceClient { + return &testResourceServiceClient{cc} +} + +func (c *testResourceServiceClient) TestListResource(ctx context.Context, in *TestListResourceRequest, opts ...grpc.CallOption) (*TestListResourceResponse, error) { + out := new(TestListResourceResponse) + err := c.cc.Invoke(ctx, "/testing.attribute.v1.TestResourceService/TestListResource", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *testResourceServiceClient) TestCreateResource(ctx context.Context, in *TestCreateResourceRequest, opts ...grpc.CallOption) (*TestCreateResourceResponse, error) { + out := new(TestCreateResourceResponse) + err := c.cc.Invoke(ctx, "/testing.attribute.v1.TestResourceService/TestCreateResource", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *testResourceServiceClient) TestUpdateResource(ctx context.Context, in *TestUpdateResourceRequest, opts ...grpc.CallOption) (*TestUpdateResourceResponse, error) { + out := new(TestUpdateResourceResponse) + err := c.cc.Invoke(ctx, "/testing.attribute.v1.TestResourceService/TestUpdateResource", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *testResourceServiceClient) TestGetResource(ctx context.Context, in *TestGetResourceRequest, opts ...grpc.CallOption) (*TestGetResourceResponse, error) { + out := new(TestGetResourceResponse) + err := c.cc.Invoke(ctx, "/testing.attribute.v1.TestResourceService/TestGetResource", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// TestResourceServiceServer is the server API for TestResourceService service. +// All implementations must embed UnimplementedTestResourceServiceServer +// for forward compatibility +type TestResourceServiceServer interface { + TestListResource(context.Context, *TestListResourceRequest) (*TestListResourceResponse, error) + TestCreateResource(context.Context, *TestCreateResourceRequest) (*TestCreateResourceResponse, error) + TestUpdateResource(context.Context, *TestUpdateResourceRequest) (*TestUpdateResourceResponse, error) + TestGetResource(context.Context, *TestGetResourceRequest) (*TestGetResourceResponse, error) + mustEmbedUnimplementedTestResourceServiceServer() +} + +// UnimplementedTestResourceServiceServer must be embedded to have forward compatible implementations. +type UnimplementedTestResourceServiceServer struct { +} + +func (UnimplementedTestResourceServiceServer) TestListResource(context.Context, *TestListResourceRequest) (*TestListResourceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method TestListResource not implemented") +} +func (UnimplementedTestResourceServiceServer) TestCreateResource(context.Context, *TestCreateResourceRequest) (*TestCreateResourceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method TestCreateResource not implemented") +} +func (UnimplementedTestResourceServiceServer) TestUpdateResource(context.Context, *TestUpdateResourceRequest) (*TestUpdateResourceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method TestUpdateResource not implemented") +} +func (UnimplementedTestResourceServiceServer) TestGetResource(context.Context, *TestGetResourceRequest) (*TestGetResourceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method TestGetResource not implemented") +} +func (UnimplementedTestResourceServiceServer) mustEmbedUnimplementedTestResourceServiceServer() {} + +// UnsafeTestResourceServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to TestResourceServiceServer will +// result in compilation errors. +type UnsafeTestResourceServiceServer interface { + mustEmbedUnimplementedTestResourceServiceServer() +} + +func RegisterTestResourceServiceServer(s grpc.ServiceRegistrar, srv TestResourceServiceServer) { + s.RegisterService(&TestResourceService_ServiceDesc, srv) +} + +func _TestResourceService_TestListResource_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(TestListResourceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TestResourceServiceServer).TestListResource(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/testing.attribute.v1.TestResourceService/TestListResource", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TestResourceServiceServer).TestListResource(ctx, req.(*TestListResourceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _TestResourceService_TestCreateResource_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(TestCreateResourceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TestResourceServiceServer).TestCreateResource(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/testing.attribute.v1.TestResourceService/TestCreateResource", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TestResourceServiceServer).TestCreateResource(ctx, req.(*TestCreateResourceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _TestResourceService_TestUpdateResource_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(TestUpdateResourceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TestResourceServiceServer).TestUpdateResource(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/testing.attribute.v1.TestResourceService/TestUpdateResource", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TestResourceServiceServer).TestUpdateResource(ctx, req.(*TestUpdateResourceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _TestResourceService_TestGetResource_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(TestGetResourceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TestResourceServiceServer).TestGetResource(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/testing.attribute.v1.TestResourceService/TestGetResource", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TestResourceServiceServer).TestGetResource(ctx, req.(*TestGetResourceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// TestResourceService_ServiceDesc is the grpc.ServiceDesc for TestResourceService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var TestResourceService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "testing.attribute.v1.TestResourceService", + HandlerType: (*TestResourceServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "TestListResource", + Handler: _TestResourceService_TestListResource_Handler, + }, + { + MethodName: "TestCreateResource", + Handler: _TestResourceService_TestCreateResource_Handler, + }, + { + MethodName: "TestUpdateResource", + Handler: _TestResourceService_TestUpdateResource_Handler, + }, + { + MethodName: "TestGetResource", + Handler: _TestResourceService_TestGetResource_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "testing/attribute/v1/attribute.proto", +} diff --git a/internal/proto/local/testing/attribute/v1/attribute.proto b/internal/proto/local/testing/attribute/v1/attribute.proto index 6b3d95b04a..0d921d7852 100644 --- a/internal/proto/local/testing/attribute/v1/attribute.proto +++ b/internal/proto/local/testing/attribute/v1/attribute.proto @@ -4,11 +4,19 @@ package testing.attribute.v1; option go_package = "github.com/hashicorp/boundary/internal/gen/testing/attribute;attribute"; +import "protoc-gen-openapiv2/options/annotations.proto"; +import "google/api/annotations.proto"; import "google/protobuf/struct.proto"; +import "google/protobuf/field_mask.proto"; import "controller/custom_options/v1/options.proto"; +option (controller.custom_options.v1.domain) = "test"; + message TestResource { string id = 1; + string type = 2; + + string other_id = 3 [(controller.custom_options.v1.subtype_source_id) = true]; oneof attrs { google.protobuf.Struct attributes = 10 [(controller.custom_options.v1.subtype) = "default"]; @@ -22,4 +30,141 @@ message TestSubResourceAttributes { message TestNoAttributes { string id = 1; + string type = 2; +} + +message TestNoOneOf { + string id = 1; + string type = 2; + + google.protobuf.Struct attributes = 10; +} + +service TestResourceService { + rpc TestListResource(TestListResourceRequest) returns (TestListResourceResponse) { + option (google.api.http) = { + get: "/v1/test-resources" + }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + summary: "Test list" + }; + } + + rpc TestCreateResource(TestCreateResourceRequest) returns (TestCreateResourceResponse) { + option (google.api.http) = { + post: "/v1/test-resources" + body: "item" + response_body: "item" + }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + summary: "Test create" + }; + } + + rpc TestUpdateResource(TestUpdateResourceRequest) returns (TestUpdateResourceResponse) { + option (google.api.http) = { + patch: "/v1/test-resources/{id}" + body: "item" + response_body: "item" + }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + summary: "Test update" + }; + } + + rpc TestGetResource(TestGetResourceRequest) returns (TestGetResourceResponse) { + option (google.api.http) = { + get: "/v1/test-resources/{id}" + response_body: "item" + }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + summary: "Test get" + }; + } +} + +message TestListResourceRequest {} + +message TestListResourceResponse { + repeated TestResource items = 1; +} + +message TestGetResourceRequest { + string id = 1; +} + +message TestGetResourceResponse { + TestResource item = 1; +} + +message TestCreateResourceRequest { + TestResource item = 2; +} + +message TestCreateResourceResponse { + TestResource item = 1; +} + +message TestUpdateResourceRequest { + string id = 1; + TestResource item = 2; + google.protobuf.FieldMask update_mask = 3 [json_name="update_mask"]; +} + +message TestUpdateResourceResponse { + TestResource item = 1; +} + +message TestRequestNoItem { + string name = 1; +} + +message TestRequestItemNotMessage { + string item = 1; +} + +message TestItemNoType { + string id = 1; +} + +message TestRequestItemNoType { + TestItemNoType item = 1; +} + +message TestNoItemAttributes { + string id = 1; + + oneof attrs { + google.protobuf.Struct attributes = 10 [(controller.custom_options.v1.subtype) = "default"]; + TestSubResourceAttributes sub_resource_attributes = 20 [(controller.custom_options.v1.subtype) = "sub_resource"]; + } +} + +message TestCreateNoOneOfRequest { + TestNoOneOf item = 1; +} + +message TestUpdateNoOneOfRequest { + string id = 1; + TestNoOneOf item = 2; +} + +message TestResponseNoItem { + string name = 1; +} + +message TestResponseItemNotMessage { + string item = 1; +} + +message TestResponseItemNoType { + TestItemNoType item = 1; +} + +message TestCreateNoOneOfResponse { + TestNoOneOf item = 1; +} + +message TestUpdateNoOneOfResponse { + TestNoOneOf item = 1; } diff --git a/internal/servers/controller/gateway.go b/internal/servers/controller/gateway.go index 005e188034..397486684a 100644 --- a/internal/servers/controller/gateway.go +++ b/internal/servers/controller/gateway.go @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/boundary/internal/observability/event" "github.com/hashicorp/boundary/internal/servers/controller/common" "github.com/hashicorp/boundary/internal/servers/controller/handlers" + "github.com/hashicorp/boundary/internal/types/subtypes" "google.golang.org/grpc" "google.golang.org/grpc/test/bufconn" ) @@ -73,11 +74,12 @@ func newGrpcServer( grpc.MaxSendMsgSize(math.MaxInt32), grpc.UnaryInterceptor( grpc_middleware.ChainUnaryServer( - requestCtxInterceptor, // populated requestInfo from headers into the request ctx - auditRequestInterceptor(ctx), // before we get started, audit the request - errorInterceptor(ctx), // convert domain and api errors into headers for the http proxy - statusCodeInterceptor(ctx), // convert grpc codes into http status codes for the http proxy (can modify the resp) - auditResponseInterceptor(ctx), // as we finish, audit the response + requestCtxInterceptor, // populated requestInfo from headers into the request ctx + subtypes.AttributeTransformerInterceptor(ctx), // convert to/from generic attributes from/to subtype specific attributes + auditRequestInterceptor(ctx), // before we get started, audit the request + errorInterceptor(ctx), // convert domain and api errors into headers for the http proxy + statusCodeInterceptor(ctx), // convert grpc codes into http status codes for the http proxy (can modify the resp) + auditResponseInterceptor(ctx), // as we finish, audit the response grpc_recovery.UnaryServerInterceptor( // recover from panics with a grpc internal error grpc_recovery.WithRecoveryHandlerContext(recoveryHandler()), ), diff --git a/internal/types/subtypes/attribute_transform.go b/internal/types/subtypes/attribute_transform.go new file mode 100644 index 0000000000..9c59509dd2 --- /dev/null +++ b/internal/types/subtypes/attribute_transform.go @@ -0,0 +1,132 @@ +package subtypes + +import ( + "fmt" + + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/known/structpb" +) + +func convertAttributesToSubtype(msg proto.Message, st Subtype) error { + r := msg.ProtoReflect() + d := r.Descriptor() + + defaultAttrField, err := attributeField(d, defaultSubtype) + if err != nil { + // If unable to get a default attribute field, the message is either + // not registered or not in the format needed for conversion, so no + // conversion should be performed. The most likely case here is that + // the message has not been changed to use a oneof for attributes yet. + return nil + } + + stAttrField, err := attributeField(d, st) + if err != nil { + // This error should not be possible, since any registration issue + // would trigger the previous call, and if this particular subtype + // is unknown, the default should be returned. + return nil + } + + if defaultAttrField == stAttrField { + // no need to convert + return nil + } + + defaultAttrs, ok := r.Get(defaultAttrField).Message().Interface().(*structpb.Struct) + if !ok { + // This should not be possible since this is checked in + // (attributeRegistry).register at initialization time and would panic + // if this was the case. + return fmt.Errorf("found default attribute field that is not structpb.Struct: %s %s", d.FullName(), defaultAttrField.FullName()) + } + stAttrs := r.Get(stAttrField).Message().New().Interface() + if err := structToProto(defaultAttrs, stAttrs); err != nil { + return err + } + + // implicitly clears any previously set oneof value + r.Set(stAttrField, protoreflect.ValueOfMessage(stAttrs.ProtoReflect())) + return nil +} + +func convertAttributesToDefault(msg proto.Message, st Subtype) error { + r := msg.ProtoReflect() + d := r.Descriptor() + + defaultAttrField, err := attributeField(d, defaultSubtype) + if err != nil { + // If unable to get a default attribute field, the message is either + // not registered or not in the format needed for conversion, so no + // conversion should be performed. The most likely case here is that + // the message has not been changed to use a oneof for attributes yet. + return nil + } + + stAttrField, err := attributeField(d, st) + if err != nil { + // This error should not be possible, since any registration issue + // would trigger the previous call, and if this particular subtype + // is unknown, the default should be returned. + return nil + } + + if defaultAttrField == stAttrField { + // no need to convert + return nil + } + + stAttrs, ok := r.Get(stAttrField).Message().Interface().(proto.Message) + if !ok { + return fmt.Errorf("found subtype attribute field that is not proto.Message: %s %s", d.FullName(), stAttrField.FullName()) + } + defaultAttrs, err := protoToStruct(stAttrs) + if err != nil { + return err + } + // implicitly clears any previously set oneof value + r.Set(defaultAttrField, protoreflect.ValueOfMessage(defaultAttrs.ProtoReflect())) + return nil +} + +func structToProto(fields *structpb.Struct, p proto.Message) error { + if fields == nil { + // If there is no struct, don't update the default proto message. + return nil + } + js, err := fields.MarshalJSON() + if err != nil { + return err + } + + // TODO: replicate this logic but with a proto extension set on the Field + // descriptor There are some attributes where we want to discard unknown + // fields, while others that should error if there are unknown fields + // + // opts := GetOpts(opt...) + // if opts.withDiscardUnknownFields { + // err = (protojson.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(js, p)) + // } else { + // err = protojson.Unmarshal(js, p) + // } + + err = protojson.Unmarshal(js, p) + if err != nil { + return err + } + return nil +} + +func protoToStruct(p proto.Message) (*structpb.Struct, error) { + js, err := protojson.MarshalOptions{UseProtoNames: true}.Marshal(p) + if err != nil { + return nil, err + } + st := &structpb.Struct{} + if err := protojson.Unmarshal(js, st); err != nil { + return nil, err + } + return st, nil +} diff --git a/internal/types/subtypes/attributes.go b/internal/types/subtypes/attributes.go index 95ab53c695..7b3ad12d02 100644 --- a/internal/types/subtypes/attributes.go +++ b/internal/types/subtypes/attributes.go @@ -9,6 +9,7 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" "google.golang.org/protobuf/types/descriptorpb" + "google.golang.org/protobuf/types/known/structpb" ) const ( @@ -16,13 +17,13 @@ const ( ) func init() { - globalAttributeKeys = attributeKeys{ + globalAttributeRegistry = attributeRegistry{ m: make(map[protoreflect.FullName]fieldMap), } protoregistry.GlobalTypes.RangeMessages(func(m protoreflect.MessageType) bool { d := m.Descriptor() - if err := globalAttributeKeys.register(d); err != nil { + if err := globalAttributeRegistry.register(d); err != nil { panic(err) } return true @@ -31,20 +32,21 @@ func init() { type fieldMap map[Subtype]protoreflect.FieldDescriptor -type attributeKeys struct { +type attributeRegistry struct { sync.RWMutex m map[protoreflect.FullName]fieldMap } -var globalAttributeKeys attributeKeys +var globalAttributeRegistry attributeRegistry // register examines the given protobuf MessageDescriptor for fields that have // the Subtype protobuf extension. It uses these to build a fieldMap of subtype // strings to the protobuf FieldDescriptors. If the message does not have any // subtypes it will not be registered, but no error is returned, allowing this // to be called on any protobuf message. However, if a message has subtypes but -// does not provide a field with a subtype of "default" an error is returned. -func (ak attributeKeys) register(d protoreflect.MessageDescriptor) error { +// does not provide a field with a subtype of "default", or if the default +// field is not a *structpb.Struct type, an error is returned. +func (ak attributeRegistry) register(d protoreflect.MessageDescriptor) error { ak.Lock() defer ak.Unlock() @@ -77,19 +79,24 @@ func (ak attributeKeys) register(d protoreflect.MessageDescriptor) error { } // If a message has subtypes, it must provide a "default" to support plugins. - if _, ok := km[defaultSubtype]; !ok { + defSubtype, ok := km[defaultSubtype] + if !ok { return fmt.Errorf("proto message %s with subtype attributes but no 'default'", fn) } + if defSubtype.Message().FullName() != (&structpb.Struct{}).ProtoReflect().Descriptor().FullName() { + return fmt.Errorf("proto message %s with 'default' subtype attributes that is not structpb.Struct", fn) + } + ak.m[fn] = km return nil } -// protoAttributeField retrieves the FieldDescriptor for a given subtype's +// attributeField retrieves the FieldDescriptor for a given subtype's // attribute fields. If the corresponding protobuf message has not been // registered it will return an error. -func (ak attributeKeys) protoAttributeField(d protoreflect.MessageDescriptor, t Subtype) (protoreflect.FieldDescriptor, error) { +func (ak attributeRegistry) attributeField(d protoreflect.MessageDescriptor, t Subtype) (protoreflect.FieldDescriptor, error) { ak.RLock() defer ak.RUnlock() @@ -112,13 +119,8 @@ func (ak attributeKeys) protoAttributeField(d protoreflect.MessageDescriptor, t return tt, nil } -// TODO: fix doc -// protoAttributeField is used by the attrMarshaler to translate between JSON -// formats for the API and for the protobuf messages. It expects a -// proto.Message with a OneOf field for the subtype attributes and the subtype -// string. It returns the string for the JSON key that that should be used for -// the subtype's attributes fields. -func protoAttributeField(msg proto.Message, t Subtype) (protoreflect.FieldDescriptor, error) { - d := msg.ProtoReflect().Descriptor() - return globalAttributeKeys.protoAttributeField(d, t) +// attributeField is used by the AttributeTransformInterceptor to retrieve +// the proto FieldDescriptor for a given subtype. +func attributeField(d protoreflect.MessageDescriptor, t Subtype) (protoreflect.FieldDescriptor, error) { + return globalAttributeRegistry.attributeField(d, t) } diff --git a/internal/types/subtypes/attributes_test.go b/internal/types/subtypes/attributes_test.go index cd39577ad4..842a7c5845 100644 --- a/internal/types/subtypes/attributes_test.go +++ b/internal/types/subtypes/attributes_test.go @@ -39,7 +39,7 @@ func TestProtoAttributeKey(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - k, err := protoAttributeField(tc.msg, tc.subtype) + k, err := attributeField(tc.msg.ProtoReflect().Descriptor(), tc.subtype) require.NoError(t, err) assert.Equal(t, tc.expected, k.FullName()) }) @@ -76,7 +76,7 @@ func TestProtoAttributeKeyErrors(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - _, err := protoAttributeField(tc.msg, tc.subtype) + _, err := attributeField(tc.msg.ProtoReflect().Descriptor(), tc.subtype) require.EqualError(t, err, tc.expectedErr) }) } @@ -97,14 +97,14 @@ func TestRegisterErrors(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - err := globalAttributeKeys.register(tc.msg.ProtoReflect().Descriptor()) + err := globalAttributeRegistry.register(tc.msg.ProtoReflect().Descriptor()) require.EqualError(t, err, tc.expectedErr) }) } } func TestRegisterNoSubtypes(t *testing.T) { - ak := attributeKeys{ + ak := attributeRegistry{ m: make(map[protoreflect.FullName]fieldMap), } diff --git a/internal/types/subtypes/interceptor.go b/internal/types/subtypes/interceptor.go new file mode 100644 index 0000000000..ea4b1aad89 --- /dev/null +++ b/internal/types/subtypes/interceptor.go @@ -0,0 +1,308 @@ +package subtypes + +import ( + "context" + + "github.com/hashicorp/boundary/internal/servers/controller/handlers" + "github.com/hashicorp/boundary/sdk/pbs/controller/protooptions" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/descriptorpb" +) + +func messageDomain(m proto.Message) string { + r := m.ProtoReflect() + fd := r.Descriptor().ParentFile() + if fd == nil { + return "" + } + + opts, ok := fd.Options().(*descriptorpb.FileOptions) + if !ok { + return "" + } + + domain := proto.GetExtension(opts, protooptions.E_Domain).(string) + return domain +} + +// transformRequestAttributes will modify the request proto.Message, setting +// any subtype attribute fields into the corresponding strongly-typed struct +// for the subtype. It looks for some specific structure in the proto.Message +// to identify the correct subtype and apply the transformation. +// +// The first structure is a message that contains a single "item" that is a +// message that has a "type" and an "attrs" oneof for attributes: +// +// message CreateFooRequest { +// item Foo = 1; +// } +// message Foo { +// string type = 1; +// // other fields +// oneof attrs { +// google.protobuf.Struct attributes = 10 [(custom_options.v1.subtype) = "default"]; +// // other subtype attributes types +// } +// } +// +// The second structure is similar to the first, but rather then the type field +// being provided, an id field is set. Note this is a different id from the +// third structure. In this case it is an id for a related resource and the id +// is marked with the "subtype_source_id" custom option: +// +// message CreateFooRequest { +// item Foo = 1; +// } +// message Foo { +// string bar_id = 1 [(custom_options.v1.subtype_source_id) = true]; +// // other fields +// oneof attrs { +// google.protobuf.Struct attributes = 10 [(custom_options.v1.subtype) = "default"]; +// // other subtype attributes types +// } +// } +// +// The third structure is a message that contains an id string and an "item" +// that is a message that has an "attrs" oneof for attributes: +// +// message UpdateFooRequest { +// string id = 1; +// item Foo = 2; +// } +// message Foo { +// // other fields +// oneof attrs { +// google.protobuf.Struct attributes = 10 [(custom_options.v1.subtype) = "default"]; +// // other subtype attributes types +// } +// } +// +// The forth structure is a message that contains an id string and an "attrs" oneof for +// attributes: +// +// message FooActionRequest { +// string id = 1; +// oneof attrs { +// google.protobuf.Struct attributes = 10 [(custom_options.v1.subtype) = "default"]; +// // other subtype attributes types +// } +// } +// +// Also note that for any of the id based lookups to function, the file that contains +// the proto.Message definition must set the "domain" custom option. +func transformRequestAttributes(req proto.Message) (proto.Message, error) { + domain := messageDomain(req) + + r := req.ProtoReflect() + fields := r.Descriptor().Fields() + + itemField := fields.ByName("item") + idField := fields.ByName("id") + attributesField := fields.ByName("attributes") + + fieldValue := func(m protoreflect.Message, fd protoreflect.FieldDescriptor) string { + if fd == nil { + return "" + } + return m.Get(fd).String() + } + + var st Subtype + switch { + case itemField != nil: + itemR := itemField.Message() + if itemR == nil { + return req, nil + } + id := fieldValue(r, idField) + + item := r.Get(itemField).Message().Interface() + itemFields := itemR.Fields() + + typeField := itemFields.ByName("type") + t := fieldValue(item.ProtoReflect(), typeField) + + sourceIdField := sourceIdFieldDescriptor(item.ProtoReflect().Descriptor()) + sourceId := fieldValue(item.ProtoReflect(), sourceIdField) + + switch { + case idField != nil && id != "": + st = SubtypeFromId(domain, id) + case sourceIdField != nil && sourceId != "": + st = SubtypeFromId(domain, sourceId) + case typeField != nil && t != "": + st = Subtype(t) + default: // need either type or id + return req, nil + } + if err := convertAttributesToSubtype(item, st); err != nil { + return req, err + } + case idField != nil && attributesField != nil: + id := r.Get(idField).String() + st = SubtypeFromId(domain, id) + if err := convertAttributesToSubtype(req, st); err != nil { + return req, err + } + } + return req, nil +} + +func transformResponseItemAttributes(item proto.Message) error { + r := item.ProtoReflect() + desc := r.Descriptor() + + typeField := desc.Fields().ByName("type") + if typeField == nil { + // not an item with subtypes + return nil + } + + attrsField := desc.Oneofs().ByName("attrs") + if attrsField == nil { + // not an item with attrs oneof + return nil + } + + if r.WhichOneof(attrsField) == nil { + // attrs field is not set, nothing to do + return nil + } + + st := Subtype(item.ProtoReflect().Get(typeField).String()) + return convertAttributesToDefault(item, st) +} + +// transformResponseAttributes will modify the response proto.Message, setting +// any subtype attribute fields into the default structpb.Struct field. It looks +// for some specific structure in the proto.Message to identify that it is a +// message that needs transformation. +// +// The first structure is a message that contains a single "item" that is a +// message that has an "attrs" oneof for attributes: +// +// message CreateFooResponse { +// item Foo = 1; +// } +// message Foo { +// oneof attrs { +// google.protobuf.Struct attributes = 10 [(custom_options.v1.subtype) = "default"]; +// // other subtype attributes types +// } +// } +// +// The second structure is a message that contains a single "items" that is a +// slice of item messages that have an "attrs" oneof for attributes: +// +// message ListFooResponse { +// items []Foo = 1; +// } +// message Foo { +// oneof attrs { +// google.protobuf.Struct attributes = 10 [(custom_options.v1.subtype) = "default"]; +// // other subtype attributes types +// } +// } +func transformResponseAttributes(res proto.Message) (proto.Message, error) { + r := res.ProtoReflect() + fields := r.Descriptor().Fields() + + itemField := fields.ByName("item") + itemsField := fields.ByName("items") + switch { + case itemField != nil: + if itemR := itemField.Message(); itemR == nil { + return res, nil + } + + item := r.Get(itemField).Message().Interface() + if err := transformResponseItemAttributes(item); err != nil { + return res, err + } + case itemsField != nil: + if !itemsField.IsList() { + return res, nil + } + items := r.Get(itemsField).List() + + for i := 0; i < items.Len(); i++ { + item := items.Get(i).Message().Interface() + if err := transformResponseItemAttributes(item); err != nil { + return res, err + } + } + } + return res, nil +} + +// AttributeTransformerInterceptor is a grpc server interceptor that will +// transform subtype attributes for requests and responses. This will only +// modify requests and responses that adhere to a specific structure and is done +// to support the use of a oneof for attributes to strongly type the attributes +// while allowing the JSON API to provide attributes via a single key. +// +// For example with a protobuf message definition like: +// +// message Account { +// string id = 1; +// string type = 2; +// oneof attrs { +// google.protobuf.Struct attributes = 10 [(controller.custom_options.v1.subtype) = "default"]; +// PasswordAttributes password_attributes = 20 [(controller.custom_options.v1.subtype) = "password"]; +// } +// } +// +// message PasswordAttributes { +// string login_name = 1; +// } +// +// message AccountCreateRequest { +// Account item = 1; +// } +// +// message AccountCreateResponse { +// Account item = 1; +// } +// +// And a create request with JSON request body like: +// { +// "type": "password", +// "attributes": { +// "login_name": "tim" +// } +// } +// +// Will result in a proto request like: +// +// type:"password" attributes:{fields:{key:"login_name" value:{string_value:"tim"}}} +// +// This request will be transformed into: +// +// type:"password" password_attributes:{login_name:"tim"} +func AttributeTransformerInterceptor(_ context.Context) grpc.UnaryServerInterceptor { + const op = "subtypes.AttributeTransformInterceptor" + return func(interceptorCtx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + var err error + if reqMsg, ok := req.(proto.Message); ok { + req, err = transformRequestAttributes(reqMsg) + if err != nil { + return nil, handlers.InvalidArgumentErrorf("Error in provided request.", + map[string]string{"attributes": "Attribute fields do not match the expected format."}) + } + } + + res, handlerErr := handler(interceptorCtx, req) + newRes := res + + if res, ok := res.(proto.Message); ok { + newRes, err = transformResponseAttributes(res) + if err != nil { + return nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "failed building attribute struct: %v", err) + } + } + return newRes, handlerErr + } +} diff --git a/internal/types/subtypes/interceptor_ext_test.go b/internal/types/subtypes/interceptor_ext_test.go new file mode 100644 index 0000000000..4d1d18dab0 --- /dev/null +++ b/internal/types/subtypes/interceptor_ext_test.go @@ -0,0 +1,355 @@ +package subtypes_test + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/hashicorp/boundary/internal/gen/testing/attribute" + "github.com/hashicorp/boundary/internal/servers/controller/handlers" + "github.com/hashicorp/boundary/internal/types/subtypes" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/testing/protocmp" + "google.golang.org/protobuf/types/known/structpb" +) + +func TestAttributeTransformerInterceptor(t *testing.T) { + cases := []struct { + name string + req interface{} + handlerResp interface{} + expectHandlerReq interface{} + excpetResp interface{} + }{ + { + "TestCreateResource/SubResourceRequest", + &attribute.TestCreateResourceRequest{ + Item: &attribute.TestResource{ + Type: "sub_resource", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + &attribute.TestCreateResourceResponse{ + Item: &attribute.TestResource{ + Id: "trsr_one", + Type: "sub_resource", + Attrs: &attribute.TestResource_SubResourceAttributes{ + SubResourceAttributes: &attribute.TestSubResourceAttributes{ + Name: "test", + }, + }, + }, + }, + &attribute.TestCreateResourceRequest{ + Item: &attribute.TestResource{ + Type: "sub_resource", + Attrs: &attribute.TestResource_SubResourceAttributes{ + SubResourceAttributes: &attribute.TestSubResourceAttributes{ + Name: "test", + }, + }, + }, + }, + &attribute.TestCreateResourceResponse{ + Item: &attribute.TestResource{ + Id: "trsr_one", + Type: "sub_resource", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + }, + { + "TestCreateResource/SubResourceRequest/OtherId", + &attribute.TestCreateResourceRequest{ + Item: &attribute.TestResource{ + OtherId: "trsr_parent", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + &attribute.TestCreateResourceResponse{ + Item: &attribute.TestResource{ + Id: "trsr_one", + OtherId: "trsr_parent", + Type: "sub_resource", + Attrs: &attribute.TestResource_SubResourceAttributes{ + SubResourceAttributes: &attribute.TestSubResourceAttributes{ + Name: "test", + }, + }, + }, + }, + &attribute.TestCreateResourceRequest{ + Item: &attribute.TestResource{ + OtherId: "trsr_parent", + Attrs: &attribute.TestResource_SubResourceAttributes{ + SubResourceAttributes: &attribute.TestSubResourceAttributes{ + Name: "test", + }, + }, + }, + }, + &attribute.TestCreateResourceResponse{ + Item: &attribute.TestResource{ + Id: "trsr_one", + OtherId: "trsr_parent", + Type: "sub_resource", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + }, + { + "TestUpdateResource/SubResourceRequest", + &attribute.TestUpdateResourceRequest{ + Id: "trsr_one", + Item: &attribute.TestResource{ + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + &attribute.TestUpdateResourceResponse{ + Item: &attribute.TestResource{ + Id: "trsr_one", + Type: "sub_resource", + Attrs: &attribute.TestResource_SubResourceAttributes{ + SubResourceAttributes: &attribute.TestSubResourceAttributes{ + Name: "test", + }, + }, + }, + }, + &attribute.TestUpdateResourceRequest{ + Id: "trsr_one", + Item: &attribute.TestResource{ + Attrs: &attribute.TestResource_SubResourceAttributes{ + SubResourceAttributes: &attribute.TestSubResourceAttributes{ + Name: "test", + }, + }, + }, + }, + &attribute.TestUpdateResourceResponse{ + Item: &attribute.TestResource{ + Id: "trsr_one", + Type: "sub_resource", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + }, + { + "TestNoItemAttributes/SubResourceRequest", + &attribute.TestNoItemAttributes{ + Id: "trsr_one", + Attrs: &attribute.TestNoItemAttributes_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + &attribute.TestNoItemAttributes{ + Id: "trsr_one", + Attrs: &attribute.TestNoItemAttributes_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + &attribute.TestNoItemAttributes{ + Id: "trsr_one", + Attrs: &attribute.TestNoItemAttributes_SubResourceAttributes{ + SubResourceAttributes: &attribute.TestSubResourceAttributes{ + Name: "test", + }, + }, + }, + &attribute.TestNoItemAttributes{ + Id: "trsr_one", + Attrs: &attribute.TestNoItemAttributes_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + { + "TestListResourceResponse", + nil, + &attribute.TestListResourceResponse{ + Items: []*attribute.TestResource{ + { + Type: "sub_resource", + Attrs: &attribute.TestResource_SubResourceAttributes{ + SubResourceAttributes: &attribute.TestSubResourceAttributes{ + Name: "test", + }, + }, + }, + { + Type: "default", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + { + Type: "unknown", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + }, + nil, + &attribute.TestListResourceResponse{ + Items: []*attribute.TestResource{ + { + Type: "sub_resource", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + { + Type: "default", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + { + Type: "unknown", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + }, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + ctx := context.Background() + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + require.Empty(t, cmp.Diff(req, tc.expectHandlerReq, protocmp.Transform())) + return tc.handlerResp, nil + } + + got, err := subtypes.AttributeTransformerInterceptor(ctx)(ctx, tc.req, nil, handler) + require.NoError(t, err) + require.Empty(t, cmp.Diff(got, tc.excpetResp, protocmp.Transform())) + }) + } +} + +func TestAttributeTransformerInterceptorRequestErrors(t *testing.T) { + cases := []struct { + name string + req interface{} + want error + }{ + { + "InvalidAttributes", + &attribute.TestCreateResourceRequest{ + Item: &attribute.TestResource{ + Type: "sub_resource", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "foo": "test", + }) + return attrs + }(), + }, + }, + }, + handlers.InvalidArgumentErrorf("Error in provided request.", + map[string]string{"attributes": "Attribute fields do not match the expected format."}), + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + ctx := context.Background() + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + t.Fatalf("handler should not be called") + return nil, nil + } + + _, err := subtypes.AttributeTransformerInterceptor(ctx)(ctx, tc.req, nil, handler) + require.Error(t, err) + require.ErrorIs(t, err, tc.want) + }) + } +} diff --git a/internal/types/subtypes/interceptor_test.go b/internal/types/subtypes/interceptor_test.go new file mode 100644 index 0000000000..3a15853217 --- /dev/null +++ b/internal/types/subtypes/interceptor_test.go @@ -0,0 +1,590 @@ +package subtypes + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/hashicorp/boundary/internal/gen/testing/attribute" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/testing/protocmp" + "google.golang.org/protobuf/types/known/structpb" +) + +func init() { + Register("test", Subtype("sub_resource"), "trsr") + Register("test", Subtype("resource_plugin"), "trrp") +} + +func TestTransformRequestAttributes(t *testing.T) { + cases := []struct { + name string + req proto.Message + expected proto.Message + }{ + { + "TestCreateResource/SubResourceRequest", + &attribute.TestCreateResourceRequest{ + Item: &attribute.TestResource{ + Type: "sub_resource", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + &attribute.TestCreateResourceRequest{ + Item: &attribute.TestResource{ + Type: "sub_resource", + Attrs: &attribute.TestResource_SubResourceAttributes{ + SubResourceAttributes: &attribute.TestSubResourceAttributes{ + Name: "test", + }, + }, + }, + }, + }, + { + "TestCreateResource/DefaultResourceRequest", + &attribute.TestCreateResourceRequest{ + Item: &attribute.TestResource{ + Type: "default", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + &attribute.TestCreateResourceRequest{ + Item: &attribute.TestResource{ + Type: "default", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + }, + { + "TestCreateResource/UnknownResourceRequest", + &attribute.TestCreateResourceRequest{ + Item: &attribute.TestResource{ + Type: "unknown", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + &attribute.TestCreateResourceRequest{ + Item: &attribute.TestResource{ + Type: "unknown", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + }, + { + "TestUpdateResource/SubResourceRequest", + &attribute.TestUpdateResourceRequest{ + Id: "trsr_one", + Item: &attribute.TestResource{ + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + &attribute.TestUpdateResourceRequest{ + Id: "trsr_one", + Item: &attribute.TestResource{ + Attrs: &attribute.TestResource_SubResourceAttributes{ + SubResourceAttributes: &attribute.TestSubResourceAttributes{ + Name: "test", + }, + }, + }, + }, + }, + { + "TestUpdateResource/PluginResourceRequest", + &attribute.TestUpdateResourceRequest{ + Id: "trdp_one", + Item: &attribute.TestResource{ + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + &attribute.TestUpdateResourceRequest{ + Id: "trdp_one", + Item: &attribute.TestResource{ + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + }, + { + "TestUpdateResource/UnknownResourceRequest", + &attribute.TestUpdateResourceRequest{ + Id: "unknown", + Item: &attribute.TestResource{ + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + &attribute.TestUpdateResourceRequest{ + Id: "unknown", + Item: &attribute.TestResource{ + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + }, + { + "TestRequestNoItem", + &attribute.TestRequestNoItem{ + Name: "test", + }, + &attribute.TestRequestNoItem{ + Name: "test", + }, + }, + { + "TestRequestItemNotMessage", + &attribute.TestRequestItemNotMessage{ + Item: "test", + }, + &attribute.TestRequestItemNotMessage{ + Item: "test", + }, + }, + { + "TestRequestItemNoType", + &attribute.TestRequestItemNoType{ + Item: &attribute.TestItemNoType{ + Id: "test", + }, + }, + &attribute.TestRequestItemNoType{ + Item: &attribute.TestItemNoType{ + Id: "test", + }, + }, + }, + { + "TestNoItemAttributes/SubResourceRequest", + &attribute.TestNoItemAttributes{ + Id: "trsr_one", + Attrs: &attribute.TestNoItemAttributes_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + &attribute.TestNoItemAttributes{ + Id: "trsr_one", + Attrs: &attribute.TestNoItemAttributes_SubResourceAttributes{ + SubResourceAttributes: &attribute.TestSubResourceAttributes{ + Name: "test", + }, + }, + }, + }, + { + "TestCreateNoOneOfRequest", + &attribute.TestCreateNoOneOfRequest{ + Item: &attribute.TestNoOneOf{ + Type: "sub_resource", + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + &attribute.TestCreateNoOneOfRequest{ + Item: &attribute.TestNoOneOf{ + Type: "sub_resource", + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + { + "TestUpdateNoOneOfRequest", + &attribute.TestUpdateNoOneOfRequest{ + Id: "trsr_one", + Item: &attribute.TestNoOneOf{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + &attribute.TestUpdateNoOneOfRequest{ + Id: "trsr_one", + Item: &attribute.TestNoOneOf{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + got, err := transformRequestAttributes(tc.req) + require.NoError(t, err) + assert.Empty(t, cmp.Diff(got, tc.expected, protocmp.Transform())) + }) + } +} + +func TestTransformResponseAttributes(t *testing.T) { + cases := []struct { + name string + resp proto.Message + expected proto.Message + }{ + { + "TestListResourceResponse", + &attribute.TestListResourceResponse{ + Items: []*attribute.TestResource{ + { + Type: "sub_resource", + Attrs: &attribute.TestResource_SubResourceAttributes{ + SubResourceAttributes: &attribute.TestSubResourceAttributes{ + Name: "test", + }, + }, + }, + { + Type: "default", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + }, + &attribute.TestListResourceResponse{ + Items: []*attribute.TestResource{ + { + Type: "sub_resource", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + { + Type: "default", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + }, + }, + { + "TestGetResourceResponse/SubResourceAttributes", + &attribute.TestGetResourceResponse{ + Item: &attribute.TestResource{ + Id: "trsr_one", + Type: "sub_resource", + Attrs: &attribute.TestResource_SubResourceAttributes{ + SubResourceAttributes: &attribute.TestSubResourceAttributes{ + Name: "test", + }, + }, + }, + }, + &attribute.TestGetResourceResponse{ + Item: &attribute.TestResource{ + Id: "trsr_one", + Type: "sub_resource", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + }, + { + "TestGetResourceResponse/PluginAttributes", + &attribute.TestGetResourceResponse{ + Item: &attribute.TestResource{ + Id: "trrp_one", + Type: "plugin", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + &attribute.TestGetResourceResponse{ + Item: &attribute.TestResource{ + Id: "trrp_one", + Type: "plugin", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + }, + { + "TestCreateResourceResponse", + &attribute.TestCreateResourceResponse{ + Item: &attribute.TestResource{ + Id: "trsr_one", + Type: "sub_resource", + Attrs: &attribute.TestResource_SubResourceAttributes{ + SubResourceAttributes: &attribute.TestSubResourceAttributes{ + Name: "test", + }, + }, + }, + }, + &attribute.TestCreateResourceResponse{ + Item: &attribute.TestResource{ + Id: "trsr_one", + Type: "sub_resource", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + }, + { + "TestUpdateResourceResponse", + &attribute.TestUpdateResourceResponse{ + Item: &attribute.TestResource{ + Id: "trsr_one", + Type: "sub_resource", + Attrs: &attribute.TestResource_SubResourceAttributes{ + SubResourceAttributes: &attribute.TestSubResourceAttributes{ + Name: "test", + }, + }, + }, + }, + &attribute.TestUpdateResourceResponse{ + Item: &attribute.TestResource{ + Id: "trsr_one", + Type: "sub_resource", + Attrs: &attribute.TestResource_Attributes{ + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + }, + { + "TestResponseNoItem", + &attribute.TestResponseNoItem{ + Name: "test", + }, + &attribute.TestResponseNoItem{ + Name: "test", + }, + }, + { + "TestResponseItemNotMessage", + &attribute.TestResponseItemNotMessage{ + Item: "test", + }, + &attribute.TestResponseItemNotMessage{ + Item: "test", + }, + }, + { + "TestResponseItemNoType", + &attribute.TestResponseItemNoType{ + Item: &attribute.TestItemNoType{ + Id: "test", + }, + }, + &attribute.TestResponseItemNoType{ + Item: &attribute.TestItemNoType{ + Id: "test", + }, + }, + }, + { + "TestCreateNoOneOfResponse", + &attribute.TestCreateNoOneOfResponse{ + Item: &attribute.TestNoOneOf{ + Id: "trsr_one", + Type: "sub_resource", + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + &attribute.TestCreateNoOneOfResponse{ + Item: &attribute.TestNoOneOf{ + Id: "trsr_one", + Type: "sub_resource", + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + { + "TestUpdateNoOneOfResponse", + &attribute.TestUpdateNoOneOfResponse{ + Item: &attribute.TestNoOneOf{ + Id: "trsr_one", + Type: "sub_resource", + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + &attribute.TestUpdateNoOneOfResponse{ + Item: &attribute.TestNoOneOf{ + Id: "trsr_one", + Type: "sub_resource", + Attributes: func() *structpb.Struct { + attrs, _ := structpb.NewStruct(map[string]interface{}{ + "name": "test", + }) + return attrs + }(), + }, + }, + }, + { + "TestCreateResourceOneofUnset", + &attribute.TestCreateResourceResponse{ + Item: &attribute.TestResource{ + Id: "trsr_one", + Type: "sub_resource", + }, + }, + &attribute.TestCreateResourceResponse{ + Item: &attribute.TestResource{ + Id: "trsr_one", + Type: "sub_resource", + }, + }, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + got, err := transformResponseAttributes(tc.resp) + require.NoError(t, err) + assert.Empty(t, cmp.Diff(got, tc.expected, protocmp.Transform())) + }) + } +} diff --git a/internal/types/subtypes/source_registry.go b/internal/types/subtypes/source_registry.go new file mode 100644 index 0000000000..d0bfb5f1e1 --- /dev/null +++ b/internal/types/subtypes/source_registry.go @@ -0,0 +1,73 @@ +package subtypes + +import ( + "fmt" + "sync" + + "github.com/hashicorp/boundary/sdk/pbs/controller/protooptions" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/reflect/protoregistry" + "google.golang.org/protobuf/types/descriptorpb" +) + +func init() { + globalSourceRegistry = sourceRegistry{ + m: make(map[protoreflect.FullName]protoreflect.FieldDescriptor), + } + + protoregistry.GlobalTypes.RangeMessages(func(m protoreflect.MessageType) bool { + d := m.Descriptor() + if err := globalSourceRegistry.register(d); err != nil { + panic(err) + } + return true + }) +} + +var globalSourceRegistry sourceRegistry + +// sourceRegistry is collection of proto messages with a corresponding +// field descriptor that can be used to determine the Subtype for the message. +type sourceRegistry struct { + sync.RWMutex + + m map[protoreflect.FullName]protoreflect.FieldDescriptor +} + +func (s sourceRegistry) register(d protoreflect.MessageDescriptor) error { + s.Lock() + defer s.Unlock() + + fn := d.FullName() + + if _, present := s.m[fn]; present { + return fmt.Errorf("proto message %s already registered", fn) + } + + fields := d.Fields() + for i := 0; i < fields.Len(); i++ { + f := fields.Get(i) + + opts := f.Options().(*descriptorpb.FieldOptions) + isSourceId := proto.GetExtension(opts, protooptions.E_SubtypeSourceId).(bool) + if isSourceId { + s.m[fn] = f + } + } + return nil +} + +func (s sourceRegistry) get(d protoreflect.MessageDescriptor) protoreflect.FieldDescriptor { + s.RLock() + defer s.RUnlock() + + return s.m[d.FullName()] +} + +// sourceIdFieldDescriptor is used by the AttributeTransformInterceptor to retrieve +// a proto FieldDescriptor of an id field that can be used to determine +// the given Message's subtype. +func sourceIdFieldDescriptor(d protoreflect.MessageDescriptor) protoreflect.FieldDescriptor { + return globalSourceRegistry.get(d) +}