diff --git a/pb/c1/connector/v2/entitlement.pb.go b/pb/c1/connector/v2/entitlement.pb.go index ec6c1d0e2..b275419e5 100644 --- a/pb/c1/connector/v2/entitlement.pb.go +++ b/pb/c1/connector/v2/entitlement.pb.go @@ -300,6 +300,134 @@ func (x *EntitlementsServiceListEntitlementsResponse) GetAnnotations() []*anypb. return nil } +type EntitlementsServiceListEntitlementsRequestStream struct { + state protoimpl.MessageState `protogen:"open.v1"` + Resource *Resource `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"` + PageSize uint32 `protobuf:"varint,2,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + PageToken string `protobuf:"bytes,3,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` + Annotations []*anypb.Any `protobuf:"bytes,4,rep,name=annotations,proto3" json:"annotations,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *EntitlementsServiceListEntitlementsRequestStream) Reset() { + *x = EntitlementsServiceListEntitlementsRequestStream{} + mi := &file_c1_connector_v2_entitlement_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *EntitlementsServiceListEntitlementsRequestStream) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EntitlementsServiceListEntitlementsRequestStream) ProtoMessage() {} + +func (x *EntitlementsServiceListEntitlementsRequestStream) ProtoReflect() protoreflect.Message { + mi := &file_c1_connector_v2_entitlement_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EntitlementsServiceListEntitlementsRequestStream.ProtoReflect.Descriptor instead. +func (*EntitlementsServiceListEntitlementsRequestStream) Descriptor() ([]byte, []int) { + return file_c1_connector_v2_entitlement_proto_rawDescGZIP(), []int{3} +} + +func (x *EntitlementsServiceListEntitlementsRequestStream) GetResource() *Resource { + if x != nil { + return x.Resource + } + return nil +} + +func (x *EntitlementsServiceListEntitlementsRequestStream) GetPageSize() uint32 { + if x != nil { + return x.PageSize + } + return 0 +} + +func (x *EntitlementsServiceListEntitlementsRequestStream) GetPageToken() string { + if x != nil { + return x.PageToken + } + return "" +} + +func (x *EntitlementsServiceListEntitlementsRequestStream) GetAnnotations() []*anypb.Any { + if x != nil { + return x.Annotations + } + return nil +} + +type EntitlementsServiceListEntitlementsResponseStream struct { + state protoimpl.MessageState `protogen:"open.v1"` + List []*Entitlement `protobuf:"bytes,1,rep,name=list,proto3" json:"list,omitempty"` + NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` + Annotations []*anypb.Any `protobuf:"bytes,3,rep,name=annotations,proto3" json:"annotations,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *EntitlementsServiceListEntitlementsResponseStream) Reset() { + *x = EntitlementsServiceListEntitlementsResponseStream{} + mi := &file_c1_connector_v2_entitlement_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *EntitlementsServiceListEntitlementsResponseStream) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EntitlementsServiceListEntitlementsResponseStream) ProtoMessage() {} + +func (x *EntitlementsServiceListEntitlementsResponseStream) ProtoReflect() protoreflect.Message { + mi := &file_c1_connector_v2_entitlement_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EntitlementsServiceListEntitlementsResponseStream.ProtoReflect.Descriptor instead. +func (*EntitlementsServiceListEntitlementsResponseStream) Descriptor() ([]byte, []int) { + return file_c1_connector_v2_entitlement_proto_rawDescGZIP(), []int{4} +} + +func (x *EntitlementsServiceListEntitlementsResponseStream) GetList() []*Entitlement { + if x != nil { + return x.List + } + return nil +} + +func (x *EntitlementsServiceListEntitlementsResponseStream) GetNextPageToken() string { + if x != nil { + return x.NextPageToken + } + return "" +} + +func (x *EntitlementsServiceListEntitlementsResponseStream) GetAnnotations() []*anypb.Any { + if x != nil { + return x.Annotations + } + return nil +} + var File_c1_connector_v2_entitlement_proto protoreflect.FileDescriptor var file_c1_connector_v2_entitlement_proto_rawDesc = string([]byte{ @@ -373,21 +501,61 @@ var file_c1_connector_v2_entitlement_proto_rawDesc = string([]byte{ 0x12, 0x36, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x0b, 0x61, 0x6e, 0x6e, - 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x32, 0xa5, 0x01, 0x0a, 0x13, 0x45, 0x6e, 0x74, + 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xf9, 0x01, 0x0a, 0x30, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x8d, 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x3b, 0x2e, 0x63, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x32, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x45, - 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x3c, 0x2e, 0x63, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, + 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x35, 0x0a, + 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x63, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2e, 0x76, + 0x32, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x12, 0x27, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x0a, 0xfa, 0x42, 0x07, 0x2a, 0x05, 0x18, 0xfa, + 0x01, 0x40, 0x01, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x2d, 0x0a, + 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x0e, 0xfa, 0x42, 0x0b, 0x72, 0x09, 0x20, 0x01, 0x28, 0x80, 0x80, 0x40, 0xd0, 0x01, + 0x01, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x36, 0x0a, 0x0b, + 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xd5, 0x01, 0x0a, 0x31, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, + 0x45, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x30, 0x0a, 0x04, 0x6c, 0x69, + 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x31, 0x2e, 0x63, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x32, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, + 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x0f, + 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0e, 0xfa, 0x42, 0x0b, 0x72, 0x09, 0x20, 0x01, 0x28, 0x80, + 0x80, 0x40, 0xd0, 0x01, 0x01, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, + 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x36, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, + 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x32, 0xcb, 0x02, 0x0a, + 0x13, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x12, 0x8d, 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, + 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x3b, 0x2e, 0x63, 0x31, 0x2e, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x32, 0x2e, 0x45, 0x6e, 0x74, 0x69, + 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, + 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3c, 0x2e, 0x63, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x32, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, + 0x45, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0xa3, 0x01, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, + 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, + 0x41, 0x2e, 0x63, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2e, 0x76, + 0x32, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x1a, 0x42, 0x2e, 0x63, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x32, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, - 0x6f, 0x6e, 0x64, 0x75, 0x63, 0x74, 0x6f, 0x72, 0x6f, 0x6e, 0x65, 0x2f, 0x62, 0x61, 0x74, 0x6f, - 0x6e, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x62, 0x2f, 0x63, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x28, 0x01, 0x30, 0x01, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x64, 0x75, 0x63, 0x74, + 0x6f, 0x72, 0x6f, 0x6e, 0x65, 0x2f, 0x62, 0x61, 0x74, 0x6f, 0x6e, 0x2d, 0x73, 0x64, 0x6b, 0x2f, + 0x70, 0x62, 0x2f, 0x63, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2f, + 0x76, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, }) var ( @@ -403,32 +571,40 @@ func file_c1_connector_v2_entitlement_proto_rawDescGZIP() []byte { } var file_c1_connector_v2_entitlement_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_c1_connector_v2_entitlement_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_c1_connector_v2_entitlement_proto_msgTypes = make([]protoimpl.MessageInfo, 5) var file_c1_connector_v2_entitlement_proto_goTypes = []any{ - (Entitlement_PurposeValue)(0), // 0: c1.connector.v2.Entitlement.PurposeValue - (*Entitlement)(nil), // 1: c1.connector.v2.Entitlement - (*EntitlementsServiceListEntitlementsRequest)(nil), // 2: c1.connector.v2.EntitlementsServiceListEntitlementsRequest - (*EntitlementsServiceListEntitlementsResponse)(nil), // 3: c1.connector.v2.EntitlementsServiceListEntitlementsResponse - (*Resource)(nil), // 4: c1.connector.v2.Resource - (*ResourceType)(nil), // 5: c1.connector.v2.ResourceType - (*anypb.Any)(nil), // 6: google.protobuf.Any + (Entitlement_PurposeValue)(0), // 0: c1.connector.v2.Entitlement.PurposeValue + (*Entitlement)(nil), // 1: c1.connector.v2.Entitlement + (*EntitlementsServiceListEntitlementsRequest)(nil), // 2: c1.connector.v2.EntitlementsServiceListEntitlementsRequest + (*EntitlementsServiceListEntitlementsResponse)(nil), // 3: c1.connector.v2.EntitlementsServiceListEntitlementsResponse + (*EntitlementsServiceListEntitlementsRequestStream)(nil), // 4: c1.connector.v2.EntitlementsServiceListEntitlementsRequestStream + (*EntitlementsServiceListEntitlementsResponseStream)(nil), // 5: c1.connector.v2.EntitlementsServiceListEntitlementsResponseStream + (*Resource)(nil), // 6: c1.connector.v2.Resource + (*ResourceType)(nil), // 7: c1.connector.v2.ResourceType + (*anypb.Any)(nil), // 8: google.protobuf.Any } var file_c1_connector_v2_entitlement_proto_depIdxs = []int32{ - 4, // 0: c1.connector.v2.Entitlement.resource:type_name -> c1.connector.v2.Resource - 5, // 1: c1.connector.v2.Entitlement.grantable_to:type_name -> c1.connector.v2.ResourceType - 6, // 2: c1.connector.v2.Entitlement.annotations:type_name -> google.protobuf.Any - 0, // 3: c1.connector.v2.Entitlement.purpose:type_name -> c1.connector.v2.Entitlement.PurposeValue - 4, // 4: c1.connector.v2.EntitlementsServiceListEntitlementsRequest.resource:type_name -> c1.connector.v2.Resource - 6, // 5: c1.connector.v2.EntitlementsServiceListEntitlementsRequest.annotations:type_name -> google.protobuf.Any - 1, // 6: c1.connector.v2.EntitlementsServiceListEntitlementsResponse.list:type_name -> c1.connector.v2.Entitlement - 6, // 7: c1.connector.v2.EntitlementsServiceListEntitlementsResponse.annotations:type_name -> google.protobuf.Any - 2, // 8: c1.connector.v2.EntitlementsService.ListEntitlements:input_type -> c1.connector.v2.EntitlementsServiceListEntitlementsRequest - 3, // 9: c1.connector.v2.EntitlementsService.ListEntitlements:output_type -> c1.connector.v2.EntitlementsServiceListEntitlementsResponse - 9, // [9:10] is the sub-list for method output_type - 8, // [8:9] is the sub-list for method input_type - 8, // [8:8] is the sub-list for extension type_name - 8, // [8:8] is the sub-list for extension extendee - 0, // [0:8] is the sub-list for field type_name + 6, // 0: c1.connector.v2.Entitlement.resource:type_name -> c1.connector.v2.Resource + 7, // 1: c1.connector.v2.Entitlement.grantable_to:type_name -> c1.connector.v2.ResourceType + 8, // 2: c1.connector.v2.Entitlement.annotations:type_name -> google.protobuf.Any + 0, // 3: c1.connector.v2.Entitlement.purpose:type_name -> c1.connector.v2.Entitlement.PurposeValue + 6, // 4: c1.connector.v2.EntitlementsServiceListEntitlementsRequest.resource:type_name -> c1.connector.v2.Resource + 8, // 5: c1.connector.v2.EntitlementsServiceListEntitlementsRequest.annotations:type_name -> google.protobuf.Any + 1, // 6: c1.connector.v2.EntitlementsServiceListEntitlementsResponse.list:type_name -> c1.connector.v2.Entitlement + 8, // 7: c1.connector.v2.EntitlementsServiceListEntitlementsResponse.annotations:type_name -> google.protobuf.Any + 6, // 8: c1.connector.v2.EntitlementsServiceListEntitlementsRequestStream.resource:type_name -> c1.connector.v2.Resource + 8, // 9: c1.connector.v2.EntitlementsServiceListEntitlementsRequestStream.annotations:type_name -> google.protobuf.Any + 1, // 10: c1.connector.v2.EntitlementsServiceListEntitlementsResponseStream.list:type_name -> c1.connector.v2.Entitlement + 8, // 11: c1.connector.v2.EntitlementsServiceListEntitlementsResponseStream.annotations:type_name -> google.protobuf.Any + 2, // 12: c1.connector.v2.EntitlementsService.ListEntitlements:input_type -> c1.connector.v2.EntitlementsServiceListEntitlementsRequest + 4, // 13: c1.connector.v2.EntitlementsService.ListEntitlementsStream:input_type -> c1.connector.v2.EntitlementsServiceListEntitlementsRequestStream + 3, // 14: c1.connector.v2.EntitlementsService.ListEntitlements:output_type -> c1.connector.v2.EntitlementsServiceListEntitlementsResponse + 5, // 15: c1.connector.v2.EntitlementsService.ListEntitlementsStream:output_type -> c1.connector.v2.EntitlementsServiceListEntitlementsResponseStream + 14, // [14:16] is the sub-list for method output_type + 12, // [12:14] is the sub-list for method input_type + 12, // [12:12] is the sub-list for extension type_name + 12, // [12:12] is the sub-list for extension extendee + 0, // [0:12] is the sub-list for field type_name } func init() { file_c1_connector_v2_entitlement_proto_init() } @@ -443,7 +619,7 @@ func file_c1_connector_v2_entitlement_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_c1_connector_v2_entitlement_proto_rawDesc), len(file_c1_connector_v2_entitlement_proto_rawDesc)), NumEnums: 1, - NumMessages: 3, + NumMessages: 5, NumExtensions: 0, NumServices: 1, }, diff --git a/pb/c1/connector/v2/entitlement.pb.validate.go b/pb/c1/connector/v2/entitlement.pb.validate.go index 4f9790765..56539a713 100644 --- a/pb/c1/connector/v2/entitlement.pb.validate.go +++ b/pb/c1/connector/v2/entitlement.pb.validate.go @@ -683,3 +683,405 @@ var _ interface { Cause() error ErrorName() string } = EntitlementsServiceListEntitlementsResponseValidationError{} + +// Validate checks the field values on +// EntitlementsServiceListEntitlementsRequestStream with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *EntitlementsServiceListEntitlementsRequestStream) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on +// EntitlementsServiceListEntitlementsRequestStream with the rules defined in +// the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in +// EntitlementsServiceListEntitlementsRequestStreamMultiError, or nil if none found. +func (m *EntitlementsServiceListEntitlementsRequestStream) ValidateAll() error { + return m.validate(true) +} + +func (m *EntitlementsServiceListEntitlementsRequestStream) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if all { + switch v := interface{}(m.GetResource()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, EntitlementsServiceListEntitlementsRequestStreamValidationError{ + field: "Resource", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, EntitlementsServiceListEntitlementsRequestStreamValidationError{ + field: "Resource", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetResource()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return EntitlementsServiceListEntitlementsRequestStreamValidationError{ + field: "Resource", + reason: "embedded message failed validation", + cause: err, + } + } + } + + if m.GetPageSize() != 0 { + + if m.GetPageSize() > 250 { + err := EntitlementsServiceListEntitlementsRequestStreamValidationError{ + field: "PageSize", + reason: "value must be less than or equal to 250", + } + if !all { + return err + } + errors = append(errors, err) + } + + } + + if m.GetPageToken() != "" { + + if l := len(m.GetPageToken()); l < 1 || l > 1048576 { + err := EntitlementsServiceListEntitlementsRequestStreamValidationError{ + field: "PageToken", + reason: "value length must be between 1 and 1048576 bytes, inclusive", + } + if !all { + return err + } + errors = append(errors, err) + } + + } + + for idx, item := range m.GetAnnotations() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, EntitlementsServiceListEntitlementsRequestStreamValidationError{ + field: fmt.Sprintf("Annotations[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, EntitlementsServiceListEntitlementsRequestStreamValidationError{ + field: fmt.Sprintf("Annotations[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return EntitlementsServiceListEntitlementsRequestStreamValidationError{ + field: fmt.Sprintf("Annotations[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if len(errors) > 0 { + return EntitlementsServiceListEntitlementsRequestStreamMultiError(errors) + } + + return nil +} + +// EntitlementsServiceListEntitlementsRequestStreamMultiError is an error +// wrapping multiple validation errors returned by +// EntitlementsServiceListEntitlementsRequestStream.ValidateAll() if the +// designated constraints aren't met. +type EntitlementsServiceListEntitlementsRequestStreamMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m EntitlementsServiceListEntitlementsRequestStreamMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m EntitlementsServiceListEntitlementsRequestStreamMultiError) AllErrors() []error { return m } + +// EntitlementsServiceListEntitlementsRequestStreamValidationError is the +// validation error returned by +// EntitlementsServiceListEntitlementsRequestStream.Validate if the designated +// constraints aren't met. +type EntitlementsServiceListEntitlementsRequestStreamValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e EntitlementsServiceListEntitlementsRequestStreamValidationError) Field() string { + return e.field +} + +// Reason function returns reason value. +func (e EntitlementsServiceListEntitlementsRequestStreamValidationError) Reason() string { + return e.reason +} + +// Cause function returns cause value. +func (e EntitlementsServiceListEntitlementsRequestStreamValidationError) Cause() error { + return e.cause +} + +// Key function returns key value. +func (e EntitlementsServiceListEntitlementsRequestStreamValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e EntitlementsServiceListEntitlementsRequestStreamValidationError) ErrorName() string { + return "EntitlementsServiceListEntitlementsRequestStreamValidationError" +} + +// Error satisfies the builtin error interface +func (e EntitlementsServiceListEntitlementsRequestStreamValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sEntitlementsServiceListEntitlementsRequestStream.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = EntitlementsServiceListEntitlementsRequestStreamValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = EntitlementsServiceListEntitlementsRequestStreamValidationError{} + +// Validate checks the field values on +// EntitlementsServiceListEntitlementsResponseStream with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *EntitlementsServiceListEntitlementsResponseStream) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on +// EntitlementsServiceListEntitlementsResponseStream with the rules defined in +// the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in +// EntitlementsServiceListEntitlementsResponseStreamMultiError, or nil if none found. +func (m *EntitlementsServiceListEntitlementsResponseStream) ValidateAll() error { + return m.validate(true) +} + +func (m *EntitlementsServiceListEntitlementsResponseStream) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + for idx, item := range m.GetList() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, EntitlementsServiceListEntitlementsResponseStreamValidationError{ + field: fmt.Sprintf("List[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, EntitlementsServiceListEntitlementsResponseStreamValidationError{ + field: fmt.Sprintf("List[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return EntitlementsServiceListEntitlementsResponseStreamValidationError{ + field: fmt.Sprintf("List[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if m.GetNextPageToken() != "" { + + if l := len(m.GetNextPageToken()); l < 1 || l > 1048576 { + err := EntitlementsServiceListEntitlementsResponseStreamValidationError{ + field: "NextPageToken", + reason: "value length must be between 1 and 1048576 bytes, inclusive", + } + if !all { + return err + } + errors = append(errors, err) + } + + } + + for idx, item := range m.GetAnnotations() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, EntitlementsServiceListEntitlementsResponseStreamValidationError{ + field: fmt.Sprintf("Annotations[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, EntitlementsServiceListEntitlementsResponseStreamValidationError{ + field: fmt.Sprintf("Annotations[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return EntitlementsServiceListEntitlementsResponseStreamValidationError{ + field: fmt.Sprintf("Annotations[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if len(errors) > 0 { + return EntitlementsServiceListEntitlementsResponseStreamMultiError(errors) + } + + return nil +} + +// EntitlementsServiceListEntitlementsResponseStreamMultiError is an error +// wrapping multiple validation errors returned by +// EntitlementsServiceListEntitlementsResponseStream.ValidateAll() if the +// designated constraints aren't met. +type EntitlementsServiceListEntitlementsResponseStreamMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m EntitlementsServiceListEntitlementsResponseStreamMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m EntitlementsServiceListEntitlementsResponseStreamMultiError) AllErrors() []error { return m } + +// EntitlementsServiceListEntitlementsResponseStreamValidationError is the +// validation error returned by +// EntitlementsServiceListEntitlementsResponseStream.Validate if the +// designated constraints aren't met. +type EntitlementsServiceListEntitlementsResponseStreamValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e EntitlementsServiceListEntitlementsResponseStreamValidationError) Field() string { + return e.field +} + +// Reason function returns reason value. +func (e EntitlementsServiceListEntitlementsResponseStreamValidationError) Reason() string { + return e.reason +} + +// Cause function returns cause value. +func (e EntitlementsServiceListEntitlementsResponseStreamValidationError) Cause() error { + return e.cause +} + +// Key function returns key value. +func (e EntitlementsServiceListEntitlementsResponseStreamValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e EntitlementsServiceListEntitlementsResponseStreamValidationError) ErrorName() string { + return "EntitlementsServiceListEntitlementsResponseStreamValidationError" +} + +// Error satisfies the builtin error interface +func (e EntitlementsServiceListEntitlementsResponseStreamValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sEntitlementsServiceListEntitlementsResponseStream.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = EntitlementsServiceListEntitlementsResponseStreamValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = EntitlementsServiceListEntitlementsResponseStreamValidationError{} diff --git a/pb/c1/connector/v2/entitlement_grpc.pb.go b/pb/c1/connector/v2/entitlement_grpc.pb.go index 821161d32..fd44b8ff2 100644 --- a/pb/c1/connector/v2/entitlement_grpc.pb.go +++ b/pb/c1/connector/v2/entitlement_grpc.pb.go @@ -19,7 +19,8 @@ import ( const _ = grpc.SupportPackageIsVersion9 const ( - EntitlementsService_ListEntitlements_FullMethodName = "/c1.connector.v2.EntitlementsService/ListEntitlements" + EntitlementsService_ListEntitlements_FullMethodName = "/c1.connector.v2.EntitlementsService/ListEntitlements" + EntitlementsService_ListEntitlementsStream_FullMethodName = "/c1.connector.v2.EntitlementsService/ListEntitlementsStream" ) // EntitlementsServiceClient is the client API for EntitlementsService service. @@ -27,6 +28,7 @@ const ( // 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 EntitlementsServiceClient interface { ListEntitlements(ctx context.Context, in *EntitlementsServiceListEntitlementsRequest, opts ...grpc.CallOption) (*EntitlementsServiceListEntitlementsResponse, error) + ListEntitlementsStream(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[EntitlementsServiceListEntitlementsRequestStream, EntitlementsServiceListEntitlementsResponseStream], error) } type entitlementsServiceClient struct { @@ -47,11 +49,25 @@ func (c *entitlementsServiceClient) ListEntitlements(ctx context.Context, in *En return out, nil } +func (c *entitlementsServiceClient) ListEntitlementsStream(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[EntitlementsServiceListEntitlementsRequestStream, EntitlementsServiceListEntitlementsResponseStream], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &EntitlementsService_ServiceDesc.Streams[0], EntitlementsService_ListEntitlementsStream_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[EntitlementsServiceListEntitlementsRequestStream, EntitlementsServiceListEntitlementsResponseStream]{ClientStream: stream} + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type EntitlementsService_ListEntitlementsStreamClient = grpc.BidiStreamingClient[EntitlementsServiceListEntitlementsRequestStream, EntitlementsServiceListEntitlementsResponseStream] + // EntitlementsServiceServer is the server API for EntitlementsService service. // All implementations should embed UnimplementedEntitlementsServiceServer // for forward compatibility. type EntitlementsServiceServer interface { ListEntitlements(context.Context, *EntitlementsServiceListEntitlementsRequest) (*EntitlementsServiceListEntitlementsResponse, error) + ListEntitlementsStream(grpc.BidiStreamingServer[EntitlementsServiceListEntitlementsRequestStream, EntitlementsServiceListEntitlementsResponseStream]) error } // UnimplementedEntitlementsServiceServer should be embedded to have @@ -64,6 +80,9 @@ type UnimplementedEntitlementsServiceServer struct{} func (UnimplementedEntitlementsServiceServer) ListEntitlements(context.Context, *EntitlementsServiceListEntitlementsRequest) (*EntitlementsServiceListEntitlementsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListEntitlements not implemented") } +func (UnimplementedEntitlementsServiceServer) ListEntitlementsStream(grpc.BidiStreamingServer[EntitlementsServiceListEntitlementsRequestStream, EntitlementsServiceListEntitlementsResponseStream]) error { + return status.Errorf(codes.Unimplemented, "method ListEntitlementsStream not implemented") +} func (UnimplementedEntitlementsServiceServer) testEmbeddedByValue() {} // UnsafeEntitlementsServiceServer may be embedded to opt out of forward compatibility for this service. @@ -102,6 +121,13 @@ func _EntitlementsService_ListEntitlements_Handler(srv interface{}, ctx context. return interceptor(ctx, in, info, handler) } +func _EntitlementsService_ListEntitlementsStream_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(EntitlementsServiceServer).ListEntitlementsStream(&grpc.GenericServerStream[EntitlementsServiceListEntitlementsRequestStream, EntitlementsServiceListEntitlementsResponseStream]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type EntitlementsService_ListEntitlementsStreamServer = grpc.BidiStreamingServer[EntitlementsServiceListEntitlementsRequestStream, EntitlementsServiceListEntitlementsResponseStream] + // EntitlementsService_ServiceDesc is the grpc.ServiceDesc for EntitlementsService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -114,6 +140,13 @@ var EntitlementsService_ServiceDesc = grpc.ServiceDesc{ Handler: _EntitlementsService_ListEntitlements_Handler, }, }, - Streams: []grpc.StreamDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "ListEntitlementsStream", + Handler: _EntitlementsService_ListEntitlementsStream_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, Metadata: "c1/connector/v2/entitlement.proto", } diff --git a/pkg/connectorbuilder/connectorbuilder.go b/pkg/connectorbuilder/connectorbuilder.go index ee6c5c78e..eb46ea391 100644 --- a/pkg/connectorbuilder/connectorbuilder.go +++ b/pkg/connectorbuilder/connectorbuilder.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "io" "slices" "sort" "time" @@ -11,6 +12,7 @@ import ( "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap" "go.opentelemetry.io/otel" "go.uber.org/zap" + "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" @@ -826,6 +828,54 @@ func (b *builderImpl) ListEntitlements(ctx context.Context, request *v2.Entitlem return resp, nil } +// ListEntitlementsStream returns all the entitlements for a given resource. +func (b *builderImpl) ListEntitlementsStream(s grpc.BidiStreamingServer[v2.EntitlementsServiceListEntitlementsRequestStream, v2.EntitlementsServiceListEntitlementsResponseStream]) error { + ctx := s.Context() + ctx, span := tracer.Start(ctx, "builderImpl.ListEntitlementsStream") + defer span.End() + + for { + request, err := s.Recv() + if err != nil { + if errors.Is(err, io.EOF) { + return nil + } + return err + } + + start := b.nowFunc() + tt := tasks.ListEntitlementsType + rb, ok := b.resourceBuilders[request.Resource.Id.ResourceType] + if !ok { + b.m.RecordTaskFailure(ctx, tt, b.nowFunc().Sub(start)) + return fmt.Errorf("error: list entitlements with unknown resource type %s", request.Resource.Id.ResourceType) + } + + out, nextPageToken, annos, err := rb.Entitlements(ctx, request.Resource, &pagination.Token{ + Size: int(request.PageSize), + Token: request.PageToken, + }) + resp := &v2.EntitlementsServiceListEntitlementsResponseStream{ + List: out, + NextPageToken: nextPageToken, + Annotations: annos, + } + if err != nil { + b.m.RecordTaskFailure(ctx, tt, b.nowFunc().Sub(start)) + return fmt.Errorf("error: listing entitlements failed: %w", err) + } + if request.PageToken != "" && request.PageToken == nextPageToken { + b.m.RecordTaskFailure(ctx, tt, b.nowFunc().Sub(start)) + return fmt.Errorf("error: listing entitlements failed: next page token is the same as the current page token. this is most likely a connector bug") + } + + b.m.RecordTaskSuccess(ctx, tt, b.nowFunc().Sub(start)) + if err := s.Send(resp); err != nil { + return err + } + } +} + // ListGrants lists all the grants for a given resource. func (b *builderImpl) ListGrants(ctx context.Context, request *v2.GrantsServiceListGrantsRequest) (*v2.GrantsServiceListGrantsResponse, error) { ctx, span := tracer.Start(ctx, "builderImpl.ListGrants") diff --git a/pkg/dotc1z/c1file.go b/pkg/dotc1z/c1file.go index ba6f8a139..5965e004a 100644 --- a/pkg/dotc1z/c1file.go +++ b/pkg/dotc1z/c1file.go @@ -11,6 +11,7 @@ import ( "time" "github.com/doug-martin/goqu/v9" + // NOTE: required to register the dialect for goqu. // // If you remove this import, goqu.Dialect("sqlite3") will diff --git a/pkg/dotc1z/entitlements.go b/pkg/dotc1z/entitlements.go index 9456ae77e..cbcc375b0 100644 --- a/pkg/dotc1z/entitlements.go +++ b/pkg/dotc1z/entitlements.go @@ -2,9 +2,12 @@ package dotc1z import ( "context" + "errors" "fmt" + "io" "github.com/doug-martin/goqu/v9" + "google.golang.org/grpc" "google.golang.org/protobuf/proto" v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2" @@ -78,6 +81,45 @@ func (c *C1File) ListEntitlements(ctx context.Context, request *v2.EntitlementsS }, nil } +func (c *C1File) ListEntitlementsStream(g grpc.BidiStreamingServer[v2.EntitlementsServiceListEntitlementsRequestStream, v2.EntitlementsServiceListEntitlementsResponseStream]) error { + ctx := g.Context() + ctx, span := tracer.Start(ctx, "C1File.ListEntitlementsStream") + defer span.End() + + for { + req, err := g.Recv() + if err != nil { + if errors.Is(err, io.EOF) { + // End of stream + return nil + } + return err + } + + objs, nextPageToken, err := c.listConnectorObjects(ctx, entitlements.Name(), req) + if err != nil { + return fmt.Errorf("error listing entitlements: %w", err) + } + + ret := make([]*v2.Entitlement, 0, len(objs)) + for _, o := range objs { + en := &v2.Entitlement{} + err = proto.Unmarshal(o, en) + if err != nil { + return err + } + ret = append(ret, en) + } + + if err := g.Send(&v2.EntitlementsServiceListEntitlementsResponseStream{ + List: ret, + NextPageToken: nextPageToken, + }); err != nil { + return err + } + } +} + func (c *C1File) GetEntitlement(ctx context.Context, request *reader_v2.EntitlementsReaderServiceGetEntitlementRequest) (*reader_v2.EntitlementsReaderServiceGetEntitlementResponse, error) { ctx, span := tracer.Start(ctx, "C1File.GetEntitlement") defer span.End() diff --git a/pkg/sdk/empty_connector.go b/pkg/sdk/empty_connector.go index 2667bbab5..757625629 100644 --- a/pkg/sdk/empty_connector.go +++ b/pkg/sdk/empty_connector.go @@ -53,6 +53,14 @@ func (n *emptyConnector) ListEntitlements( }, nil } +// ListEntitlementsStream returns a list of entitlements. +func (n *emptyConnector) ListEntitlementsStream(ctx context.Context, opts ...grpc.CallOption) ( + grpc.BidiStreamingClient[v2.EntitlementsServiceListEntitlementsRequestStream, v2.EntitlementsServiceListEntitlementsResponseStream], + error, +) { + return MockBidiClient[v2.EntitlementsServiceListEntitlementsRequestStream, v2.EntitlementsServiceListEntitlementsResponseStream]{}, nil +} + // ListGrants returns a list of grants. func (n *emptyConnector) ListGrants(ctx context.Context, request *v2.GrantsServiceListGrantsRequest, opts ...grpc.CallOption) (*v2.GrantsServiceListGrantsResponse, error) { return &v2.GrantsServiceListGrantsResponse{ diff --git a/pkg/sdk/mock_grpc_client.go b/pkg/sdk/mock_grpc_client.go new file mode 100644 index 000000000..c685115ba --- /dev/null +++ b/pkg/sdk/mock_grpc_client.go @@ -0,0 +1,43 @@ +package sdk + +import ( + "context" + + "google.golang.org/grpc/metadata" +) + +type MockBidiClient[Req any, Resp any] struct { +} + +func (m MockBidiClient[Req, Resp]) Send(req *Req) error { + return nil +} + +func (m MockBidiClient[Req, Resp]) Recv() (*Resp, error) { + var res Resp + return &res, nil +} + +func (m MockBidiClient[Req, Resp]) Header() (metadata.MD, error) { + return nil, nil +} + +func (m MockBidiClient[Req, Resp]) Trailer() metadata.MD { + return nil +} + +func (m MockBidiClient[Req, Resp]) CloseSend() error { + return nil +} + +func (m MockBidiClient[Req, Resp]) Context() context.Context { + return context.Background() +} + +func (m MockBidiClient[Req, Resp]) SendMsg(msg any) error { + return nil +} + +func (m MockBidiClient[Req, Resp]) RecvMsg(msg any) error { + return nil +} diff --git a/pkg/sync/syncer.go b/pkg/sync/syncer.go index 7127ba879..eea1529d3 100644 --- a/pkg/sync/syncer.go +++ b/pkg/sync/syncer.go @@ -25,6 +25,7 @@ import ( "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.uber.org/zap" + "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" @@ -214,6 +215,8 @@ type syncer struct { skipEGForResourceType map[string]bool skipEntitlementsAndGrants bool resourceTypeTraits map[string][]v2.ResourceType_Trait + + entitlementStreamer grpc.BidiStreamingClient[v2.EntitlementsServiceListEntitlementsRequestStream, v2.EntitlementsServiceListEntitlementsResponseStream] } const minCheckpointInterval = 10 * time.Second @@ -1075,13 +1078,31 @@ func (s *syncer) syncEntitlementsForResource(ctx context.Context, resourceID *v2 pageToken := s.state.PageToken(ctx) - resp, err := s.connector.ListEntitlements(ctx, &v2.EntitlementsServiceListEntitlementsRequest{ + if s.entitlementStreamer == nil { + entitlementStreamer, err := s.connector.ListEntitlementsStream(ctx) + if err != nil { + return err + } + s.entitlementStreamer = entitlementStreamer + } + + err = s.entitlementStreamer.Send(&v2.EntitlementsServiceListEntitlementsRequestStream{ Resource: resourceResponse.Resource, PageToken: pageToken, }) if err != nil { return err } + + resp, err := s.entitlementStreamer.Recv() + if err != nil { + if errors.Is(err, io.EOF) { + s.entitlementStreamer = nil + return errors.New("expected entitlement response but got end of stream") + } + return err + } + err = s.store.PutEntitlements(ctx, resp.List...) if err != nil { return err @@ -1736,7 +1757,7 @@ func (s *syncer) SyncExternalResourcesWithGrantToEntitlement(ctx context.Context } ents := make([]*v2.Entitlement, 0) - principals := make([]*v2.Resource, 0) + resources := make([]*v2.Resource, 0) resourceTypes := make([]*v2.ResourceType, 0) resourceTypeIDs := mapset.NewSet[string]() resourceIDs := make(map[string]*v2.ResourceId) @@ -1784,17 +1805,17 @@ func (s *syncer) SyncExternalResourcesWithGrantToEntitlement(ctx context.Context batonID := &v2.BatonID{} resourceAnnos.Update(batonID) resourceVal.Annotations = resourceAnnos - principals = append(principals, resourceVal) + resources = append(resources, resourceVal) } - for _, principal := range principals { - rAnnos := annotations.Annotations(principal.GetAnnotations()) - skipEnts := skipEGForResourceType[principal.Id.ResourceType] || rAnnos.Contains(&v2.SkipEntitlementsAndGrants{}) + for _, resource := range resources { + rAnnos := annotations.Annotations(resource.GetAnnotations()) + skipEnts := skipEGForResourceType[resource.Id.ResourceType] || rAnnos.Contains(&v2.SkipEntitlementsAndGrants{}) if skipEnts { continue } - resourceEnts, err := s.listExternalEntitlementsForResource(ctx, principal) + resourceEnts, err := s.listExternalEntitlementsForResource(ctx, resource) if err != nil { return err } @@ -1818,7 +1839,7 @@ func (s *syncer) SyncExternalResourcesWithGrantToEntitlement(ctx context.Context return err } - err = s.store.PutResources(ctx, principals...) + err = s.store.PutResources(ctx, resources...) if err != nil { return err } @@ -1835,12 +1856,12 @@ func (s *syncer) SyncExternalResourcesWithGrantToEntitlement(ctx context.Context l.Info("Synced external resources for entitlement", zap.Int("resource_type_count", len(resourceTypes)), - zap.Int("resource_count", len(principals)), + zap.Int("resource_count", len(resources)), zap.Int("entitlement_count", len(ents)), zap.Int("grant_count", len(grantsForEnts)), ) - err = s.processGrantsWithExternalPrincipals(ctx, principals) + err = s.processGrantsWithExternalPrincipals(ctx, resources) if err != nil { return err } @@ -1984,6 +2005,7 @@ func (s *syncer) listExternalResourcesForResourceType(ctx context.Context, resou func (s *syncer) listExternalEntitlementsForResource(ctx context.Context, resource *v2.Resource) ([]*v2.Entitlement, error) { ents := make([]*v2.Entitlement, 0) + entitlementToken := "" for { entitlementsList, err := s.externalResourceReader.ListEntitlements(ctx, &v2.EntitlementsServiceListEntitlementsRequest{ diff --git a/pkg/sync/syncer_test.go b/pkg/sync/syncer_test.go index 01b87277c..848b0cad1 100644 --- a/pkg/sync/syncer_test.go +++ b/pkg/sync/syncer_test.go @@ -15,6 +15,7 @@ import ( "github.com/conductorone/baton-sdk/pkg/dotc1z" "github.com/conductorone/baton-sdk/pkg/dotc1z/manager" "github.com/conductorone/baton-sdk/pkg/logging" + "github.com/conductorone/baton-sdk/pkg/sdk" et "github.com/conductorone/baton-sdk/pkg/types/entitlement" gt "github.com/conductorone/baton-sdk/pkg/types/grant" rs "github.com/conductorone/baton-sdk/pkg/types/resource" @@ -943,6 +944,13 @@ func (mc *mockConnector) ListEntitlements(ctx context.Context, in *v2.Entitlemen return &v2.EntitlementsServiceListEntitlementsResponse{List: mc.entDB[in.Resource.Id.Resource]}, nil } +func (mc *mockConnector) ListEntitlementsStream(ctx context.Context, opts ...grpc.CallOption) ( + grpc.BidiStreamingClient[v2.EntitlementsServiceListEntitlementsRequestStream, v2.EntitlementsServiceListEntitlementsResponseStream], + error, +) { + return sdk.MockBidiClient[v2.EntitlementsServiceListEntitlementsRequestStream, v2.EntitlementsServiceListEntitlementsResponseStream]{}, nil +} + func (mc *mockConnector) ListGrants(ctx context.Context, in *v2.GrantsServiceListGrantsRequest, opts ...grpc.CallOption) (*v2.GrantsServiceListGrantsResponse, error) { return &v2.GrantsServiceListGrantsResponse{List: mc.grantDB[in.Resource.Id.Resource]}, nil } diff --git a/pkg/types/types.go b/pkg/types/types.go index fc52f6f4e..191c0a9bf 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -1,4 +1,4 @@ -package types //nolint:revive // we want this to be "types" +package types import ( "context" diff --git a/proto/c1/connector/v2/entitlement.proto b/proto/c1/connector/v2/entitlement.proto index b6955a5f5..66785c6a5 100644 --- a/proto/c1/connector/v2/entitlement.proto +++ b/proto/c1/connector/v2/entitlement.proto @@ -10,6 +10,7 @@ option go_package = "github.com/conductorone/baton-sdk/pb/c1/connector/v2"; service EntitlementsService { rpc ListEntitlements(EntitlementsServiceListEntitlementsRequest) returns (EntitlementsServiceListEntitlementsResponse); + rpc ListEntitlementsStream(stream EntitlementsServiceListEntitlementsRequestStream) returns (stream EntitlementsServiceListEntitlementsResponseStream); } message Entitlement { @@ -63,3 +64,27 @@ message EntitlementsServiceListEntitlementsResponse { }]; repeated google.protobuf.Any annotations = 3; } + +message EntitlementsServiceListEntitlementsRequestStream { + c1.connector.v2.Resource resource = 1; + uint32 page_size = 2 [(validate.rules).uint32 = { + ignore_empty: true + lte: 250 + }]; + string page_token = 3 [(validate.rules).string = { + ignore_empty: true + min_bytes: 1 + max_bytes: 1048576 // 1MB + }]; + repeated google.protobuf.Any annotations = 4; +} + +message EntitlementsServiceListEntitlementsResponseStream { + repeated Entitlement list = 1; + string next_page_token = 2 [(validate.rules).string = { + ignore_empty: true + min_bytes: 1 + max_bytes: 1048576 // 1MB + }]; + repeated google.protobuf.Any annotations = 3; +}