Add agent inventory, management, and remote config
Extends the heartbeat mechanism with a second gRPC service on the same mTLS channel (AgentControl.CheckIn, agent-initiated on the existing heartbeat ticker -- still push-only, no inbound port on any agent) so an agent reports its running config and can pick up an operator-set override. A new web UI section (/agents) lists every agent that's checked in, shows its reported config, and lets an operator edit a narrow, deliberately-scoped subset remotely: batch/heartbeat tuning, and (journald sources only) the unit filter. TLS material and the ingest endpoint are never reportable or remotely editable, by proto shape rather than a validation rule -- a bad or malicious edit there could permanently strand an agent or redirect where its logs go, unlike every other editable field, which only degrades behavior. An override lives only in the agent's memory (agent.toml is never rewritten) and re-syncs on the agent's own schedule; changing the journald filter aborts and respawns the source task since there's no other way to change what's being tailed. Building the hot-reload path surfaced a real, independent, pre-existing bug: shutdown was using poll_timeout(), which only drains once flush_interval has elapsed, silently dropping anything buffered more recently on every graceful shutdown that landed between flushes -- fixed with a new unconditional Batcher::flush_all(), now used at both shutdown and hot-reload. Verified live end-to-end against a real stack: an edited heartbeat interval changed a running agent's actual send cadence within one check-in cycle (confirmed by the real timestamps landing in ClickHouse), and an edited journald filter triggered a real source restart, both reflected back in the next reported-config snapshot. See /docs/agent-management-design.md.
This commit is contained in:
@@ -0,0 +1,440 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.12
|
||||
// protoc v7.35.1
|
||||
// source: sentry/agent/v1/agent_control.proto
|
||||
|
||||
package agentv1
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
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)
|
||||
)
|
||||
|
||||
// ReportedConfig is what an agent tells the platform about itself --
|
||||
// read-only, for inventory/visibility. Deliberately excludes tls/ingest
|
||||
// endpoint fields: those are never reported and never remotely
|
||||
// overridable (see DesiredOverride's comment) -- reporting the ingest
|
||||
// endpoint back to itself would be redundant (that's exactly the
|
||||
// connection this request arrived over), and TLS material has no
|
||||
// business leaving the host at all.
|
||||
type ReportedConfig struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
AgentVersion string `protobuf:"bytes,1,opt,name=agent_version,json=agentVersion,proto3" json:"agent_version,omitempty"`
|
||||
SourceKind string `protobuf:"bytes,2,opt,name=source_kind,json=sourceKind,proto3" json:"source_kind,omitempty"` // "journald", "file", "eventlog", "etw"
|
||||
SourceDetail string `protobuf:"bytes,3,opt,name=source_detail,json=sourceDetail,proto3" json:"source_detail,omitempty"` // human-readable summary: unit name, file path, or channel list
|
||||
BatchMaxSize uint64 `protobuf:"varint,4,opt,name=batch_max_size,json=batchMaxSize,proto3" json:"batch_max_size,omitempty"`
|
||||
BatchFlushIntervalMs uint64 `protobuf:"varint,5,opt,name=batch_flush_interval_ms,json=batchFlushIntervalMs,proto3" json:"batch_flush_interval_ms,omitempty"`
|
||||
HeartbeatEnabled bool `protobuf:"varint,6,opt,name=heartbeat_enabled,json=heartbeatEnabled,proto3" json:"heartbeat_enabled,omitempty"`
|
||||
HeartbeatIntervalMs uint64 `protobuf:"varint,7,opt,name=heartbeat_interval_ms,json=heartbeatIntervalMs,proto3" json:"heartbeat_interval_ms,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ReportedConfig) Reset() {
|
||||
*x = ReportedConfig{}
|
||||
mi := &file_sentry_agent_v1_agent_control_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ReportedConfig) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ReportedConfig) ProtoMessage() {}
|
||||
|
||||
func (x *ReportedConfig) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_sentry_agent_v1_agent_control_proto_msgTypes[0]
|
||||
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 ReportedConfig.ProtoReflect.Descriptor instead.
|
||||
func (*ReportedConfig) Descriptor() ([]byte, []int) {
|
||||
return file_sentry_agent_v1_agent_control_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *ReportedConfig) GetAgentVersion() string {
|
||||
if x != nil {
|
||||
return x.AgentVersion
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ReportedConfig) GetSourceKind() string {
|
||||
if x != nil {
|
||||
return x.SourceKind
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ReportedConfig) GetSourceDetail() string {
|
||||
if x != nil {
|
||||
return x.SourceDetail
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ReportedConfig) GetBatchMaxSize() uint64 {
|
||||
if x != nil {
|
||||
return x.BatchMaxSize
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ReportedConfig) GetBatchFlushIntervalMs() uint64 {
|
||||
if x != nil {
|
||||
return x.BatchFlushIntervalMs
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ReportedConfig) GetHeartbeatEnabled() bool {
|
||||
if x != nil {
|
||||
return x.HeartbeatEnabled
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *ReportedConfig) GetHeartbeatIntervalMs() uint64 {
|
||||
if x != nil {
|
||||
return x.HeartbeatIntervalMs
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type CheckInRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Host string `protobuf:"bytes,1,opt,name=host,proto3" json:"host,omitempty"`
|
||||
Service string `protobuf:"bytes,2,opt,name=service,proto3" json:"service,omitempty"`
|
||||
CurrentConfig *ReportedConfig `protobuf:"bytes,3,opt,name=current_config,json=currentConfig,proto3" json:"current_config,omitempty"`
|
||||
// The DesiredOverride.version this agent last successfully applied,
|
||||
// empty if it has never applied one. Lets the server distinguish
|
||||
// "pending" (an edit exists the agent hasn't picked up yet) from
|
||||
// "applied" for the web UI, without the agent needing to know
|
||||
// anything about that distinction itself.
|
||||
AppliedOverrideVersion string `protobuf:"bytes,4,opt,name=applied_override_version,json=appliedOverrideVersion,proto3" json:"applied_override_version,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *CheckInRequest) Reset() {
|
||||
*x = CheckInRequest{}
|
||||
mi := &file_sentry_agent_v1_agent_control_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *CheckInRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*CheckInRequest) ProtoMessage() {}
|
||||
|
||||
func (x *CheckInRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_sentry_agent_v1_agent_control_proto_msgTypes[1]
|
||||
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 CheckInRequest.ProtoReflect.Descriptor instead.
|
||||
func (*CheckInRequest) Descriptor() ([]byte, []int) {
|
||||
return file_sentry_agent_v1_agent_control_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *CheckInRequest) GetHost() string {
|
||||
if x != nil {
|
||||
return x.Host
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *CheckInRequest) GetService() string {
|
||||
if x != nil {
|
||||
return x.Service
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *CheckInRequest) GetCurrentConfig() *ReportedConfig {
|
||||
if x != nil {
|
||||
return x.CurrentConfig
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *CheckInRequest) GetAppliedOverrideVersion() string {
|
||||
if x != nil {
|
||||
return x.AppliedOverrideVersion
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// DesiredOverride is the remotely-editable subset of an agent's config
|
||||
// -- batch/heartbeat tuning, and, for journald sources, the unit
|
||||
// filter. Every field is optional: unset means "no override for this
|
||||
// field, keep whatever agent.toml says locally" -- a partial edit only
|
||||
// touches the fields it sets. Never includes tls/ingest: those stay
|
||||
// local-file-only, permanently, a deliberate security boundary (see
|
||||
// /docs/agent-management-design.md) so a bad or malicious remote edit
|
||||
// can never strand an agent or redirect where its logs go.
|
||||
type DesiredOverride struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
BatchMaxSize *uint64 `protobuf:"varint,1,opt,name=batch_max_size,json=batchMaxSize,proto3,oneof" json:"batch_max_size,omitempty"`
|
||||
BatchFlushIntervalMs *uint64 `protobuf:"varint,2,opt,name=batch_flush_interval_ms,json=batchFlushIntervalMs,proto3,oneof" json:"batch_flush_interval_ms,omitempty"`
|
||||
HeartbeatEnabled *bool `protobuf:"varint,3,opt,name=heartbeat_enabled,json=heartbeatEnabled,proto3,oneof" json:"heartbeat_enabled,omitempty"`
|
||||
HeartbeatIntervalMs *uint64 `protobuf:"varint,4,opt,name=heartbeat_interval_ms,json=heartbeatIntervalMs,proto3,oneof" json:"heartbeat_interval_ms,omitempty"`
|
||||
// Only meaningful when the agent's local source is journald; ignored
|
||||
// otherwise. Empty string means "no unit filter" (tail the whole
|
||||
// journal), same semantics as the local config's own unit field.
|
||||
JournaldUnit *string `protobuf:"bytes,5,opt,name=journald_unit,json=journaldUnit,proto3,oneof" json:"journald_unit,omitempty"`
|
||||
// Opaque version stamp the platform assigns on every edit. The
|
||||
// agent's only obligation is to echo it back as
|
||||
// CheckInRequest.applied_override_version once applied -- it never
|
||||
// interprets the value itself.
|
||||
Version string `protobuf:"bytes,6,opt,name=version,proto3" json:"version,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *DesiredOverride) Reset() {
|
||||
*x = DesiredOverride{}
|
||||
mi := &file_sentry_agent_v1_agent_control_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *DesiredOverride) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*DesiredOverride) ProtoMessage() {}
|
||||
|
||||
func (x *DesiredOverride) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_sentry_agent_v1_agent_control_proto_msgTypes[2]
|
||||
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 DesiredOverride.ProtoReflect.Descriptor instead.
|
||||
func (*DesiredOverride) Descriptor() ([]byte, []int) {
|
||||
return file_sentry_agent_v1_agent_control_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *DesiredOverride) GetBatchMaxSize() uint64 {
|
||||
if x != nil && x.BatchMaxSize != nil {
|
||||
return *x.BatchMaxSize
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *DesiredOverride) GetBatchFlushIntervalMs() uint64 {
|
||||
if x != nil && x.BatchFlushIntervalMs != nil {
|
||||
return *x.BatchFlushIntervalMs
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *DesiredOverride) GetHeartbeatEnabled() bool {
|
||||
if x != nil && x.HeartbeatEnabled != nil {
|
||||
return *x.HeartbeatEnabled
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *DesiredOverride) GetHeartbeatIntervalMs() uint64 {
|
||||
if x != nil && x.HeartbeatIntervalMs != nil {
|
||||
return *x.HeartbeatIntervalMs
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *DesiredOverride) GetJournaldUnit() string {
|
||||
if x != nil && x.JournaldUnit != nil {
|
||||
return *x.JournaldUnit
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *DesiredOverride) GetVersion() string {
|
||||
if x != nil {
|
||||
return x.Version
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type CheckInResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// False when no override has ever been set for this agent -- it
|
||||
// should be running whatever agent.toml already has, untouched.
|
||||
HasOverride bool `protobuf:"varint,1,opt,name=has_override,json=hasOverride,proto3" json:"has_override,omitempty"`
|
||||
Override *DesiredOverride `protobuf:"bytes,2,opt,name=override,proto3" json:"override,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *CheckInResponse) Reset() {
|
||||
*x = CheckInResponse{}
|
||||
mi := &file_sentry_agent_v1_agent_control_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *CheckInResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*CheckInResponse) ProtoMessage() {}
|
||||
|
||||
func (x *CheckInResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_sentry_agent_v1_agent_control_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 CheckInResponse.ProtoReflect.Descriptor instead.
|
||||
func (*CheckInResponse) Descriptor() ([]byte, []int) {
|
||||
return file_sentry_agent_v1_agent_control_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *CheckInResponse) GetHasOverride() bool {
|
||||
if x != nil {
|
||||
return x.HasOverride
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *CheckInResponse) GetOverride() *DesiredOverride {
|
||||
if x != nil {
|
||||
return x.Override
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_sentry_agent_v1_agent_control_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_sentry_agent_v1_agent_control_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"#sentry/agent/v1/agent_control.proto\x12\x0fsentry.agent.v1\"\xb9\x02\n" +
|
||||
"\x0eReportedConfig\x12#\n" +
|
||||
"\ragent_version\x18\x01 \x01(\tR\fagentVersion\x12\x1f\n" +
|
||||
"\vsource_kind\x18\x02 \x01(\tR\n" +
|
||||
"sourceKind\x12#\n" +
|
||||
"\rsource_detail\x18\x03 \x01(\tR\fsourceDetail\x12$\n" +
|
||||
"\x0ebatch_max_size\x18\x04 \x01(\x04R\fbatchMaxSize\x125\n" +
|
||||
"\x17batch_flush_interval_ms\x18\x05 \x01(\x04R\x14batchFlushIntervalMs\x12+\n" +
|
||||
"\x11heartbeat_enabled\x18\x06 \x01(\bR\x10heartbeatEnabled\x122\n" +
|
||||
"\x15heartbeat_interval_ms\x18\a \x01(\x04R\x13heartbeatIntervalMs\"\xc0\x01\n" +
|
||||
"\x0eCheckInRequest\x12\x12\n" +
|
||||
"\x04host\x18\x01 \x01(\tR\x04host\x12\x18\n" +
|
||||
"\aservice\x18\x02 \x01(\tR\aservice\x12F\n" +
|
||||
"\x0ecurrent_config\x18\x03 \x01(\v2\x1f.sentry.agent.v1.ReportedConfigR\rcurrentConfig\x128\n" +
|
||||
"\x18applied_override_version\x18\x04 \x01(\tR\x16appliedOverrideVersion\"\x98\x03\n" +
|
||||
"\x0fDesiredOverride\x12)\n" +
|
||||
"\x0ebatch_max_size\x18\x01 \x01(\x04H\x00R\fbatchMaxSize\x88\x01\x01\x12:\n" +
|
||||
"\x17batch_flush_interval_ms\x18\x02 \x01(\x04H\x01R\x14batchFlushIntervalMs\x88\x01\x01\x120\n" +
|
||||
"\x11heartbeat_enabled\x18\x03 \x01(\bH\x02R\x10heartbeatEnabled\x88\x01\x01\x127\n" +
|
||||
"\x15heartbeat_interval_ms\x18\x04 \x01(\x04H\x03R\x13heartbeatIntervalMs\x88\x01\x01\x12(\n" +
|
||||
"\rjournald_unit\x18\x05 \x01(\tH\x04R\fjournaldUnit\x88\x01\x01\x12\x18\n" +
|
||||
"\aversion\x18\x06 \x01(\tR\aversionB\x11\n" +
|
||||
"\x0f_batch_max_sizeB\x1a\n" +
|
||||
"\x18_batch_flush_interval_msB\x14\n" +
|
||||
"\x12_heartbeat_enabledB\x18\n" +
|
||||
"\x16_heartbeat_interval_msB\x10\n" +
|
||||
"\x0e_journald_unit\"r\n" +
|
||||
"\x0fCheckInResponse\x12!\n" +
|
||||
"\fhas_override\x18\x01 \x01(\bR\vhasOverride\x12<\n" +
|
||||
"\boverride\x18\x02 \x01(\v2 .sentry.agent.v1.DesiredOverrideR\boverride2\\\n" +
|
||||
"\fAgentControl\x12L\n" +
|
||||
"\aCheckIn\x12\x1f.sentry.agent.v1.CheckInRequest\x1a .sentry.agent.v1.CheckInResponseB8Z6github.com/sentry/sentry/proto/sentry/agent/v1;agentv1b\x06proto3"
|
||||
|
||||
var (
|
||||
file_sentry_agent_v1_agent_control_proto_rawDescOnce sync.Once
|
||||
file_sentry_agent_v1_agent_control_proto_rawDescData []byte
|
||||
)
|
||||
|
||||
func file_sentry_agent_v1_agent_control_proto_rawDescGZIP() []byte {
|
||||
file_sentry_agent_v1_agent_control_proto_rawDescOnce.Do(func() {
|
||||
file_sentry_agent_v1_agent_control_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_sentry_agent_v1_agent_control_proto_rawDesc), len(file_sentry_agent_v1_agent_control_proto_rawDesc)))
|
||||
})
|
||||
return file_sentry_agent_v1_agent_control_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_sentry_agent_v1_agent_control_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
|
||||
var file_sentry_agent_v1_agent_control_proto_goTypes = []any{
|
||||
(*ReportedConfig)(nil), // 0: sentry.agent.v1.ReportedConfig
|
||||
(*CheckInRequest)(nil), // 1: sentry.agent.v1.CheckInRequest
|
||||
(*DesiredOverride)(nil), // 2: sentry.agent.v1.DesiredOverride
|
||||
(*CheckInResponse)(nil), // 3: sentry.agent.v1.CheckInResponse
|
||||
}
|
||||
var file_sentry_agent_v1_agent_control_proto_depIdxs = []int32{
|
||||
0, // 0: sentry.agent.v1.CheckInRequest.current_config:type_name -> sentry.agent.v1.ReportedConfig
|
||||
2, // 1: sentry.agent.v1.CheckInResponse.override:type_name -> sentry.agent.v1.DesiredOverride
|
||||
1, // 2: sentry.agent.v1.AgentControl.CheckIn:input_type -> sentry.agent.v1.CheckInRequest
|
||||
3, // 3: sentry.agent.v1.AgentControl.CheckIn:output_type -> sentry.agent.v1.CheckInResponse
|
||||
3, // [3:4] is the sub-list for method output_type
|
||||
2, // [2:3] is the sub-list for method input_type
|
||||
2, // [2:2] is the sub-list for extension type_name
|
||||
2, // [2:2] is the sub-list for extension extendee
|
||||
0, // [0:2] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_sentry_agent_v1_agent_control_proto_init() }
|
||||
func file_sentry_agent_v1_agent_control_proto_init() {
|
||||
if File_sentry_agent_v1_agent_control_proto != nil {
|
||||
return
|
||||
}
|
||||
file_sentry_agent_v1_agent_control_proto_msgTypes[2].OneofWrappers = []any{}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_sentry_agent_v1_agent_control_proto_rawDesc), len(file_sentry_agent_v1_agent_control_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 4,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_sentry_agent_v1_agent_control_proto_goTypes,
|
||||
DependencyIndexes: file_sentry_agent_v1_agent_control_proto_depIdxs,
|
||||
MessageInfos: file_sentry_agent_v1_agent_control_proto_msgTypes,
|
||||
}.Build()
|
||||
File_sentry_agent_v1_agent_control_proto = out.File
|
||||
file_sentry_agent_v1_agent_control_proto_goTypes = nil
|
||||
file_sentry_agent_v1_agent_control_proto_depIdxs = nil
|
||||
}
|
||||
Reference in New Issue
Block a user