diff --git a/Makefile b/Makefile index a9aae001d5..84a4f270bc 100644 --- a/Makefile +++ b/Makefile @@ -395,7 +395,7 @@ deploy: $(BIN)/kind $(BIN)/helm docker-image/pyroscope/build .PHONY: deploy-micro-services deploy-micro-services: $(BIN)/kind $(BIN)/helm docker-image/pyroscope/build - $(call deploy,pyroscope-micro-services,--values=operations/pyroscope/helm/pyroscope/values-micro-services.yaml --set pyroscope.components.querier.resources=null --set pyroscope.components.distributor.resources=null --set pyroscope.components.ingester.resources=null --set pyroscope.components.store-gateway.resources=null --set pyroscope.components.compactor.resources=null) + $(call deploy,pyroscope-micro-services,--values=operations/pyroscope/helm/pyroscope/values-micro-services.yaml --set pyroscope.components.querier.resources=null --set pyroscope.components.distributor.resources=null --set pyroscope.components.ingester.resources=null --set pyroscope.components.store-gateway.resources=null --set pyroscope.components.compactor.resources=null --set pyroscope.components.tenant-settings.resources=null) .PHONY: deploy-monitoring deploy-monitoring: $(BIN)/tk $(BIN)/kind tools/monitoring/environments/default/spec.json diff --git a/api/gen/proto/go/settings/v1/setting.pb.go b/api/gen/proto/go/settings/v1/setting.pb.go new file mode 100644 index 0000000000..8e5b81b220 --- /dev/null +++ b/api/gen/proto/go/settings/v1/setting.pb.go @@ -0,0 +1,436 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc (unknown) +// source: settings/v1/setting.proto + +package settingsv1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type GetSettingsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetSettingsRequest) Reset() { + *x = GetSettingsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_settings_v1_setting_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetSettingsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetSettingsRequest) ProtoMessage() {} + +func (x *GetSettingsRequest) ProtoReflect() protoreflect.Message { + mi := &file_settings_v1_setting_proto_msgTypes[0] + 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 GetSettingsRequest.ProtoReflect.Descriptor instead. +func (*GetSettingsRequest) Descriptor() ([]byte, []int) { + return file_settings_v1_setting_proto_rawDescGZIP(), []int{0} +} + +type GetSettingsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Settings []*Setting `protobuf:"bytes,1,rep,name=settings,proto3" json:"settings,omitempty"` +} + +func (x *GetSettingsResponse) Reset() { + *x = GetSettingsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_settings_v1_setting_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetSettingsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetSettingsResponse) ProtoMessage() {} + +func (x *GetSettingsResponse) ProtoReflect() protoreflect.Message { + mi := &file_settings_v1_setting_proto_msgTypes[1] + 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 GetSettingsResponse.ProtoReflect.Descriptor instead. +func (*GetSettingsResponse) Descriptor() ([]byte, []int) { + return file_settings_v1_setting_proto_rawDescGZIP(), []int{1} +} + +func (x *GetSettingsResponse) GetSettings() []*Setting { + if x != nil { + return x.Settings + } + return nil +} + +type SetSettingsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Setting *Setting `protobuf:"bytes,1,opt,name=setting,proto3" json:"setting,omitempty"` +} + +func (x *SetSettingsRequest) Reset() { + *x = SetSettingsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_settings_v1_setting_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SetSettingsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetSettingsRequest) ProtoMessage() {} + +func (x *SetSettingsRequest) ProtoReflect() protoreflect.Message { + mi := &file_settings_v1_setting_proto_msgTypes[2] + 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 SetSettingsRequest.ProtoReflect.Descriptor instead. +func (*SetSettingsRequest) Descriptor() ([]byte, []int) { + return file_settings_v1_setting_proto_rawDescGZIP(), []int{2} +} + +func (x *SetSettingsRequest) GetSetting() *Setting { + if x != nil { + return x.Setting + } + return nil +} + +type SetSettingsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Setting *Setting `protobuf:"bytes,1,opt,name=setting,proto3" json:"setting,omitempty"` +} + +func (x *SetSettingsResponse) Reset() { + *x = SetSettingsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_settings_v1_setting_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SetSettingsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetSettingsResponse) ProtoMessage() {} + +func (x *SetSettingsResponse) ProtoReflect() protoreflect.Message { + mi := &file_settings_v1_setting_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) +} + +// Deprecated: Use SetSettingsResponse.ProtoReflect.Descriptor instead. +func (*SetSettingsResponse) Descriptor() ([]byte, []int) { + return file_settings_v1_setting_proto_rawDescGZIP(), []int{3} +} + +func (x *SetSettingsResponse) GetSetting() *Setting { + if x != nil { + return x.Setting + } + return nil +} + +type Setting struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + ModifiedAt int64 `protobuf:"varint,3,opt,name=modifiedAt,proto3" json:"modifiedAt,omitempty"` +} + +func (x *Setting) Reset() { + *x = Setting{} + if protoimpl.UnsafeEnabled { + mi := &file_settings_v1_setting_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Setting) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Setting) ProtoMessage() {} + +func (x *Setting) ProtoReflect() protoreflect.Message { + mi := &file_settings_v1_setting_proto_msgTypes[4] + 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 Setting.ProtoReflect.Descriptor instead. +func (*Setting) Descriptor() ([]byte, []int) { + return file_settings_v1_setting_proto_rawDescGZIP(), []int{4} +} + +func (x *Setting) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Setting) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +func (x *Setting) GetModifiedAt() int64 { + if x != nil { + return x.ModifiedAt + } + return 0 +} + +var File_settings_v1_setting_proto protoreflect.FileDescriptor + +var file_settings_v1_setting_proto_rawDesc = []byte{ + 0x0a, 0x19, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, + 0x74, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x73, 0x65, 0x74, + 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x76, 0x31, 0x22, 0x14, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x53, + 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x47, + 0x0a, 0x13, 0x47, 0x65, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, + 0x67, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x73, + 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x44, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x53, 0x65, + 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, + 0x07, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, + 0x2e, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, + 0x74, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x45, 0x0a, + 0x13, 0x53, 0x65, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x73, 0x65, 0x74, + 0x74, 0x69, 0x6e, 0x67, 0x22, 0x53, 0x0a, 0x07, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x6f, 0x64, + 0x69, 0x66, 0x69, 0x65, 0x64, 0x41, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x6d, + 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x41, 0x74, 0x32, 0xa9, 0x01, 0x0a, 0x0f, 0x53, 0x65, + 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4a, 0x0a, + 0x03, 0x47, 0x65, 0x74, 0x12, 0x1f, 0x2e, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4a, 0x0a, 0x03, 0x53, 0x65, 0x74, + 0x12, 0x1f, 0x2e, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x65, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x20, 0x2e, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x65, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0xb2, 0x01, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x65, + 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x53, 0x65, 0x74, 0x74, 0x69, + 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x44, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x70, 0x79, + 0x72, 0x6f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, + 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x76, 0x31, 0xa2, + 0x02, 0x03, 0x53, 0x58, 0x58, 0xaa, 0x02, 0x0b, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, + 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0b, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x5c, 0x56, + 0x31, 0xe2, 0x02, 0x17, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x5c, 0x56, 0x31, 0x5c, + 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0c, 0x53, 0x65, + 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, +} + +var ( + file_settings_v1_setting_proto_rawDescOnce sync.Once + file_settings_v1_setting_proto_rawDescData = file_settings_v1_setting_proto_rawDesc +) + +func file_settings_v1_setting_proto_rawDescGZIP() []byte { + file_settings_v1_setting_proto_rawDescOnce.Do(func() { + file_settings_v1_setting_proto_rawDescData = protoimpl.X.CompressGZIP(file_settings_v1_setting_proto_rawDescData) + }) + return file_settings_v1_setting_proto_rawDescData +} + +var file_settings_v1_setting_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_settings_v1_setting_proto_goTypes = []interface{}{ + (*GetSettingsRequest)(nil), // 0: settings.v1.GetSettingsRequest + (*GetSettingsResponse)(nil), // 1: settings.v1.GetSettingsResponse + (*SetSettingsRequest)(nil), // 2: settings.v1.SetSettingsRequest + (*SetSettingsResponse)(nil), // 3: settings.v1.SetSettingsResponse + (*Setting)(nil), // 4: settings.v1.Setting +} +var file_settings_v1_setting_proto_depIdxs = []int32{ + 4, // 0: settings.v1.GetSettingsResponse.settings:type_name -> settings.v1.Setting + 4, // 1: settings.v1.SetSettingsRequest.setting:type_name -> settings.v1.Setting + 4, // 2: settings.v1.SetSettingsResponse.setting:type_name -> settings.v1.Setting + 0, // 3: settings.v1.SettingsService.Get:input_type -> settings.v1.GetSettingsRequest + 2, // 4: settings.v1.SettingsService.Set:input_type -> settings.v1.SetSettingsRequest + 1, // 5: settings.v1.SettingsService.Get:output_type -> settings.v1.GetSettingsResponse + 3, // 6: settings.v1.SettingsService.Set:output_type -> settings.v1.SetSettingsResponse + 5, // [5:7] is the sub-list for method output_type + 3, // [3:5] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name +} + +func init() { file_settings_v1_setting_proto_init() } +func file_settings_v1_setting_proto_init() { + if File_settings_v1_setting_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_settings_v1_setting_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetSettingsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_settings_v1_setting_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetSettingsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_settings_v1_setting_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SetSettingsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_settings_v1_setting_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SetSettingsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_settings_v1_setting_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Setting); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_settings_v1_setting_proto_rawDesc, + NumEnums: 0, + NumMessages: 5, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_settings_v1_setting_proto_goTypes, + DependencyIndexes: file_settings_v1_setting_proto_depIdxs, + MessageInfos: file_settings_v1_setting_proto_msgTypes, + }.Build() + File_settings_v1_setting_proto = out.File + file_settings_v1_setting_proto_rawDesc = nil + file_settings_v1_setting_proto_goTypes = nil + file_settings_v1_setting_proto_depIdxs = nil +} diff --git a/api/gen/proto/go/settings/v1/setting_vtproto.pb.go b/api/gen/proto/go/settings/v1/setting_vtproto.pb.go new file mode 100644 index 0000000000..3ec4bb1d70 --- /dev/null +++ b/api/gen/proto/go/settings/v1/setting_vtproto.pb.go @@ -0,0 +1,1084 @@ +// Code generated by protoc-gen-go-vtproto. DO NOT EDIT. +// protoc-gen-go-vtproto version: v0.0.0-20230725111439-5b3aae6571b8 +// source: settings/v1/setting.proto + +package settingsv1 + +import ( + context "context" + fmt "fmt" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + proto "google.golang.org/protobuf/proto" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + io "io" + bits "math/bits" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +func (m *GetSettingsRequest) CloneVT() *GetSettingsRequest { + if m == nil { + return (*GetSettingsRequest)(nil) + } + r := &GetSettingsRequest{} + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *GetSettingsRequest) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *GetSettingsResponse) CloneVT() *GetSettingsResponse { + if m == nil { + return (*GetSettingsResponse)(nil) + } + r := &GetSettingsResponse{} + if rhs := m.Settings; rhs != nil { + tmpContainer := make([]*Setting, len(rhs)) + for k, v := range rhs { + tmpContainer[k] = v.CloneVT() + } + r.Settings = tmpContainer + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *GetSettingsResponse) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *SetSettingsRequest) CloneVT() *SetSettingsRequest { + if m == nil { + return (*SetSettingsRequest)(nil) + } + r := &SetSettingsRequest{ + Setting: m.Setting.CloneVT(), + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *SetSettingsRequest) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *SetSettingsResponse) CloneVT() *SetSettingsResponse { + if m == nil { + return (*SetSettingsResponse)(nil) + } + r := &SetSettingsResponse{ + Setting: m.Setting.CloneVT(), + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *SetSettingsResponse) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *Setting) CloneVT() *Setting { + if m == nil { + return (*Setting)(nil) + } + r := &Setting{ + Name: m.Name, + Value: m.Value, + ModifiedAt: m.ModifiedAt, + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *Setting) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +// 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 + +// SettingsServiceClient is the client API for SettingsService 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 SettingsServiceClient interface { + Get(ctx context.Context, in *GetSettingsRequest, opts ...grpc.CallOption) (*GetSettingsResponse, error) + Set(ctx context.Context, in *SetSettingsRequest, opts ...grpc.CallOption) (*SetSettingsResponse, error) +} + +type settingsServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewSettingsServiceClient(cc grpc.ClientConnInterface) SettingsServiceClient { + return &settingsServiceClient{cc} +} + +func (c *settingsServiceClient) Get(ctx context.Context, in *GetSettingsRequest, opts ...grpc.CallOption) (*GetSettingsResponse, error) { + out := new(GetSettingsResponse) + err := c.cc.Invoke(ctx, "/settings.v1.SettingsService/Get", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *settingsServiceClient) Set(ctx context.Context, in *SetSettingsRequest, opts ...grpc.CallOption) (*SetSettingsResponse, error) { + out := new(SetSettingsResponse) + err := c.cc.Invoke(ctx, "/settings.v1.SettingsService/Set", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// SettingsServiceServer is the server API for SettingsService service. +// All implementations must embed UnimplementedSettingsServiceServer +// for forward compatibility +type SettingsServiceServer interface { + Get(context.Context, *GetSettingsRequest) (*GetSettingsResponse, error) + Set(context.Context, *SetSettingsRequest) (*SetSettingsResponse, error) + mustEmbedUnimplementedSettingsServiceServer() +} + +// UnimplementedSettingsServiceServer must be embedded to have forward compatible implementations. +type UnimplementedSettingsServiceServer struct { +} + +func (UnimplementedSettingsServiceServer) Get(context.Context, *GetSettingsRequest) (*GetSettingsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Get not implemented") +} +func (UnimplementedSettingsServiceServer) Set(context.Context, *SetSettingsRequest) (*SetSettingsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Set not implemented") +} +func (UnimplementedSettingsServiceServer) mustEmbedUnimplementedSettingsServiceServer() {} + +// UnsafeSettingsServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to SettingsServiceServer will +// result in compilation errors. +type UnsafeSettingsServiceServer interface { + mustEmbedUnimplementedSettingsServiceServer() +} + +func RegisterSettingsServiceServer(s grpc.ServiceRegistrar, srv SettingsServiceServer) { + s.RegisterService(&SettingsService_ServiceDesc, srv) +} + +func _SettingsService_Get_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetSettingsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SettingsServiceServer).Get(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/settings.v1.SettingsService/Get", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SettingsServiceServer).Get(ctx, req.(*GetSettingsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _SettingsService_Set_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SetSettingsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SettingsServiceServer).Set(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/settings.v1.SettingsService/Set", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SettingsServiceServer).Set(ctx, req.(*SetSettingsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// SettingsService_ServiceDesc is the grpc.ServiceDesc for SettingsService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var SettingsService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "settings.v1.SettingsService", + HandlerType: (*SettingsServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Get", + Handler: _SettingsService_Get_Handler, + }, + { + MethodName: "Set", + Handler: _SettingsService_Set_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "settings/v1/setting.proto", +} + +func (m *GetSettingsRequest) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetSettingsRequest) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *GetSettingsRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + return len(dAtA) - i, nil +} + +func (m *GetSettingsResponse) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetSettingsResponse) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *GetSettingsResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.Settings) > 0 { + for iNdEx := len(m.Settings) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Settings[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *SetSettingsRequest) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SetSettingsRequest) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *SetSettingsRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Setting != nil { + size, err := m.Setting.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *SetSettingsResponse) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SetSettingsResponse) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *SetSettingsResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Setting != nil { + size, err := m.Setting.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *Setting) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Setting) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *Setting) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.ModifiedAt != 0 { + i = encodeVarint(dAtA, i, uint64(m.ModifiedAt)) + i-- + dAtA[i] = 0x18 + } + if len(m.Value) > 0 { + i -= len(m.Value) + copy(dAtA[i:], m.Value) + i = encodeVarint(dAtA, i, uint64(len(m.Value))) + i-- + dAtA[i] = 0x12 + } + if len(m.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarint(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarint(dAtA []byte, offset int, v uint64) int { + offset -= sov(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GetSettingsRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + n += len(m.unknownFields) + return n +} + +func (m *GetSettingsResponse) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Settings) > 0 { + for _, e := range m.Settings { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } + n += len(m.unknownFields) + return n +} + +func (m *SetSettingsRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Setting != nil { + l = m.Setting.SizeVT() + n += 1 + l + sov(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *SetSettingsResponse) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Setting != nil { + l = m.Setting.SizeVT() + n += 1 + l + sov(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *Setting) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Name) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.Value) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if m.ModifiedAt != 0 { + n += 1 + sov(uint64(m.ModifiedAt)) + } + n += len(m.unknownFields) + return n +} + +func sov(x uint64) (n int) { + return (bits.Len64(x|1) + 6) / 7 +} +func soz(x uint64) (n int) { + return sov(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GetSettingsRequest) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetSettingsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetSettingsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetSettingsResponse) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetSettingsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetSettingsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Settings", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Settings = append(m.Settings, &Setting{}) + if err := m.Settings[len(m.Settings)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SetSettingsRequest) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SetSettingsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SetSettingsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Setting", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Setting == nil { + m.Setting = &Setting{} + } + if err := m.Setting.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SetSettingsResponse) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SetSettingsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SetSettingsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Setting", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Setting == nil { + m.Setting = &Setting{} + } + if err := m.Setting.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Setting) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Setting: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Setting: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Value = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ModifiedAt", wireType) + } + m.ModifiedAt = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ModifiedAt |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} + +func skip(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflow + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflow + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflow + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLength + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroup + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLength + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLength = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflow = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroup = fmt.Errorf("proto: unexpected end of group") +) diff --git a/api/gen/proto/go/settings/v1/settingsv1connect/setting.connect.go b/api/gen/proto/go/settings/v1/settingsv1connect/setting.connect.go new file mode 100644 index 0000000000..15b5bb3474 --- /dev/null +++ b/api/gen/proto/go/settings/v1/settingsv1connect/setting.connect.go @@ -0,0 +1,130 @@ +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: settings/v1/setting.proto + +package settingsv1connect + +import ( + context "context" + errors "errors" + connect_go "github.com/bufbuild/connect-go" + v1 "github.com/grafana/pyroscope/api/gen/proto/go/settings/v1" + http "net/http" + strings "strings" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect_go.IsAtLeastVersion0_1_0 + +const ( + // SettingsServiceName is the fully-qualified name of the SettingsService service. + SettingsServiceName = "settings.v1.SettingsService" +) + +// These constants are the fully-qualified names of the RPCs defined in this package. They're +// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. +// +// Note that these are different from the fully-qualified method names used by +// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to +// reflection-formatted method names, remove the leading slash and convert the remaining slash to a +// period. +const ( + // SettingsServiceGetProcedure is the fully-qualified name of the SettingsService's Get RPC. + SettingsServiceGetProcedure = "/settings.v1.SettingsService/Get" + // SettingsServiceSetProcedure is the fully-qualified name of the SettingsService's Set RPC. + SettingsServiceSetProcedure = "/settings.v1.SettingsService/Set" +) + +// SettingsServiceClient is a client for the settings.v1.SettingsService service. +type SettingsServiceClient interface { + Get(context.Context, *connect_go.Request[v1.GetSettingsRequest]) (*connect_go.Response[v1.GetSettingsResponse], error) + Set(context.Context, *connect_go.Request[v1.SetSettingsRequest]) (*connect_go.Response[v1.SetSettingsResponse], error) +} + +// NewSettingsServiceClient constructs a client for the settings.v1.SettingsService service. By +// default, it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, +// and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the +// connect.WithGRPC() or connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewSettingsServiceClient(httpClient connect_go.HTTPClient, baseURL string, opts ...connect_go.ClientOption) SettingsServiceClient { + baseURL = strings.TrimRight(baseURL, "/") + return &settingsServiceClient{ + get: connect_go.NewClient[v1.GetSettingsRequest, v1.GetSettingsResponse]( + httpClient, + baseURL+SettingsServiceGetProcedure, + opts..., + ), + set: connect_go.NewClient[v1.SetSettingsRequest, v1.SetSettingsResponse]( + httpClient, + baseURL+SettingsServiceSetProcedure, + opts..., + ), + } +} + +// settingsServiceClient implements SettingsServiceClient. +type settingsServiceClient struct { + get *connect_go.Client[v1.GetSettingsRequest, v1.GetSettingsResponse] + set *connect_go.Client[v1.SetSettingsRequest, v1.SetSettingsResponse] +} + +// Get calls settings.v1.SettingsService.Get. +func (c *settingsServiceClient) Get(ctx context.Context, req *connect_go.Request[v1.GetSettingsRequest]) (*connect_go.Response[v1.GetSettingsResponse], error) { + return c.get.CallUnary(ctx, req) +} + +// Set calls settings.v1.SettingsService.Set. +func (c *settingsServiceClient) Set(ctx context.Context, req *connect_go.Request[v1.SetSettingsRequest]) (*connect_go.Response[v1.SetSettingsResponse], error) { + return c.set.CallUnary(ctx, req) +} + +// SettingsServiceHandler is an implementation of the settings.v1.SettingsService service. +type SettingsServiceHandler interface { + Get(context.Context, *connect_go.Request[v1.GetSettingsRequest]) (*connect_go.Response[v1.GetSettingsResponse], error) + Set(context.Context, *connect_go.Request[v1.SetSettingsRequest]) (*connect_go.Response[v1.SetSettingsResponse], error) +} + +// NewSettingsServiceHandler builds an HTTP handler from the service implementation. It returns the +// path on which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewSettingsServiceHandler(svc SettingsServiceHandler, opts ...connect_go.HandlerOption) (string, http.Handler) { + settingsServiceGetHandler := connect_go.NewUnaryHandler( + SettingsServiceGetProcedure, + svc.Get, + opts..., + ) + settingsServiceSetHandler := connect_go.NewUnaryHandler( + SettingsServiceSetProcedure, + svc.Set, + opts..., + ) + return "/settings.v1.SettingsService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case SettingsServiceGetProcedure: + settingsServiceGetHandler.ServeHTTP(w, r) + case SettingsServiceSetProcedure: + settingsServiceSetHandler.ServeHTTP(w, r) + default: + http.NotFound(w, r) + } + }) +} + +// UnimplementedSettingsServiceHandler returns CodeUnimplemented from all methods. +type UnimplementedSettingsServiceHandler struct{} + +func (UnimplementedSettingsServiceHandler) Get(context.Context, *connect_go.Request[v1.GetSettingsRequest]) (*connect_go.Response[v1.GetSettingsResponse], error) { + return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("settings.v1.SettingsService.Get is not implemented")) +} + +func (UnimplementedSettingsServiceHandler) Set(context.Context, *connect_go.Request[v1.SetSettingsRequest]) (*connect_go.Response[v1.SetSettingsResponse], error) { + return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("settings.v1.SettingsService.Set is not implemented")) +} diff --git a/api/gen/proto/go/settings/v1/settingsv1connect/setting.connect.mux.go b/api/gen/proto/go/settings/v1/settingsv1connect/setting.connect.mux.go new file mode 100644 index 0000000000..78c97c6e14 --- /dev/null +++ b/api/gen/proto/go/settings/v1/settingsv1connect/setting.connect.mux.go @@ -0,0 +1,32 @@ +// Code generated by protoc-gen-connect-go-mux. DO NOT EDIT. +// +// Source: settings/v1/setting.proto + +package settingsv1connect + +import ( + connect_go "github.com/bufbuild/connect-go" + mux "github.com/gorilla/mux" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect_go.IsAtLeastVersion0_1_0 + +// RegisterSettingsServiceHandler register an HTTP handler to a mux.Router from the service +// implementation. +func RegisterSettingsServiceHandler(mux *mux.Router, svc SettingsServiceHandler, opts ...connect_go.HandlerOption) { + mux.Handle("/settings.v1.SettingsService/Get", connect_go.NewUnaryHandler( + "/settings.v1.SettingsService/Get", + svc.Get, + opts..., + )) + mux.Handle("/settings.v1.SettingsService/Set", connect_go.NewUnaryHandler( + "/settings.v1.SettingsService/Set", + svc.Set, + opts..., + )) +} diff --git a/api/openapiv2/gen/phlare.swagger.json b/api/openapiv2/gen/phlare.swagger.json index 0b02101597..62faa94ac7 100644 --- a/api/openapiv2/gen/phlare.swagger.json +++ b/api/openapiv2/gen/phlare.swagger.json @@ -14,6 +14,9 @@ { "name": "QuerierService" }, + { + "name": "SettingsService" + }, { "name": "StatusService" }, @@ -588,6 +591,18 @@ } } }, + "v1GetSettingsResponse": { + "type": "object", + "properties": { + "settings": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1Setting" + } + } + } + }, "v1Hints": { "type": "object", "properties": { @@ -1086,6 +1101,29 @@ } } }, + "v1SetSettingsResponse": { + "type": "object", + "properties": { + "setting": { + "$ref": "#/definitions/v1Setting" + } + } + }, + "v1Setting": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "string" + }, + "modifiedAt": { + "type": "string", + "format": "int64" + } + } + }, "v1StacktraceSample": { "type": "object", "properties": { diff --git a/api/settings/v1/setting.proto b/api/settings/v1/setting.proto new file mode 100644 index 0000000000..fb7375bfb9 --- /dev/null +++ b/api/settings/v1/setting.proto @@ -0,0 +1,28 @@ +syntax = "proto3"; + +package settings.v1; + +service SettingsService { + rpc Get(GetSettingsRequest) returns (GetSettingsResponse) {} + rpc Set(SetSettingsRequest) returns (SetSettingsResponse) {} +} + +message GetSettingsRequest {} + +message GetSettingsResponse { + repeated Setting settings = 1; +} + +message SetSettingsRequest { + Setting setting = 1; +} + +message SetSettingsResponse { + Setting setting = 1; +} + +message Setting { + string name = 1; + string value = 2; + int64 modifiedAt = 3; +} diff --git a/operations/pyroscope/helm/pyroscope/rendered/micro-services.yaml b/operations/pyroscope/helm/pyroscope/rendered/micro-services.yaml index c0e5edca45..19056443eb 100644 --- a/operations/pyroscope/helm/pyroscope/rendered/micro-services.yaml +++ b/operations/pyroscope/helm/pyroscope/rendered/micro-services.yaml @@ -146,6 +146,27 @@ spec: app.kubernetes.io/instance: pyroscope-dev app.kubernetes.io/component: "store-gateway" --- +# Source: pyroscope/templates/deployments-statefulsets.yaml +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: pyroscope-dev-tenant-settings + namespace: default + labels: + helm.sh/chart: pyroscope-1.3.0 + app.kubernetes.io/name: pyroscope + app.kubernetes.io/instance: pyroscope-dev + app.kubernetes.io/version: "1.2.0" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: "tenant-settings" +spec: + maxUnavailable: 1 + selector: + matchLabels: + app.kubernetes.io/name: pyroscope + app.kubernetes.io/instance: pyroscope-dev + app.kubernetes.io/component: "tenant-settings" +--- # Source: pyroscope/charts/agent/templates/serviceaccount.yaml apiVersion: v1 kind: ServiceAccount @@ -2008,6 +2029,57 @@ spec: app.kubernetes.io/instance: pyroscope-dev app.kubernetes.io/component: "store-gateway" --- +# Source: pyroscope/templates/services.yaml +apiVersion: v1 +kind: Service +metadata: + name: pyroscope-dev-tenant-settings + namespace: default + labels: + helm.sh/chart: pyroscope-1.3.0 + app.kubernetes.io/name: pyroscope + app.kubernetes.io/instance: pyroscope-dev + app.kubernetes.io/version: "1.2.0" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: "tenant-settings" +spec: + type: ClusterIP + ports: + - port: 4040 + targetPort: http2 + protocol: TCP + name: http2 + selector: + app.kubernetes.io/name: pyroscope + app.kubernetes.io/instance: pyroscope-dev + app.kubernetes.io/component: "tenant-settings" +--- +# Source: pyroscope/templates/services.yaml +apiVersion: v1 +kind: Service +metadata: + name: pyroscope-dev-tenant-settings-headless + namespace: default + labels: + helm.sh/chart: pyroscope-1.3.0 + app.kubernetes.io/name: pyroscope + app.kubernetes.io/instance: pyroscope-dev + app.kubernetes.io/version: "1.2.0" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: "tenant-settings" +spec: + type: ClusterIP + clusterIP: None + ports: + - port: 4040 + targetPort: http2 + protocol: TCP + name: http2 + selector: + app.kubernetes.io/name: pyroscope + app.kubernetes.io/instance: pyroscope-dev + app.kubernetes.io/component: "tenant-settings" +--- # Source: pyroscope/templates/deployments-statefulsets.yaml apiVersion: apps/v1 kind: Deployment @@ -2384,6 +2456,100 @@ spec: - name: data emptyDir: {} --- +# Source: pyroscope/templates/deployments-statefulsets.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: pyroscope-dev-tenant-settings + namespace: default + labels: + helm.sh/chart: pyroscope-1.3.0 + app.kubernetes.io/name: pyroscope + app.kubernetes.io/instance: pyroscope-dev + app.kubernetes.io/version: "1.2.0" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: "tenant-settings" +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: pyroscope + app.kubernetes.io/instance: pyroscope-dev + app.kubernetes.io/component: "tenant-settings" + template: + metadata: + annotations: + checksum/config: 11f9ecbf886ed3111de896860fddb7fa1d5d5a01654ff5bb6cdfa993bcbd90ae + profiles.grafana.com/cpu.port_name: http2 + profiles.grafana.com/cpu.scrape: "true" + profiles.grafana.com/goroutine.port_name: http2 + profiles.grafana.com/goroutine.scrape: "true" + profiles.grafana.com/memory.port_name: http2 + profiles.grafana.com/memory.scrape: "true" + labels: + app.kubernetes.io/name: pyroscope + app.kubernetes.io/instance: pyroscope-dev + app.kubernetes.io/component: "tenant-settings" + name: "tenant-settings" + spec: + serviceAccountName: pyroscope-dev + securityContext: + fsGroup: 10001 + runAsNonRoot: true + runAsUser: 10001 + dnsPolicy: ClusterFirst + containers: + - name: "tenant-settings" + securityContext: + {} + image: "grafana/pyroscope:1.2.0" + imagePullPolicy: IfNotPresent + args: + - "-target=tenant-settings" + - "-self-profiling.disable-push=true" + - "-server.http-listen-port=4040" + - "-memberlist.cluster-label=default-pyroscope-dev" + - "-memberlist.join=dns+pyroscope-dev-memberlist.default.svc.cluster.local.:7946" + - "-config.file=/etc/pyroscope/config.yaml" + - "-runtime-config.file=/etc/pyroscope/overrides/overrides.yaml" + - "-log.level=debug" + - "-store-gateway.sharding-ring.replication-factor=3" + ports: + - name: http2 + containerPort: 4040 + protocol: TCP + - name: memberlist + containerPort: 7946 + protocol: TCP + readinessProbe: + httpGet: + path: /ready + port: http2 + scheme: HTTP + volumeMounts: + - name: config + mountPath: /etc/pyroscope/config.yaml + subPath: config.yaml + - name: overrides-config + mountPath: /etc/pyroscope/overrides/ + - name: data + mountPath: /data + resources: + limits: + memory: 1Gi + requests: + cpu: 1 + memory: 256Mi + volumes: + - name: config + configMap: + name: pyroscope-dev-config + - name: overrides-config + configMap: + name: pyroscope-dev-overrides-config + - name: data + emptyDir: {} +--- # Source: pyroscope/charts/agent/templates/controllers/statefulset.yaml apiVersion: apps/v1 kind: StatefulSet diff --git a/operations/pyroscope/helm/pyroscope/templates/ingress.yaml b/operations/pyroscope/helm/pyroscope/templates/ingress.yaml index 8f5b0c7045..3b63dcdf38 100644 --- a/operations/pyroscope/helm/pyroscope/templates/ingress.yaml +++ b/operations/pyroscope/helm/pyroscope/templates/ingress.yaml @@ -89,5 +89,16 @@ spec: number: {{ $.Values.pyroscope.service.port }} path: /ingest pathType: Prefix + - backend: + service: + {{- if gt (len $.Values.pyroscope.components) 1}} + name: {{ include "pyroscope.fullname" $ }}-tenant-settings + {{- else }} + name: {{ include "pyroscope.fullname" $ }} + {{- end }} + port: + number: {{ $.Values.pyroscope.service.port }} + path: /settings.v1.SettingsService/ + pathType: Prefix {{- end }} {{- end }} diff --git a/operations/pyroscope/helm/pyroscope/values-micro-services.yaml b/operations/pyroscope/helm/pyroscope/values-micro-services.yaml index 9dca8086e1..ba9e415ffe 100644 --- a/operations/pyroscope/helm/pyroscope/values-micro-services.yaml +++ b/operations/pyroscope/helm/pyroscope/values-micro-services.yaml @@ -76,6 +76,15 @@ pyroscope: requests: memory: 8Gi cpu: 1 + tenant-settings: + kind: Deployment + replicaCount: 1 + resources: + limits: + memory: 1Gi + requests: + memory: 256Mi + cpu: 1 minio: enabled: true diff --git a/operations/pyroscope/jsonnet/values-micro-services.json b/operations/pyroscope/jsonnet/values-micro-services.json index 13d0b7dd49..bd4f18ffce 100644 --- a/operations/pyroscope/jsonnet/values-micro-services.json +++ b/operations/pyroscope/jsonnet/values-micro-services.json @@ -101,6 +101,19 @@ "memory": "8Gi" } } + }, + "tenant-settings": { + "kind": "Deployment", + "replicaCount": 1, + "resources": { + "limits": { + "memory": "1Gi" + }, + "requests": { + "cpu": 1, + "memory": "256Mi" + } + } } }, "extraArgs": { diff --git a/pkg/api/api.go b/pkg/api/api.go index c3390b8bd0..7940c1ab34 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -27,6 +27,7 @@ import ( "github.com/grafana/pyroscope/api/gen/proto/go/ingester/v1/ingesterv1connect" "github.com/grafana/pyroscope/api/gen/proto/go/push/v1/pushv1connect" "github.com/grafana/pyroscope/api/gen/proto/go/querier/v1/querierv1connect" + "github.com/grafana/pyroscope/api/gen/proto/go/settings/v1/settingsv1connect" statusv1 "github.com/grafana/pyroscope/api/gen/proto/go/status/v1" "github.com/grafana/pyroscope/api/gen/proto/go/storegateway/v1/storegatewayv1connect" "github.com/grafana/pyroscope/api/gen/proto/go/version/v1/versionv1connect" @@ -41,6 +42,7 @@ import ( "github.com/grafana/pyroscope/pkg/querier" "github.com/grafana/pyroscope/pkg/scheduler" "github.com/grafana/pyroscope/pkg/scheduler/schedulerpb/schedulerpbconnect" + "github.com/grafana/pyroscope/pkg/settings" "github.com/grafana/pyroscope/pkg/storegateway" "github.com/grafana/pyroscope/pkg/util" "github.com/grafana/pyroscope/pkg/util/gziphandler" @@ -190,6 +192,10 @@ func (a *API) RegisterRuntimeConfig(runtimeConfigHandler http.HandlerFunc, userL }) } +func (a *API) RegisterTenantSettings(ts *settings.TenantSettings) { + settingsv1connect.RegisterSettingsServiceHandler(a.server.HTTP, ts, a.grpcAuthMiddleware) +} + // RegisterOverridesExporter registers the endpoints associated with the overrides exporter. func (a *API) RegisterOverridesExporter(oe *exporter.OverridesExporter) { a.RegisterRoute("/overrides-exporter/ring", http.HandlerFunc(oe.RingHandler), false, true, "GET", "POST") diff --git a/pkg/phlare/modules.go b/pkg/phlare/modules.go index 7223d67394..39ecf62ddd 100644 --- a/pkg/phlare/modules.go +++ b/pkg/phlare/modules.go @@ -43,6 +43,7 @@ import ( "github.com/grafana/pyroscope/pkg/querier" "github.com/grafana/pyroscope/pkg/querier/worker" "github.com/grafana/pyroscope/pkg/scheduler" + "github.com/grafana/pyroscope/pkg/settings" "github.com/grafana/pyroscope/pkg/storegateway" "github.com/grafana/pyroscope/pkg/usagestats" "github.com/grafana/pyroscope/pkg/util" @@ -73,6 +74,7 @@ const ( OverridesExporter string = "overrides-exporter" Compactor string = "compactor" Admin string = "admin" + TenantSettings string = "tenant-settings" // QueryFrontendTripperware string = "query-frontend-tripperware" // IndexGateway string = "index-gateway" @@ -132,6 +134,21 @@ func (f *Phlare) initRuntimeConfig() (services.Service, error) { return serv, err } +func (f *Phlare) initTenantSettings() (services.Service, error) { + mem, err := settings.NewMemoryStore() + if err != nil { + return nil, err + } + + settings, err := settings.New(mem) + if err != nil { + return nil, errors.Wrapf(err, "failed to init %s", TenantSettings) + } + + f.API.RegisterTenantSettings(settings) + return settings, nil +} + func (f *Phlare) initOverrides() (serv services.Service, err error) { f.Overrides, err = validation.NewOverrides(f.Cfg.LimitsConfig, f.TenantLimits) // overrides don't have operational state, nor do they need to do anything more in starting/stopping phase, @@ -219,6 +236,7 @@ func (f *Phlare) initQuerier() (services.Service, error) { if err != nil { return nil, err } + if !f.isModuleActive(QueryFrontend) { f.API.RegisterPyroscopeHandlers(querierSvc) f.API.RegisterQuerier(querierSvc) diff --git a/pkg/phlare/phlare.go b/pkg/phlare/phlare.go index c873d5d7a9..5fbb7a3bde 100644 --- a/pkg/phlare/phlare.go +++ b/pkg/phlare/phlare.go @@ -300,10 +300,11 @@ func (f *Phlare) setupModuleManager() error { mm.RegisterModule(Compactor, f.initCompactor) mm.RegisterModule(Admin, f.initAdmin) mm.RegisterModule(All, nil) + mm.RegisterModule(TenantSettings, f.initTenantSettings) // Add dependencies deps := map[string][]string{ - All: {Ingester, Distributor, QueryScheduler, QueryFrontend, Querier, StoreGateway, Admin}, + All: {Ingester, Distributor, QueryScheduler, QueryFrontend, Querier, StoreGateway, Admin, TenantSettings}, Server: {GRPCGateway}, API: {Server}, @@ -322,6 +323,7 @@ func (f *Phlare) setupModuleManager() error { MemberlistKV: {API}, Admin: {API, Storage}, Version: {API, MemberlistKV}, + TenantSettings: {API}, } for mod, targets := range deps { diff --git a/pkg/settings/memory.go b/pkg/settings/memory.go new file mode 100644 index 0000000000..2a789f9fd6 --- /dev/null +++ b/pkg/settings/memory.go @@ -0,0 +1,62 @@ +package settings + +import ( + "context" + "sync" + + "github.com/pkg/errors" + "golang.org/x/exp/slices" + + settingsv1 "github.com/grafana/pyroscope/api/gen/proto/go/settings/v1" +) + +var oldSettingErr = errors.New("newer update already written") + +func NewMemoryStore() (Store, error) { + store := &memoryStore{ + store: make(map[string]map[string]*settingsv1.Setting), + } + return store, nil +} + +type memoryStore struct { + storeLock sync.RWMutex + + // store is kv pairs, indexed first by tenant id. + store map[string]map[string]*settingsv1.Setting +} + +func (s *memoryStore) Get(ctx context.Context, tenantID string) ([]*settingsv1.Setting, error) { + s.storeLock.RLock() + defer s.storeLock.RUnlock() + + tenantSettings := s.store[tenantID] + + settings := make([]*settingsv1.Setting, 0, len(s.store[tenantID])) + for _, setting := range tenantSettings { + settings = append(settings, setting) + } + + slices.SortFunc(settings, func(a, b *settingsv1.Setting) bool { + return a.Name < b.Name + }) + return settings, nil +} + +func (s *memoryStore) Set(ctx context.Context, tenantID string, setting *settingsv1.Setting) (*settingsv1.Setting, error) { + s.storeLock.Lock() + defer s.storeLock.Unlock() + + _, ok := s.store[tenantID] + if !ok { + s.store[tenantID] = make(map[string]*settingsv1.Setting, 1) + } + + oldSetting, ok := s.store[tenantID][setting.Name] + if ok && oldSetting.ModifiedAt > setting.ModifiedAt { + return nil, errors.Wrapf(oldSettingErr, "failed to update %s", setting.Name) + } + s.store[tenantID][setting.Name] = setting + + return setting, nil +} diff --git a/pkg/settings/memory_test.go b/pkg/settings/memory_test.go new file mode 100644 index 0000000000..934db60002 --- /dev/null +++ b/pkg/settings/memory_test.go @@ -0,0 +1,126 @@ +package settings + +import ( + "context" + "sort" + "testing" + + "github.com/stretchr/testify/assert" + + settingsv1 "github.com/grafana/pyroscope/api/gen/proto/go/settings/v1" +) + +func TestMemory_Get(t *testing.T) { + ctx := context.Background() + tenantID := "[anonymous]" + + t.Run("get settings are sorted", func(t *testing.T) { + mem, err := NewMemoryStore() + assert.NoError(t, err) + + settings := []*settingsv1.Setting{ + {Name: "key1", Value: "val1"}, + {Name: "key2", Value: "val2"}, + } + for _, s := range settings { + _, err = mem.Set(ctx, tenantID, s) + assert.NoError(t, err) + } + got, err := mem.Get(ctx, tenantID) + assert.NoError(t, err) + assert.Equal(t, settings, got) + assert.True(t, sort.SliceIsSorted(got, func(i, j int) bool { + return got[i].Name < got[j].Name + })) + }) + + t.Run("don't get settings from another tenant", func(t *testing.T) { + mem, err := NewMemoryStore() + assert.NoError(t, err) + + otherTenantID := "other" + + tenant1Settings := []*settingsv1.Setting{ + {Name: "t1_key1", Value: "val1"}, + {Name: "t1_key2", Value: "val2"}, + } + for _, s := range tenant1Settings { + _, err = mem.Set(ctx, tenantID, s) + assert.NoError(t, err) + } + + tenant2Settings := []*settingsv1.Setting{ + {Name: "t2_key1", Value: "val1"}, + {Name: "t2_key2", Value: "val2"}, + } + for _, s := range tenant2Settings { + _, err = mem.Set(ctx, otherTenantID, s) + assert.NoError(t, err) + } + + got, err := mem.Get(ctx, otherTenantID) + assert.NoError(t, err) + assert.Equal(t, tenant2Settings, got) + }) +} + +func TestMemory_Set(t *testing.T) { + ctx := context.Background() + tenantID := "[anonymous]" + + t.Run("set a new key", func(t *testing.T) { + mem, err := NewMemoryStore() + assert.NoError(t, err) + + setting := &settingsv1.Setting{ + Name: "key1", + Value: "val1", + } + got, err := mem.Set(ctx, tenantID, setting) + assert.NoError(t, err) + assert.Equal(t, setting, got) + }) + + t.Run("update a key", func(t *testing.T) { + mem, err := NewMemoryStore() + assert.NoError(t, err) + + setting := &settingsv1.Setting{ + Name: "key1", + Value: "val1", + } + got, err := mem.Set(ctx, tenantID, setting) + assert.NoError(t, err) + assert.Equal(t, setting, got) + + newSetting := &settingsv1.Setting{ + Name: "key1", + Value: "val2", + } + got, err = mem.Set(ctx, tenantID, newSetting) + assert.NoError(t, err) + assert.Equal(t, newSetting, got) + }) + + t.Run("don't update a key that's too old", func(t *testing.T) { + mem, err := NewMemoryStore() + assert.NoError(t, err) + + setting := &settingsv1.Setting{ + Name: "key1", + Value: "val1", + ModifiedAt: 10, + } + got, err := mem.Set(ctx, tenantID, setting) + assert.NoError(t, err) + assert.Equal(t, setting, got) + + newSetting := &settingsv1.Setting{ + Name: "key1", + Value: "val2", + ModifiedAt: 5, + } + _, err = mem.Set(ctx, tenantID, newSetting) + assert.EqualError(t, err, "failed to update key1: newer update already written") + }) +} diff --git a/pkg/settings/settings.go b/pkg/settings/settings.go new file mode 100644 index 0000000000..59e3efda53 --- /dev/null +++ b/pkg/settings/settings.go @@ -0,0 +1,76 @@ +package settings + +import ( + "context" + + "github.com/bufbuild/connect-go" + "github.com/grafana/dskit/services" + "github.com/grafana/dskit/tenant" + "github.com/pkg/errors" + + settingsv1 "github.com/grafana/pyroscope/api/gen/proto/go/settings/v1" +) + +func New(store Store) (*TenantSettings, error) { + ts := &TenantSettings{ + store: store, + } + + ts.Service = services.NewBasicService(ts.starting, ts.running, ts.stopping) + + return ts, nil +} + +type TenantSettings struct { + services.Service + + store Store +} + +func (ts *TenantSettings) starting(ctx context.Context) error { + return nil +} + +func (ts *TenantSettings) running(ctx context.Context) error { + <-ctx.Done() + return nil +} + +func (ts *TenantSettings) stopping(_ error) error { + return nil +} + +func (ts *TenantSettings) Get(ctx context.Context, req *connect.Request[settingsv1.GetSettingsRequest]) (*connect.Response[settingsv1.GetSettingsResponse], error) { + tenantID, err := tenant.TenantID(ctx) + if err != nil { + return nil, connect.NewError(connect.CodeInvalidArgument, err) + } + + settings, err := ts.store.Get(ctx, tenantID) + if err != nil { + return nil, connect.NewError(connect.CodeInternal, err) + } + + return connect.NewResponse(&settingsv1.GetSettingsResponse{ + Settings: settings, + }), nil +} + +func (ts *TenantSettings) Set(ctx context.Context, req *connect.Request[settingsv1.SetSettingsRequest]) (*connect.Response[settingsv1.SetSettingsResponse], error) { + tenantID, err := tenant.TenantID(ctx) + if err != nil { + return nil, connect.NewError(connect.CodeInvalidArgument, err) + } + + setting, err := ts.store.Set(ctx, tenantID, req.Msg.Setting) + if err != nil { + if errors.Is(err, oldSettingErr) { + return nil, connect.NewError(connect.CodeAlreadyExists, err) + } + return nil, connect.NewError(connect.CodeInternal, err) + } + + return connect.NewResponse(&settingsv1.SetSettingsResponse{ + Setting: setting, + }), nil +} diff --git a/pkg/settings/store.go b/pkg/settings/store.go new file mode 100644 index 0000000000..ae738a0e0b --- /dev/null +++ b/pkg/settings/store.go @@ -0,0 +1,15 @@ +package settings + +import ( + "context" + + settingsv1 "github.com/grafana/pyroscope/api/gen/proto/go/settings/v1" +) + +type Store interface { + // Get settings for a tenant. + Get(ctx context.Context, tenantID string) ([]*settingsv1.Setting, error) + + // Set a setting for a tenant. + Set(ctx context.Context, tenantID string, setting *settingsv1.Setting) (*settingsv1.Setting, error) +}