diff --git a/api/client/client.go b/api/client/client.go index 112df266425ac..69973a1ee14d1 100644 --- a/api/client/client.go +++ b/api/client/client.go @@ -3295,6 +3295,23 @@ func (c *Client) UpsertAutoUpdateAgentReport(ctx context.Context, report *autoup return resp, nil } +// GetAutoUpdateBotInstanceReport gets the singleton auto-update bot report. +func (c *Client) GetAutoUpdateBotInstanceReport(ctx context.Context) (*autoupdatev1pb.AutoUpdateBotInstanceReport, error) { + client := autoupdatev1pb.NewAutoUpdateServiceClient(c.conn) + resp, err := client.GetAutoUpdateBotInstanceReport(ctx, &autoupdatev1pb.GetAutoUpdateBotInstanceReportRequest{}) + if err != nil { + return nil, trace.Wrap(err) + } + return resp, nil +} + +// DeleteAutoUpdateBotInstanceReport deletes the singleton auto-update bot instance report. +func (c *Client) DeleteAutoUpdateBotInstanceReport(ctx context.Context) error { + client := autoupdatev1pb.NewAutoUpdateServiceClient(c.conn) + _, err := client.DeleteAutoUpdateBotInstanceReport(ctx, &autoupdatev1pb.DeleteAutoUpdateBotInstanceReportRequest{}) + return trace.Wrap(err) +} + // GetClusterAccessGraphConfig retrieves the Cluster Access Graph configuration from Auth server. func (c *Client) GetClusterAccessGraphConfig(ctx context.Context) (*clusterconfigpb.AccessGraphConfig, error) { rsp, err := c.ClusterConfigClient().GetClusterAccessGraphConfig(ctx, &clusterconfigpb.GetClusterAccessGraphConfigRequest{}) diff --git a/api/client/events.go b/api/client/events.go index dfccf26a37706..a78dd7044c028 100644 --- a/api/client/events.go +++ b/api/client/events.go @@ -128,6 +128,10 @@ func EventToGRPC(in types.Event) (*proto.Event, error) { out.Resource = &proto.Event_AutoUpdateAgentReport{ AutoUpdateAgentReport: r, } + case *autoupdate.AutoUpdateBotInstanceReport: + out.Resource = &proto.Event_AutoUpdateBotInstanceReport{ + AutoUpdateBotInstanceReport: r, + } case *identitycenterv1.Account: out.Resource = &proto.Event_IdentityCenterAccount{ IdentityCenterAccount: r, @@ -619,6 +623,9 @@ func EventFromGRPC(in *proto.Event) (*types.Event, error) { } else if r := in.GetAutoUpdateAgentReport(); r != nil { out.Resource = types.Resource153ToLegacy(r) return &out, nil + } else if r := in.GetAutoUpdateBotInstanceReport(); r != nil { + out.Resource = types.Resource153ToLegacy(r) + return &out, nil } else if r := in.GetUserTask(); r != nil { out.Resource = types.Resource153ToLegacy(r) return &out, nil diff --git a/api/client/proto/event.pb.go b/api/client/proto/event.pb.go index 5c39a4b96c8b6..4f904a3f019b9 100644 --- a/api/client/proto/event.pb.go +++ b/api/client/proto/event.pb.go @@ -190,6 +190,7 @@ type Event struct { // *Event_WorkloadIdentityX509Revocation // *Event_AutoUpdateAgentReport // *Event_Plugin + // *Event_AutoUpdateBotInstanceReport Resource isEvent_Resource `protobuf_oneof:"Resource"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -905,6 +906,15 @@ func (x *Event) GetPlugin() *types.PluginV1 { return nil } +func (x *Event) GetAutoUpdateBotInstanceReport() *v111.AutoUpdateBotInstanceReport { + if x != nil { + if x, ok := x.Resource.(*Event_AutoUpdateBotInstanceReport); ok { + return x.AutoUpdateBotInstanceReport + } + } + return nil +} + type isEvent_Resource interface { isEvent_Resource() } @@ -1285,6 +1295,11 @@ type Event_Plugin struct { Plugin *types.PluginV1 `protobuf:"bytes,84,opt,name=plugin,proto3,oneof"` } +type Event_AutoUpdateBotInstanceReport struct { + // AutoUpdateAgentReport is a resource for counting connected bot instances. + AutoUpdateBotInstanceReport *v111.AutoUpdateBotInstanceReport `protobuf:"bytes,85,opt,name=AutoUpdateBotInstanceReport,proto3,oneof"` +} + func (*Event_ResourceHeader) isEvent_Resource() {} func (*Event_CertAuthority) isEvent_Resource() {} @@ -1433,11 +1448,13 @@ func (*Event_AutoUpdateAgentReport) isEvent_Resource() {} func (*Event_Plugin) isEvent_Resource() {} +func (*Event_AutoUpdateBotInstanceReport) isEvent_Resource() {} + var File_teleport_legacy_client_proto_event_proto protoreflect.FileDescriptor const file_teleport_legacy_client_proto_event_proto_rawDesc = "" + "\n" + - "(teleport/legacy/client/proto/event.proto\x12\x05proto\x1a'teleport/accesslist/v1/accesslist.proto\x1a?teleport/accessmonitoringrules/v1/access_monitoring_rules.proto\x1a'teleport/autoupdate/v1/autoupdate.proto\x1a5teleport/clusterconfig/v1/access_graph_settings.proto\x1a'teleport/crownjewel/v1/crownjewel.proto\x1a#teleport/dbobject/v1/dbobject.proto\x1a1teleport/discoveryconfig/v1/discoveryconfig.proto\x1a/teleport/identitycenter/v1/identitycenter.proto\x1a;teleport/kubewaitingcontainer/v1/kubewaitingcontainer.proto\x1a!teleport/legacy/types/types.proto\x1a(teleport/machineid/v1/bot_instance.proto\x1a&teleport/machineid/v1/federation.proto\x1a-teleport/notifications/v1/notifications.proto\x1a+teleport/provisioning/v1/provisioning.proto\x1a'teleport/secreports/v1/secreports.proto\x1a/teleport/userloginstate/v1/userloginstate.proto\x1a1teleport/userprovisioning/v2/statichostuser.proto\x1a&teleport/usertasks/v1/user_tasks.proto\x1a+teleport/workloadidentity/v1/resource.proto\x1a6teleport/workloadidentity/v1/revocation_resource.proto\"\xa6,\n" + + "(teleport/legacy/client/proto/event.proto\x12\x05proto\x1a'teleport/accesslist/v1/accesslist.proto\x1a?teleport/accessmonitoringrules/v1/access_monitoring_rules.proto\x1a'teleport/autoupdate/v1/autoupdate.proto\x1a5teleport/clusterconfig/v1/access_graph_settings.proto\x1a'teleport/crownjewel/v1/crownjewel.proto\x1a#teleport/dbobject/v1/dbobject.proto\x1a1teleport/discoveryconfig/v1/discoveryconfig.proto\x1a/teleport/identitycenter/v1/identitycenter.proto\x1a;teleport/kubewaitingcontainer/v1/kubewaitingcontainer.proto\x1a!teleport/legacy/types/types.proto\x1a(teleport/machineid/v1/bot_instance.proto\x1a&teleport/machineid/v1/federation.proto\x1a-teleport/notifications/v1/notifications.proto\x1a+teleport/provisioning/v1/provisioning.proto\x1a'teleport/secreports/v1/secreports.proto\x1a/teleport/userloginstate/v1/userloginstate.proto\x1a1teleport/userprovisioning/v2/statichostuser.proto\x1a&teleport/usertasks/v1/user_tasks.proto\x1a+teleport/workloadidentity/v1/resource.proto\x1a6teleport/workloadidentity/v1/revocation_resource.proto\"\x9f-\n" + "\x05Event\x12$\n" + "\x04Type\x18\x01 \x01(\x0e2\x10.proto.OperationR\x04Type\x12?\n" + "\x0eResourceHeader\x18\x02 \x01(\v2\x15.types.ResourceHeaderH\x00R\x0eResourceHeader\x12>\n" + @@ -1524,7 +1541,8 @@ const file_teleport_legacy_client_proto_event_proto_rawDesc = "" + "\x10WorkloadIdentity\x18L \x01(\v2..teleport.workloadidentity.v1.WorkloadIdentityH\x00R\x10WorkloadIdentity\x12\x86\x01\n" + "\x1eWorkloadIdentityX509Revocation\x18M \x01(\v2<.teleport.workloadidentity.v1.WorkloadIdentityX509RevocationH\x00R\x1eWorkloadIdentityX509Revocation\x12e\n" + "\x15AutoUpdateAgentReport\x18O \x01(\v2-.teleport.autoupdate.v1.AutoUpdateAgentReportH\x00R\x15AutoUpdateAgentReport\x12)\n" + - "\x06plugin\x18T \x01(\v2\x0f.types.PluginV1H\x00R\x06pluginB\n" + + "\x06plugin\x18T \x01(\v2\x0f.types.PluginV1H\x00R\x06plugin\x12w\n" + + "\x1bAutoUpdateBotInstanceReport\x18U \x01(\v23.teleport.autoupdate.v1.AutoUpdateBotInstanceReportH\x00R\x1bAutoUpdateBotInstanceReportB\n" + "\n" + "\bResourceJ\x04\b\a\x10\bJ\x04\b1\x102J\x04\b?\x10@J\x04\bD\x10ER\x12ExternalCloudAuditR\x0eStaticHostUserR\x13AutoUpdateAgentPlan**\n" + "\tOperation\x12\b\n" + @@ -1621,6 +1639,7 @@ var file_teleport_legacy_client_proto_event_proto_goTypes = []any{ (*v115.WorkloadIdentityX509Revocation)(nil), // 70: teleport.workloadidentity.v1.WorkloadIdentityX509Revocation (*v111.AutoUpdateAgentReport)(nil), // 71: teleport.autoupdate.v1.AutoUpdateAgentReport (*types.PluginV1)(nil), // 72: types.PluginV1 + (*v111.AutoUpdateBotInstanceReport)(nil), // 73: teleport.autoupdate.v1.AutoUpdateBotInstanceReport } var file_teleport_legacy_client_proto_event_proto_depIdxs = []int32{ 0, // 0: proto.Event.Type:type_name -> proto.Operation @@ -1698,11 +1717,12 @@ var file_teleport_legacy_client_proto_event_proto_depIdxs = []int32{ 70, // 72: proto.Event.WorkloadIdentityX509Revocation:type_name -> teleport.workloadidentity.v1.WorkloadIdentityX509Revocation 71, // 73: proto.Event.AutoUpdateAgentReport:type_name -> teleport.autoupdate.v1.AutoUpdateAgentReport 72, // 74: proto.Event.plugin:type_name -> types.PluginV1 - 75, // [75:75] is the sub-list for method output_type - 75, // [75:75] is the sub-list for method input_type - 75, // [75:75] is the sub-list for extension type_name - 75, // [75:75] is the sub-list for extension extendee - 0, // [0:75] is the sub-list for field type_name + 73, // 75: proto.Event.AutoUpdateBotInstanceReport:type_name -> teleport.autoupdate.v1.AutoUpdateBotInstanceReport + 76, // [76:76] is the sub-list for method output_type + 76, // [76:76] is the sub-list for method input_type + 76, // [76:76] is the sub-list for extension type_name + 76, // [76:76] is the sub-list for extension extendee + 0, // [0:76] is the sub-list for field type_name } func init() { file_teleport_legacy_client_proto_event_proto_init() } @@ -1785,6 +1805,7 @@ func file_teleport_legacy_client_proto_event_proto_init() { (*Event_WorkloadIdentityX509Revocation)(nil), (*Event_AutoUpdateAgentReport)(nil), (*Event_Plugin)(nil), + (*Event_AutoUpdateBotInstanceReport)(nil), } type x struct{} out := protoimpl.TypeBuilder{ diff --git a/api/gen/proto/go/teleport/autoupdate/v1/autoupdate.pb.go b/api/gen/proto/go/teleport/autoupdate/v1/autoupdate.pb.go index 161dc011e4fc1..2e7abd8857853 100644 --- a/api/gen/proto/go/teleport/autoupdate/v1/autoupdate.pb.go +++ b/api/gen/proto/go/teleport/autoupdate/v1/autoupdate.pb.go @@ -1540,6 +1540,238 @@ func (x *AutoUpdateAgentReportSpecOmitted) GetReason() string { return "" } +// AutoUpdateBotInstanceReport is a report generated by an elected instance of the +// Teleport Auth service. The report tracks per group and per version how many +// instances of tbot are running. +type AutoUpdateBotInstanceReport struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The kind of resource represented. This is always `autoupdate_bot_instance_report`. + Kind string `protobuf:"bytes,1,opt,name=kind,proto3" json:"kind,omitempty"` + // Differentiates variations of the same kind. All resources should contain + // one, even if it is never populated. + SubKind string `protobuf:"bytes,2,opt,name=sub_kind,json=subKind,proto3" json:"sub_kind,omitempty"` + // The version of the resource being represented. + Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` + // Common metadata that all resources share. + Metadata *v1.Metadata `protobuf:"bytes,4,opt,name=metadata,proto3" json:"metadata,omitempty"` + // Contents of the report. + Spec *AutoUpdateBotInstanceReportSpec `protobuf:"bytes,5,opt,name=spec,proto3" json:"spec,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AutoUpdateBotInstanceReport) Reset() { + *x = AutoUpdateBotInstanceReport{} + mi := &file_teleport_autoupdate_v1_autoupdate_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AutoUpdateBotInstanceReport) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AutoUpdateBotInstanceReport) ProtoMessage() {} + +func (x *AutoUpdateBotInstanceReport) ProtoReflect() protoreflect.Message { + mi := &file_teleport_autoupdate_v1_autoupdate_proto_msgTypes[19] + 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 AutoUpdateBotInstanceReport.ProtoReflect.Descriptor instead. +func (*AutoUpdateBotInstanceReport) Descriptor() ([]byte, []int) { + return file_teleport_autoupdate_v1_autoupdate_proto_rawDescGZIP(), []int{19} +} + +func (x *AutoUpdateBotInstanceReport) GetKind() string { + if x != nil { + return x.Kind + } + return "" +} + +func (x *AutoUpdateBotInstanceReport) GetSubKind() string { + if x != nil { + return x.SubKind + } + return "" +} + +func (x *AutoUpdateBotInstanceReport) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *AutoUpdateBotInstanceReport) GetMetadata() *v1.Metadata { + if x != nil { + return x.Metadata + } + return nil +} + +func (x *AutoUpdateBotInstanceReport) GetSpec() *AutoUpdateBotInstanceReportSpec { + if x != nil { + return x.Spec + } + return nil +} + +// AutoUpdateBotInstanceReportSpec holds the contents of an AutoUpdateBotInstanceReport. +type AutoUpdateBotInstanceReportSpec struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Timestamp is when the report was generated. + Timestamp *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + // Bot counts aggregated by update group. + Groups map[string]*AutoUpdateBotInstanceReportSpecGroup `protobuf:"bytes,2,rep,name=groups,proto3" json:"groups,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AutoUpdateBotInstanceReportSpec) Reset() { + *x = AutoUpdateBotInstanceReportSpec{} + mi := &file_teleport_autoupdate_v1_autoupdate_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AutoUpdateBotInstanceReportSpec) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AutoUpdateBotInstanceReportSpec) ProtoMessage() {} + +func (x *AutoUpdateBotInstanceReportSpec) ProtoReflect() protoreflect.Message { + mi := &file_teleport_autoupdate_v1_autoupdate_proto_msgTypes[20] + 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 AutoUpdateBotInstanceReportSpec.ProtoReflect.Descriptor instead. +func (*AutoUpdateBotInstanceReportSpec) Descriptor() ([]byte, []int) { + return file_teleport_autoupdate_v1_autoupdate_proto_rawDescGZIP(), []int{20} +} + +func (x *AutoUpdateBotInstanceReportSpec) GetTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.Timestamp + } + return nil +} + +func (x *AutoUpdateBotInstanceReportSpec) GetGroups() map[string]*AutoUpdateBotInstanceReportSpecGroup { + if x != nil { + return x.Groups + } + return nil +} + +// AutoUpdateBotInstanceReportSpecGroup holds an update group's bot counts. +type AutoUpdateBotInstanceReportSpecGroup struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Bot counts aggregated by version. + Versions map[string]*AutoUpdateBotInstanceReportSpecGroupVersion `protobuf:"bytes,1,rep,name=versions,proto3" json:"versions,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AutoUpdateBotInstanceReportSpecGroup) Reset() { + *x = AutoUpdateBotInstanceReportSpecGroup{} + mi := &file_teleport_autoupdate_v1_autoupdate_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AutoUpdateBotInstanceReportSpecGroup) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AutoUpdateBotInstanceReportSpecGroup) ProtoMessage() {} + +func (x *AutoUpdateBotInstanceReportSpecGroup) ProtoReflect() protoreflect.Message { + mi := &file_teleport_autoupdate_v1_autoupdate_proto_msgTypes[21] + 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 AutoUpdateBotInstanceReportSpecGroup.ProtoReflect.Descriptor instead. +func (*AutoUpdateBotInstanceReportSpecGroup) Descriptor() ([]byte, []int) { + return file_teleport_autoupdate_v1_autoupdate_proto_rawDescGZIP(), []int{21} +} + +func (x *AutoUpdateBotInstanceReportSpecGroup) GetVersions() map[string]*AutoUpdateBotInstanceReportSpecGroupVersion { + if x != nil { + return x.Versions + } + return nil +} + +// AutoUpdateBotInstanceReportSpecGroupVersion holds a version's bot count. +type AutoUpdateBotInstanceReportSpecGroupVersion struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Count of bot instances running this version. + Count int32 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AutoUpdateBotInstanceReportSpecGroupVersion) Reset() { + *x = AutoUpdateBotInstanceReportSpecGroupVersion{} + mi := &file_teleport_autoupdate_v1_autoupdate_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AutoUpdateBotInstanceReportSpecGroupVersion) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AutoUpdateBotInstanceReportSpecGroupVersion) ProtoMessage() {} + +func (x *AutoUpdateBotInstanceReportSpecGroupVersion) ProtoReflect() protoreflect.Message { + mi := &file_teleport_autoupdate_v1_autoupdate_proto_msgTypes[22] + 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 AutoUpdateBotInstanceReportSpecGroupVersion.ProtoReflect.Descriptor instead. +func (*AutoUpdateBotInstanceReportSpecGroupVersion) Descriptor() ([]byte, []int) { + return file_teleport_autoupdate_v1_autoupdate_proto_rawDescGZIP(), []int{22} +} + +func (x *AutoUpdateBotInstanceReportSpecGroupVersion) GetCount() int32 { + if x != nil { + return x.Count + } + return 0 +} + // Canary describes a node that is acting as a canary and being updated before other nodes in its group. type Canary struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -1560,7 +1792,7 @@ type Canary struct { func (x *Canary) Reset() { *x = Canary{} - mi := &file_teleport_autoupdate_v1_autoupdate_proto_msgTypes[19] + mi := &file_teleport_autoupdate_v1_autoupdate_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1572,7 +1804,7 @@ func (x *Canary) String() string { func (*Canary) ProtoMessage() {} func (x *Canary) ProtoReflect() protoreflect.Message { - mi := &file_teleport_autoupdate_v1_autoupdate_proto_msgTypes[19] + mi := &file_teleport_autoupdate_v1_autoupdate_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1585,7 +1817,7 @@ func (x *Canary) ProtoReflect() protoreflect.Message { // Deprecated: Use Canary.ProtoReflect.Descriptor instead. func (*Canary) Descriptor() ([]byte, []int) { - return file_teleport_autoupdate_v1_autoupdate_proto_rawDescGZIP(), []int{19} + return file_teleport_autoupdate_v1_autoupdate_proto_rawDescGZIP(), []int{23} } func (x *Canary) GetUpdaterId() string { @@ -1722,7 +1954,26 @@ const file_teleport_autoupdate_v1_autoupdate_proto_rawDesc = "" + "\x05count\x18\x01 \x01(\x05R\x05count\"P\n" + " AutoUpdateAgentReportSpecOmitted\x12\x14\n" + "\x05count\x18\x01 \x01(\x03R\x05count\x12\x16\n" + - "\x06reason\x18\x02 \x01(\tR\x06reason\"v\n" + + "\x06reason\x18\x02 \x01(\tR\x06reason\"\xed\x01\n" + + "\x1bAutoUpdateBotInstanceReport\x12\x12\n" + + "\x04kind\x18\x01 \x01(\tR\x04kind\x12\x19\n" + + "\bsub_kind\x18\x02 \x01(\tR\asubKind\x12\x18\n" + + "\aversion\x18\x03 \x01(\tR\aversion\x128\n" + + "\bmetadata\x18\x04 \x01(\v2\x1c.teleport.header.v1.MetadataR\bmetadata\x12K\n" + + "\x04spec\x18\x05 \x01(\v27.teleport.autoupdate.v1.AutoUpdateBotInstanceReportSpecR\x04spec\"\xb1\x02\n" + + "\x1fAutoUpdateBotInstanceReportSpec\x128\n" + + "\ttimestamp\x18\x01 \x01(\v2\x1a.google.protobuf.TimestampR\ttimestamp\x12[\n" + + "\x06groups\x18\x02 \x03(\v2C.teleport.autoupdate.v1.AutoUpdateBotInstanceReportSpec.GroupsEntryR\x06groups\x1aw\n" + + "\vGroupsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12R\n" + + "\x05value\x18\x02 \x01(\v2<.teleport.autoupdate.v1.AutoUpdateBotInstanceReportSpecGroupR\x05value:\x028\x01\"\x91\x02\n" + + "$AutoUpdateBotInstanceReportSpecGroup\x12f\n" + + "\bversions\x18\x01 \x03(\v2J.teleport.autoupdate.v1.AutoUpdateBotInstanceReportSpecGroup.VersionsEntryR\bversions\x1a\x80\x01\n" + + "\rVersionsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12Y\n" + + "\x05value\x18\x02 \x01(\v2C.teleport.autoupdate.v1.AutoUpdateBotInstanceReportSpecGroupVersionR\x05value:\x028\x01\"C\n" + + "+AutoUpdateBotInstanceReportSpecGroupVersion\x12\x14\n" + + "\x05count\x18\x01 \x01(\x05R\x05count\"v\n" + "\x06Canary\x12\x1d\n" + "\n" + "updater_id\x18\x01 \x01(\tR\tupdaterId\x12\x17\n" + @@ -1756,73 +2007,86 @@ func file_teleport_autoupdate_v1_autoupdate_proto_rawDescGZIP() []byte { } var file_teleport_autoupdate_v1_autoupdate_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_teleport_autoupdate_v1_autoupdate_proto_msgTypes = make([]protoimpl.MessageInfo, 22) +var file_teleport_autoupdate_v1_autoupdate_proto_msgTypes = make([]protoimpl.MessageInfo, 28) var file_teleport_autoupdate_v1_autoupdate_proto_goTypes = []any{ - (AutoUpdateAgentGroupState)(0), // 0: teleport.autoupdate.v1.AutoUpdateAgentGroupState - (AutoUpdateAgentRolloutState)(0), // 1: teleport.autoupdate.v1.AutoUpdateAgentRolloutState - (*AutoUpdateConfig)(nil), // 2: teleport.autoupdate.v1.AutoUpdateConfig - (*AutoUpdateConfigSpec)(nil), // 3: teleport.autoupdate.v1.AutoUpdateConfigSpec - (*AutoUpdateConfigSpecTools)(nil), // 4: teleport.autoupdate.v1.AutoUpdateConfigSpecTools - (*AutoUpdateConfigSpecAgents)(nil), // 5: teleport.autoupdate.v1.AutoUpdateConfigSpecAgents - (*AgentAutoUpdateSchedules)(nil), // 6: teleport.autoupdate.v1.AgentAutoUpdateSchedules - (*AgentAutoUpdateGroup)(nil), // 7: teleport.autoupdate.v1.AgentAutoUpdateGroup - (*AutoUpdateVersion)(nil), // 8: teleport.autoupdate.v1.AutoUpdateVersion - (*AutoUpdateVersionSpec)(nil), // 9: teleport.autoupdate.v1.AutoUpdateVersionSpec - (*AutoUpdateVersionSpecTools)(nil), // 10: teleport.autoupdate.v1.AutoUpdateVersionSpecTools - (*AutoUpdateVersionSpecAgents)(nil), // 11: teleport.autoupdate.v1.AutoUpdateVersionSpecAgents - (*AutoUpdateAgentRollout)(nil), // 12: teleport.autoupdate.v1.AutoUpdateAgentRollout - (*AutoUpdateAgentRolloutSpec)(nil), // 13: teleport.autoupdate.v1.AutoUpdateAgentRolloutSpec - (*AutoUpdateAgentRolloutStatus)(nil), // 14: teleport.autoupdate.v1.AutoUpdateAgentRolloutStatus - (*AutoUpdateAgentRolloutStatusGroup)(nil), // 15: teleport.autoupdate.v1.AutoUpdateAgentRolloutStatusGroup - (*AutoUpdateAgentReport)(nil), // 16: teleport.autoupdate.v1.AutoUpdateAgentReport - (*AutoUpdateAgentReportSpec)(nil), // 17: teleport.autoupdate.v1.AutoUpdateAgentReportSpec - (*AutoUpdateAgentReportSpecGroup)(nil), // 18: teleport.autoupdate.v1.AutoUpdateAgentReportSpecGroup - (*AutoUpdateAgentReportSpecGroupVersion)(nil), // 19: teleport.autoupdate.v1.AutoUpdateAgentReportSpecGroupVersion - (*AutoUpdateAgentReportSpecOmitted)(nil), // 20: teleport.autoupdate.v1.AutoUpdateAgentReportSpecOmitted - (*Canary)(nil), // 21: teleport.autoupdate.v1.Canary - nil, // 22: teleport.autoupdate.v1.AutoUpdateAgentReportSpec.GroupsEntry - nil, // 23: teleport.autoupdate.v1.AutoUpdateAgentReportSpecGroup.VersionsEntry - (*v1.Metadata)(nil), // 24: teleport.header.v1.Metadata - (*durationpb.Duration)(nil), // 25: google.protobuf.Duration - (*timestamppb.Timestamp)(nil), // 26: google.protobuf.Timestamp + (AutoUpdateAgentGroupState)(0), // 0: teleport.autoupdate.v1.AutoUpdateAgentGroupState + (AutoUpdateAgentRolloutState)(0), // 1: teleport.autoupdate.v1.AutoUpdateAgentRolloutState + (*AutoUpdateConfig)(nil), // 2: teleport.autoupdate.v1.AutoUpdateConfig + (*AutoUpdateConfigSpec)(nil), // 3: teleport.autoupdate.v1.AutoUpdateConfigSpec + (*AutoUpdateConfigSpecTools)(nil), // 4: teleport.autoupdate.v1.AutoUpdateConfigSpecTools + (*AutoUpdateConfigSpecAgents)(nil), // 5: teleport.autoupdate.v1.AutoUpdateConfigSpecAgents + (*AgentAutoUpdateSchedules)(nil), // 6: teleport.autoupdate.v1.AgentAutoUpdateSchedules + (*AgentAutoUpdateGroup)(nil), // 7: teleport.autoupdate.v1.AgentAutoUpdateGroup + (*AutoUpdateVersion)(nil), // 8: teleport.autoupdate.v1.AutoUpdateVersion + (*AutoUpdateVersionSpec)(nil), // 9: teleport.autoupdate.v1.AutoUpdateVersionSpec + (*AutoUpdateVersionSpecTools)(nil), // 10: teleport.autoupdate.v1.AutoUpdateVersionSpecTools + (*AutoUpdateVersionSpecAgents)(nil), // 11: teleport.autoupdate.v1.AutoUpdateVersionSpecAgents + (*AutoUpdateAgentRollout)(nil), // 12: teleport.autoupdate.v1.AutoUpdateAgentRollout + (*AutoUpdateAgentRolloutSpec)(nil), // 13: teleport.autoupdate.v1.AutoUpdateAgentRolloutSpec + (*AutoUpdateAgentRolloutStatus)(nil), // 14: teleport.autoupdate.v1.AutoUpdateAgentRolloutStatus + (*AutoUpdateAgentRolloutStatusGroup)(nil), // 15: teleport.autoupdate.v1.AutoUpdateAgentRolloutStatusGroup + (*AutoUpdateAgentReport)(nil), // 16: teleport.autoupdate.v1.AutoUpdateAgentReport + (*AutoUpdateAgentReportSpec)(nil), // 17: teleport.autoupdate.v1.AutoUpdateAgentReportSpec + (*AutoUpdateAgentReportSpecGroup)(nil), // 18: teleport.autoupdate.v1.AutoUpdateAgentReportSpecGroup + (*AutoUpdateAgentReportSpecGroupVersion)(nil), // 19: teleport.autoupdate.v1.AutoUpdateAgentReportSpecGroupVersion + (*AutoUpdateAgentReportSpecOmitted)(nil), // 20: teleport.autoupdate.v1.AutoUpdateAgentReportSpecOmitted + (*AutoUpdateBotInstanceReport)(nil), // 21: teleport.autoupdate.v1.AutoUpdateBotInstanceReport + (*AutoUpdateBotInstanceReportSpec)(nil), // 22: teleport.autoupdate.v1.AutoUpdateBotInstanceReportSpec + (*AutoUpdateBotInstanceReportSpecGroup)(nil), // 23: teleport.autoupdate.v1.AutoUpdateBotInstanceReportSpecGroup + (*AutoUpdateBotInstanceReportSpecGroupVersion)(nil), // 24: teleport.autoupdate.v1.AutoUpdateBotInstanceReportSpecGroupVersion + (*Canary)(nil), // 25: teleport.autoupdate.v1.Canary + nil, // 26: teleport.autoupdate.v1.AutoUpdateAgentReportSpec.GroupsEntry + nil, // 27: teleport.autoupdate.v1.AutoUpdateAgentReportSpecGroup.VersionsEntry + nil, // 28: teleport.autoupdate.v1.AutoUpdateBotInstanceReportSpec.GroupsEntry + nil, // 29: teleport.autoupdate.v1.AutoUpdateBotInstanceReportSpecGroup.VersionsEntry + (*v1.Metadata)(nil), // 30: teleport.header.v1.Metadata + (*durationpb.Duration)(nil), // 31: google.protobuf.Duration + (*timestamppb.Timestamp)(nil), // 32: google.protobuf.Timestamp } var file_teleport_autoupdate_v1_autoupdate_proto_depIdxs = []int32{ - 24, // 0: teleport.autoupdate.v1.AutoUpdateConfig.metadata:type_name -> teleport.header.v1.Metadata + 30, // 0: teleport.autoupdate.v1.AutoUpdateConfig.metadata:type_name -> teleport.header.v1.Metadata 3, // 1: teleport.autoupdate.v1.AutoUpdateConfig.spec:type_name -> teleport.autoupdate.v1.AutoUpdateConfigSpec 4, // 2: teleport.autoupdate.v1.AutoUpdateConfigSpec.tools:type_name -> teleport.autoupdate.v1.AutoUpdateConfigSpecTools 5, // 3: teleport.autoupdate.v1.AutoUpdateConfigSpec.agents:type_name -> teleport.autoupdate.v1.AutoUpdateConfigSpecAgents - 25, // 4: teleport.autoupdate.v1.AutoUpdateConfigSpecAgents.maintenance_window_duration:type_name -> google.protobuf.Duration + 31, // 4: teleport.autoupdate.v1.AutoUpdateConfigSpecAgents.maintenance_window_duration:type_name -> google.protobuf.Duration 6, // 5: teleport.autoupdate.v1.AutoUpdateConfigSpecAgents.schedules:type_name -> teleport.autoupdate.v1.AgentAutoUpdateSchedules 7, // 6: teleport.autoupdate.v1.AgentAutoUpdateSchedules.regular:type_name -> teleport.autoupdate.v1.AgentAutoUpdateGroup - 24, // 7: teleport.autoupdate.v1.AutoUpdateVersion.metadata:type_name -> teleport.header.v1.Metadata + 30, // 7: teleport.autoupdate.v1.AutoUpdateVersion.metadata:type_name -> teleport.header.v1.Metadata 9, // 8: teleport.autoupdate.v1.AutoUpdateVersion.spec:type_name -> teleport.autoupdate.v1.AutoUpdateVersionSpec 10, // 9: teleport.autoupdate.v1.AutoUpdateVersionSpec.tools:type_name -> teleport.autoupdate.v1.AutoUpdateVersionSpecTools 11, // 10: teleport.autoupdate.v1.AutoUpdateVersionSpec.agents:type_name -> teleport.autoupdate.v1.AutoUpdateVersionSpecAgents - 24, // 11: teleport.autoupdate.v1.AutoUpdateAgentRollout.metadata:type_name -> teleport.header.v1.Metadata + 30, // 11: teleport.autoupdate.v1.AutoUpdateAgentRollout.metadata:type_name -> teleport.header.v1.Metadata 13, // 12: teleport.autoupdate.v1.AutoUpdateAgentRollout.spec:type_name -> teleport.autoupdate.v1.AutoUpdateAgentRolloutSpec 14, // 13: teleport.autoupdate.v1.AutoUpdateAgentRollout.status:type_name -> teleport.autoupdate.v1.AutoUpdateAgentRolloutStatus - 25, // 14: teleport.autoupdate.v1.AutoUpdateAgentRolloutSpec.maintenance_window_duration:type_name -> google.protobuf.Duration + 31, // 14: teleport.autoupdate.v1.AutoUpdateAgentRolloutSpec.maintenance_window_duration:type_name -> google.protobuf.Duration 15, // 15: teleport.autoupdate.v1.AutoUpdateAgentRolloutStatus.groups:type_name -> teleport.autoupdate.v1.AutoUpdateAgentRolloutStatusGroup 1, // 16: teleport.autoupdate.v1.AutoUpdateAgentRolloutStatus.state:type_name -> teleport.autoupdate.v1.AutoUpdateAgentRolloutState - 26, // 17: teleport.autoupdate.v1.AutoUpdateAgentRolloutStatus.start_time:type_name -> google.protobuf.Timestamp - 26, // 18: teleport.autoupdate.v1.AutoUpdateAgentRolloutStatus.time_override:type_name -> google.protobuf.Timestamp - 26, // 19: teleport.autoupdate.v1.AutoUpdateAgentRolloutStatusGroup.start_time:type_name -> google.protobuf.Timestamp + 32, // 17: teleport.autoupdate.v1.AutoUpdateAgentRolloutStatus.start_time:type_name -> google.protobuf.Timestamp + 32, // 18: teleport.autoupdate.v1.AutoUpdateAgentRolloutStatus.time_override:type_name -> google.protobuf.Timestamp + 32, // 19: teleport.autoupdate.v1.AutoUpdateAgentRolloutStatusGroup.start_time:type_name -> google.protobuf.Timestamp 0, // 20: teleport.autoupdate.v1.AutoUpdateAgentRolloutStatusGroup.state:type_name -> teleport.autoupdate.v1.AutoUpdateAgentGroupState - 26, // 21: teleport.autoupdate.v1.AutoUpdateAgentRolloutStatusGroup.last_update_time:type_name -> google.protobuf.Timestamp - 21, // 22: teleport.autoupdate.v1.AutoUpdateAgentRolloutStatusGroup.canaries:type_name -> teleport.autoupdate.v1.Canary - 24, // 23: teleport.autoupdate.v1.AutoUpdateAgentReport.metadata:type_name -> teleport.header.v1.Metadata + 32, // 21: teleport.autoupdate.v1.AutoUpdateAgentRolloutStatusGroup.last_update_time:type_name -> google.protobuf.Timestamp + 25, // 22: teleport.autoupdate.v1.AutoUpdateAgentRolloutStatusGroup.canaries:type_name -> teleport.autoupdate.v1.Canary + 30, // 23: teleport.autoupdate.v1.AutoUpdateAgentReport.metadata:type_name -> teleport.header.v1.Metadata 17, // 24: teleport.autoupdate.v1.AutoUpdateAgentReport.spec:type_name -> teleport.autoupdate.v1.AutoUpdateAgentReportSpec - 26, // 25: teleport.autoupdate.v1.AutoUpdateAgentReportSpec.timestamp:type_name -> google.protobuf.Timestamp - 22, // 26: teleport.autoupdate.v1.AutoUpdateAgentReportSpec.groups:type_name -> teleport.autoupdate.v1.AutoUpdateAgentReportSpec.GroupsEntry + 32, // 25: teleport.autoupdate.v1.AutoUpdateAgentReportSpec.timestamp:type_name -> google.protobuf.Timestamp + 26, // 26: teleport.autoupdate.v1.AutoUpdateAgentReportSpec.groups:type_name -> teleport.autoupdate.v1.AutoUpdateAgentReportSpec.GroupsEntry 20, // 27: teleport.autoupdate.v1.AutoUpdateAgentReportSpec.omitted:type_name -> teleport.autoupdate.v1.AutoUpdateAgentReportSpecOmitted - 23, // 28: teleport.autoupdate.v1.AutoUpdateAgentReportSpecGroup.versions:type_name -> teleport.autoupdate.v1.AutoUpdateAgentReportSpecGroup.VersionsEntry - 18, // 29: teleport.autoupdate.v1.AutoUpdateAgentReportSpec.GroupsEntry.value:type_name -> teleport.autoupdate.v1.AutoUpdateAgentReportSpecGroup - 19, // 30: teleport.autoupdate.v1.AutoUpdateAgentReportSpecGroup.VersionsEntry.value:type_name -> teleport.autoupdate.v1.AutoUpdateAgentReportSpecGroupVersion - 31, // [31:31] is the sub-list for method output_type - 31, // [31:31] is the sub-list for method input_type - 31, // [31:31] is the sub-list for extension type_name - 31, // [31:31] is the sub-list for extension extendee - 0, // [0:31] is the sub-list for field type_name + 27, // 28: teleport.autoupdate.v1.AutoUpdateAgentReportSpecGroup.versions:type_name -> teleport.autoupdate.v1.AutoUpdateAgentReportSpecGroup.VersionsEntry + 30, // 29: teleport.autoupdate.v1.AutoUpdateBotInstanceReport.metadata:type_name -> teleport.header.v1.Metadata + 22, // 30: teleport.autoupdate.v1.AutoUpdateBotInstanceReport.spec:type_name -> teleport.autoupdate.v1.AutoUpdateBotInstanceReportSpec + 32, // 31: teleport.autoupdate.v1.AutoUpdateBotInstanceReportSpec.timestamp:type_name -> google.protobuf.Timestamp + 28, // 32: teleport.autoupdate.v1.AutoUpdateBotInstanceReportSpec.groups:type_name -> teleport.autoupdate.v1.AutoUpdateBotInstanceReportSpec.GroupsEntry + 29, // 33: teleport.autoupdate.v1.AutoUpdateBotInstanceReportSpecGroup.versions:type_name -> teleport.autoupdate.v1.AutoUpdateBotInstanceReportSpecGroup.VersionsEntry + 18, // 34: teleport.autoupdate.v1.AutoUpdateAgentReportSpec.GroupsEntry.value:type_name -> teleport.autoupdate.v1.AutoUpdateAgentReportSpecGroup + 19, // 35: teleport.autoupdate.v1.AutoUpdateAgentReportSpecGroup.VersionsEntry.value:type_name -> teleport.autoupdate.v1.AutoUpdateAgentReportSpecGroupVersion + 23, // 36: teleport.autoupdate.v1.AutoUpdateBotInstanceReportSpec.GroupsEntry.value:type_name -> teleport.autoupdate.v1.AutoUpdateBotInstanceReportSpecGroup + 24, // 37: teleport.autoupdate.v1.AutoUpdateBotInstanceReportSpecGroup.VersionsEntry.value:type_name -> teleport.autoupdate.v1.AutoUpdateBotInstanceReportSpecGroupVersion + 38, // [38:38] is the sub-list for method output_type + 38, // [38:38] is the sub-list for method input_type + 38, // [38:38] is the sub-list for extension type_name + 38, // [38:38] is the sub-list for extension extendee + 0, // [0:38] is the sub-list for field type_name } func init() { file_teleport_autoupdate_v1_autoupdate_proto_init() } @@ -1836,7 +2100,7 @@ func file_teleport_autoupdate_v1_autoupdate_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_teleport_autoupdate_v1_autoupdate_proto_rawDesc), len(file_teleport_autoupdate_v1_autoupdate_proto_rawDesc)), NumEnums: 2, - NumMessages: 22, + NumMessages: 28, NumExtensions: 0, NumServices: 0, }, diff --git a/api/gen/proto/go/teleport/autoupdate/v1/autoupdate_service.pb.go b/api/gen/proto/go/teleport/autoupdate/v1/autoupdate_service.pb.go index f2e2b2f8c95b8..61578cf222afe 100644 --- a/api/gen/proto/go/teleport/autoupdate/v1/autoupdate_service.pb.go +++ b/api/gen/proto/go/teleport/autoupdate/v1/autoupdate_service.pb.go @@ -1173,6 +1173,80 @@ func (x *DeleteAutoUpdateAgentReportRequest) GetName() string { return "" } +// Request for GetAutoUpdateBotInstanceReport. +type GetAutoUpdateBotInstanceReportRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetAutoUpdateBotInstanceReportRequest) Reset() { + *x = GetAutoUpdateBotInstanceReportRequest{} + mi := &file_teleport_autoupdate_v1_autoupdate_service_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetAutoUpdateBotInstanceReportRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetAutoUpdateBotInstanceReportRequest) ProtoMessage() {} + +func (x *GetAutoUpdateBotInstanceReportRequest) ProtoReflect() protoreflect.Message { + mi := &file_teleport_autoupdate_v1_autoupdate_service_proto_msgTypes[25] + 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 GetAutoUpdateBotInstanceReportRequest.ProtoReflect.Descriptor instead. +func (*GetAutoUpdateBotInstanceReportRequest) Descriptor() ([]byte, []int) { + return file_teleport_autoupdate_v1_autoupdate_service_proto_rawDescGZIP(), []int{25} +} + +// Request for DeleteAutoUpdateBotInstanceReport. +type DeleteAutoUpdateBotInstanceReportRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteAutoUpdateBotInstanceReportRequest) Reset() { + *x = DeleteAutoUpdateBotInstanceReportRequest{} + mi := &file_teleport_autoupdate_v1_autoupdate_service_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteAutoUpdateBotInstanceReportRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteAutoUpdateBotInstanceReportRequest) ProtoMessage() {} + +func (x *DeleteAutoUpdateBotInstanceReportRequest) ProtoReflect() protoreflect.Message { + mi := &file_teleport_autoupdate_v1_autoupdate_service_proto_msgTypes[26] + 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 DeleteAutoUpdateBotInstanceReportRequest.ProtoReflect.Descriptor instead. +func (*DeleteAutoUpdateBotInstanceReportRequest) Descriptor() ([]byte, []int) { + return file_teleport_autoupdate_v1_autoupdate_service_proto_rawDescGZIP(), []int{26} +} + var File_teleport_autoupdate_v1_autoupdate_service_proto protoreflect.FileDescriptor const file_teleport_autoupdate_v1_autoupdate_service_proto_rawDesc = "" + @@ -1228,7 +1302,9 @@ const file_teleport_autoupdate_v1_autoupdate_service_proto_rawDesc = "" + "\"UpsertAutoUpdateAgentReportRequest\x12e\n" + "\x17autoupdate_agent_report\x18\x01 \x01(\v2-.teleport.autoupdate.v1.AutoUpdateAgentReportR\x15autoupdateAgentReport\"8\n" + "\"DeleteAutoUpdateAgentReportRequest\x12\x12\n" + - "\x04name\x18\x01 \x01(\tR\x04name2\xb7\x18\n" + + "\x04name\x18\x01 \x01(\tR\x04name\"'\n" + + "%GetAutoUpdateBotInstanceReportRequest\"*\n" + + "(DeleteAutoUpdateBotInstanceReportRequest2\xcd\x1a\n" + "\x11AutoUpdateService\x12s\n" + "\x13GetAutoUpdateConfig\x122.teleport.autoupdate.v1.GetAutoUpdateConfigRequest\x1a(.teleport.autoupdate.v1.AutoUpdateConfig\x12y\n" + "\x16CreateAutoUpdateConfig\x125.teleport.autoupdate.v1.CreateAutoUpdateConfigRequest\x1a(.teleport.autoupdate.v1.AutoUpdateConfig\x12y\n" + @@ -1253,7 +1329,9 @@ const file_teleport_autoupdate_v1_autoupdate_service_proto_rawDesc = "" + "\x1bCreateAutoUpdateAgentReport\x12:.teleport.autoupdate.v1.CreateAutoUpdateAgentReportRequest\x1a-.teleport.autoupdate.v1.AutoUpdateAgentReport\x12\x88\x01\n" + "\x1bUpdateAutoUpdateAgentReport\x12:.teleport.autoupdate.v1.UpdateAutoUpdateAgentReportRequest\x1a-.teleport.autoupdate.v1.AutoUpdateAgentReport\x12\x88\x01\n" + "\x1bUpsertAutoUpdateAgentReport\x12:.teleport.autoupdate.v1.UpsertAutoUpdateAgentReportRequest\x1a-.teleport.autoupdate.v1.AutoUpdateAgentReport\x12q\n" + - "\x1bDeleteAutoUpdateAgentReport\x12:.teleport.autoupdate.v1.DeleteAutoUpdateAgentReportRequest\x1a\x16.google.protobuf.EmptyBVZTgithub.com/gravitational/teleport/api/gen/proto/go/teleport/autoupdate/v1;autoupdateb\x06proto3" + "\x1bDeleteAutoUpdateAgentReport\x12:.teleport.autoupdate.v1.DeleteAutoUpdateAgentReportRequest\x1a\x16.google.protobuf.Empty\x12\x94\x01\n" + + "\x1eGetAutoUpdateBotInstanceReport\x12=.teleport.autoupdate.v1.GetAutoUpdateBotInstanceReportRequest\x1a3.teleport.autoupdate.v1.AutoUpdateBotInstanceReport\x12}\n" + + "!DeleteAutoUpdateBotInstanceReport\x12@.teleport.autoupdate.v1.DeleteAutoUpdateBotInstanceReportRequest\x1a\x16.google.protobuf.EmptyBVZTgithub.com/gravitational/teleport/api/gen/proto/go/teleport/autoupdate/v1;autoupdateb\x06proto3" var ( file_teleport_autoupdate_v1_autoupdate_service_proto_rawDescOnce sync.Once @@ -1267,55 +1345,58 @@ func file_teleport_autoupdate_v1_autoupdate_service_proto_rawDescGZIP() []byte { return file_teleport_autoupdate_v1_autoupdate_service_proto_rawDescData } -var file_teleport_autoupdate_v1_autoupdate_service_proto_msgTypes = make([]protoimpl.MessageInfo, 25) +var file_teleport_autoupdate_v1_autoupdate_service_proto_msgTypes = make([]protoimpl.MessageInfo, 27) var file_teleport_autoupdate_v1_autoupdate_service_proto_goTypes = []any{ - (*GetAutoUpdateConfigRequest)(nil), // 0: teleport.autoupdate.v1.GetAutoUpdateConfigRequest - (*CreateAutoUpdateConfigRequest)(nil), // 1: teleport.autoupdate.v1.CreateAutoUpdateConfigRequest - (*UpdateAutoUpdateConfigRequest)(nil), // 2: teleport.autoupdate.v1.UpdateAutoUpdateConfigRequest - (*UpsertAutoUpdateConfigRequest)(nil), // 3: teleport.autoupdate.v1.UpsertAutoUpdateConfigRequest - (*DeleteAutoUpdateConfigRequest)(nil), // 4: teleport.autoupdate.v1.DeleteAutoUpdateConfigRequest - (*GetAutoUpdateVersionRequest)(nil), // 5: teleport.autoupdate.v1.GetAutoUpdateVersionRequest - (*CreateAutoUpdateVersionRequest)(nil), // 6: teleport.autoupdate.v1.CreateAutoUpdateVersionRequest - (*UpdateAutoUpdateVersionRequest)(nil), // 7: teleport.autoupdate.v1.UpdateAutoUpdateVersionRequest - (*UpsertAutoUpdateVersionRequest)(nil), // 8: teleport.autoupdate.v1.UpsertAutoUpdateVersionRequest - (*DeleteAutoUpdateVersionRequest)(nil), // 9: teleport.autoupdate.v1.DeleteAutoUpdateVersionRequest - (*GetAutoUpdateAgentRolloutRequest)(nil), // 10: teleport.autoupdate.v1.GetAutoUpdateAgentRolloutRequest - (*CreateAutoUpdateAgentRolloutRequest)(nil), // 11: teleport.autoupdate.v1.CreateAutoUpdateAgentRolloutRequest - (*UpdateAutoUpdateAgentRolloutRequest)(nil), // 12: teleport.autoupdate.v1.UpdateAutoUpdateAgentRolloutRequest - (*UpsertAutoUpdateAgentRolloutRequest)(nil), // 13: teleport.autoupdate.v1.UpsertAutoUpdateAgentRolloutRequest - (*DeleteAutoUpdateAgentRolloutRequest)(nil), // 14: teleport.autoupdate.v1.DeleteAutoUpdateAgentRolloutRequest - (*TriggerAutoUpdateAgentGroupRequest)(nil), // 15: teleport.autoupdate.v1.TriggerAutoUpdateAgentGroupRequest - (*ForceAutoUpdateAgentGroupRequest)(nil), // 16: teleport.autoupdate.v1.ForceAutoUpdateAgentGroupRequest - (*RollbackAutoUpdateAgentGroupRequest)(nil), // 17: teleport.autoupdate.v1.RollbackAutoUpdateAgentGroupRequest - (*ListAutoUpdateAgentReportsRequest)(nil), // 18: teleport.autoupdate.v1.ListAutoUpdateAgentReportsRequest - (*ListAutoUpdateAgentReportsResponse)(nil), // 19: teleport.autoupdate.v1.ListAutoUpdateAgentReportsResponse - (*GetAutoUpdateAgentReportRequest)(nil), // 20: teleport.autoupdate.v1.GetAutoUpdateAgentReportRequest - (*CreateAutoUpdateAgentReportRequest)(nil), // 21: teleport.autoupdate.v1.CreateAutoUpdateAgentReportRequest - (*UpdateAutoUpdateAgentReportRequest)(nil), // 22: teleport.autoupdate.v1.UpdateAutoUpdateAgentReportRequest - (*UpsertAutoUpdateAgentReportRequest)(nil), // 23: teleport.autoupdate.v1.UpsertAutoUpdateAgentReportRequest - (*DeleteAutoUpdateAgentReportRequest)(nil), // 24: teleport.autoupdate.v1.DeleteAutoUpdateAgentReportRequest - (*AutoUpdateConfig)(nil), // 25: teleport.autoupdate.v1.AutoUpdateConfig - (*AutoUpdateVersion)(nil), // 26: teleport.autoupdate.v1.AutoUpdateVersion - (*AutoUpdateAgentRollout)(nil), // 27: teleport.autoupdate.v1.AutoUpdateAgentRollout - (AutoUpdateAgentGroupState)(0), // 28: teleport.autoupdate.v1.AutoUpdateAgentGroupState - (*AutoUpdateAgentReport)(nil), // 29: teleport.autoupdate.v1.AutoUpdateAgentReport - (*emptypb.Empty)(nil), // 30: google.protobuf.Empty + (*GetAutoUpdateConfigRequest)(nil), // 0: teleport.autoupdate.v1.GetAutoUpdateConfigRequest + (*CreateAutoUpdateConfigRequest)(nil), // 1: teleport.autoupdate.v1.CreateAutoUpdateConfigRequest + (*UpdateAutoUpdateConfigRequest)(nil), // 2: teleport.autoupdate.v1.UpdateAutoUpdateConfigRequest + (*UpsertAutoUpdateConfigRequest)(nil), // 3: teleport.autoupdate.v1.UpsertAutoUpdateConfigRequest + (*DeleteAutoUpdateConfigRequest)(nil), // 4: teleport.autoupdate.v1.DeleteAutoUpdateConfigRequest + (*GetAutoUpdateVersionRequest)(nil), // 5: teleport.autoupdate.v1.GetAutoUpdateVersionRequest + (*CreateAutoUpdateVersionRequest)(nil), // 6: teleport.autoupdate.v1.CreateAutoUpdateVersionRequest + (*UpdateAutoUpdateVersionRequest)(nil), // 7: teleport.autoupdate.v1.UpdateAutoUpdateVersionRequest + (*UpsertAutoUpdateVersionRequest)(nil), // 8: teleport.autoupdate.v1.UpsertAutoUpdateVersionRequest + (*DeleteAutoUpdateVersionRequest)(nil), // 9: teleport.autoupdate.v1.DeleteAutoUpdateVersionRequest + (*GetAutoUpdateAgentRolloutRequest)(nil), // 10: teleport.autoupdate.v1.GetAutoUpdateAgentRolloutRequest + (*CreateAutoUpdateAgentRolloutRequest)(nil), // 11: teleport.autoupdate.v1.CreateAutoUpdateAgentRolloutRequest + (*UpdateAutoUpdateAgentRolloutRequest)(nil), // 12: teleport.autoupdate.v1.UpdateAutoUpdateAgentRolloutRequest + (*UpsertAutoUpdateAgentRolloutRequest)(nil), // 13: teleport.autoupdate.v1.UpsertAutoUpdateAgentRolloutRequest + (*DeleteAutoUpdateAgentRolloutRequest)(nil), // 14: teleport.autoupdate.v1.DeleteAutoUpdateAgentRolloutRequest + (*TriggerAutoUpdateAgentGroupRequest)(nil), // 15: teleport.autoupdate.v1.TriggerAutoUpdateAgentGroupRequest + (*ForceAutoUpdateAgentGroupRequest)(nil), // 16: teleport.autoupdate.v1.ForceAutoUpdateAgentGroupRequest + (*RollbackAutoUpdateAgentGroupRequest)(nil), // 17: teleport.autoupdate.v1.RollbackAutoUpdateAgentGroupRequest + (*ListAutoUpdateAgentReportsRequest)(nil), // 18: teleport.autoupdate.v1.ListAutoUpdateAgentReportsRequest + (*ListAutoUpdateAgentReportsResponse)(nil), // 19: teleport.autoupdate.v1.ListAutoUpdateAgentReportsResponse + (*GetAutoUpdateAgentReportRequest)(nil), // 20: teleport.autoupdate.v1.GetAutoUpdateAgentReportRequest + (*CreateAutoUpdateAgentReportRequest)(nil), // 21: teleport.autoupdate.v1.CreateAutoUpdateAgentReportRequest + (*UpdateAutoUpdateAgentReportRequest)(nil), // 22: teleport.autoupdate.v1.UpdateAutoUpdateAgentReportRequest + (*UpsertAutoUpdateAgentReportRequest)(nil), // 23: teleport.autoupdate.v1.UpsertAutoUpdateAgentReportRequest + (*DeleteAutoUpdateAgentReportRequest)(nil), // 24: teleport.autoupdate.v1.DeleteAutoUpdateAgentReportRequest + (*GetAutoUpdateBotInstanceReportRequest)(nil), // 25: teleport.autoupdate.v1.GetAutoUpdateBotInstanceReportRequest + (*DeleteAutoUpdateBotInstanceReportRequest)(nil), // 26: teleport.autoupdate.v1.DeleteAutoUpdateBotInstanceReportRequest + (*AutoUpdateConfig)(nil), // 27: teleport.autoupdate.v1.AutoUpdateConfig + (*AutoUpdateVersion)(nil), // 28: teleport.autoupdate.v1.AutoUpdateVersion + (*AutoUpdateAgentRollout)(nil), // 29: teleport.autoupdate.v1.AutoUpdateAgentRollout + (AutoUpdateAgentGroupState)(0), // 30: teleport.autoupdate.v1.AutoUpdateAgentGroupState + (*AutoUpdateAgentReport)(nil), // 31: teleport.autoupdate.v1.AutoUpdateAgentReport + (*emptypb.Empty)(nil), // 32: google.protobuf.Empty + (*AutoUpdateBotInstanceReport)(nil), // 33: teleport.autoupdate.v1.AutoUpdateBotInstanceReport } var file_teleport_autoupdate_v1_autoupdate_service_proto_depIdxs = []int32{ - 25, // 0: teleport.autoupdate.v1.CreateAutoUpdateConfigRequest.config:type_name -> teleport.autoupdate.v1.AutoUpdateConfig - 25, // 1: teleport.autoupdate.v1.UpdateAutoUpdateConfigRequest.config:type_name -> teleport.autoupdate.v1.AutoUpdateConfig - 25, // 2: teleport.autoupdate.v1.UpsertAutoUpdateConfigRequest.config:type_name -> teleport.autoupdate.v1.AutoUpdateConfig - 26, // 3: teleport.autoupdate.v1.CreateAutoUpdateVersionRequest.version:type_name -> teleport.autoupdate.v1.AutoUpdateVersion - 26, // 4: teleport.autoupdate.v1.UpdateAutoUpdateVersionRequest.version:type_name -> teleport.autoupdate.v1.AutoUpdateVersion - 26, // 5: teleport.autoupdate.v1.UpsertAutoUpdateVersionRequest.version:type_name -> teleport.autoupdate.v1.AutoUpdateVersion - 27, // 6: teleport.autoupdate.v1.CreateAutoUpdateAgentRolloutRequest.rollout:type_name -> teleport.autoupdate.v1.AutoUpdateAgentRollout - 27, // 7: teleport.autoupdate.v1.UpdateAutoUpdateAgentRolloutRequest.rollout:type_name -> teleport.autoupdate.v1.AutoUpdateAgentRollout - 27, // 8: teleport.autoupdate.v1.UpsertAutoUpdateAgentRolloutRequest.rollout:type_name -> teleport.autoupdate.v1.AutoUpdateAgentRollout - 28, // 9: teleport.autoupdate.v1.TriggerAutoUpdateAgentGroupRequest.desired_state:type_name -> teleport.autoupdate.v1.AutoUpdateAgentGroupState - 29, // 10: teleport.autoupdate.v1.ListAutoUpdateAgentReportsResponse.autoupdate_agent_reports:type_name -> teleport.autoupdate.v1.AutoUpdateAgentReport - 29, // 11: teleport.autoupdate.v1.CreateAutoUpdateAgentReportRequest.autoupdate_agent_report:type_name -> teleport.autoupdate.v1.AutoUpdateAgentReport - 29, // 12: teleport.autoupdate.v1.UpdateAutoUpdateAgentReportRequest.autoupdate_agent_report:type_name -> teleport.autoupdate.v1.AutoUpdateAgentReport - 29, // 13: teleport.autoupdate.v1.UpsertAutoUpdateAgentReportRequest.autoupdate_agent_report:type_name -> teleport.autoupdate.v1.AutoUpdateAgentReport + 27, // 0: teleport.autoupdate.v1.CreateAutoUpdateConfigRequest.config:type_name -> teleport.autoupdate.v1.AutoUpdateConfig + 27, // 1: teleport.autoupdate.v1.UpdateAutoUpdateConfigRequest.config:type_name -> teleport.autoupdate.v1.AutoUpdateConfig + 27, // 2: teleport.autoupdate.v1.UpsertAutoUpdateConfigRequest.config:type_name -> teleport.autoupdate.v1.AutoUpdateConfig + 28, // 3: teleport.autoupdate.v1.CreateAutoUpdateVersionRequest.version:type_name -> teleport.autoupdate.v1.AutoUpdateVersion + 28, // 4: teleport.autoupdate.v1.UpdateAutoUpdateVersionRequest.version:type_name -> teleport.autoupdate.v1.AutoUpdateVersion + 28, // 5: teleport.autoupdate.v1.UpsertAutoUpdateVersionRequest.version:type_name -> teleport.autoupdate.v1.AutoUpdateVersion + 29, // 6: teleport.autoupdate.v1.CreateAutoUpdateAgentRolloutRequest.rollout:type_name -> teleport.autoupdate.v1.AutoUpdateAgentRollout + 29, // 7: teleport.autoupdate.v1.UpdateAutoUpdateAgentRolloutRequest.rollout:type_name -> teleport.autoupdate.v1.AutoUpdateAgentRollout + 29, // 8: teleport.autoupdate.v1.UpsertAutoUpdateAgentRolloutRequest.rollout:type_name -> teleport.autoupdate.v1.AutoUpdateAgentRollout + 30, // 9: teleport.autoupdate.v1.TriggerAutoUpdateAgentGroupRequest.desired_state:type_name -> teleport.autoupdate.v1.AutoUpdateAgentGroupState + 31, // 10: teleport.autoupdate.v1.ListAutoUpdateAgentReportsResponse.autoupdate_agent_reports:type_name -> teleport.autoupdate.v1.AutoUpdateAgentReport + 31, // 11: teleport.autoupdate.v1.CreateAutoUpdateAgentReportRequest.autoupdate_agent_report:type_name -> teleport.autoupdate.v1.AutoUpdateAgentReport + 31, // 12: teleport.autoupdate.v1.UpdateAutoUpdateAgentReportRequest.autoupdate_agent_report:type_name -> teleport.autoupdate.v1.AutoUpdateAgentReport + 31, // 13: teleport.autoupdate.v1.UpsertAutoUpdateAgentReportRequest.autoupdate_agent_report:type_name -> teleport.autoupdate.v1.AutoUpdateAgentReport 0, // 14: teleport.autoupdate.v1.AutoUpdateService.GetAutoUpdateConfig:input_type -> teleport.autoupdate.v1.GetAutoUpdateConfigRequest 1, // 15: teleport.autoupdate.v1.AutoUpdateService.CreateAutoUpdateConfig:input_type -> teleport.autoupdate.v1.CreateAutoUpdateConfigRequest 2, // 16: teleport.autoupdate.v1.AutoUpdateService.UpdateAutoUpdateConfig:input_type -> teleport.autoupdate.v1.UpdateAutoUpdateConfigRequest @@ -1340,32 +1421,36 @@ var file_teleport_autoupdate_v1_autoupdate_service_proto_depIdxs = []int32{ 22, // 35: teleport.autoupdate.v1.AutoUpdateService.UpdateAutoUpdateAgentReport:input_type -> teleport.autoupdate.v1.UpdateAutoUpdateAgentReportRequest 23, // 36: teleport.autoupdate.v1.AutoUpdateService.UpsertAutoUpdateAgentReport:input_type -> teleport.autoupdate.v1.UpsertAutoUpdateAgentReportRequest 24, // 37: teleport.autoupdate.v1.AutoUpdateService.DeleteAutoUpdateAgentReport:input_type -> teleport.autoupdate.v1.DeleteAutoUpdateAgentReportRequest - 25, // 38: teleport.autoupdate.v1.AutoUpdateService.GetAutoUpdateConfig:output_type -> teleport.autoupdate.v1.AutoUpdateConfig - 25, // 39: teleport.autoupdate.v1.AutoUpdateService.CreateAutoUpdateConfig:output_type -> teleport.autoupdate.v1.AutoUpdateConfig - 25, // 40: teleport.autoupdate.v1.AutoUpdateService.UpdateAutoUpdateConfig:output_type -> teleport.autoupdate.v1.AutoUpdateConfig - 25, // 41: teleport.autoupdate.v1.AutoUpdateService.UpsertAutoUpdateConfig:output_type -> teleport.autoupdate.v1.AutoUpdateConfig - 30, // 42: teleport.autoupdate.v1.AutoUpdateService.DeleteAutoUpdateConfig:output_type -> google.protobuf.Empty - 26, // 43: teleport.autoupdate.v1.AutoUpdateService.GetAutoUpdateVersion:output_type -> teleport.autoupdate.v1.AutoUpdateVersion - 26, // 44: teleport.autoupdate.v1.AutoUpdateService.CreateAutoUpdateVersion:output_type -> teleport.autoupdate.v1.AutoUpdateVersion - 26, // 45: teleport.autoupdate.v1.AutoUpdateService.UpdateAutoUpdateVersion:output_type -> teleport.autoupdate.v1.AutoUpdateVersion - 26, // 46: teleport.autoupdate.v1.AutoUpdateService.UpsertAutoUpdateVersion:output_type -> teleport.autoupdate.v1.AutoUpdateVersion - 30, // 47: teleport.autoupdate.v1.AutoUpdateService.DeleteAutoUpdateVersion:output_type -> google.protobuf.Empty - 27, // 48: teleport.autoupdate.v1.AutoUpdateService.GetAutoUpdateAgentRollout:output_type -> teleport.autoupdate.v1.AutoUpdateAgentRollout - 27, // 49: teleport.autoupdate.v1.AutoUpdateService.CreateAutoUpdateAgentRollout:output_type -> teleport.autoupdate.v1.AutoUpdateAgentRollout - 27, // 50: teleport.autoupdate.v1.AutoUpdateService.UpdateAutoUpdateAgentRollout:output_type -> teleport.autoupdate.v1.AutoUpdateAgentRollout - 27, // 51: teleport.autoupdate.v1.AutoUpdateService.UpsertAutoUpdateAgentRollout:output_type -> teleport.autoupdate.v1.AutoUpdateAgentRollout - 30, // 52: teleport.autoupdate.v1.AutoUpdateService.DeleteAutoUpdateAgentRollout:output_type -> google.protobuf.Empty - 27, // 53: teleport.autoupdate.v1.AutoUpdateService.TriggerAutoUpdateAgentGroup:output_type -> teleport.autoupdate.v1.AutoUpdateAgentRollout - 27, // 54: teleport.autoupdate.v1.AutoUpdateService.ForceAutoUpdateAgentGroup:output_type -> teleport.autoupdate.v1.AutoUpdateAgentRollout - 27, // 55: teleport.autoupdate.v1.AutoUpdateService.RollbackAutoUpdateAgentGroup:output_type -> teleport.autoupdate.v1.AutoUpdateAgentRollout - 19, // 56: teleport.autoupdate.v1.AutoUpdateService.ListAutoUpdateAgentReports:output_type -> teleport.autoupdate.v1.ListAutoUpdateAgentReportsResponse - 29, // 57: teleport.autoupdate.v1.AutoUpdateService.GetAutoUpdateAgentReport:output_type -> teleport.autoupdate.v1.AutoUpdateAgentReport - 29, // 58: teleport.autoupdate.v1.AutoUpdateService.CreateAutoUpdateAgentReport:output_type -> teleport.autoupdate.v1.AutoUpdateAgentReport - 29, // 59: teleport.autoupdate.v1.AutoUpdateService.UpdateAutoUpdateAgentReport:output_type -> teleport.autoupdate.v1.AutoUpdateAgentReport - 29, // 60: teleport.autoupdate.v1.AutoUpdateService.UpsertAutoUpdateAgentReport:output_type -> teleport.autoupdate.v1.AutoUpdateAgentReport - 30, // 61: teleport.autoupdate.v1.AutoUpdateService.DeleteAutoUpdateAgentReport:output_type -> google.protobuf.Empty - 38, // [38:62] is the sub-list for method output_type - 14, // [14:38] is the sub-list for method input_type + 25, // 38: teleport.autoupdate.v1.AutoUpdateService.GetAutoUpdateBotInstanceReport:input_type -> teleport.autoupdate.v1.GetAutoUpdateBotInstanceReportRequest + 26, // 39: teleport.autoupdate.v1.AutoUpdateService.DeleteAutoUpdateBotInstanceReport:input_type -> teleport.autoupdate.v1.DeleteAutoUpdateBotInstanceReportRequest + 27, // 40: teleport.autoupdate.v1.AutoUpdateService.GetAutoUpdateConfig:output_type -> teleport.autoupdate.v1.AutoUpdateConfig + 27, // 41: teleport.autoupdate.v1.AutoUpdateService.CreateAutoUpdateConfig:output_type -> teleport.autoupdate.v1.AutoUpdateConfig + 27, // 42: teleport.autoupdate.v1.AutoUpdateService.UpdateAutoUpdateConfig:output_type -> teleport.autoupdate.v1.AutoUpdateConfig + 27, // 43: teleport.autoupdate.v1.AutoUpdateService.UpsertAutoUpdateConfig:output_type -> teleport.autoupdate.v1.AutoUpdateConfig + 32, // 44: teleport.autoupdate.v1.AutoUpdateService.DeleteAutoUpdateConfig:output_type -> google.protobuf.Empty + 28, // 45: teleport.autoupdate.v1.AutoUpdateService.GetAutoUpdateVersion:output_type -> teleport.autoupdate.v1.AutoUpdateVersion + 28, // 46: teleport.autoupdate.v1.AutoUpdateService.CreateAutoUpdateVersion:output_type -> teleport.autoupdate.v1.AutoUpdateVersion + 28, // 47: teleport.autoupdate.v1.AutoUpdateService.UpdateAutoUpdateVersion:output_type -> teleport.autoupdate.v1.AutoUpdateVersion + 28, // 48: teleport.autoupdate.v1.AutoUpdateService.UpsertAutoUpdateVersion:output_type -> teleport.autoupdate.v1.AutoUpdateVersion + 32, // 49: teleport.autoupdate.v1.AutoUpdateService.DeleteAutoUpdateVersion:output_type -> google.protobuf.Empty + 29, // 50: teleport.autoupdate.v1.AutoUpdateService.GetAutoUpdateAgentRollout:output_type -> teleport.autoupdate.v1.AutoUpdateAgentRollout + 29, // 51: teleport.autoupdate.v1.AutoUpdateService.CreateAutoUpdateAgentRollout:output_type -> teleport.autoupdate.v1.AutoUpdateAgentRollout + 29, // 52: teleport.autoupdate.v1.AutoUpdateService.UpdateAutoUpdateAgentRollout:output_type -> teleport.autoupdate.v1.AutoUpdateAgentRollout + 29, // 53: teleport.autoupdate.v1.AutoUpdateService.UpsertAutoUpdateAgentRollout:output_type -> teleport.autoupdate.v1.AutoUpdateAgentRollout + 32, // 54: teleport.autoupdate.v1.AutoUpdateService.DeleteAutoUpdateAgentRollout:output_type -> google.protobuf.Empty + 29, // 55: teleport.autoupdate.v1.AutoUpdateService.TriggerAutoUpdateAgentGroup:output_type -> teleport.autoupdate.v1.AutoUpdateAgentRollout + 29, // 56: teleport.autoupdate.v1.AutoUpdateService.ForceAutoUpdateAgentGroup:output_type -> teleport.autoupdate.v1.AutoUpdateAgentRollout + 29, // 57: teleport.autoupdate.v1.AutoUpdateService.RollbackAutoUpdateAgentGroup:output_type -> teleport.autoupdate.v1.AutoUpdateAgentRollout + 19, // 58: teleport.autoupdate.v1.AutoUpdateService.ListAutoUpdateAgentReports:output_type -> teleport.autoupdate.v1.ListAutoUpdateAgentReportsResponse + 31, // 59: teleport.autoupdate.v1.AutoUpdateService.GetAutoUpdateAgentReport:output_type -> teleport.autoupdate.v1.AutoUpdateAgentReport + 31, // 60: teleport.autoupdate.v1.AutoUpdateService.CreateAutoUpdateAgentReport:output_type -> teleport.autoupdate.v1.AutoUpdateAgentReport + 31, // 61: teleport.autoupdate.v1.AutoUpdateService.UpdateAutoUpdateAgentReport:output_type -> teleport.autoupdate.v1.AutoUpdateAgentReport + 31, // 62: teleport.autoupdate.v1.AutoUpdateService.UpsertAutoUpdateAgentReport:output_type -> teleport.autoupdate.v1.AutoUpdateAgentReport + 32, // 63: teleport.autoupdate.v1.AutoUpdateService.DeleteAutoUpdateAgentReport:output_type -> google.protobuf.Empty + 33, // 64: teleport.autoupdate.v1.AutoUpdateService.GetAutoUpdateBotInstanceReport:output_type -> teleport.autoupdate.v1.AutoUpdateBotInstanceReport + 32, // 65: teleport.autoupdate.v1.AutoUpdateService.DeleteAutoUpdateBotInstanceReport:output_type -> google.protobuf.Empty + 40, // [40:66] is the sub-list for method output_type + 14, // [14:40] is the sub-list for method input_type 14, // [14:14] is the sub-list for extension type_name 14, // [14:14] is the sub-list for extension extendee 0, // [0:14] is the sub-list for field type_name @@ -1383,7 +1468,7 @@ func file_teleport_autoupdate_v1_autoupdate_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_teleport_autoupdate_v1_autoupdate_service_proto_rawDesc), len(file_teleport_autoupdate_v1_autoupdate_service_proto_rawDesc)), NumEnums: 0, - NumMessages: 25, + NumMessages: 27, NumExtensions: 0, NumServices: 1, }, diff --git a/api/gen/proto/go/teleport/autoupdate/v1/autoupdate_service_grpc.pb.go b/api/gen/proto/go/teleport/autoupdate/v1/autoupdate_service_grpc.pb.go index 7ca9d489f208a..94ac9ed1f28fe 100644 --- a/api/gen/proto/go/teleport/autoupdate/v1/autoupdate_service_grpc.pb.go +++ b/api/gen/proto/go/teleport/autoupdate/v1/autoupdate_service_grpc.pb.go @@ -34,30 +34,32 @@ import ( const _ = grpc.SupportPackageIsVersion9 const ( - AutoUpdateService_GetAutoUpdateConfig_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/GetAutoUpdateConfig" - AutoUpdateService_CreateAutoUpdateConfig_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/CreateAutoUpdateConfig" - AutoUpdateService_UpdateAutoUpdateConfig_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/UpdateAutoUpdateConfig" - AutoUpdateService_UpsertAutoUpdateConfig_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/UpsertAutoUpdateConfig" - AutoUpdateService_DeleteAutoUpdateConfig_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/DeleteAutoUpdateConfig" - AutoUpdateService_GetAutoUpdateVersion_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/GetAutoUpdateVersion" - AutoUpdateService_CreateAutoUpdateVersion_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/CreateAutoUpdateVersion" - AutoUpdateService_UpdateAutoUpdateVersion_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/UpdateAutoUpdateVersion" - AutoUpdateService_UpsertAutoUpdateVersion_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/UpsertAutoUpdateVersion" - AutoUpdateService_DeleteAutoUpdateVersion_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/DeleteAutoUpdateVersion" - AutoUpdateService_GetAutoUpdateAgentRollout_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/GetAutoUpdateAgentRollout" - AutoUpdateService_CreateAutoUpdateAgentRollout_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/CreateAutoUpdateAgentRollout" - AutoUpdateService_UpdateAutoUpdateAgentRollout_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/UpdateAutoUpdateAgentRollout" - AutoUpdateService_UpsertAutoUpdateAgentRollout_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/UpsertAutoUpdateAgentRollout" - AutoUpdateService_DeleteAutoUpdateAgentRollout_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/DeleteAutoUpdateAgentRollout" - AutoUpdateService_TriggerAutoUpdateAgentGroup_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/TriggerAutoUpdateAgentGroup" - AutoUpdateService_ForceAutoUpdateAgentGroup_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/ForceAutoUpdateAgentGroup" - AutoUpdateService_RollbackAutoUpdateAgentGroup_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/RollbackAutoUpdateAgentGroup" - AutoUpdateService_ListAutoUpdateAgentReports_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/ListAutoUpdateAgentReports" - AutoUpdateService_GetAutoUpdateAgentReport_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/GetAutoUpdateAgentReport" - AutoUpdateService_CreateAutoUpdateAgentReport_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/CreateAutoUpdateAgentReport" - AutoUpdateService_UpdateAutoUpdateAgentReport_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/UpdateAutoUpdateAgentReport" - AutoUpdateService_UpsertAutoUpdateAgentReport_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/UpsertAutoUpdateAgentReport" - AutoUpdateService_DeleteAutoUpdateAgentReport_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/DeleteAutoUpdateAgentReport" + AutoUpdateService_GetAutoUpdateConfig_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/GetAutoUpdateConfig" + AutoUpdateService_CreateAutoUpdateConfig_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/CreateAutoUpdateConfig" + AutoUpdateService_UpdateAutoUpdateConfig_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/UpdateAutoUpdateConfig" + AutoUpdateService_UpsertAutoUpdateConfig_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/UpsertAutoUpdateConfig" + AutoUpdateService_DeleteAutoUpdateConfig_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/DeleteAutoUpdateConfig" + AutoUpdateService_GetAutoUpdateVersion_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/GetAutoUpdateVersion" + AutoUpdateService_CreateAutoUpdateVersion_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/CreateAutoUpdateVersion" + AutoUpdateService_UpdateAutoUpdateVersion_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/UpdateAutoUpdateVersion" + AutoUpdateService_UpsertAutoUpdateVersion_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/UpsertAutoUpdateVersion" + AutoUpdateService_DeleteAutoUpdateVersion_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/DeleteAutoUpdateVersion" + AutoUpdateService_GetAutoUpdateAgentRollout_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/GetAutoUpdateAgentRollout" + AutoUpdateService_CreateAutoUpdateAgentRollout_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/CreateAutoUpdateAgentRollout" + AutoUpdateService_UpdateAutoUpdateAgentRollout_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/UpdateAutoUpdateAgentRollout" + AutoUpdateService_UpsertAutoUpdateAgentRollout_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/UpsertAutoUpdateAgentRollout" + AutoUpdateService_DeleteAutoUpdateAgentRollout_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/DeleteAutoUpdateAgentRollout" + AutoUpdateService_TriggerAutoUpdateAgentGroup_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/TriggerAutoUpdateAgentGroup" + AutoUpdateService_ForceAutoUpdateAgentGroup_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/ForceAutoUpdateAgentGroup" + AutoUpdateService_RollbackAutoUpdateAgentGroup_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/RollbackAutoUpdateAgentGroup" + AutoUpdateService_ListAutoUpdateAgentReports_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/ListAutoUpdateAgentReports" + AutoUpdateService_GetAutoUpdateAgentReport_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/GetAutoUpdateAgentReport" + AutoUpdateService_CreateAutoUpdateAgentReport_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/CreateAutoUpdateAgentReport" + AutoUpdateService_UpdateAutoUpdateAgentReport_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/UpdateAutoUpdateAgentReport" + AutoUpdateService_UpsertAutoUpdateAgentReport_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/UpsertAutoUpdateAgentReport" + AutoUpdateService_DeleteAutoUpdateAgentReport_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/DeleteAutoUpdateAgentReport" + AutoUpdateService_GetAutoUpdateBotInstanceReport_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/GetAutoUpdateBotInstanceReport" + AutoUpdateService_DeleteAutoUpdateBotInstanceReport_FullMethodName = "/teleport.autoupdate.v1.AutoUpdateService/DeleteAutoUpdateBotInstanceReport" ) // AutoUpdateServiceClient is the client API for AutoUpdateService service. @@ -116,6 +118,10 @@ type AutoUpdateServiceClient interface { UpsertAutoUpdateAgentReport(ctx context.Context, in *UpsertAutoUpdateAgentReportRequest, opts ...grpc.CallOption) (*AutoUpdateAgentReport, error) // DeleteAutoUpdateAgentReport removes the specified AutoUpdateAgentReport resource. DeleteAutoUpdateAgentReport(ctx context.Context, in *DeleteAutoUpdateAgentReportRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + // GetAutoUpdateBotInstanceReport returns the singleton AutoUpdateBotInstanceReport resource. + GetAutoUpdateBotInstanceReport(ctx context.Context, in *GetAutoUpdateBotInstanceReportRequest, opts ...grpc.CallOption) (*AutoUpdateBotInstanceReport, error) + // DeleteAutoUpdateBotInstanceReport removes the singleton AutoUpdateBotInstanceReport resource. + DeleteAutoUpdateBotInstanceReport(ctx context.Context, in *DeleteAutoUpdateBotInstanceReportRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) } type autoUpdateServiceClient struct { @@ -366,6 +372,26 @@ func (c *autoUpdateServiceClient) DeleteAutoUpdateAgentReport(ctx context.Contex return out, nil } +func (c *autoUpdateServiceClient) GetAutoUpdateBotInstanceReport(ctx context.Context, in *GetAutoUpdateBotInstanceReportRequest, opts ...grpc.CallOption) (*AutoUpdateBotInstanceReport, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(AutoUpdateBotInstanceReport) + err := c.cc.Invoke(ctx, AutoUpdateService_GetAutoUpdateBotInstanceReport_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *autoUpdateServiceClient) DeleteAutoUpdateBotInstanceReport(ctx context.Context, in *DeleteAutoUpdateBotInstanceReportRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, AutoUpdateService_DeleteAutoUpdateBotInstanceReport_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + // AutoUpdateServiceServer is the server API for AutoUpdateService service. // All implementations must embed UnimplementedAutoUpdateServiceServer // for forward compatibility. @@ -422,6 +448,10 @@ type AutoUpdateServiceServer interface { UpsertAutoUpdateAgentReport(context.Context, *UpsertAutoUpdateAgentReportRequest) (*AutoUpdateAgentReport, error) // DeleteAutoUpdateAgentReport removes the specified AutoUpdateAgentReport resource. DeleteAutoUpdateAgentReport(context.Context, *DeleteAutoUpdateAgentReportRequest) (*emptypb.Empty, error) + // GetAutoUpdateBotInstanceReport returns the singleton AutoUpdateBotInstanceReport resource. + GetAutoUpdateBotInstanceReport(context.Context, *GetAutoUpdateBotInstanceReportRequest) (*AutoUpdateBotInstanceReport, error) + // DeleteAutoUpdateBotInstanceReport removes the singleton AutoUpdateBotInstanceReport resource. + DeleteAutoUpdateBotInstanceReport(context.Context, *DeleteAutoUpdateBotInstanceReportRequest) (*emptypb.Empty, error) mustEmbedUnimplementedAutoUpdateServiceServer() } @@ -504,6 +534,12 @@ func (UnimplementedAutoUpdateServiceServer) UpsertAutoUpdateAgentReport(context. func (UnimplementedAutoUpdateServiceServer) DeleteAutoUpdateAgentReport(context.Context, *DeleteAutoUpdateAgentReportRequest) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method DeleteAutoUpdateAgentReport not implemented") } +func (UnimplementedAutoUpdateServiceServer) GetAutoUpdateBotInstanceReport(context.Context, *GetAutoUpdateBotInstanceReportRequest) (*AutoUpdateBotInstanceReport, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetAutoUpdateBotInstanceReport not implemented") +} +func (UnimplementedAutoUpdateServiceServer) DeleteAutoUpdateBotInstanceReport(context.Context, *DeleteAutoUpdateBotInstanceReportRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeleteAutoUpdateBotInstanceReport not implemented") +} func (UnimplementedAutoUpdateServiceServer) mustEmbedUnimplementedAutoUpdateServiceServer() {} func (UnimplementedAutoUpdateServiceServer) testEmbeddedByValue() {} @@ -957,6 +993,42 @@ func _AutoUpdateService_DeleteAutoUpdateAgentReport_Handler(srv interface{}, ctx return interceptor(ctx, in, info, handler) } +func _AutoUpdateService_GetAutoUpdateBotInstanceReport_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetAutoUpdateBotInstanceReportRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AutoUpdateServiceServer).GetAutoUpdateBotInstanceReport(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AutoUpdateService_GetAutoUpdateBotInstanceReport_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AutoUpdateServiceServer).GetAutoUpdateBotInstanceReport(ctx, req.(*GetAutoUpdateBotInstanceReportRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AutoUpdateService_DeleteAutoUpdateBotInstanceReport_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteAutoUpdateBotInstanceReportRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AutoUpdateServiceServer).DeleteAutoUpdateBotInstanceReport(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AutoUpdateService_DeleteAutoUpdateBotInstanceReport_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AutoUpdateServiceServer).DeleteAutoUpdateBotInstanceReport(ctx, req.(*DeleteAutoUpdateBotInstanceReportRequest)) + } + return interceptor(ctx, in, info, handler) +} + // AutoUpdateService_ServiceDesc is the grpc.ServiceDesc for AutoUpdateService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -1060,6 +1132,14 @@ var AutoUpdateService_ServiceDesc = grpc.ServiceDesc{ MethodName: "DeleteAutoUpdateAgentReport", Handler: _AutoUpdateService_DeleteAutoUpdateAgentReport_Handler, }, + { + MethodName: "GetAutoUpdateBotInstanceReport", + Handler: _AutoUpdateService_GetAutoUpdateBotInstanceReport_Handler, + }, + { + MethodName: "DeleteAutoUpdateBotInstanceReport", + Handler: _AutoUpdateService_DeleteAutoUpdateBotInstanceReport_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "teleport/autoupdate/v1/autoupdate_service.proto", diff --git a/api/gen/proto/go/teleport/machineid/v1/bot_instance.pb.go b/api/gen/proto/go/teleport/machineid/v1/bot_instance.pb.go index 352e22d6326ce..760db64a395f9 100644 --- a/api/gen/proto/go/teleport/machineid/v1/bot_instance.pb.go +++ b/api/gen/proto/go/teleport/machineid/v1/bot_instance.pb.go @@ -23,6 +23,7 @@ package machineidv1 import ( v1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" v11 "github.com/gravitational/teleport/api/gen/proto/go/teleport/workloadidentity/v1" + types "github.com/gravitational/teleport/api/types" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" durationpb "google.golang.org/protobuf/types/known/durationpb" @@ -224,7 +225,14 @@ type BotInstanceStatusHeartbeat struct { // runtime.GOARCH. Architecture string `protobuf:"bytes,8,opt,name=architecture,proto3" json:"architecture,omitempty"` // The OS of the host that `tbot` is running on, determined by runtime.GOOS. - Os string `protobuf:"bytes,9,opt,name=os,proto3" json:"os,omitempty"` + Os string `protobuf:"bytes,9,opt,name=os,proto3" json:"os,omitempty"` + // Identifies the external updater process. + ExternalUpdater string `protobuf:"bytes,10,opt,name=external_updater,json=externalUpdater,proto3" json:"external_updater,omitempty"` + // Identifies the external updated version. Empty if no updater is configured. + ExternalUpdaterVersion string `protobuf:"bytes,11,opt,name=external_updater_version,json=externalUpdaterVersion,proto3" json:"external_updater_version,omitempty"` + // Information provided by the external updater, including the update group + // and updater status. + UpdaterInfo *types.UpdaterV2Info `protobuf:"bytes,12,opt,name=updater_info,json=updaterInfo,proto3" json:"updater_info,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -322,6 +330,27 @@ func (x *BotInstanceStatusHeartbeat) GetOs() string { return "" } +func (x *BotInstanceStatusHeartbeat) GetExternalUpdater() string { + if x != nil { + return x.ExternalUpdater + } + return "" +} + +func (x *BotInstanceStatusHeartbeat) GetExternalUpdaterVersion() string { + if x != nil { + return x.ExternalUpdaterVersion + } + return "" +} + +func (x *BotInstanceStatusHeartbeat) GetUpdaterInfo() *types.UpdaterV2Info { + if x != nil { + return x.UpdaterInfo + } + return nil +} + // BotInstanceStatusAuthentication contains information about a join or renewal. // Ths information is entirely sourced by the Auth Server and can be trusted. type BotInstanceStatusAuthentication struct { @@ -513,7 +542,7 @@ var File_teleport_machineid_v1_bot_instance_proto protoreflect.FileDescriptor const file_teleport_machineid_v1_bot_instance_proto_rawDesc = "" + "\n" + - "(teleport/machineid/v1/bot_instance.proto\x12\x15teleport.machineid.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a!teleport/header/v1/metadata.proto\x1a-teleport/workloadidentity/v1/join_attrs.proto\"\x8e\x02\n" + + "(teleport/machineid/v1/bot_instance.proto\x12\x15teleport.machineid.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a!teleport/header/v1/metadata.proto\x1a!teleport/legacy/types/types.proto\x1a-teleport/workloadidentity/v1/join_attrs.proto\"\x8e\x02\n" + "\vBotInstance\x12\x12\n" + "\x04kind\x18\x01 \x01(\tR\x04kind\x12\x19\n" + "\bsub_kind\x18\x02 \x01(\tR\asubKind\x12\x18\n" + @@ -525,7 +554,7 @@ const file_teleport_machineid_v1_bot_instance_proto_rawDesc = "" + "\bbot_name\x18\x01 \x01(\tR\abotName\x12\x1f\n" + "\vinstance_id\x18\x02 \x01(\tR\n" + "instanceId\x120\n" + - "\x14previous_instance_id\x18\x04 \x01(\tR\x12previousInstanceIdJ\x04\b\x03\x10\x04R\x03ttl\"\xd1\x02\n" + + "\x14previous_instance_id\x18\x04 \x01(\tR\x12previousInstanceIdJ\x04\b\x03\x10\x04R\x03ttl\"\xef\x03\n" + "\x1aBotInstanceStatusHeartbeat\x12;\n" + "\vrecorded_at\x18\x01 \x01(\v2\x1a.google.protobuf.TimestampR\n" + "recordedAt\x12\x1d\n" + @@ -538,7 +567,11 @@ const file_teleport_machineid_v1_bot_instance_proto_rawDesc = "" + "joinMethod\x12\x19\n" + "\bone_shot\x18\a \x01(\bR\aoneShot\x12\"\n" + "\farchitecture\x18\b \x01(\tR\farchitecture\x12\x0e\n" + - "\x02os\x18\t \x01(\tR\x02os\"\xf7\x02\n" + + "\x02os\x18\t \x01(\tR\x02os\x12)\n" + + "\x10external_updater\x18\n" + + " \x01(\tR\x0fexternalUpdater\x128\n" + + "\x18external_updater_version\x18\v \x01(\tR\x16externalUpdaterVersion\x127\n" + + "\fupdater_info\x18\f \x01(\v2\x14.types.UpdaterV2InfoR\vupdaterInfo\"\xf7\x02\n" + "\x1fBotInstanceStatusAuthentication\x12E\n" + "\x10authenticated_at\x18\x01 \x01(\v2\x1a.google.protobuf.TimestampR\x0fauthenticatedAt\x12\x1f\n" + "\vjoin_method\x18\x02 \x01(\tR\n" + @@ -581,8 +614,9 @@ var file_teleport_machineid_v1_bot_instance_proto_goTypes = []any{ (*v1.Metadata)(nil), // 5: teleport.header.v1.Metadata (*timestamppb.Timestamp)(nil), // 6: google.protobuf.Timestamp (*durationpb.Duration)(nil), // 7: google.protobuf.Duration - (*structpb.Struct)(nil), // 8: google.protobuf.Struct - (*v11.JoinAttrs)(nil), // 9: teleport.workloadidentity.v1.JoinAttrs + (*types.UpdaterV2Info)(nil), // 8: types.UpdaterV2Info + (*structpb.Struct)(nil), // 9: google.protobuf.Struct + (*v11.JoinAttrs)(nil), // 10: teleport.workloadidentity.v1.JoinAttrs } var file_teleport_machineid_v1_bot_instance_proto_depIdxs = []int32{ 5, // 0: teleport.machineid.v1.BotInstance.metadata:type_name -> teleport.header.v1.Metadata @@ -590,18 +624,19 @@ var file_teleport_machineid_v1_bot_instance_proto_depIdxs = []int32{ 4, // 2: teleport.machineid.v1.BotInstance.status:type_name -> teleport.machineid.v1.BotInstanceStatus 6, // 3: teleport.machineid.v1.BotInstanceStatusHeartbeat.recorded_at:type_name -> google.protobuf.Timestamp 7, // 4: teleport.machineid.v1.BotInstanceStatusHeartbeat.uptime:type_name -> google.protobuf.Duration - 6, // 5: teleport.machineid.v1.BotInstanceStatusAuthentication.authenticated_at:type_name -> google.protobuf.Timestamp - 8, // 6: teleport.machineid.v1.BotInstanceStatusAuthentication.metadata:type_name -> google.protobuf.Struct - 9, // 7: teleport.machineid.v1.BotInstanceStatusAuthentication.join_attrs:type_name -> teleport.workloadidentity.v1.JoinAttrs - 3, // 8: teleport.machineid.v1.BotInstanceStatus.initial_authentication:type_name -> teleport.machineid.v1.BotInstanceStatusAuthentication - 3, // 9: teleport.machineid.v1.BotInstanceStatus.latest_authentications:type_name -> teleport.machineid.v1.BotInstanceStatusAuthentication - 2, // 10: teleport.machineid.v1.BotInstanceStatus.initial_heartbeat:type_name -> teleport.machineid.v1.BotInstanceStatusHeartbeat - 2, // 11: teleport.machineid.v1.BotInstanceStatus.latest_heartbeats:type_name -> teleport.machineid.v1.BotInstanceStatusHeartbeat - 12, // [12:12] is the sub-list for method output_type - 12, // [12:12] 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 + 8, // 5: teleport.machineid.v1.BotInstanceStatusHeartbeat.updater_info:type_name -> types.UpdaterV2Info + 6, // 6: teleport.machineid.v1.BotInstanceStatusAuthentication.authenticated_at:type_name -> google.protobuf.Timestamp + 9, // 7: teleport.machineid.v1.BotInstanceStatusAuthentication.metadata:type_name -> google.protobuf.Struct + 10, // 8: teleport.machineid.v1.BotInstanceStatusAuthentication.join_attrs:type_name -> teleport.workloadidentity.v1.JoinAttrs + 3, // 9: teleport.machineid.v1.BotInstanceStatus.initial_authentication:type_name -> teleport.machineid.v1.BotInstanceStatusAuthentication + 3, // 10: teleport.machineid.v1.BotInstanceStatus.latest_authentications:type_name -> teleport.machineid.v1.BotInstanceStatusAuthentication + 2, // 11: teleport.machineid.v1.BotInstanceStatus.initial_heartbeat:type_name -> teleport.machineid.v1.BotInstanceStatusHeartbeat + 2, // 12: teleport.machineid.v1.BotInstanceStatus.latest_heartbeats:type_name -> teleport.machineid.v1.BotInstanceStatusHeartbeat + 13, // [13:13] is the sub-list for method output_type + 13, // [13:13] is the sub-list for method input_type + 13, // [13:13] is the sub-list for extension type_name + 13, // [13:13] is the sub-list for extension extendee + 0, // [0:13] is the sub-list for field type_name } func init() { file_teleport_machineid_v1_bot_instance_proto_init() } diff --git a/api/proto/teleport/autoupdate/v1/autoupdate.proto b/api/proto/teleport/autoupdate/v1/autoupdate.proto index 005d29996c8d7..8a029bb3cd703 100644 --- a/api/proto/teleport/autoupdate/v1/autoupdate.proto +++ b/api/proto/teleport/autoupdate/v1/autoupdate.proto @@ -319,6 +319,48 @@ message AutoUpdateAgentReportSpecOmitted { string reason = 2; } +// AutoUpdateBotInstanceReport is a report generated by an elected instance of the +// Teleport Auth service. The report tracks per group and per version how many +// instances of tbot are running. +message AutoUpdateBotInstanceReport { + // The kind of resource represented. This is always `autoupdate_bot_instance_report`. + string kind = 1; + + // Differentiates variations of the same kind. All resources should contain + // one, even if it is never populated. + string sub_kind = 2; + + // The version of the resource being represented. + string version = 3; + + // Common metadata that all resources share. + teleport.header.v1.Metadata metadata = 4; + + // Contents of the report. + AutoUpdateBotInstanceReportSpec spec = 5; +} + +// AutoUpdateBotInstanceReportSpec holds the contents of an AutoUpdateBotInstanceReport. +message AutoUpdateBotInstanceReportSpec { + // Timestamp is when the report was generated. + google.protobuf.Timestamp timestamp = 1; + + // Bot counts aggregated by update group. + map groups = 2; +} + +// AutoUpdateBotInstanceReportSpecGroup holds an update group's bot counts. +message AutoUpdateBotInstanceReportSpecGroup { + // Bot counts aggregated by version. + map versions = 1; +} + +// AutoUpdateBotInstanceReportSpecGroupVersion holds a version's bot count. +message AutoUpdateBotInstanceReportSpecGroupVersion { + // Count of bot instances running this version. + int32 count = 1; +} + // Canary describes a node that is acting as a canary and being updated before other nodes in its group. message Canary { // updater_id is reported by the agent in its control stream Hello. This allows us to uniquely identify an updater so diff --git a/api/proto/teleport/autoupdate/v1/autoupdate_service.proto b/api/proto/teleport/autoupdate/v1/autoupdate_service.proto index 10146e5981f8e..e00c699ae8c9b 100644 --- a/api/proto/teleport/autoupdate/v1/autoupdate_service.proto +++ b/api/proto/teleport/autoupdate/v1/autoupdate_service.proto @@ -96,6 +96,12 @@ service AutoUpdateService { // DeleteAutoUpdateAgentReport removes the specified AutoUpdateAgentReport resource. rpc DeleteAutoUpdateAgentReport(DeleteAutoUpdateAgentReportRequest) returns (google.protobuf.Empty); + + // GetAutoUpdateBotInstanceReport returns the singleton AutoUpdateBotInstanceReport resource. + rpc GetAutoUpdateBotInstanceReport(GetAutoUpdateBotInstanceReportRequest) returns (AutoUpdateBotInstanceReport); + + // DeleteAutoUpdateBotInstanceReport removes the singleton AutoUpdateBotInstanceReport resource. + rpc DeleteAutoUpdateBotInstanceReport(DeleteAutoUpdateBotInstanceReportRequest) returns (google.protobuf.Empty); } // Request for GetAutoUpdateConfig. @@ -237,3 +243,9 @@ message DeleteAutoUpdateAgentReportRequest { // Name is the name of the AutoUpdateAgentReport to be deleted. string name = 1; } + +// Request for GetAutoUpdateBotInstanceReport. +message GetAutoUpdateBotInstanceReportRequest {} + +// Request for DeleteAutoUpdateBotInstanceReport. +message DeleteAutoUpdateBotInstanceReportRequest {} diff --git a/api/proto/teleport/legacy/client/proto/event.proto b/api/proto/teleport/legacy/client/proto/event.proto index 834e9c75818c2..76436c3a08253 100644 --- a/api/proto/teleport/legacy/client/proto/event.proto +++ b/api/proto/teleport/legacy/client/proto/event.proto @@ -218,5 +218,7 @@ message Event { teleport.autoupdate.v1.AutoUpdateAgentReport AutoUpdateAgentReport = 79; // PluginV1 is a resource for Teleport plugins. types.PluginV1 plugin = 84; + // AutoUpdateAgentReport is a resource for counting connected bot instances. + teleport.autoupdate.v1.AutoUpdateBotInstanceReport AutoUpdateBotInstanceReport = 85; } } diff --git a/api/proto/teleport/machineid/v1/bot_instance.proto b/api/proto/teleport/machineid/v1/bot_instance.proto index 68ce4835b2139..54d3d3fb13e9a 100644 --- a/api/proto/teleport/machineid/v1/bot_instance.proto +++ b/api/proto/teleport/machineid/v1/bot_instance.proto @@ -20,6 +20,7 @@ import "google/protobuf/duration.proto"; import "google/protobuf/struct.proto"; import "google/protobuf/timestamp.proto"; import "teleport/header/v1/metadata.proto"; +import "teleport/legacy/types/types.proto"; import "teleport/workloadidentity/v1/join_attrs.proto"; option go_package = "github.com/gravitational/teleport/api/gen/proto/go/teleport/machineid/v1;machineidv1"; @@ -83,6 +84,14 @@ message BotInstanceStatusHeartbeat { string architecture = 8; // The OS of the host that `tbot` is running on, determined by runtime.GOOS. string os = 9; + // Identifies the external updater process. + string external_updater = 10; + // Identifies the external updated version. Empty if no updater is configured. + string external_updater_version = 11; + // Information provided by the external updater, including the update group + // and updater status. + types.UpdaterV2Info updater_info = 12; + // In future iterations, additional information can be submitted here. // For example, the configuration of `tbot` or the health of individual // outputs. diff --git a/api/types/autoupdate/report.go b/api/types/autoupdate/report.go index 0a2bb9d1642c3..07b2f48a00b55 100644 --- a/api/types/autoupdate/report.go +++ b/api/types/autoupdate/report.go @@ -28,28 +28,28 @@ import ( ) const ( - autoUpdateAgentReportTTL = time.Hour - maxGroups = 50 - maxVersions = 20 + autoUpdateReportTTL = time.Hour + maxGroups = 50 + maxVersions = 20 ) -// NewAutoUpdateAgentReport creates a new auto update version resource. +// NewAutoUpdateAgentReport creates a new auto update agent report resource. func NewAutoUpdateAgentReport(spec *autoupdate.AutoUpdateAgentReportSpec, authName string) (*autoupdate.AutoUpdateAgentReport, error) { - rollout := &autoupdate.AutoUpdateAgentReport{ + report := &autoupdate.AutoUpdateAgentReport{ Kind: types.KindAutoUpdateAgentReport, Version: types.V1, Metadata: &headerv1.Metadata{ Name: authName, // Validate will fail later if timestamp is zero - Expires: timestamppb.New(spec.GetTimestamp().AsTime().Add(autoUpdateAgentReportTTL)), + Expires: timestamppb.New(spec.GetTimestamp().AsTime().Add(autoUpdateReportTTL)), }, Spec: spec, } - if err := ValidateAutoUpdateAgentReport(rollout); err != nil { + if err := ValidateAutoUpdateAgentReport(report); err != nil { return nil, trace.Wrap(err) } - return rollout, nil + return report, nil } // ValidateAutoUpdateAgentReport checks that required parameters are set @@ -78,3 +78,49 @@ func ValidateAutoUpdateAgentReport(v *autoupdate.AutoUpdateAgentReport) error { return nil } + +// NewAutoUpdateBotInstanceReport creates a new auto update bot instance report resource. +func NewAutoUpdateBotInstanceReport(spec *autoupdate.AutoUpdateBotInstanceReportSpec) (*autoupdate.AutoUpdateBotInstanceReport, error) { + report := &autoupdate.AutoUpdateBotInstanceReport{ + Kind: types.KindAutoUpdateBotInstanceReport, + Version: types.V1, + Metadata: &headerv1.Metadata{ + Name: types.MetaNameAutoUpdateBotInstanceReport, + // Validate will fail later if timestamp is zero + Expires: timestamppb.New(spec.GetTimestamp().AsTime().Add(autoUpdateReportTTL)), + }, + Spec: spec, + } + if err := ValidateAutoUpdateBotInstanceReport(report); err != nil { + return nil, trace.Wrap(err) + } + + return report, nil +} + +// ValidateAutoUpdateBotInstanceReport checks that the given bot instance report +// is well-formed and doesn't exceed limits. +func ValidateAutoUpdateBotInstanceReport(v *autoupdate.AutoUpdateBotInstanceReport) error { + if v.GetMetadata().GetName() == "" { + return trace.BadParameter("Metadata.Name is empty") + } + if v.Spec == nil { + return trace.BadParameter("Spec is nil") + } + + if ts := v.GetSpec().GetTimestamp(); ts.GetSeconds() == 0 && ts.GetNanos() == 0 { + return trace.BadParameter("Spec.Timestamp is empty or zero") + } + + if numGroups := len(v.GetSpec().GetGroups()); numGroups > maxGroups { + return trace.BadParameter("Spec.Groups is too large (%d while the max is %d)", numGroups, maxGroups) + } + + for groupName, group := range v.GetSpec().GetGroups() { + if numVersions := len(group.GetVersions()); numVersions > maxVersions { + return trace.BadParameter("group %q has too many versions (%d while the max is %d)", groupName, numVersions, maxVersions) + } + } + + return nil +} diff --git a/api/types/autoupdate/report_test.go b/api/types/autoupdate/report_test.go index b93d9719c20c7..e46327aae09c5 100644 --- a/api/types/autoupdate/report_test.go +++ b/api/types/autoupdate/report_test.go @@ -19,6 +19,7 @@ package autoupdate import ( + "strconv" "testing" "github.com/google/go-cmp/cmp" @@ -33,7 +34,7 @@ import ( func TestNewAutoUpdateAgentReport(t *testing.T) { now := timestamppb.Now() - expires := timestamppb.New(now.AsTime().Add(autoUpdateAgentReportTTL)) + expires := timestamppb.New(now.AsTime().Add(autoUpdateReportTTL)) tests := []struct { name string spec *autoupdate.AutoUpdateAgentReportSpec @@ -88,3 +89,85 @@ func TestNewAutoUpdateAgentReport(t *testing.T) { }) } } + +func TestNewAutoUpdateBotInstanceReport(t *testing.T) { + now := timestamppb.Now() + expires := timestamppb.New(now.AsTime().Add(autoUpdateReportTTL)) + + generateGroups := func(t *testing.T, numGroups, numVersions int) map[string]*autoupdate.AutoUpdateBotInstanceReportSpecGroup { + t.Helper() + + groups := make(map[string]*autoupdate.AutoUpdateBotInstanceReportSpecGroup, numGroups) + for groupIdx := range numGroups { + group := &autoupdate.AutoUpdateBotInstanceReportSpecGroup{ + Versions: make(map[string]*autoupdate.AutoUpdateBotInstanceReportSpecGroupVersion, numVersions), + } + for versionIdx := range numVersions { + group.Versions[strconv.Itoa(versionIdx)] = &autoupdate.AutoUpdateBotInstanceReportSpecGroupVersion{Count: 1} + } + groups[strconv.Itoa(groupIdx)] = group + } + return groups + } + + tests := []struct { + name string + spec *autoupdate.AutoUpdateBotInstanceReportSpec + + want *autoupdate.AutoUpdateBotInstanceReport + wantErr require.ErrorAssertionFunc + }{ + { + name: "nil spec", + wantErr: require.Error, + }, + { + name: "no timestamp", + spec: &autoupdate.AutoUpdateBotInstanceReportSpec{}, + wantErr: require.Error, + }, + { + name: "too many groups", + spec: &autoupdate.AutoUpdateBotInstanceReportSpec{ + Timestamp: now, + Groups: generateGroups(t, 51, 0), + }, + wantErr: require.Error, + }, + { + name: "too many versions", + spec: &autoupdate.AutoUpdateBotInstanceReportSpec{ + Timestamp: now, + Groups: generateGroups(t, 1, 21), + }, + wantErr: require.Error, + }, + { + name: "ok", + spec: &autoupdate.AutoUpdateBotInstanceReportSpec{ + Timestamp: now, + Groups: generateGroups(t, 1, 1), + }, + want: &autoupdate.AutoUpdateBotInstanceReport{ + Kind: types.KindAutoUpdateBotInstanceReport, + Version: types.V1, + Metadata: &headerv1.Metadata{ + Name: types.MetaNameAutoUpdateBotInstanceReport, + Expires: expires, + }, + Spec: &autoupdate.AutoUpdateBotInstanceReportSpec{ + Timestamp: now, + Groups: generateGroups(t, 1, 1), + }, + }, + wantErr: require.NoError, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result, err := NewAutoUpdateBotInstanceReport(tt.spec) + tt.wantErr(t, err) + require.Empty(t, cmp.Diff(tt.want, result, protocmp.Transform())) + }) + } +} diff --git a/api/types/constants.go b/api/types/constants.go index eb78ccc032029..60fe46987b32c 100644 --- a/api/types/constants.go +++ b/api/types/constants.go @@ -342,6 +342,12 @@ const ( // KindAutoUpdateAgentReport is the resource that tracks connected agents. KindAutoUpdateAgentReport = "autoupdate_agent_report" + // KindAutoUpdateBotInstanceReport is the resource that tracks connected bots. + KindAutoUpdateBotInstanceReport = "autoupdate_bot_instance_report" + + // MetaNameAutoUpdateBotInstanceReport is the name of the singleton auto update bot report. + MetaNameAutoUpdateBotInstanceReport = "autoupdate-bot-instance-report" + // MetaNameAutoUpdateConfig is the name of a configuration resource for autoupdate config. MetaNameAutoUpdateConfig = "autoupdate-config" diff --git a/docs/pages/includes/metrics.mdx b/docs/pages/includes/metrics.mdx index d3ff005ac946b..b7da228fa81ae 100644 --- a/docs/pages/includes/metrics.mdx +++ b/docs/pages/includes/metrics.mdx @@ -70,6 +70,7 @@ | `teleport_registered_servers_by_install_methods` | gauge | Teleport Auth | The number of Teleport services that are connected to an Auth Service instance grouped by install methods. | | `teleport_roles_total` | gauge | Teleport Auth | The number of roles that exist in the cluster. | | `teleport_migrations` | gauge | Teleport Auth | Tracks for each migration if it is active (1) or not (0). | +| `teleport_bot_instances` | gauge | Teleport Auth | The number of bot instances across the entire cluster grouped by version. | | `user_login_total` | counter | Teleport Auth | Number of user logins. | | `watcher_event_sizes` | histogram | cache | Overall size of events emitted. | | `watcher_events` | histogram | cache | Per resource size of events emitted. | diff --git a/lib/auth/auth.go b/lib/auth/auth.go index cf0954eb935c9..a66c5ebda71ec 100644 --- a/lib/auth/auth.go +++ b/lib/auth/auth.go @@ -88,6 +88,7 @@ import ( "github.com/gravitational/teleport/entitlements" "github.com/gravitational/teleport/lib/auth/authclient" "github.com/gravitational/teleport/lib/auth/keystore" + "github.com/gravitational/teleport/lib/auth/machineid/machineidv1" "github.com/gravitational/teleport/lib/auth/machineid/workloadidentityv1" "github.com/gravitational/teleport/lib/auth/okta" "github.com/gravitational/teleport/lib/auth/userloginstate" @@ -725,6 +726,21 @@ func NewServer(cfg *InitConfig, opts ...ServerOption) (*Server, error) { as.RegisterLoginHook(as.ulsGenerator.LoginHook(services.UserLoginStates)) + as.BotInstanceVersionReporter, err = machineidv1.NewAutoUpdateVersionReporter(machineidv1.AutoUpdateVersionReporterConfig{ + Clock: cfg.Clock, + Logger: as.logger.With( + teleport.ComponentKey, + teleport.Component(teleport.ComponentAuth, "bot-version-reporter"), + ), + Semaphores: &as, + HostUUID: cfg.HostUUID, + Store: &as, + Cache: as.Cache, + }) + if err != nil { + return nil, trace.Wrap(err) + } + if _, ok := as.getCache(); !ok { log.Warn("Auth server starting without cache (may have negative performance implications).") } @@ -940,6 +956,18 @@ var ( []string{teleport.TagPrivateKeyPolicy}, ) + botInstancesMetric = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: teleport.MetricNamespace, + Name: teleport.MetricBotInstances, + Help: "The number of bot instances across the entire cluster", + }, + []string{ + teleport.TagVersion, + teleport.TagAutomaticUpdates, + }, + ) + prometheusCollectors = []prometheus.Collector{ generateRequestsCount, generateThrottledRequestsCount, generateRequestsCurrent, generateRequestsLatencies, UserLoginCount, heartbeatsMissedByAuth, @@ -949,6 +977,7 @@ var ( registeredAgentsInstallMethod, userCertificatesGeneratedMetric, roleCount, + botInstancesMetric, } ) @@ -1196,6 +1225,10 @@ type Server struct { // logger is the logger used by the auth server. logger *slog.Logger + + // BotInstanceVersionReporter is called periodically to generate a report of + // the number of bot instances by version and update group. + BotInstanceVersionReporter *machineidv1.AutoUpdateVersionReporter } // SetSAMLService registers svc as the SAMLService that provides the SAML @@ -1440,6 +1473,8 @@ const ( roleCountKey accessListReminderNotificationsKey autoUpdateAgentReportKey + autoUpdateBotInstanceReportKey + autoUpdateBotInstanceMetricsKey ) // runPeriodicOperations runs some periodic bookkeeping operations @@ -1535,6 +1570,18 @@ func (a *Server) runPeriodicOperations() { FirstDuration: retryutils.FullJitter(constants.AutoUpdateAgentReportPeriod), // No jitter here, this is intentional and required for accurate tracking across auths. }) + ticker.Push(interval.SubInterval[periodicIntervalKey]{ + Key: autoUpdateBotInstanceReportKey, + Duration: constants.AutoUpdateAgentReportPeriod, + FirstDuration: retryutils.HalfJitter(10 * time.Second), + Jitter: retryutils.SeventhJitter, + }) + ticker.Push(interval.SubInterval[periodicIntervalKey]{ + Key: autoUpdateBotInstanceMetricsKey, + Duration: constants.AutoUpdateAgentReportPeriod / 2, + FirstDuration: retryutils.HalfJitter(10 * time.Second), + Jitter: retryutils.SeventhJitter, + }) } if modules.GetModules().IsOSSBuild() { @@ -1661,6 +1708,10 @@ func (a *Server) runPeriodicOperations() { go a.CreateAccessListReminderNotifications(a.closeCtx) case autoUpdateAgentReportKey: go a.reportAgentVersions(a.closeCtx) + case autoUpdateBotInstanceReportKey: + go a.BotInstanceVersionReporter.Report(a.closeCtx) + case autoUpdateBotInstanceMetricsKey: + go a.updateBotInstanceMetrics() } } } @@ -1976,6 +2027,18 @@ func (a *Server) updateAgentMetrics() { } } +func (a *Server) updateBotInstanceMetrics() { + report, err := a.GetAutoUpdateBotInstanceReport(a.closeCtx) + switch { + case trace.IsNotFound(err): + // No report to emit. + case err != nil: + a.logger.ErrorContext(a.closeCtx, "Failed to get bot instance report", "error", err) + default: + machineidv1.EmitInstancesMetric(report, botInstancesMetric) + } +} + var ( // remoteClusterRefreshLimit is the maximum number of backend updates that will be performed // during periodic remote cluster connection status refresh. diff --git a/lib/auth/auth_test.go b/lib/auth/auth_test.go index 1f25864033ed8..a7b98bcef19c2 100644 --- a/lib/auth/auth_test.go +++ b/lib/auth/auth_test.go @@ -135,6 +135,7 @@ func newTestPack( // This uses lower bcrypt costs for faster tests. Identity: identityService, SkipPeriodicOperations: true, + HostUUID: uuid.NewString(), } p.a, err = auth.NewServer(authConfig, opts...) if err != nil { @@ -1226,6 +1227,7 @@ func TestUpdateConfig(t *testing.T) { VersionStorage: s.versionStorage, Authority: testauthority.New(), SkipPeriodicOperations: true, + HostUUID: uuid.NewString(), } authServer, err := auth.NewServer(authConfig) require.NoError(t, err) @@ -5086,6 +5088,7 @@ func TestCreateAuthPreference(t *testing.T) { Emitter: &eventstest.MockRecorderEmitter{}, ClusterConfiguration: clusterConfigService, SkipPeriodicOperations: true, + HostUUID: uuid.NewString(), }) require.NoError(t, err) diff --git a/lib/auth/authclient/api.go b/lib/auth/authclient/api.go index 873099d276985..8a351a97d1f8a 100644 --- a/lib/auth/authclient/api.go +++ b/lib/auth/authclient/api.go @@ -1296,6 +1296,9 @@ type Cache interface { // ListAutoUpdateAgentReports lists all AutoUpdateAgentReports from the backend. ListAutoUpdateAgentReports(ctx context.Context, pageSize int, pageToken string) ([]*autoupdate.AutoUpdateAgentReport, string, error) + // GetAutoUpdateBotInstanceReport gets the singleton AutoUpdateBotInstanceReport from the backend. + GetAutoUpdateBotInstanceReport(ctx context.Context) (*autoupdate.AutoUpdateBotInstanceReport, error) + // GetAccessGraphSettings returns the access graph settings. GetAccessGraphSettings(context.Context) (*clusterconfigpb.AccessGraphSettings, error) diff --git a/lib/auth/autoupdate/autoupdatev1/service.go b/lib/auth/autoupdate/autoupdatev1/service.go index 3828e6b344b43..48ef30070e0c1 100644 --- a/lib/auth/autoupdate/autoupdatev1/service.go +++ b/lib/auth/autoupdate/autoupdatev1/service.go @@ -55,6 +55,9 @@ type Cache interface { // ListAutoUpdateAgentReports lists all AutoUpdateAgentReport from the backend. ListAutoUpdateAgentReports(ctx context.Context, pageSize int, pageToken string) ([]*autoupdate.AutoUpdateAgentReport, string, error) + + // GetAutoUpdateBotInstanceReport gets the singleton AutoUpdateBotInstanceReport from the backend. + GetAutoUpdateBotInstanceReport(ctx context.Context) (*autoupdate.AutoUpdateBotInstanceReport, error) } // ServiceConfig holds configuration options for the auto update gRPC service. @@ -1042,6 +1045,56 @@ func (s *Service) DeleteAutoUpdateAgentReport(ctx context.Context, req *autoupda return &emptypb.Empty{}, nil } +// GetAutoUpdateBotInstanceReport gets the singleton AutoUpdateBotInstanceReport. +func (s *Service) GetAutoUpdateBotInstanceReport(ctx context.Context, _ *autoupdate.GetAutoUpdateBotInstanceReportRequest) (*autoupdate.AutoUpdateBotInstanceReport, error) { + authCtx, err := s.authorizer.Authorize(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + + if err := authCtx.CheckAccessToKind(types.KindAutoUpdateBotInstanceReport, types.VerbRead); err != nil { + return nil, trace.Wrap(err) + } + + report, err := s.backend.GetAutoUpdateBotInstanceReport(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + return report, nil +} + +// DeleteAutoUpdateBotInstanceReport gets the singleton AutoUpdateBotInstanceReport. +func (s *Service) DeleteAutoUpdateBotInstanceReport(ctx context.Context, _ *autoupdate.DeleteAutoUpdateBotInstanceReportRequest) (*emptypb.Empty, error) { + authCtx, err := s.authorizer.Authorize(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + + // Editing an agent report is restricted to cluster administrators. + // As of today we don't have any way of having + // resources that can only be edited by Teleport Cloud (when running cloud-hosted). + // The workaround is to check if the caller has the auth/admin system role. + // This is not ideal as it forces local tctl usage and can be bypassed if the user is very creative. + // In the future, if we expand the permission system and make cloud + // a first class citizen, we'll want to update this permission check. + if !authz.HasBuiltinRole(*authCtx, string(types.RoleAuth)) && !authz.HasBuiltinRole(*authCtx, string(types.RoleAdmin)) { + return nil, trace.AccessDenied("this request can be only executed by an auth server") + } + + if err := authCtx.CheckAccessToKind(types.KindAutoUpdateBotInstanceReport, types.VerbDelete); err != nil { + return nil, trace.Wrap(err) + } + + if err := authCtx.AuthorizeAdminActionAllowReusedMFA(); err != nil { + return nil, trace.Wrap(err) + } + + if err := s.backend.DeleteAutoUpdateBotInstanceReport(ctx); err != nil { + return nil, trace.Wrap(err) + } + return &emptypb.Empty{}, nil +} + func (s *Service) emitEvent(ctx context.Context, e apievents.AuditEvent) { if err := s.emitter.EmitAuditEvent(ctx, e); err != nil { slog.WarnContext(ctx, "Failed to emit audit event", diff --git a/lib/auth/autoupdate/autoupdatev1/service_test.go b/lib/auth/autoupdate/autoupdatev1/service_test.go index eaa70ca5edf6a..435659e4262e8 100644 --- a/lib/auth/autoupdate/autoupdatev1/service_test.go +++ b/lib/auth/autoupdate/autoupdatev1/service_test.go @@ -350,6 +350,29 @@ func TestServiceAccess(t *testing.T) { allowedVerbs: []string{types.VerbDelete}, builtinRole: &authz.BuiltinRole{Role: types.RoleAuth}, }, + // Autoupdate bot report check + { + name: "GetAutoUpdateBotInstanceReport", + allowedStates: []authz.AdminActionAuthState{ + authz.AdminActionAuthUnauthorized, + authz.AdminActionAuthNotRequired, + authz.AdminActionAuthMFAVerified, + authz.AdminActionAuthMFAVerifiedWithReuse, + }, + kind: types.KindAutoUpdateBotInstanceReport, + allowedVerbs: []string{types.VerbRead}, + }, + { + name: "DeleteAutoUpdateBotInstanceReport", + allowedStates: []authz.AdminActionAuthState{ + authz.AdminActionAuthNotRequired, + authz.AdminActionAuthMFAVerified, + authz.AdminActionAuthMFAVerifiedWithReuse, + }, + kind: types.KindAutoUpdateBotInstanceReport, + allowedVerbs: []string{types.VerbDelete}, + builtinRole: &authz.BuiltinRole{Role: types.RoleAuth}, + }, } for _, tt := range testCases { diff --git a/lib/auth/github_test.go b/lib/auth/github_test.go index c1e9b6b9747f9..12b924e293c05 100644 --- a/lib/auth/github_test.go +++ b/lib/auth/github_test.go @@ -88,6 +88,7 @@ func setupGithubContext(ctx context.Context, t *testing.T) *githubContext { VersionStorage: authtest.NewFakeTeleportVersion(), Authority: authority.New(), SkipPeriodicOperations: true, + HostUUID: uuid.NewString(), } tt.a, err = auth.NewServer(authConfig) require.NoError(t, err) diff --git a/lib/auth/machineid/machineidv1/auto_update_version_reporter.go b/lib/auth/machineid/machineidv1/auto_update_version_reporter.go new file mode 100644 index 0000000000000..b3029270f2a82 --- /dev/null +++ b/lib/auth/machineid/machineidv1/auto_update_version_reporter.go @@ -0,0 +1,359 @@ +/* + * Teleport + * Copyright (C) 2025 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package machineidv1 + +import ( + "context" + "log/slog" + "sync" + "time" + + "github.com/gravitational/trace" + "github.com/jonboulle/clockwork" + "github.com/prometheus/client_golang/prometheus" + "google.golang.org/protobuf/types/known/timestamppb" + + "github.com/gravitational/teleport" + "github.com/gravitational/teleport/api/defaults" + "github.com/gravitational/teleport/api/gen/proto/go/teleport/autoupdate/v1" + machineidv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/machineid/v1" + "github.com/gravitational/teleport/api/types" + update "github.com/gravitational/teleport/api/types/autoupdate" + "github.com/gravitational/teleport/api/utils/retryutils" + "github.com/gravitational/teleport/lib/services" +) + +// AutoUpdateVersionReporter aggregates bot instance version numbers into an +// `autoupdate_bot_instancenreport` resource periodically. We run a single +// leader-elected instance of the reporter per cluster. +type AutoUpdateVersionReporter struct { + clock clockwork.Clock + logger *slog.Logger + store AutoUpdateReportStore + cache BotInstancesCache + semaphores types.Semaphores + hostUUID string + + mu sync.Mutex + leaderCh chan struct{} +} + +// AutoUpdateReportStore is used to write the report. +type AutoUpdateReportStore interface { + UpsertAutoUpdateBotInstanceReport(ctx context.Context, report *autoupdate.AutoUpdateBotInstanceReport) (*autoupdate.AutoUpdateBotInstanceReport, error) +} + +// AutoUpdateVersionReporterConfig holds configuration for a version reporter. +type AutoUpdateVersionReporterConfig struct { + // Clock used to mock time in tests. + Clock clockwork.Clock + + // Logger to which errors and messages will be written. + Logger *slog.Logger + + // Store is used to write the report. + Store AutoUpdateReportStore + + // Cache will be used to list and count the bot instances. + Cache BotInstancesCache + + // Semaphores interface used to implement leader-election. + Semaphores types.Semaphores + + // HostUUID is the identity of the host running the reporter. + HostUUID string +} + +// NewAutoUpdateVersionReporter creates an AutoUpdateVersionReporter with the +// given configuration. You must call Run to start the leader-election process +// and Trigger whenever you want to generate a new report. +func NewAutoUpdateVersionReporter(cfg AutoUpdateVersionReporterConfig) (*AutoUpdateVersionReporter, error) { + if cfg.Clock == nil { + cfg.Clock = clockwork.NewRealClock() + } + if cfg.Logger == nil { + cfg.Logger = slog.Default() + } + if cfg.Semaphores == nil { + return nil, trace.BadParameter("Semaphores is required") + } + if cfg.HostUUID == "" { + return nil, trace.BadParameter("HostUUID is required") + } + if cfg.Store == nil { + return nil, trace.BadParameter("Store is required") + } + if cfg.Cache == nil { + return nil, trace.BadParameter("Cache is required") + } + return &AutoUpdateVersionReporter{ + clock: cfg.Clock, + logger: cfg.Logger, + cache: cfg.Cache, + store: cfg.Store, + semaphores: cfg.Semaphores, + hostUUID: cfg.HostUUID, + leaderCh: make(chan struct{}), + }, nil +} + +// Run begins the leader-election process until the given context is canceled or +// reaches its deadline. It will spawn a new goroutine, you do not need to run it +// with the go keyword. +func (r *AutoUpdateVersionReporter) Run(ctx context.Context) error { + // The runLeader method will do its own retrying around acquiring the + // semaphore. This retries the whole operation (e.g. after the lease is + // lost). + retry, err := retryutils.NewRetryV2(retryutils.RetryV2Config{ + First: 30 * time.Second, + Driver: retryutils.NewExponentialDriver(30 * time.Second), + Max: 10 * time.Minute, + Jitter: retryutils.HalfJitter, + Clock: r.clock, + }) + if err != nil { + return trace.Wrap(err) + } + + defer r.logger.DebugContext(ctx, "Shutting down") + + for { + started := r.clock.Now() + r.runLeader(ctx) + leaderFor := r.clock.Since(started) + + // Context is done, exit immediately. + if ctx.Err() != nil { + return nil + } + + // If we were leader for a decent amount of time, any previous + // backoff likely doesn't apply anymore. + if leaderFor > 5*time.Minute { + retry.Reset() + } + + // Wait for the next retry interval. + retry.Inc() + + select { + case <-retry.After(): + case <-ctx.Done(): + return nil + } + } +} + +func (r *AutoUpdateVersionReporter) runLeader(ctx context.Context) error { + lease, err := services.AcquireSemaphoreLockWithRetry( + ctx, + services.SemaphoreLockConfigWithRetry{ + SemaphoreLockConfig: services.SemaphoreLockConfig{ + Service: r.semaphores, + Params: types.AcquireSemaphoreRequest{ + SemaphoreKind: types.KindAuthServer, + SemaphoreName: "auto_update_bot_version_reporter", + MaxLeases: 1, + Holder: r.hostUUID, + }, + Expiry: 1 * time.Minute, + Clock: r.clock, + }, + Retry: retryutils.LinearConfig{ + Clock: r.clock, + First: time.Second, + Step: 30 * time.Second, + Max: 1 * time.Minute, + Jitter: retryutils.DefaultJitter, + }, + }, + ) + if err != nil { + return trace.Wrap(err) + } + + defer func() { + r.mu.Lock() + r.leaderCh = make(chan struct{}) + r.mu.Unlock() + + r.logger.DebugContext(ctx, "No longer the leader") + lease.Stop() + + if err := lease.Wait(); err != nil { + r.logger.WarnContext(ctx, "Error cleaning up semaphore", "error", err) + } + }() + + r.mu.Lock() + close(r.leaderCh) + r.mu.Unlock() + + r.logger.DebugContext(ctx, "Acquired semaphore and became the leader") + + select { + case <-lease.Done(): + return lease.Err() + case <-ctx.Done(): + return ctx.Err() + } +} + +// Report triggers the generation of a new report, ignored if the reporter is +// not the current elected leader. This method is typically called by the auth +// server's runPeriodicOperations method. +func (r *AutoUpdateVersionReporter) Report(ctx context.Context) error { + if !r.IsLeader() { + r.logger.DebugContext(ctx, "Not the leader, ignoring trigger to generate report") + return nil + } + if err := r.generateReport(ctx); err != nil { + r.logger.ErrorContext(ctx, "Failed to generate bot instance report", "error", err) + return trace.Wrap(err) + } + return nil +} + +func (r *AutoUpdateVersionReporter) generateReport(ctx context.Context) error { + r.logger.DebugContext(ctx, "Generating report") + + groups := make(map[string]*autoupdate.AutoUpdateBotInstanceReportSpecGroup) + + var nextToken string + for { + var ( + instances []*machineidv1.BotInstance + err error + ) + instances, nextToken, err = r.cache.ListBotInstances( + ctx, + "", + defaults.DefaultChunkSize, + nextToken, + "", + nil, + ) + if err != nil { + return trace.Wrap(err, "listing bot instances") + } + + for _, inst := range instances { + // Defend against backends not removing expired items in a timely manner. + expiry := inst.GetMetadata().GetExpires().AsTime() + if expiry.Before(r.clock.Now()) && !expiry.IsZero() { + continue + } + + // Take the version information from the latest heartbeat. + heartbeats := inst.GetStatus().GetLatestHeartbeats() + if len(heartbeats) == 0 { + continue + } + latest := heartbeats[len(heartbeats)-1] + + // If the bot did not send an ExternalUpdater, it does not properly + // support managed updates - so we put it in the no-group ("") group. + var groupName string + if ui := latest.GetUpdaterInfo(); latest.ExternalUpdater != "" && ui != nil { + groupName = ui.UpdateGroup + } + + group, ok := groups[groupName] + if !ok { + group = &autoupdate.AutoUpdateBotInstanceReportSpecGroup{ + Versions: make(map[string]*autoupdate.AutoUpdateBotInstanceReportSpecGroupVersion), + } + groups[groupName] = group + } + + version, ok := group.Versions[latest.GetVersion()] + if !ok { + version = &autoupdate.AutoUpdateBotInstanceReportSpecGroupVersion{} + group.Versions[latest.GetVersion()] = version + } + version.Count++ + } + + if nextToken == "" || len(instances) == 0 { + break + } + } + + report, err := update.NewAutoUpdateBotInstanceReport(&autoupdate.AutoUpdateBotInstanceReportSpec{ + Timestamp: timestamppb.New(r.clock.Now()), + Groups: groups, + }) + if err != nil { + return trace.Wrap(err, "creating report") + } + if _, err = r.store.UpsertAutoUpdateBotInstanceReport(ctx, report); err != nil { + return trace.Wrap(err, "storing report") + } + + return nil +} + +// LeaderCh returns a channel that will be closed when this instance of the +// reporter becomes the leader. It is used to block in tests. +func (r *AutoUpdateVersionReporter) LeaderCh() <-chan struct{} { + r.mu.Lock() + defer r.mu.Unlock() + + return r.leaderCh +} + +// IsLeader returns whether this instance of the reporter is the current leader. +func (r *AutoUpdateVersionReporter) IsLeader() bool { + select { + case <-r.LeaderCh(): + return true + default: + return false + } +} + +// EmitInstancesMetric updates the given gauge metric based on the instance report. +func EmitInstancesMetric(report *autoupdate.AutoUpdateBotInstanceReport, gauge *prometheus.GaugeVec) { + gauge.Reset() + + byVersion := make(map[string]int32) + + for group, groupMetrics := range report.GetSpec().GetGroups() { + // Empty group means the bot isn't using Managed Updates. + if group == "" { + for version, versionMetrics := range groupMetrics.GetVersions() { + gauge.With(prometheus.Labels{ + teleport.TagVersion: version, + teleport.TagAutomaticUpdates: "false", + }).Set(float64(versionMetrics.Count)) + } + continue + } + + for version, metrics := range groupMetrics.GetVersions() { + byVersion[version] += metrics.Count + } + } + + for version, count := range byVersion { + gauge.With(prometheus.Labels{ + teleport.TagVersion: version, + teleport.TagAutomaticUpdates: "true", + }).Set(float64(count)) + } +} diff --git a/lib/auth/machineid/machineidv1/auto_update_version_reporter_test.go b/lib/auth/machineid/machineidv1/auto_update_version_reporter_test.go new file mode 100644 index 0000000000000..b22b91480bf4f --- /dev/null +++ b/lib/auth/machineid/machineidv1/auto_update_version_reporter_test.go @@ -0,0 +1,223 @@ +/* + * Teleport + * Copyright (C) 2025 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package machineidv1_test + +import ( + "context" + "fmt" + "strconv" + "testing" + "time" + + "github.com/google/go-cmp/cmp" + "github.com/google/uuid" + "github.com/jonboulle/clockwork" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/testutil" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/testing/protocmp" + "google.golang.org/protobuf/types/known/timestamppb" + + "github.com/gravitational/teleport" + autoupdatev1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/autoupdate/v1" + headerv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" + machineidv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/machineid/v1" + "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/auth/machineid/machineidv1" + "github.com/gravitational/teleport/lib/backend/memory" + "github.com/gravitational/teleport/lib/services/local" + "github.com/gravitational/teleport/lib/utils" + "github.com/gravitational/teleport/lib/utils/slices" +) + +func TestAutoUpdateVersionReporter(t *testing.T) { + t.Parallel() + + ctx, cancel := context.WithCancel(t.Context()) + t.Cleanup(cancel) + + clock := clockwork.NewFakeClockAt(time.Now().UTC()) + + backend, err := memory.New(memory.Config{ + Context: ctx, + Clock: clock, + }) + require.NoError(t, err) + + autoUpdateService, err := local.NewAutoUpdateService(backend) + require.NoError(t, err) + + botInstanceService, err := local.NewBotInstanceService(backend, clock) + require.NoError(t, err) + + // Create a couple of bot instances with different versions. + createBotInstance := func(t *testing.T, group string, versions []string) { + t.Helper() + + _, err = botInstanceService.CreateBotInstance(ctx, &machineidv1pb.BotInstance{ + Metadata: &headerv1.Metadata{ + Expires: timestamppb.New(clock.Now().Add(1 * time.Hour)), + }, + Spec: &machineidv1pb.BotInstanceSpec{ + InstanceId: uuid.NewString(), + BotName: "bot-1234", + }, + Status: &machineidv1pb.BotInstanceStatus{ + LatestHeartbeats: slices.Map(versions, func(v string) *machineidv1pb.BotInstanceStatusHeartbeat { + heartbeat := &machineidv1pb.BotInstanceStatusHeartbeat{Version: v} + if group != "" { + heartbeat.ExternalUpdater = "kube" + heartbeat.UpdaterInfo = &types.UpdaterV2Info{UpdateGroup: group} + } + return heartbeat + }), + }, + }) + require.NoError(t, err) + } + createBotInstance(t, "", []string{"17.0.0", "18.0.0"}) + createBotInstance(t, "", []string{"18.1.0"}) + createBotInstance(t, "", []string{"18.1.0"}) + createBotInstance(t, "prod", []string{"18.1.0"}) + createBotInstance(t, "stage", []string{"19.0.0-dev"}) + + reporter, err := machineidv1.NewAutoUpdateVersionReporter(machineidv1.AutoUpdateVersionReporterConfig{ + Clock: clock, + Logger: utils.NewSlogLoggerForTests(), + Store: autoUpdateService, + Cache: botInstanceService, + Semaphores: &testSemaphores{}, + HostUUID: uuid.NewString(), + }) + require.NoError(t, err) + + // Run the leader election process. Wait for the semaphore to be acquired. + errCh := make(chan error, 1) + go func() { errCh <- reporter.Run(ctx) }() + + select { + case <-reporter.LeaderCh(): + case <-time.After(1 * time.Second): + t.Fatal("timeout waiting for semaphore to be acquired") + } + + // Trigger the report. + require.NoError(t, reporter.Report(ctx)) + + // Check the report records the bots. + report, err := autoUpdateService.GetAutoUpdateBotInstanceReport(ctx) + require.NoError(t, err) + + diff := cmp.Diff( + &autoupdatev1pb.AutoUpdateBotInstanceReportSpec{ + Timestamp: timestamppb.New(clock.Now()), + Groups: map[string]*autoupdatev1pb.AutoUpdateBotInstanceReportSpecGroup{ + "prod": { + Versions: map[string]*autoupdatev1pb.AutoUpdateBotInstanceReportSpecGroupVersion{ + "18.1.0": {Count: 1}, + }, + }, + "stage": { + Versions: map[string]*autoupdatev1pb.AutoUpdateBotInstanceReportSpecGroupVersion{ + "19.0.0-dev": {Count: 1}, + }, + }, + + // Unmanaged (no-group) group. + "": { + Versions: map[string]*autoupdatev1pb.AutoUpdateBotInstanceReportSpecGroupVersion{ + "18.0.0": {Count: 1}, + "18.1.0": {Count: 2}, + }, + }, + }, + }, + report.GetSpec(), + protocmp.Transform(), + ) + if diff != "" { + t.Fatal(diff) + } + + cancel() + require.NoError(t, <-errCh) +} + +func TestEmitInstancesMetric(t *testing.T) { + gauge := prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: teleport.MetricNamespace, + Name: teleport.MetricBotInstances, + }, + []string{ + teleport.TagVersion, + teleport.TagAutomaticUpdates, + }, + ) + + machineidv1.EmitInstancesMetric( + &autoupdatev1pb.AutoUpdateBotInstanceReport{ + Spec: &autoupdatev1pb.AutoUpdateBotInstanceReportSpec{ + Groups: map[string]*autoupdatev1pb.AutoUpdateBotInstanceReportSpecGroup{ + "prod": { + Versions: map[string]*autoupdatev1pb.AutoUpdateBotInstanceReportSpecGroupVersion{ + "18.0.0": {Count: 1}, + "19.0.0": {Count: 1}, + }, + }, + "stage": { + Versions: map[string]*autoupdatev1pb.AutoUpdateBotInstanceReportSpecGroupVersion{ + "18.0.0": {Count: 1}, + "19.0.0": {Count: 1}, + }, + }, + "": { + Versions: map[string]*autoupdatev1pb.AutoUpdateBotInstanceReportSpecGroupVersion{ + "19.0.0": {Count: 123}, + "20.0.0": {Count: 321}, + }, + }, + }, + }, + }, + gauge, + ) + + for _, tc := range []struct { + version string + automaticUpdates bool + expectedValue float64 + }{ + {version: "18.0.0", automaticUpdates: true, expectedValue: 2}, + {version: "19.0.0", automaticUpdates: true, expectedValue: 2}, + {version: "19.0.0", automaticUpdates: false, expectedValue: 123}, + {version: "20.0.0", automaticUpdates: false, expectedValue: 321}, + } { + t.Run(fmt.Sprintf("%s/%v", tc.version, tc.automaticUpdates), func(t *testing.T) { + metric := gauge.WithLabelValues(tc.version, strconv.FormatBool(tc.automaticUpdates)) + require.InEpsilon(t, tc.expectedValue, testutil.ToFloat64(metric), 0) + }) + } + +} + +type testSemaphores struct{ types.Semaphores } + +func (s *testSemaphores) AcquireSemaphore(ctx context.Context, params types.AcquireSemaphoreRequest) (*types.SemaphoreLease, error) { + return &types.SemaphoreLease{}, nil +} diff --git a/lib/auth/password_test.go b/lib/auth/password_test.go index 9f9d970fe8ff8..69982d3ec6970 100644 --- a/lib/auth/password_test.go +++ b/lib/auth/password_test.go @@ -26,6 +26,7 @@ import ( "testing" "time" + "github.com/google/uuid" "github.com/gravitational/trace" "github.com/jonboulle/clockwork" "github.com/pquerna/otp/totp" @@ -88,6 +89,7 @@ func setupPasswordSuite(t *testing.T) *passwordSuite { VersionStorage: authtest.NewFakeTeleportVersion(), Authority: authority.New(), SkipPeriodicOperations: true, + HostUUID: uuid.NewString(), } s.a, err = auth.NewServer(authConfig) require.NoError(t, err) diff --git a/lib/auth/trustedcluster_test.go b/lib/auth/trustedcluster_test.go index 433cc120b3fc8..606ecce352cc5 100644 --- a/lib/auth/trustedcluster_test.go +++ b/lib/auth/trustedcluster_test.go @@ -26,6 +26,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" "github.com/gravitational/trace" "github.com/stretchr/testify/require" @@ -439,6 +440,7 @@ func newTestAuthServer(ctx context.Context, t *testing.T, name ...string) *auth. VersionStorage: authtest.NewFakeTeleportVersion(), Authority: authority.New(), SkipPeriodicOperations: true, + HostUUID: uuid.NewString(), } a, err := auth.NewServer(authConfig) require.NoError(t, err) diff --git a/lib/cache/auto_update.go b/lib/cache/auto_update.go index 310343dd2a5aa..53ac629cff36d 100644 --- a/lib/cache/auto_update.go +++ b/lib/cache/auto_update.go @@ -88,7 +88,7 @@ func (c *Cache) GetAutoUpdateAgentReport(ctx context.Context, name string) (*aut getter := genericGetter[*autoupdatev1.AutoUpdateAgentReport, autoUpdateAgentReportIndex]{ cache: c, - collection: c.collections.autoUpdateReports, + collection: c.collections.autoUpdateAgentReports, index: autoUpdateAgentReportNameIndex, upstreamGet: c.Config.AutoUpdateService.GetAutoUpdateAgentReport, } @@ -103,7 +103,7 @@ func (c *Cache) ListAutoUpdateAgentReports(ctx context.Context, pageSize int, pa lister := genericLister[*autoupdatev1.AutoUpdateAgentReport, autoUpdateAgentReportIndex]{ cache: c, - collection: c.collections.autoUpdateReports, + collection: c.collections.autoUpdateAgentReports, index: autoUpdateAgentReportNameIndex, upstreamList: c.Config.AutoUpdateService.ListAutoUpdateAgentReports, nextToken: func(t *autoupdatev1.AutoUpdateAgentReport) string { @@ -113,3 +113,57 @@ func (c *Cache) ListAutoUpdateAgentReports(ctx context.Context, pageSize int, pa out, next, err := lister.list(ctx, pageSize, pageToken) return out, next, trace.Wrap(err) } + +type autoUpdateBotInstanceReportIndex string + +const autoUpdateBotInstanceReportNameIndex autoUpdateBotInstanceReportIndex = "name" + +func newAutoUpdateBotInstanceReportCollection(upstream services.AutoUpdateServiceGetter, w types.WatchKind) (*collection[*autoupdatev1.AutoUpdateBotInstanceReport, autoUpdateBotInstanceReportIndex], error) { + if upstream == nil { + return nil, trace.BadParameter("missing parameter AutoUpdateServiceGetter") + } + + return &collection[*autoupdatev1.AutoUpdateBotInstanceReport, autoUpdateBotInstanceReportIndex]{ + store: newStore( + types.KindAutoUpdateBotInstanceReport, + proto.CloneOf[*autoupdatev1.AutoUpdateBotInstanceReport], + map[autoUpdateBotInstanceReportIndex]func(*autoupdatev1.AutoUpdateBotInstanceReport) string{ + autoUpdateBotInstanceReportNameIndex: func(r *autoupdatev1.AutoUpdateBotInstanceReport) string { + return r.GetMetadata().Name + }, + }), + fetcher: func(ctx context.Context, loadSecrets bool) ([]*autoupdatev1.AutoUpdateBotInstanceReport, error) { + report, err := upstream.GetAutoUpdateBotInstanceReport(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + return []*autoupdatev1.AutoUpdateBotInstanceReport{report}, nil + }, + headerTransform: func(hdr *types.ResourceHeader) *autoupdatev1.AutoUpdateBotInstanceReport { + return &autoupdatev1.AutoUpdateBotInstanceReport{ + Kind: hdr.Kind, + Version: hdr.Version, + Metadata: &headerv1.Metadata{ + Name: hdr.Metadata.Name, + }, + } + }, + watch: w, + }, nil +} + +func (c *Cache) GetAutoUpdateBotInstanceReport(ctx context.Context) (*autoupdatev1.AutoUpdateBotInstanceReport, error) { + ctx, span := c.Tracer.Start(ctx, "cache/GetAutoUpdateBotInstanceReport") + defer span.End() + + getter := genericGetter[*autoupdatev1.AutoUpdateBotInstanceReport, autoUpdateBotInstanceReportIndex]{ + cache: c, + collection: c.collections.autoUpdateBotInstanceReports, + index: autoUpdateBotInstanceReportNameIndex, + upstreamGet: func(ctx context.Context, _ string) (*autoupdatev1.AutoUpdateBotInstanceReport, error) { + return c.Config.AutoUpdateService.GetAutoUpdateBotInstanceReport(ctx) + }, + } + out, err := getter.get(ctx, types.MetaNameAutoUpdateBotInstanceReport) + return out, trace.Wrap(err) +} diff --git a/lib/cache/cache.go b/lib/cache/cache.go index a8aa6372bb87b..813ebcaac8274 100644 --- a/lib/cache/cache.go +++ b/lib/cache/cache.go @@ -215,6 +215,7 @@ func ForAuth(cfg Config) Config { {Kind: types.KindAutoUpdateConfig}, {Kind: types.KindAutoUpdateAgentRollout}, {Kind: types.KindAutoUpdateAgentReport}, + {Kind: types.KindAutoUpdateBotInstanceReport}, {Kind: types.KindUserTask}, {Kind: types.KindProvisioningPrincipalState}, {Kind: types.KindIdentityCenterAccount}, diff --git a/lib/cache/cache_test.go b/lib/cache/cache_test.go index 58af877975fea..d0a7cae8bb8a7 100644 --- a/lib/cache/cache_test.go +++ b/lib/cache/cache_test.go @@ -3631,6 +3631,7 @@ func TestCacheWatchKindExistsInEvents(t *testing.T) { types.KindAutoUpdateVersion: types.Resource153ToLegacy(newAutoUpdateVersion(t)), types.KindAutoUpdateAgentRollout: types.Resource153ToLegacy(newAutoUpdateAgentRollout(t)), types.KindAutoUpdateAgentReport: types.Resource153ToLegacy(newAutoUpdateAgentReport(t, "test")), + types.KindAutoUpdateBotInstanceReport: types.Resource153ToLegacy(newAutoUpdateBotInstanceReport(t)), types.KindUserTask: types.Resource153ToLegacy(newUserTasks(t)), types.KindProvisioningPrincipalState: types.Resource153ToLegacy(newProvisioningPrincipalState("u-alice@example.com")), types.KindIdentityCenterAccount: types.Resource153ToLegacy(newIdentityCenterAccount("some_account")), @@ -4250,6 +4251,35 @@ func newAutoUpdateAgentReport(t *testing.T, name string) *autoupdate.AutoUpdateA return r } +func newAutoUpdateBotInstanceReport(t *testing.T) *autoupdate.AutoUpdateBotInstanceReport { + t.Helper() + + return &autoupdate.AutoUpdateBotInstanceReport{ + Kind: types.KindAutoUpdateBotInstanceReport, + Version: types.V1, + Metadata: &headerv1.Metadata{ + Name: types.MetaNameAutoUpdateBotInstanceReport, + }, + Spec: &autoupdate.AutoUpdateBotInstanceReportSpec{ + Timestamp: timestamppb.Now(), + Groups: map[string]*autoupdate.AutoUpdateBotInstanceReportSpecGroup{ + "foo": { + Versions: map[string]*autoupdate.AutoUpdateBotInstanceReportSpecGroupVersion{ + "1.2.3": {Count: 1}, + "1.2.4": {Count: 2}, + }, + }, + "bar": { + Versions: map[string]*autoupdate.AutoUpdateBotInstanceReportSpecGroupVersion{ + "2.3.4": {Count: 3}, + "2.3.5": {Count: 4}, + }, + }, + }, + }, + } +} + func withKeepalive[T any](fn func(context.Context, T) (*types.KeepAlive, error)) func(context.Context, T) error { return func(ctx context.Context, resource T) error { _, err := fn(ctx, resource) diff --git a/lib/cache/collections.go b/lib/cache/collections.go index 8fa4ed383c3c6..e4b3997188793 100644 --- a/lib/cache/collections.go +++ b/lib/cache/collections.go @@ -51,11 +51,12 @@ type collectionHandler interface { type collections struct { byKind map[resourceKind]collectionHandler - botInstances *collection[*machineidv1.BotInstance, botInstanceIndex] - remoteClusters *collection[types.RemoteCluster, remoteClusterIndex] - plugins *collection[types.Plugin, pluginIndex] - autoUpdateReports *collection[*autoupdatev1.AutoUpdateAgentReport, autoUpdateAgentReportIndex] - workloadIdentity *collection[*workloadidentityv1.WorkloadIdentity, workloadIdentityIndex] + botInstances *collection[*machineidv1.BotInstance, botInstanceIndex] + remoteClusters *collection[types.RemoteCluster, remoteClusterIndex] + plugins *collection[types.Plugin, pluginIndex] + autoUpdateAgentReports *collection[*autoupdatev1.AutoUpdateAgentReport, autoUpdateAgentReportIndex] + autoUpdateBotInstanceReports *collection[*autoupdatev1.AutoUpdateBotInstanceReport, autoUpdateBotInstanceReportIndex] + workloadIdentity *collection[*workloadidentityv1.WorkloadIdentity, workloadIdentityIndex] } // isKnownUncollectedKind is true if a resource kind is not stored in @@ -99,8 +100,16 @@ func setupCollections(c Config, legacyCollections map[resourceKind]legacyCollect return nil, trace.Wrap(err) } - out.autoUpdateReports = collect - out.byKind[resourceKind] = out.autoUpdateReports + out.autoUpdateAgentReports = collect + out.byKind[resourceKind] = out.autoUpdateAgentReports + case types.KindAutoUpdateBotInstanceReport: + collect, err := newAutoUpdateBotInstanceReportCollection(c.AutoUpdateService, watch) + if err != nil { + return nil, trace.Wrap(err) + } + + out.autoUpdateBotInstanceReports = collect + out.byKind[resourceKind] = out.autoUpdateBotInstanceReports case types.KindRemoteCluster: collect, err := newRemoteClusterCollection(c.Trust, watch) if err != nil { diff --git a/lib/service/service.go b/lib/service/service.go index ba097e4dc17ec..ec9fa7e6069ac 100644 --- a/lib/service/service.go +++ b/lib/service/service.go @@ -2576,6 +2576,9 @@ func (process *TeleportProcess) initAuthService() error { process.RegisterFunc("auth.autoupdate_agent_rollout_controller", func() error { return trace.Wrap(agentRolloutController.Run(process.GracefulExitContext()), "running autoupdate_agent_rollout controller") }) + process.RegisterFunc("auth.autoupdate_bot_instance_version_reporter", func() error { + return trace.Wrap(authServer.BotInstanceVersionReporter.Run(process.GracefulExitContext())) + }) process.RegisterFunc("auth.server_info", func() error { return trace.Wrap(auth.ReconcileServerInfos(process.GracefulExitContext(), authServer)) diff --git a/lib/services/autoupdates.go b/lib/services/autoupdates.go index c30e244531fdc..6f0f3dbe3884b 100644 --- a/lib/services/autoupdates.go +++ b/lib/services/autoupdates.go @@ -40,6 +40,12 @@ type AutoUpdateServiceGetter interface { // ListAutoUpdateAgentReports returns an AutoUpdateAgentReports page. ListAutoUpdateAgentReports(ctx context.Context, pageSize int, pageToken string) ([]*autoupdate.AutoUpdateAgentReport, string, error) + + // GetAutoUpdateBotInstanceReport gets the singleton auto-update bot report. + GetAutoUpdateBotInstanceReport(ctx context.Context) (*autoupdate.AutoUpdateBotInstanceReport, error) + + // DeleteAutoUpdateBotInstanceReport deletes the singleton auto-update bot instance report. + DeleteAutoUpdateBotInstanceReport(ctx context.Context) error } // AutoUpdateService stores the autoupdate service. @@ -96,4 +102,7 @@ type AutoUpdateService interface { // DeleteAllAutoUpdateAgentReports deletes all AutoUpdateAgentReport resources. DeleteAllAutoUpdateAgentReports(ctx context.Context) error + + // UpsertAutoUpdateBotInstanceReport creates or updates the bot instance report. + UpsertAutoUpdateBotInstanceReport(ctx context.Context, spec *autoupdate.AutoUpdateBotInstanceReport) (*autoupdate.AutoUpdateBotInstanceReport, error) } diff --git a/lib/services/local/autoupdate.go b/lib/services/local/autoupdate.go index 3ee58395f451c..65760da3d1553 100644 --- a/lib/services/local/autoupdate.go +++ b/lib/services/local/autoupdate.go @@ -32,18 +32,20 @@ import ( ) const ( - autoUpdateConfigPrefix = "auto_update_config" - autoUpdateVersionPrefix = "auto_update_version" - autoUpdateAgentRolloutPrefix = "auto_update_agent_rollout" - autoUpdateAgentReportPrefix = "auto_update_agent_report" + autoUpdateConfigPrefix = "auto_update_config" + autoUpdateVersionPrefix = "auto_update_version" + autoUpdateAgentRolloutPrefix = "auto_update_agent_rollout" + autoUpdateAgentReportPrefix = "auto_update_agent_report" + autoUpdateBotInstanceReportPrefix = "auto_update_bot_instance_report" ) // AutoUpdateService is responsible for managing AutoUpdateConfig and AutoUpdateVersion singleton resources. type AutoUpdateService struct { - config *generic.ServiceWrapper[*autoupdate.AutoUpdateConfig] - version *generic.ServiceWrapper[*autoupdate.AutoUpdateVersion] - rollout *generic.ServiceWrapper[*autoupdate.AutoUpdateAgentRollout] - report *generic.ServiceWrapper[*autoupdate.AutoUpdateAgentReport] + config *generic.ServiceWrapper[*autoupdate.AutoUpdateConfig] + version *generic.ServiceWrapper[*autoupdate.AutoUpdateVersion] + rollout *generic.ServiceWrapper[*autoupdate.AutoUpdateAgentRollout] + agentReport *generic.ServiceWrapper[*autoupdate.AutoUpdateAgentReport] + botInstanceReport *generic.ServiceWrapper[*autoupdate.AutoUpdateBotInstanceReport] } // NewAutoUpdateService returns a new AutoUpdateService. @@ -93,7 +95,7 @@ func NewAutoUpdateService(b backend.Backend) (*AutoUpdateService, error) { if err != nil { return nil, trace.Wrap(err) } - report, err := generic.NewServiceWrapper( + agentReport, err := generic.NewServiceWrapper( generic.ServiceConfig[*autoupdate.AutoUpdateAgentReport]{ Backend: b, ResourceKind: types.KindAutoUpdateAgentRollout, @@ -105,11 +107,24 @@ func NewAutoUpdateService(b backend.Backend) (*AutoUpdateService, error) { return nil, trace.Wrap(err) } + botInstanceReport, err := generic.NewServiceWrapper( + generic.ServiceConfig[*autoupdate.AutoUpdateBotInstanceReport]{ + Backend: b, + ResourceKind: types.KindAutoUpdateBotInstanceReport, + BackendPrefix: backend.NewKey(autoUpdateBotInstanceReportPrefix), + MarshalFunc: services.MarshalProtoResource[*autoupdate.AutoUpdateBotInstanceReport], + UnmarshalFunc: services.UnmarshalProtoResource[*autoupdate.AutoUpdateBotInstanceReport], + }) + if err != nil { + return nil, trace.Wrap(err) + } + return &AutoUpdateService{ - config: config, - version: version, - rollout: rollout, - report: report, + config: config, + version: version, + rollout: rollout, + agentReport: agentReport, + botInstanceReport: botInstanceReport, }, nil } @@ -229,13 +244,13 @@ func (s *AutoUpdateService) DeleteAutoUpdateAgentRollout(ctx context.Context) er // ListAutoUpdateAgentReports returns a paginated list of AutoUpdateAgentReport resources. func (s *AutoUpdateService) ListAutoUpdateAgentReports(ctx context.Context, pageSize int, pageToken string) ([]*autoupdate.AutoUpdateAgentReport, string, error) { - agentReports, nextKey, err := s.report.ListResources(ctx, pageSize, pageToken) + agentReports, nextKey, err := s.agentReport.ListResources(ctx, pageSize, pageToken) return agentReports, nextKey, trace.Wrap(err) } // GetAutoUpdateAgentReport returns the specified AutoUpdateAgentReport resource. func (s *AutoUpdateService) GetAutoUpdateAgentReport(ctx context.Context, name string) (*autoupdate.AutoUpdateAgentReport, error) { - agentReport, err := s.report.GetResource(ctx, name) + agentReport, err := s.agentReport.GetResource(ctx, name) return agentReport, trace.Wrap(err) } @@ -244,7 +259,7 @@ func (s *AutoUpdateService) CreateAutoUpdateAgentReport(ctx context.Context, age if err := update.ValidateAutoUpdateAgentReport(agentReport); err != nil { return nil, trace.Wrap(err, "validating autoupdate agent report") } - created, err := s.report.CreateResource(ctx, agentReport) + created, err := s.agentReport.CreateResource(ctx, agentReport) return created, trace.Wrap(err) } @@ -253,7 +268,7 @@ func (s *AutoUpdateService) UpdateAutoUpdateAgentReport(ctx context.Context, age if err := update.ValidateAutoUpdateAgentReport(agentReport); err != nil { return nil, trace.Wrap(err, "validating autoupdate agent report") } - updated, err := s.report.ConditionalUpdateResource(ctx, agentReport) + updated, err := s.agentReport.ConditionalUpdateResource(ctx, agentReport) return updated, trace.Wrap(err) } @@ -262,18 +277,18 @@ func (s *AutoUpdateService) UpsertAutoUpdateAgentReport(ctx context.Context, age if err := update.ValidateAutoUpdateAgentReport(agentReport); err != nil { return nil, trace.Wrap(err, "validating autoupdate agent report") } - upserted, err := s.report.UpsertResource(ctx, agentReport) + upserted, err := s.agentReport.UpsertResource(ctx, agentReport) return upserted, trace.Wrap(err) } // DeleteAutoUpdateAgentReport removes the specified AutoUpdateAgentReport resource. func (s *AutoUpdateService) DeleteAutoUpdateAgentReport(ctx context.Context, name string) error { - return trace.Wrap(s.report.DeleteResource(ctx, name)) + return trace.Wrap(s.agentReport.DeleteResource(ctx, name)) } // DeleteAllAutoUpdateAgentReports removes all AutoUpdateAgentReport resources. func (s *AutoUpdateService) DeleteAllAutoUpdateAgentReports(ctx context.Context) error { - return trace.Wrap(s.report.DeleteAllResources(ctx)) + return trace.Wrap(s.agentReport.DeleteAllResources(ctx)) } // itemFromAutoUpdateConfig generates `backend.Item` from `AutoUpdateConfig` resource type. @@ -327,3 +342,23 @@ func itemFromAutoUpdateVersion(version *autoupdate.AutoUpdateVersion) (*backend. } return item, nil } + +// GetAutoUpdateBotInstanceReport gets the singleton auto-update bot report. +func (s *AutoUpdateService) GetAutoUpdateBotInstanceReport(ctx context.Context) (*autoupdate.AutoUpdateBotInstanceReport, error) { + report, err := s.botInstanceReport.GetResource(ctx, types.MetaNameAutoUpdateBotInstanceReport) + return report, trace.Wrap(err) +} + +// UpsertAutoUpdateBotInstanceReport creates or updates the bot instance report. +func (s *AutoUpdateService) UpsertAutoUpdateBotInstanceReport(ctx context.Context, report *autoupdate.AutoUpdateBotInstanceReport) (*autoupdate.AutoUpdateBotInstanceReport, error) { + if err := update.ValidateAutoUpdateBotInstanceReport(report); err != nil { + return nil, trace.Wrap(err) + } + report, err := s.botInstanceReport.UpsertResource(ctx, report) + return report, trace.Wrap(err) +} + +// DeleteAutoUpdateBotInstanceReport deletes the singleton auto-update bot instance report. +func (s *AutoUpdateService) DeleteAutoUpdateBotInstanceReport(ctx context.Context) error { + return trace.Wrap(s.botInstanceReport.DeleteResource(ctx, types.MetaNameAutoUpdateBotInstanceReport)) +} diff --git a/lib/services/local/events.go b/lib/services/local/events.go index d183f236a5609..34c804737ad71 100644 --- a/lib/services/local/events.go +++ b/lib/services/local/events.go @@ -104,6 +104,8 @@ func (e *EventsService) NewWatcher(ctx context.Context, watch types.Watch) (type parser = newAutoUpdateAgentRolloutParser() case types.KindAutoUpdateAgentReport: parser = newAutoUpdateAgentReportParser() + case types.KindAutoUpdateBotInstanceReport: + parser = newAutoUpdateBotInstanceReportParser() case types.KindNamespace: parser = newNamespaceParser(kind.Name) case types.KindRole: @@ -904,6 +906,45 @@ func (p *autoUpdateAgentReportParser) parse(event backend.Event) (types.Resource } } +func newAutoUpdateBotInstanceReportParser() *autoUpdateBotInstanceReportParser { + return &autoUpdateBotInstanceReportParser{ + baseParser: newBaseParser(backend.NewKey(autoUpdateBotInstanceReportPrefix)), + } +} + +type autoUpdateBotInstanceReportParser struct { + baseParser +} + +func (p *autoUpdateBotInstanceReportParser) parse(event backend.Event) (types.Resource, error) { + switch event.Type { + case types.OpDelete: + name := event.Item.Key.TrimPrefix(backend.NewKey(autoUpdateBotInstanceReportPrefix)).String() + if name == "" { + return nil, trace.NotFound("failed parsing %v", event.Item.Key.String()) + } + return &types.ResourceHeader{ + Kind: types.KindAutoUpdateBotInstanceReport, + Version: types.V1, + Metadata: types.Metadata{ + Name: strings.TrimPrefix(name, backend.SeparatorString), + Namespace: apidefaults.Namespace, + }, + }, nil + case types.OpPut: + autoUpdateBotInstanceReport, err := services.UnmarshalProtoResource[*autoupdate.AutoUpdateBotInstanceReport](event.Item.Value, + services.WithExpires(event.Item.Expires), + services.WithRevision(event.Item.Revision), + ) + if err != nil { + return nil, trace.Wrap(err) + } + return types.Resource153ToLegacy(autoUpdateBotInstanceReport), nil + default: + return nil, trace.BadParameter("event %v is not supported", event.Type) + } +} + func newNamespaceParser(name string) *namespaceParser { prefix := backend.NewKey(namespacesPrefix) if name != "" { diff --git a/lib/services/resource.go b/lib/services/resource.go index f5ac2807108dd..1176a02eabfb2 100644 --- a/lib/services/resource.go +++ b/lib/services/resource.go @@ -275,6 +275,8 @@ func ParseShortcut(in string) (string, error) { return types.KindAutoUpdateAgentRollout, nil case types.KindAutoUpdateAgentReport: return types.KindAutoUpdateAgentReport, nil + case types.KindAutoUpdateBotInstanceReport: + return types.KindAutoUpdateBotInstanceReport, nil case types.KindGitServer, types.KindGitServer + "s": return types.KindGitServer, nil case types.KindWorkloadIdentityX509Revocation, types.KindWorkloadIdentityX509Revocation + "s": diff --git a/lib/srv/mock_test.go b/lib/srv/mock_test.go index d11127b5d8147..1c23e9fbec79f 100644 --- a/lib/srv/mock_test.go +++ b/lib/srv/mock_test.go @@ -27,6 +27,7 @@ import ( "os/user" "testing" + "github.com/google/uuid" "github.com/gravitational/trace" "github.com/jonboulle/clockwork" "github.com/sirupsen/logrus" @@ -147,6 +148,7 @@ func newMockServer(t *testing.T) *mockServer { Authority: testauthority.New(), ClusterName: clusterName, StaticTokens: staticTokens, + HostUUID: uuid.NewString(), } authServer, err := auth.NewServer(authCfg, authtest.WithClock(clock)) diff --git a/metrics.go b/metrics.go index eccd553d0c635..a6e99af625008 100644 --- a/metrics.go +++ b/metrics.go @@ -263,6 +263,9 @@ const ( // MetricRegisteredServers tracks the number of Teleport servers that have successfully registered with the Teleport cluster and have not reached the end of their ttl MetricRegisteredServers = "registered_servers" + // MetricBotInstances tracks the number of bot instances across the entire cluster, labeled by version + MetricBotInstances = "bot_instances" + // MetricRegisteredServersByInstallMethods tracks the number of Teleport servers, and their installation method, // that have successfully registered with the Teleport cluster and have not reached the end of their ttl MetricRegisteredServersByInstallMethods = "registered_servers_by_install_methods" diff --git a/tool/tctl/common/collection.go b/tool/tctl/common/collection.go index bafb494396ebb..1415bdc711f14 100644 --- a/tool/tctl/common/collection.go +++ b/tool/tctl/common/collection.go @@ -2111,3 +2111,27 @@ func (c *accessMonitoringRuleCollection) writeText(w io.Writer, verbose bool) er _, err := t.AsBuffer().WriteTo(w) return trace.Wrap(err) } + +type autoUpdateBotInstanceReportCollection struct { + report *autoupdatev1pb.AutoUpdateBotInstanceReport +} + +func (c *autoUpdateBotInstanceReportCollection) resources() []types.Resource { + return []types.Resource{types.ProtoResource153ToLegacy(c.report)} +} + +func (c *autoUpdateBotInstanceReportCollection) writeText(w io.Writer, _ bool) error { + t := asciitable.MakeTable([]string{"Update Group", "Version", "Count"}) + for groupName, groupMetrics := range c.report.GetSpec().GetGroups() { + if groupName == "" { + groupName = "" + } + for versionName, versionMetrics := range groupMetrics.GetVersions() { + t.AddRow([]string{groupName, versionName, strconv.Itoa(int(versionMetrics.Count))}) + } + } + t.SortRowsBy([]int{0, 1}, true) + + _, err := t.AsBuffer().WriteTo(w) + return trace.Wrap(err) +} diff --git a/tool/tctl/common/resource_command.go b/tool/tctl/common/resource_command.go index e718ff413388b..026664d131e2c 100644 --- a/tool/tctl/common/resource_command.go +++ b/tool/tctl/common/resource_command.go @@ -1752,6 +1752,7 @@ func (rc *ResourceCommand) Delete(ctx context.Context, client *authclient.Client types.KindAutoUpdateConfig, types.KindAutoUpdateVersion, types.KindAutoUpdateAgentRollout, + types.KindAutoUpdateBotInstanceReport, } if !slices.Contains(singletonResources, rc.ref.Kind) && (rc.ref.Kind == "" || rc.ref.Name == "") { return trace.BadParameter("provide a full resource name to delete, for example:\n$ tctl rm cluster/east\n") @@ -2219,6 +2220,11 @@ func (rc *ResourceCommand) Delete(ctx context.Context, client *authclient.Client return trace.Wrap(err) } fmt.Printf("AutoUpdateAgentRollout has been deleted\n") + case types.KindAutoUpdateBotInstanceReport: + if err := client.DeleteAutoUpdateBotInstanceReport(ctx); err != nil { + return trace.Wrap(err) + } + fmt.Printf("%s has been deleted\n", types.KindAutoUpdateBotInstanceReport) default: return trace.BadParameter("deleting resources of type %q is not supported", rc.ref.Kind) } @@ -3429,6 +3435,15 @@ func (rc *ResourceCommand) getCollection(ctx context.Context, client *authclient nextToken = token } return &autoUpdateAgentReportCollection{reports: reports}, nil + case types.KindAutoUpdateBotInstanceReport: + if rc.ref.Name != "" { + return nil, trace.BadParameter("only simple `tctl get %v` can be used", types.KindAutoUpdateBotInstanceReport) + } + report, err := client.GetAutoUpdateBotInstanceReport(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + return &autoUpdateBotInstanceReportCollection{report}, nil case types.KindAccessMonitoringRule: if rc.ref.Name != "" { rule, err := client.AccessMonitoringRuleClient().GetAccessMonitoringRule(ctx, rc.ref.Name)